Beispiel #1
0
int main(int argc, char **argv) {
	SOCKET s;
	char *remote;

	if(argc > 1)
		remote = argv[1];
	else
		remote = REMOTE_ADDR;
	
	printf("Starting Winsock... ");
	if(StartWinsock() != 0) {
		printf("Failed.\n");
		return EXIT_FAILURE;
	}
	printf("OK.\n");

	printf("Connecting to %s:%d... ", remote, SERVER_PORT);

	if((s = CreateConnectSocket(remote, SERVER_PORT)) == SOCKET_ERROR) {
		printf("Failed.\n");
		return EXIT_FAILURE;
	}
	printf("OK.\n\n");

	if(ClientHandshake(s))
		CommandLoop(s);

	WSACleanup();

	if(conn.dh_remote_key)
		free(conn.dh_remote_key);
	if(conn.dh_shared_key)
		free(conn.dh_shared_key);
	if(conn.nonce)
		free(conn.nonce);

#ifdef _DEBUG
	showmemstats(stdout);
#endif

	return EXIT_SUCCESS;
}
Beispiel #2
0
//Ö§³Öhost name
//ÄÚ²¿º¯Êý ͨ¹ý½Ó¿Ú½á¹¹Ìå»ñÈ¡SOCKET ID
//Èë²Î thisÖ¸Õ룬 ·µ»ØÖµ SOCKET ID (OR INVALID SOCKET)
SOCKET IpappGetSocketId(IPAPP_USER_S* pThis)
{
  //Èë²Î¼ì²é
  CHECK_PARAM(pThis);
  
  UINT32 uiRet = VOS_OK;
  char* pcAddr = NULL;
  //SOCKET soSocket = 0;
  struct hostent *remoteHost = NULL;
  
  if (!pThis->bsocketid)
  {
    
    if(!pThis->bip)
    {
      remoteHost = gethostbyname(pThis->hostname);
      
      if (remoteHost == NULL)
      {
        uiRet = WSAGetLastError();
        printf("Function failed with error: %ld\n", uiRet);
        return VOS_ERROR;
      }
      
      pcAddr = inet_ntoa (*(struct in_addr *)*remoteHost->h_addr_list);
      
    }
    else
    {
      pcAddr = pThis->ip;
    }
    
    return CreateConnectSocket(pThis->usPort, (const char *) pcAddr);
  }
  
  return pThis->socketid;
  
}
Beispiel #3
0
bool TClient::Init()
{
	InitializeCriticalSection(&m_CS);
	int rv;
	WSADATA wsa;
	if( WSAStartup( MAKEWORD(2,2), &wsa ) != 0 )
	{
		return -1;
	}
	
	if( CreateConnectSocket( 10000 ) == 0 )
	{		
		// send thread		
		unsigned  sendThread, receiveThread;
		m_hSendThread = _beginthreadex( NULL, 0, sendMessage,
			(void*)this, 0, &sendThread);
		// recv thread
		m_hReceiveThread = _beginthreadex( NULL, 0, receiveMessage,
			(void*)this, 0, &receiveThread);		
		
	}	
	return true;
}
Beispiel #4
0
int
test_mid_clt(int ctlSocket, char tests, char* host, int conn_options, int buf_size, char* tmpstr2)
{
  char buff[BUFFSIZE+1];
  int msgLen, msgType;
  int midport = 3003;
  I2Addr sec_addr = NULL;
  int ret, one=1, i, inlth;
  int in2Socket;
  double t, spdin;
  uint32_t bytes;
  struct timeval sel_tv;
  fd_set rfd;

  if (tests & TEST_MID) {
    log_println(1, " <-- Middlebox test -->");
    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed prepare message!");
      return 1;
    }
    if (check_msg_type("Middlebox test", TEST_PREPARE, msgType, buff, msgLen)) {
      return 2;
    }
    if (msgLen <= 0) {
      log_println(0, "Improper message");
      return 3;
    }
    buff[msgLen] = 0;
    if (check_int(buff, &midport)) {
      log_println(0, "Invalid port number");
      return 4;
    }
    log_println(1, "  -- port: %d", midport);
    if ((sec_addr = I2AddrByNode(get_errhandle(), host)) == NULL) {
      log_println(0, "Unable to resolve server address: %s", strerror(errno));
      return -3;
    }
    I2AddrSetPort(sec_addr, midport);

    if (get_debuglvl() > 4) {
      char tmpbuff[200];
      size_t tmpBufLen = 199;
      memset(tmpbuff, 0, 200);
      I2AddrNodeName(sec_addr, tmpbuff, &tmpBufLen);
      log_println(5, "connecting to %s:%d", tmpbuff, I2AddrPort(sec_addr));
    }

    if ((ret = CreateConnectSocket(&in2Socket, NULL, sec_addr, conn_options, buf_size))) {
      log_println(0, "Connect() for middlebox failed: %s", strerror(errno));
      return -10;
    }

    printf("Checking for Middleboxes . . . . . . . . . . . . . . . . . .  ");
    fflush(stdout);
    tmpstr2[0] = '\0';
    i = 0;
    bytes = 0;
    t = secs() + 5.0;
    sel_tv.tv_sec = 6;
    sel_tv.tv_usec = 5;
    FD_ZERO(&rfd);
    FD_SET(in2Socket, &rfd);
    for (;;) {
      if (secs() > t)
        break;
      ret = select(in2Socket+1, &rfd, NULL, NULL, &sel_tv);
      if (ret > 0) {
        inlth = read(in2Socket, buff, sizeof(buff));
        if (inlth == 0)
          break;
        bytes += inlth;
        continue;
      }
      if (ret < 0) {
        printf("nothing to read, exiting read loop\n");
        break;
      }
      if (ret == 0) {
        printf("timer expired, exiting read loop\n");
        break;
      }
    }
    t =  secs() - t + 5.0;
    spdin = ((8.0 * bytes) / 1000) / t;

    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed text message!");
      return 1;
    }
    if (check_msg_type("Middlebox test results", TEST_MSG, msgType, buff, msgLen)) {
      return 2;
    }
    strncat(tmpstr2, buff, msgLen);

    memset(buff, 0, 128);
    sprintf(buff, "%0.0f", spdin);
    log_println(4, "CWND limited speed = %0.2f kbps", spdin);
    send_msg(ctlSocket, TEST_MSG, buff, strlen(buff));
    printf("Done\n");

    I2AddrFree(sec_addr);

    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed finalize message!");
      return 1;
    }
    if (check_msg_type("Middlebox test", TEST_FINALIZE, msgType, buff, msgLen)) {
      return 2;
    }
    log_println(1, " <-------------------->");
  }
  return 0;
}
Beispiel #5
0
int
test_s2c_clt(int ctlSocket, char tests, char* host, int conn_options, int buf_size, char* tmpstr)
{
  char buff[BUFFSIZE+1];
  int msgLen, msgType;
  int s2cport = 3003;
  I2Addr sec_addr = NULL;
  int inlth, ret, one=1, set_size;
  int inSocket;
  socklen_t optlen;
  uint32_t bytes;
  double t;
  struct timeval sel_tv;
  fd_set rfd;
  char* ptr;
  
  if (tests & TEST_S2C) {
    log_println(1, " <-- S2C throughput test -->");
    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed prepare message!");
      return 1;
    }
    if (check_msg_type("S2C throughput test", TEST_PREPARE, msgType, buff, msgLen)) {
      return 2;
    }
    if (msgLen <= 0) {
      log_println(0, "Improper message");
      return 3;
    }
    buff[msgLen] = 0;
    if (check_int(buff, &s2cport)) {
      log_println(0, "Invalid port number");
      return 4;
    }
    log_println(1, "  -- port: %d", s2cport);

    /* Cygwin seems to want/need this extra getsockopt() function
     * call.  It certainly doesn't do anything, but the S2C test fails
     * at the connect() call if it's not there.  4/14/05 RAC
     */
    optlen = sizeof(set_size);
    getsockopt(ctlSocket, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen);

    if ((sec_addr = I2AddrByNode(get_errhandle(), host)) == NULL) {
      log_println(0, "Unable to resolve server address: %s", strerror(errno));
      return -3;
    }
    I2AddrSetPort(sec_addr, s2cport);

    if ((ret = CreateConnectSocket(&inSocket, NULL, sec_addr, conn_options, buf_size))) {
      log_println(0, "Connect() for Server to Client failed", strerror(errno));
      return -15;
    }

    setsockopt(inSocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

    /* Linux updates the sel_tv time values everytime select returns.  This
     * means that eventually the timer will reach 0 seconds and select will
     * exit with a timeout signal.  Other OS's don't do that so they need
     * another method for detecting a long-running process.  The check below
     * will cause the loop to terminate if select says there is something
     * to read and the loop has been active for over 14 seconds.  This usually
     * happens when there is a problem (duplex mismatch) and there is data
     * queued up on the server.
     */
    
    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed start message!");
      return 1;
    }
    if (check_msg_type("S2C throughput test", TEST_START, msgType, buff, msgLen)) {
      return 2;
    }

    printf("running 10s inbound test (server to client) . . . . . . ");
    fflush(stdout);

    bytes = 0;
    t = secs() + 15.0;
    sel_tv.tv_sec = 15;
    sel_tv.tv_usec = 5;
    FD_ZERO(&rfd);
    FD_SET(inSocket, &rfd);
    for (;;) {
      ret = select(inSocket+1, &rfd, NULL, NULL, &sel_tv);
      if (secs() > t) {
        log_println(5, "Receive test running long, break out of read loop");
        break;
      }
      if (ret > 0) {
        inlth = read(inSocket, buff, sizeof(buff));
        if (inlth == 0)
          break;
        bytes += inlth;
        continue;
      }
      if (get_debuglvl() > 5) {
        log_println(0, "s2c read loop exiting:", strerror(errno));
      }
      break;
    }
    t = secs() - t + 15.0;
    spdin = ((8.0 * bytes) / 1000) / t;

    /* receive the s2cspd from the server */
    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed text message!");
      return 1;
    }
    if (check_msg_type("S2C throughput test", TEST_MSG, msgType, buff, msgLen)) {
      return 2;
    }
    if (msgLen <= 0) { 
      log_println(0, "Improper message");
      return 3;
    }
    buff[msgLen] = 0; 
    ptr = strtok(buff, " ");
    if (ptr == NULL) {
      log_println(0, "S2C: Improper message");
      return 4;
    }
    s2cspd = atoi(ptr);
    ptr = strtok(NULL, " ");
    if (ptr == NULL) {
      log_println(0, "S2C: Improper message");
      return 4;
    }
    ssndqueue = atoi(ptr);
    ptr = strtok(NULL, " ");
    if (ptr == NULL) {
      log_println(0, "S2C: Improper message");
      return 4;
    }
    sbytes = atoi(ptr);
    
    if (spdin < 1000)
      printf("%0.2f kb/s\n", spdin);
    else
      printf("%0.2f Mb/s\n", spdin/1000);

    I2AddrFree(sec_addr);

    sprintf(buff, "%0.0f", spdin);
    send_msg(ctlSocket, TEST_MSG, buff, strlen(buff));
    
    /* get web100 variables from server */
    tmpstr[0] = '\0';
    for (;;) {
      msgLen = sizeof(buff);
      if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
        log_println(0, "Protocol error - missed text/finalize message!");
        return 1;
      }
      if (msgType == TEST_FINALIZE) {
        break;
      }
      if (check_msg_type("S2C throughput test", TEST_MSG, msgType, buff, msgLen)) {
        return 2;
      }
      strncat(tmpstr, buff, msgLen);
      log_println(6, "tmpstr = '%s'", tmpstr);
    }
    log_println(1, " <------------------------->");
  }


  return 0;
}
Beispiel #6
0
int CMainCtrl::CheckSvrMessage()
{
	int iDoMsgCnt = 0;
	int iDoMsgLen = 0;
	int iCodeLength;
	char *pMsgBuff;	
	int iGetPtrLen = -1;
	while((iDoMsgLen < 500*1024) && (iDoMsgCnt < 500))
	{
		ssize_t iBuffUsed,iBuffCount,iObjUsed,iObjCount;
		m_stBuffMngRecv.GetBufferUsage(iBuffUsed,iBuffCount,iObjUsed,iObjCount);

		//空间已满
		if(iObjUsed/(float)iObjCount > 0.9)
		{
			//少数连接比较慢
			if(iBuffUsed/(float)iBuffCount > 0.5)
				break;
		}
			
		if(iGetPtrLen > 0)
		{
			m_Svr2MePipe.SkipHeadCodePtr();
			iGetPtrLen = -1;
		}

		iGetPtrLen = m_Svr2MePipe.GetHeadCodePtr(pMsgBuff, &iCodeLength);
		if(iGetPtrLen < 0)
		{
			iCodeLength = sizeof(m_szCodeBuff);
			int iRet = m_Svr2MePipe.GetHeadCode(m_szCodeBuff, &iCodeLength);
			if(iRet < 0 || iCodeLength <= 0)
			{
				break;
			}
			pMsgBuff = m_szCodeBuff;
		}
		else if(iGetPtrLen == 0)
		{
			break;
		}
		
		iDoMsgLen += iCodeLength;
		iDoMsgCnt++;

		char *pClientMsg = pMsgBuff + sizeof(TMQHeadInfo);
		int iClientMsgLen = iCodeLength - sizeof(TMQHeadInfo);
			
		TMQHeadInfo* pMQHeadInfo = (TMQHeadInfo*)pMsgBuff;
		//请求关闭	
		if(pMQHeadInfo->m_ucCmd == TMQHeadInfo::CMD_REQ_SCC_CLOSE)
		{
			ClearSocketNode(pMQHeadInfo->m_unClientIP,pMQHeadInfo->m_usClientPort,pMQHeadInfo->m_szSrcMQ);
			continue;
		}	
		//必须是连接或者传输包
		if ((pMQHeadInfo->m_ucCmd != TMQHeadInfo::CMD_REQ_SCC_CONN) &&
			(pMQHeadInfo->m_ucCmd != TMQHeadInfo::CMD_DATA_TRANS))
		{
			TLib_Log_LogMsg("ERR:Bad MQ cmd id %d from server!\n",pMQHeadInfo->m_ucCmd);
			continue;
		}
		//检查接收队列中的超时包
		if(m_stConfig.m_iMaxQueueWaitus)
		{	
			gettimeofday(&m_tNow,NULL);
			int iQueueWaitus = (m_tNow.tv_sec - pMQHeadInfo->m_tTimeStampSec)*1000000+
							(m_tNow.tv_usec - pMQHeadInfo->m_tTimeStampuSec);
			
			if(iQueueWaitus>m_stConfig.m_iMaxQueueWaitus)
			{
				TLib_Log_LogMsgFrequency(1,"WARN::Expire Msg From Mem Queue, QueueWait=%dus\n",iQueueWaitus);
			}
		}

		char szKey[1024];
		ssize_t iKeyLen = 0;
		if(pMQHeadInfo->m_ucDataType == TMQHeadInfo::DATA_TYPE_UDP)
		{
			iKeyLen = (ssize_t)MakeKey(0,0,pMQHeadInfo->m_szSrcMQ,szKey);
			ssize_t iNodeObjIdx = -1;
			TSocketNode* pSocketNode = (TSocketNode*)m_stSocketNodeHash.GetObjectByKey((void *)szKey,iKeyLen,iNodeObjIdx);
			if (!pSocketNode)
			{
				int iSocket = CreateConnectSocket(0,0,
							m_stConfig.SOCKET_RCVBUF,m_stConfig.SOCKET_SNDBUF,1);
				if (iSocket < 0)
				{
					char szIPAddr[32]={0};
					NtoP(pMQHeadInfo->m_unClientIP,szIPAddr);
					TLib_Log_LogMsg("ERR:UDP connect to %s:%d failed![%s:%d]\n",
									szIPAddr,pMQHeadInfo->m_usClientPort,__FILE__,__LINE__);
					continue;
				}

				iNodeObjIdx = CreateSocketNode(iSocket,TSocketNode::STATUS_OK,
							0,0,pMQHeadInfo->m_szSrcMQ,TSocketNode::UDP_SOCKET);
				if (iNodeObjIdx < 0)
				{
					close(iSocket);
					TLib_Log_LogMsg("ERR:UDP Add to socket array failed!SocketNodeMng used %d, free %d\n",
									m_stSocketNodeMng.GetUsedCount(),m_stSocketNodeMng.GetFreeCount());
					continue;
				}
				pSocketNode = (TSocketNode*)m_stSocketNodeHash.GetObjectByIdx(iNodeObjIdx);				
			}
			else if(pSocketNode->m_sSocketType != TSocketNode::UDP_SOCKET)
			{
				TLib_Log_LogMsg("ERR:MQ name %d alread exist! and its type is %d, not UDP socket.\n",
									pSocketNode->m_szSrcMQ,(int)pSocketNode->m_sSocketType);
				continue;	
			}

			struct sockaddr_in addrClient;	
			addrClient.sin_family = AF_INET;
			addrClient.sin_addr.s_addr = pMQHeadInfo->m_unClientIP;
			addrClient.sin_port = htons(pMQHeadInfo->m_usClientPort);

			int iSendBytes = sendto(pSocketNode->m_iSocket,pClientMsg,iClientMsgLen,
							0,(struct sockaddr*)&addrClient,sizeof(struct sockaddr_in));
			
			pSocketNode->m_iActiveTime = m_tNow.tv_sec;
			if(iSendBytes > 0)
			{
				m_stStat.m_llUdpSCSuccPkgNum++;
				m_stStat.m_llUdpSCPkgLen += iClientMsgLen;	
			}
			else
			{
				TLib_Log_LogMsg("ERR:Udp sendto failed ret=%d.[%s:%d]\n",iSendBytes,__FILE__,__LINE__);
				m_stStat.m_llUdpSCFailedPkgNum++;
			}
		}
		else
		{
			iKeyLen = (ssize_t)MakeKey(pMQHeadInfo->m_unClientIP,pMQHeadInfo->m_usClientPort,pMQHeadInfo->m_szSrcMQ,szKey);
			ssize_t iNodeObjIdx = -1;
			TSocketNode* pSocketNode = (TSocketNode*)m_stSocketNodeHash.GetObjectByKey((void *)szKey,iKeyLen,iNodeObjIdx);
			if (!pSocketNode)
			{
				//连接不存在
				int iSocket = CreateConnectSocket(pMQHeadInfo->m_unClientIP,pMQHeadInfo->m_usClientPort,
								m_stConfig.SOCKET_RCVBUF,m_stConfig.SOCKET_SNDBUF,0);
				if (iSocket < 0)
				{
					char szIPAddr[32]={0};
					NtoP(pMQHeadInfo->m_unClientIP,szIPAddr);
					TLib_Log_LogMsg("ERR:connect to %s:%d failed![%s:%d]\n",
									szIPAddr,pMQHeadInfo->m_usClientPort,__FILE__,__LINE__);
					continue;
				}

				int iSocketStatus = TSocketNode::STATUS_CONNECTING;
				if (pMQHeadInfo->m_ucCmd == TMQHeadInfo::CMD_DATA_TRANS)
					iSocketStatus = TSocketNode::STATUS_SENDING;

				iNodeObjIdx = CreateSocketNode(iSocket,iSocketStatus,
						pMQHeadInfo->m_unClientIP, pMQHeadInfo->m_usClientPort,
						pMQHeadInfo->m_szSrcMQ,TSocketNode::TCP_SOCKET);
				if (iNodeObjIdx < 0)
				{
					close(iSocket);
					TLib_Log_LogMsg("ERR:Add to socket array failed!SocketNodeMng used %d, free %d\n",
									m_stSocketNodeMng.GetUsedCount(),m_stSocketNodeMng.GetFreeCount());
					continue;
				}
				pSocketNode = (TSocketNode*)m_stSocketNodeHash.GetObjectByIdx(iNodeObjIdx);
			}
			else if (pMQHeadInfo->m_ucCmd == TMQHeadInfo::CMD_REQ_SCC_CONN)
			{
				//连接存在
				TMQHeadInfo stMQHeadInfo;
				FillMQHead(&stMQHeadInfo,pSocketNode,TMQHeadInfo::CMD_SCC_RSP_CONNSUCC);
				m_Me2SvrPipe.AppendOneCode((const char *)&stMQHeadInfo, sizeof(TMQHeadInfo));
				continue;
			}

			//试图发送
			int iSendBytes = m_stBuffMngSend.SendBufferToSocket(pSocketNode->m_iSocket,iNodeObjIdx);
			 if ((iSendBytes<0)&&(errno!=EAGAIN))
			{
					TLib_Log_LogMsg("ERR:write() to socket failed,ret %d,errno=%d,socket %d,clientmsglen %d[%s:%d].\n",
						iSendBytes,errno,pSocketNode->m_iSocket,iClientMsgLen,__FILE__,__LINE__);
				ClearSocketNode(pSocketNode->m_unClientIP,pSocketNode->m_usClientPort,pSocketNode->m_szSrcMQ);
				continue;
			}
			 
			//数据传输,缓存没有则直接发送,有则放入缓存	
			if (m_stBuffMngSend.GetBufferSize(iNodeObjIdx) <= 0)
			{
				int iSendBytes = write(pSocketNode->m_iSocket, pClientMsg, iClientMsgLen);
				if ((iSendBytes<0)&&(errno!=EAGAIN))
				{
					TLib_Log_LogMsg("ERR:write() to socket failed,ret %d,errno=%d,socket %d,clientmsglen %d[%s:%d]\n",
						iSendBytes,errno,pSocketNode->m_iSocket,iClientMsgLen,__FILE__,__LINE__);
					ClearSocketNode(pMQHeadInfo->m_unClientIP,pMQHeadInfo->m_usClientPort,pSocketNode->m_szSrcMQ);
					continue;
				}			
				else if (iSendBytes < iClientMsgLen)
				{
					iSendBytes = iSendBytes>0 ? iSendBytes : 0;
					if (0==m_stBuffMngSend.AppendBuffer(iNodeObjIdx, 
								pClientMsg+iSendBytes,iClientMsgLen-iSendBytes))
					{
						//增加EPOLLOUT监控
						m_stEPollFlow.Modify(pSocketNode->m_iSocket, iNodeObjIdx, EPOLLIN |EPOLLOUT| EPOLLERR|EPOLLHUP);		
					}
					else
					{
						//已经发了一部分,防止数据错乱,关闭
						ClearSocketNode(pSocketNode->m_unClientIP,pSocketNode->m_usClientPort,pSocketNode->m_szSrcMQ);			
						TLib_Log_LogMsg("ERR:AppendBuffer() failed,BuffMngSend may be full,close link![%s:%d]\n",__FILE__,__LINE__);
						continue;
					}
				}	
			}
			else
			{
				if(m_stBuffMngSend.AppendBuffer(iNodeObjIdx, pClientMsg,iClientMsgLen))
				{
					//不能秘密丢包,关闭连接,使外界感知
					ClearSocketNode(pSocketNode->m_unClientIP,pSocketNode->m_usClientPort,pSocketNode->m_szSrcMQ);
					TLib_Log_LogMsgFrequency(1,"ERR:AppendBuffer() failed,BuffMngSend may be full, close link![%s:%d]\n",__FILE__,__LINE__);
					continue;
				}	
			}
			pSocketNode->m_iActiveTime = m_tNow.tv_sec;
			m_stStat.m_llTcpSCPkgNum++;
			m_stStat.m_llTcpSCPkgLen += (unsigned int)iClientMsgLen;
		}
		
		m_pCLoadGrid->CheckLoad(m_tNow);
	}	

	if(iGetPtrLen > 0)
	{
		m_Svr2MePipe.SkipHeadCodePtr();
		iGetPtrLen = -1;
	}
		
	return 0;
}
Beispiel #7
0
/**
 * Perform the client part of the middleBox testing. The middlebox test
 * is a 5.0 second throughput test from the Server to the Client to
 * check for duplex mismatch conditions. It determines if routers or
 * switches in the path may be making changes to some TCP parameters.
 * @param ctlSocket server control socket descriptor
 * @param tests set of tests to perform
 * @param host hostname of the server
 * @param conn_options connection options
 * @param buf_size TCP send/receive buffer size
 * @param testresult_str result obtained from server (containing server ip,
 * 						client ip, currentMSS, WinSCaleSent, WinScaleRcvd)
 * @param jsonSupport Indicates if messages should be sent using JSON format
 * @return  integer
 *     => 0 on success
 *     < 0 if error
 *     Return codes used:
 *     0 = (the test has been finalized)
 *     > 0 if protocol interactions were not as expected:
 *     		1: Unable to receive protocol message successfully
 * 			2: Wrong message type received
 *			3: Protocol message received was of invalid length
 *			4: Protocol payload data received was invalid
 *			5: Protocol message received was invalid
 *     < 0 if generic error:
 *			-3: Unable to resolve server address
 *			-10: creating connection to server failed
 *
 */
