/* Send a request for thread termination. */ ih->terminate = 1; #ifdef _WIN32 WaitForSingleObject (ih->threadId, INFINITE); #else /* ! _WIN32 */ pthread_join (ih->threadId, NULL); #endif /* ! _WIN32 */ free (ih); return 0; } #ifdef _WIN32 static DWORD WINAPI ircThread (LPVOID ptr) #else /* ! _WIN32 */ static void *ircThread (void *ptr) #endif /* ! _WIN32 */ { IrcHandle ih = (IrcHandle) ptr; char *buffer, *line, *params[IRC_MAXPARAMS], *p; int rcvd, offset = 0; buffer = xmalloc (513 * sizeof (char)); line = xmalloc (513 * sizeof (char)); /* Read data from the IRC server -- 2 seconds timeout. */ while ((rcvd = socketsRecvNB (ih->socket, buffer + offset, 513 - 1 - offset, 2000)) != 0) { if (ih->terminate) { socketsShutdown (ih->socket, SOCKETS_SHUT_BOTH); /* For the case we get here again. */ ih->terminate = 0; continue; } if (rcvd == -1) { if (socketsGetLastError () == SOCKETS_ETIMEDOUT) continue; else break; } rcvd += offset; buffer[rcvd] = '\0'; /* Process the lines. */ offset = 0; while ((p = strstr (buffer + offset, "\r\n")) != NULL) { struct IrcMessage msg = {NULL, NULL, NULL, 0}; memcpy (line, buffer + offset, p - buffer - offset); line[p - buffer - offset] = '\0'; offset = p - buffer + 2; /* TODO: A callback event. */ msg.params = params; ircParseLine (line, &msg); ih->callback (ih, IRC_EVENT_MESSAGE, &msg, ih->userData); } /* If data still remain, move them to the beginning. */ if (offset < rcvd) memmove (buffer, buffer + offset, rcvd - offset); offset = rcvd - offset; } free (line); free (buffer); socketsClose (ih->socket); ih->callback (ih, IRC_EVENT_DISCONNECT, NULL, ih->userData); return 0; }
/* * ======== main ======== */ int main(int argc, char *argv[]) { int i; int sockfd = 0; int bytes_read, total_bytes_read, bytes_sent; struct addrinfo hints; struct addrinfo *results = NULL; int status = EXIT_SUCCESS; int count = 0; int id; int value; unsigned int sleepTime = 1000; unsigned int buffSize = MAXBUF; char *buffer = NULL; time_t start; start = time(NULL); /* parameter check */ if (argc < 4 || argc > 6) { printf("usage: %s <IPv4 or IPv6 addr> <port> <id> -l[length] -s[sleep in uS]\n", argv[0]); status = EXIT_FAILURE; goto QUIT; } id = atoi(argv[3]); /* Parse options */ i = argc - 1; while ((i > 3) && (argv[i][0] == '-')) { switch (argv[i][1]) { case 'l': buffSize = atoi(&argv[i][2]); break; case 's': sleepTime = atoi(&argv[i][2]); break; default: printf("Valid options are -l[length] and -s[sleep in uS]\n"); status = EXIT_FAILURE; goto QUIT; } i--; } buffer = malloc(buffSize); if (buffer == NULL) { printf("malloc failed\n"); status = EXIT_FAILURE; } memset(buffer, 0, buffSize); /* initialize sockets environment */ socketsStartup(); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; /* * getaddrinfo() fills in the results struct for us appropriately * depending on whether the IP address is v4 or v6 * * argv[1] = IPv4 or IPv6 address passed in from command line * argv[2] = port number passed in from command line */ value = getaddrinfo(argv[1], argv[2], &hints, &results); if (value != 0) { fprintf(stderr, "getaddrinfo failed: %d\n", value); if (value == -2 || value == 11004) { fprintf(stderr, "unrecognized IP address\n"); } status = EXIT_FAILURE; goto QUIT; } /* create socket. ai_family determined for us via getaddrinfo() call */ if ((sockfd = socket(results->ai_family, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "socket failed: %d\n", errno); status = errno; goto QUIT; } /* connect. ai_addr set to AF_INET or AF_INET6 by getaddrinfo() call */ if (connect(sockfd, results->ai_addr, results->ai_addrlen) < 0) { printf("connect failed: %d\n", errno); status = errno; goto QUIT; } printf("Starting test with a %d uSec delay between transmits\n", sleepTime); /* loop */ i = 0; while (1) { buffer[0] = (char)(++i); buffer[buffSize - 1] = (char)~i; bytes_sent = send(sockfd, buffer, buffSize, 0); if (bytes_sent != buffSize) { printf("[id %d] stopping test. send returned %d\n", id, bytes_sent); status = EXIT_FAILURE; goto QUIT; } total_bytes_read = 0; while (total_bytes_read < buffSize) { bytes_read = recv(sockfd, &buffer[total_bytes_read], buffSize - total_bytes_read, 0); if (bytes_read <= 0) { printf("[id %d] stopping test. recv returned %d\n", id, bytes_read); status = EXIT_FAILURE; goto QUIT; } total_bytes_read += bytes_read; } count++; if (count % 1000 == 0) { printf("[id %d] count = %d, time = %ld\n", id, count, time(NULL) - start); } /* Sleep specified time */ #if defined(__GNUC__) && defined(linux) usleep(sleepTime); #else Sleep(sleepTime / 1000); #endif if ((buffer[0] != (char)i) || (buffer[buffSize - 1] != (char)~i)) { printf("mismatch buffer[0] = %d, (char)i = %d\n", buffer[0], (char)i); printf("mismatch buffer[buffSize - 1] = %d, (char)~i = %d\n", buffer[buffSize - 1], (char)~i); } } QUIT: /* clean up */ if (sockfd) { closesocket(sockfd); } if (results) { freeaddrinfo(results); } socketsShutdown(); if (buffer) { free(buffer); } return (status); }