/* * Function: _BWLTestSessionFree * * Description: * This function is used to free the memory associated with a "configured" * test session. * * In Args: * * Out Args: * * Scope: * Returns: * Side Effect: */ BWLErrSeverity _BWLTestSessionFree( BWLContext ctx, BWLTestSession tsession, BWLAcceptType aval ) { BWLErrSeverity err=BWLErrOK; if(!tsession){ return BWLErrOK; } /* * remove this tsession from the cntrl->tests list. */ if(tsession->cntrl->tests == tsession){ tsession->cntrl->tests = NULL; } (void)_BWLEndpointStop(ctx,tsession,aval,&err); if(tsession->closure){ _BWLCallTestComplete(tsession,aval); } I2AddrFree(tsession->test_spec.client); I2AddrFree(tsession->test_spec.server); while(tsession->localfp && (fclose(tsession->localfp) < 0) && (errno == EINTR)); while(tsession->remotefp && (fclose(tsession->remotefp) < 0) && (errno == EINTR)); free(tsession); return err; }
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; }
static int OpenSocket(I2Addr addr, char* serv, int family, int options) { int fd = -1; int return_code = 0; struct addrinfo *fai = NULL; if (!(fai = I2AddrAddrInfo(addr, NULL, serv))) { return -2; } // Attempt to connect to one of the chosen addresses. struct addrinfo* ai = NULL; for (ai = fai; ai; ai = ai->ai_next) { if (ai->ai_family != family) continue; // create socket with obtained address domain, socket type and protocol fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); // socket create failed. Abandon further activities using this socket if (fd < 0) continue; // allow sockets to reuse local address while binding unless there // is an active listener. If unable to set this option, indicate failure int on = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) { return_code = -2; goto failsock; } // end trying to set socket option to reuse local address #ifdef AF_INET6 #ifdef IPV6_V6ONLY if (family == AF_INET6 && (options & OPT_IPV6_ONLY)) { on = 1; // the IPv6 version socket option setup if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) != 0) { return_code = -2; goto failsock; } } #endif #endif // try to bind to address if (bind(fd, ai->ai_addr, ai->ai_addrlen) == 0) { // successful // set values in "addr" structure if (!I2AddrSetSAddr(addr, ai->ai_addr, ai->ai_addrlen) || !I2AddrSetProtocol(addr, ai->ai_protocol) || !I2AddrSetSocktype(addr, ai->ai_socktype)) { log_println(1, "OpenSocket: Unable to set saddr in address record"); return_code = -1; goto failsock; } // set port if not already done, else return -1 if (!I2AddrPort(addr)) { struct sockaddr_storage tmp_addr; socklen_t tmp_addr_len = sizeof(tmp_addr); I2Addr tmpAddr; if (getsockname(fd, (struct sockaddr*) &tmp_addr, &tmp_addr_len)) { log_println(1, "OpenSocket: Unable to getsockname in address record"); return_code = -1; goto failsock; } tmpAddr = I2AddrBySAddr( get_errhandle(), (struct sockaddr*) &tmp_addr, tmp_addr_len, 0, 0); I2AddrSetPort(addr, I2AddrPort(tmpAddr)); I2AddrFree(tmpAddr); } // save socket file descriptor if (!I2AddrSetFD(addr, fd, True)) { log_println(1, "OpenSocket: Unable to set file descriptor in address " "record"); return_code = -1; goto failsock; } // end setting values in "addr" structure break; } // Address is indicated as being in use. Display actual socket options to // user and return if (errno == EADDRINUSE) { /* RAC debug statemement 10/11/06 */ socklen_t onSize = sizeof(on); getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, &onSize); log_println(1, "bind(%d) failed: Address already in use given as the " "reason, getsockopt() returned %d", fd, on); } else { log_println(1, "bind(%d) failed: %s", fd, strerror(errno)); } return_code = -1; goto failsock; } return fd; // If opening socket failed, print error, and try to close socket // file-descriptor. failsock: while ((close(fd) < 0) && (errno == EINTR)) { } return return_code; }
I2Addr CreateListenSocket(I2Addr addr, char* serv, int options, int buf_size) { int fd = -1; socklen_t optlen; int set_size; if (addr && (I2AddrFD(addr) > -1)) { log_println(1, "Invalid I2Addr record - fd already specified."); goto error; } if ((!addr) && !(addr = I2AddrByWildcard(get_errhandle(), SOCK_STREAM, serv))) { log_println(1, "Unable to create I2Addr record by wildcard."); goto error; } if (!I2AddrSetPassive(addr, True)) { log_println(1, "Unable to set passive mode in I2Addr record."); goto error; } // create and bind socket using arguments, prefering v6 (since v6 addresses // can be both v4 and v6). #ifdef AF_INET6 if ((options & OPT_IPV4_ONLY) == 0) fd = OpenSocket(addr, serv, AF_INET6, options); #endif if (fd < 0) if ((options & OPT_IPV6_ONLY) == 0) fd = OpenSocket(addr, serv, AF_INET, options); if (fd < 0) { log_println(1, "Unable to open socket."); goto error; } /* Set sock opt code from Marion Nakanson <[email protected] * OHSU Advanced Computing Center * email on 2/19/09 correctly notes that setsockops must be made before open() * or listen() calls are made */ optlen = sizeof(set_size); // get send buffer size getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "\nSend buffer initialized to %d, ", set_size); // get receive buffer size getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer initialized to %d", set_size); // now assign buffer sizes passed as arguments if (buf_size > 0) { setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)); // print values set to help user verify getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "Changed buffer sizes: Send buffer set to %d(%d), ", set_size, buf_size); getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer set to %d(%d)", set_size, buf_size); } // listen on socket for connections, with backlog queue length = NDT_BACKLOG if (listen(fd, NDT_BACKLOG) < 0) { // if listen returns value <0, then error log_println(1, "listen(%d,%d):%s", fd, NDT_BACKLOG, strerror(errno)); goto error; } return addr; // If error, try freeing memory error: I2AddrFree(addr); return NULL; }
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; }
static int OpenSocket(I2Addr addr, char* serv, int options) { struct addrinfo *fai; struct addrinfo *ai; int on; socklen_t onSize; int fd=-1; if (!(fai = I2AddrAddrInfo(addr, NULL, serv))) { return -2; } for (ai = fai; ai; ai = ai->ai_next) { #ifdef AF_INET6 if (options & OPT_IPV6_ONLY) { if(ai->ai_family != AF_INET6) continue; } #endif if (options & OPT_IPV4_ONLY) { if(ai->ai_family != AF_INET) continue; } fd = socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol); /* if (meta.family == 0) meta.family = ai->ai_family; */ if (fd < 0) { continue; } on=1; if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) != 0) { goto failsock; } #if defined(AF_INET6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) if ((ai->ai_family == AF_INET6) && (options & OPT_IPV6_ONLY) && setsockopt(fd,IPPROTO_IPV6,IPV6_V6ONLY,&on,sizeof(on)) != 0) { goto failsock; } #endif if (bind(fd,ai->ai_addr,ai->ai_addrlen) == 0) { if (!I2AddrSetSAddr(addr,ai->ai_addr,ai->ai_addrlen) || !I2AddrSetProtocol(addr,ai->ai_protocol) || !I2AddrSetSocktype(addr,ai->ai_socktype)) { log_println(1, "OpenSocket: Unable to set saddr in address record"); return -1; } if (!I2AddrPort(addr)) { struct sockaddr_storage tmp_addr; socklen_t tmp_addr_len = sizeof(tmp_addr); I2Addr tmpAddr; if (getsockname(fd, (struct sockaddr*) &tmp_addr, &tmp_addr_len)) { return -1; } tmpAddr = I2AddrBySAddr(get_errhandle(), (struct sockaddr*) &tmp_addr, tmp_addr_len, 0, 0); I2AddrSetPort(addr, I2AddrPort(tmpAddr)); I2AddrFree(tmpAddr); } if (!I2AddrSetFD(addr,fd,True)) { log_println(1, "OpenSocket: Unable to set file descriptor in address record"); return -1; } break; } if (errno == EADDRINUSE) { /* RAC debug statemement 10/11/06 */ onSize = sizeof(on); getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, &onSize); log_println(1, "bind(%d) failed: Address already in use given as the reason, getsockopt() returned %d", fd, on); return -2; } failsock: /* RAC debug statemement 10/11/06 */ log_println(1, "failsock: Unable to set socket options for fd=%d", fd); while((close(fd) < 0) && (errno == EINTR)); } if (meta.family == 0) meta.family = ai->ai_family; return fd; }
I2Addr CreateListenSocket(I2Addr addr, char* serv, int options, int buf_size) { int fd = -1; socklen_t optlen; int set_size; if (addr && (I2AddrFD(addr) > -1)) { log_println(1, "Invalid I2Addr record - fd already specified."); goto error; } if ((!addr) && !(addr = I2AddrByWildcard(get_errhandle(), SOCK_STREAM, serv))) { log_println(1, "Unable to create I2Addr record by wildcard."); goto error; } if (!I2AddrSetPassive(addr,True)) { log_println(1, "Unable to set passive mode in I2Addr record."); goto error; } fd = OpenSocket(addr, serv, options); if (fd < 0) { log_println(1, "Unable to open socket."); goto error; } /* Set sock opt code from Marion Nakanson <[email protected] * OHSU Advanced Computing Center * email on 2/19/09 correctly notes that setsockops must be made before open() * or listen() calls are made */ optlen = sizeof(set_size); getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "\nSend buffer initialized to %d, ", set_size); getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer initialized to %d", set_size); if (buf_size > 0) { setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)); getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); log_print(5, "Changed buffer sizes: Send buffer set to %d(%d), ", set_size, buf_size); getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &set_size, &optlen); log_println(5, "Receive buffer set to %d(%d)", set_size, buf_size); } if (listen(fd, NDT_BACKLOG) < 0) { log_println(1, "listen(%d,%d):%s", fd, NDT_BACKLOG, strerror(errno)); goto error; } return addr; error: I2AddrFree(addr); return NULL; }
/** * 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; }