int test_mid_clt(int ctlSocket, char tests, char* host, int conn_options,
                 int buf_size, char* testresult_str, int jsonSupport) {
  char buff[BUFFSIZE + 1];
  int msgLen, msgType;
  int midport = atoi(PORT3);
  I2Addr sec_addr = NULL;
  int retcode, inlth;
  int in2Socket;
  double t, spdin;
  uint32_t bytes;
  struct timeval sel_tv;
  fd_set rfd;
  char* jsonMsgValue;

  enum TEST_STATUS_INT teststatuses = TEST_NOT_STARTED;
  enum TEST_ID testids = MIDDLEBOX;

  if (tests & TEST_MID) {  // middlebox test has to be performed
    log_println(1, " <-- Middlebox test -->");
    setCurrentTest(TEST_MID);
    // protocol logs
    teststatuses = TEST_STARTED;
    protolog_status(getpid(), testids, teststatuses, ctlSocket);


    //  Initially, expecting a TEST_PREPARE message. Any other message
    // ..type is unexpected at this stage.

    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed prepare message!");
      return 1;
    }
    if (check_msg_type(MIDBOX_TEST_LOG, TEST_PREPARE, msgType, buff, msgLen)) {
      return 2;
    }

    // The server is expected to send a message with a valid payload that
    // contains the port number that server wants client to bind to for this
    // test
    buff[msgLen] = 0;
    if (jsonSupport) {
      jsonMsgValue = json_read_map_value(buff, DEFAULT_KEY);
      strlcpy(buff, jsonMsgValue, sizeof(buff));
      msgLen = strlen(buff);
      free(jsonMsgValue);
    }
    if (msgLen <= 0) {
      log_println(0, "Improper message");
      return 3;
    }
    if (check_int(buff, &midport)) {  // obtained message does not contain
                                      // integer port#
      log_println(0, "Invalid port number");
      return 4;
    }

    // get server address and set port
    log_println(1, "  -- port: %d", midport);
    if ((sec_addr = I2AddrByNode(get_errhandle(), host)) == NULL) {
      log_println(0, "Unable to resolve server address: %s", strerror(errno));
      return -3;
    }
    I2AddrSetPort(sec_addr, midport);

    // debug to check if correct port was set in addr struct
    if (get_debuglvl() > 4) {
      char tmpbuff[200];
      size_t tmpBufLen = 199;
      memset(tmpbuff, 0, 200);
      I2AddrNodeName(sec_addr, tmpbuff, &tmpBufLen);
      log_println(5, "connecting to %s:%d", tmpbuff, I2AddrPort(sec_addr));
    }

    // connect to server using port obtained above
    if ((retcode = CreateConnectSocket(&in2Socket, NULL, sec_addr,
                                       conn_options, buf_size))) {
      log_println(0, "Connect() for middlebox failed: %s", strerror(errno));
      return -10;
    }

    // start reading throughput test data from server using the connection
    // created above
    printf("Checking for Middleboxes . . . . . . . . . . . . . . . . . .  ");
    fflush(stdout);
    testresult_str[0] = '\0';
    bytes = 0;
    t = secs() + 5.0;  // set timer for 5 seconds, and read for 5 seconds
    sel_tv.tv_sec = 6;  // Time out the socket after 6.5 seconds
    sel_tv.tv_usec = 5;  // 500?
    FD_ZERO(&rfd);
    FD_SET(in2Socket, &rfd);
    for (;;) {
      if (secs() > t)
        break;
      retcode = select(in2Socket+1, &rfd, NULL, NULL, &sel_tv);
      if (retcode > 0) {
        inlth = read(in2Socket, buff, sizeof(buff));
        if (inlth == 0)
          break;
        bytes += inlth;
        continue;
      }
      if (retcode < 0) {
        printf("nothing to read, exiting read loop\n");
        break;
      }
      if (retcode == 0) {
        printf("timer expired, exiting read loop\n");
        break;
      }
    }
    // get actual time for which test was run
    t = secs() - t + 5.0;

    // calculate throughput in Kbps
    spdin = ((BITS_8_FLOAT * bytes) / KILO) / t;

    // Test is complete. Now, get results from server (includes CurrentMSS,
    // WinScaleSent, WinScaleRcvd..).
    // The results are sent from server in the form of a TEST_MSG object
    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed text message!");
      return 1;
    }
    if (check_msg_type(MIDBOX_TEST_LOG " results", TEST_MSG, msgType, buff,
                       msgLen)) {
      return 2;
    }
    buff[msgLen] = 0;

    strlcat(testresult_str, buff, MIDBOX_TEST_RES_SIZE);

    memset(buff, 0, sizeof(buff));
    // this should work since the throughput results from the server should
    //  ...fit well within BUFFSIZE
    snprintf(buff, sizeof(buff), "%0.0f", spdin);
    log_println(4, "CWND limited speed = %0.2f kbps", spdin);

    // client now sends throughput it calculated above to server, as a TEST_MSG
    send_json_message(ctlSocket, TEST_MSG, buff, strlen(buff), jsonSupport, JSON_SINGLE_VALUE);
    printf("Done\n");

    I2AddrFree(sec_addr);

    // Expect an empty TEST_FINALIZE message from server
    msgLen = sizeof(buff);
    if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) {
      log_println(0, "Protocol error - missed finalize message!");
      return 1;
    }
    if (check_msg_type(MIDBOX_TEST_LOG, TEST_FINALIZE, msgType, buff, msgLen)) {
      return 2;
    }
    log_println(1, " <-------------------->");
    // log protocol test ending
    teststatuses = TEST_ENDED;
    protolog_status(getpid(), testids, teststatuses, ctlSocket);
    setCurrentTest(TEST_NONE);
  }
  return 0;
}