-- Precondition: The socket is already connected to the server
-- Exchange ROSTCP connection headers with the server
negotiateService :: Socket -> String -> String -> String -> ExceptT ServiceResponseExcept IO ()
negotiateService sock serviceName serviceType md5 = do
    headerBytes <- liftIO $
      do sendAll sock $ genHeader [ ("callerid", "roshask"), ("service", serviceName)
                                , ("md5sum", md5), ("type", serviceType) ]
         responseLength <- runGet (fromIntegral <$> getWord32le) <$>
                           BL.fromChunks . (:[]) <$> recvAll sock 4
         recvAll sock responseLength
    let connHeader = parseHeader headerBytes
    case lookup "error" connHeader of
      Nothing -> return ()
      Just _ -> throwError . ConHeadExcept $
                "Connection header from server has error, connection header is: " ++ show connHeader
                                    
-- Helper to run the publisher's side of a topic negotiation with a
-- new client.
negotiateService :: Socket -> String -> String -> String -> ExceptT ServiceResponseExcept IO ()
negotiateService sock serviceName serviceType md5 = do
    headerBytes <- liftIO $
      do sendAll sock $ genHeader [ ("callerid", "roshask"), ("service", serviceName)
                                , ("md5sum", md5), ("type", serviceType) ]
         responseLength <- runGet (fromIntegral <$> getWord32le) <$>
                           BL.fromChunks . (:[]) <$> recvAll sock 4
         recvAll sock responseLength
    let connHeader = parseHeader headerBytes
    case lookup "error" connHeader of
      Nothing -> return ()
      Just _ -> throwError . ConHeadExcept $
                "Connection header from server has error, connection header is: " ++ show connHeader
                                    
-- Helper to run the publisher's side of a topic negotiation with a
-- new client.
negotiateService sock serviceName serviceType md5 = do
    headerBytes <- liftIO $
      do sendAll sock $ genHeader [ ("callerid", "roshask"), ("service", serviceName)
                                , ("md5sum", md5), ("type", serviceType) ]
         responseLength <- runGet (fromIntegral <$> getWord32le) <$>
                           BL.fromChunks . (:[]) <$> recvAll sock 4
         recvAll sock responseLength
    let connHeader = parseHeader headerBytes
    case lookup "error" connHeader of
      Nothing -> return ()
      Just _ -> throwError . ConHeadExcept $
                "Connection header from server has error, connection header is: " ++ show connHeader
                                    
-- Helper to run the publisher's side of a topic negotiation with a
-- new client.