/* Establish a new socket connection to a client */ ClientInfo * AcceptNewClient(int reqfd) { int i; int fd; __pmSockLen addrlen; int ok = 0; char buf[MY_BUFLEN]; char *bp; char *endp; char *abufp; i = NewClient(); addrlen = __pmSockAddrSize(); fd = __pmAccept(reqfd, client[i].addr, &addrlen); if (fd == -1) { __pmNotifyErr(LOG_ERR, "AcceptNewClient(%d) __pmAccept failed: %s", reqfd, netstrerror()); Shutdown(); exit(1); } __pmSetSocketIPC(fd); if (fd > maxSockFd) maxSockFd = fd; __pmFD_SET(fd, &sockFds); client[i].fd = fd; client[i].pmcd_fd = -1; client[i].status.connected = 1; client[i].status.allowed = 0; client[i].pmcd_hostname = NULL; /* * version negotiation (converse to negotiate_proxy() logic in * libpcp * * __pmRecv client version message * __pmSend my server version message * __pmRecv pmcd hostname and pmcd port */ for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) { if (__pmRecv(fd, bp, 1, 0) != 1) { *bp = '\0'; /* null terminate what we have */ bp = &buf[MY_BUFLEN]; /* flag error */ break; } /* end of line means no more ... */ if (*bp == '\n' || *bp == '\r') { *bp = '\0'; break; } } if (bp < &buf[MY_BUFLEN]) { /* looks OK so far ... is this a version we can support? */ if (strcmp(buf, "pmproxy-client 1") == 0) { client[i].version = 1; ok = 1; } } if (!ok) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_INFO, "Bad version string from client at %s", abufp); free(abufp); fprintf(stderr, "AcceptNewClient: bad version string was \""); for (bp = buf; *bp && bp < &buf[MY_BUFLEN]; bp++) fputc(*bp & 0xff, stderr); fprintf(stderr, "\"\n"); } #endif DeleteClient(&client[i]); return NULL; } if (__pmSend(fd, MY_VERSION, strlen(MY_VERSION), 0) != strlen(MY_VERSION)) { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_WARNING, "AcceptNewClient: failed to send version " "string (%s) to client at %s\n", MY_VERSION, abufp); free(abufp); DeleteClient(&client[i]); return NULL; } for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) { if (__pmRecv(fd, bp, 1, 0) != 1) { *bp = '\0'; /* null terminate what we have */ bp = &buf[MY_BUFLEN]; /* flag error */ break; } /* end of line means no more ... */ if (*bp == '\n' || *bp == '\r') { *bp = '\0'; break; } } if (bp < &buf[MY_BUFLEN]) { /* looks OK so far ... get hostname and port */ for (bp = buf; *bp && *bp != ' '; bp++) ; if (bp != buf) { *bp = '\0'; client[i].pmcd_hostname = strdup(buf); if (client[i].pmcd_hostname == NULL) __pmNoMem("PMCD.hostname", strlen(buf), PM_FATAL_ERR); bp++; client[i].pmcd_port = (int)strtoul(bp, &endp, 10); if (*endp != '\0') { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_WARNING, "AcceptNewClient: bad pmcd port " "\"%s\" from client at %s", bp, abufp); free(abufp); DeleteClient(&client[i]); return NULL; } } /* error, fall through */ } if (client[i].pmcd_hostname == NULL) { abufp = __pmSockAddrToString(client[i].addr); __pmNotifyErr(LOG_WARNING, "AcceptNewClient: failed to get PMCD " "hostname (%s) from client at %s", buf, abufp); free(abufp); DeleteClient(&client[i]); return NULL; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_CONTEXT) { /* * note error message gets appended to once pmcd connection is * made in ClientLoop() */ abufp = __pmSockAddrToString(client[i].addr); fprintf(stderr, "AcceptNewClient [%d] fd=%d from %s to %s (port %s)", i, fd, abufp, client[i].pmcd_hostname, bp); free(abufp); } #endif return &client[i]; }
int main (int argc, char **argv) { int listenPort = 5002; int listenFd; struct a_client *theClients=0; int nbClient=0; struct pollfd *fds=0; int maxClientFd=-1; long dataLen = 6 *1024 * 1024; long stopAfter = 0; void *buf = 0; int buflen = 0; struct timeval startTime; struct timeval endTime; initBuffer (&buf, &buflen); listenFd = socket (AF_INET, SOCK_STREAM, 0); if (listenFd < 0) { fprintf (stderr, "Unable to open socket ? errno %d\n",errno); exit (1); } if (argc >= 2) { listenPort = atoi (argv[1]); } if (argc >= 3) { dataLen= atoi (argv[2]); } if (argc >= 4) { stopAfter= atoi (argv[3]); } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (listenPort); addr.sin_addr.s_addr = INADDR_ANY; int status; status = bind (listenFd, (const struct sockaddr *) &addr, sizeof(addr)); if (status) { fprintf (stderr, "Unable to open bind ? errno %d\n",errno); exit (2); } status = listen (listenFd, 256); if (status) { fprintf (stderr, "Unable to open listen ? errno %d \n",errno); exit (3); } while (1) { fds = realloc (fds, sizeof (struct pollfd) * nbClient + 1 ); fds[0].fd = listenFd; fds[0].events = POLLIN; fds[0].revents = 0; int j = 1; int c =0; for (c=0; c <= maxClientFd ; c++) { if (theClients[c].sockfd >= 0) { if (theClients[c].writeLen < dataLen) { fds[j].fd = theClients[c].sockfd; fds[j].events = POLLOUT; fds[j].revents = 0; j++; } else { fds[j].fd = theClients[c].sockfd; fds[j].events = POLLIN; fds[j].revents = 0; j++; } } } printf ("%d: --> poll j=%d\n",time(NULL), j ); int ret = poll (fds, j, 29000 * 1000); printf ("%d: poll --> %d\n", time(NULL), ret); if (ret <= 0) { exit (0); } if (ret > 0) { int i=0; for (i=0; i < j; i++) { if ( fds[i].revents ) { if (i == 0) { // a new cnxion if ( fds[i].revents & POLLIN ) { int newFd = accept (listenFd, 0, 0); if (newFd >= 0) { if ( 0 == nbClient) { gettimeofday (&startTime, 0); } NewClient (newFd, &theClients, &nbClient, &maxClientFd); } } if ( fds[i].revents & POLLERR ) { exit (4); } } else { // a client printf ("Client %d revents %d \n", i, fds[i].revents ); gettimeofday (&endTime, 0); if ( fds[i].revents & POLLOUT ) { WriteClient (theClients, fds[i].fd, &nbClient, dataLen, buf, buflen, duration (&startTime, &endTime)); } if ( ( fds[i].revents & POLLHUP ) || ( fds[i].revents & POLLIN ) || ( fds[i].revents & POLLERR ) ) { gettimeofday (&endTime, 0); CloseClient (theClients, fds[i].fd, &nbClient, duration (&startTime, &endTime), dataLen); } if ( stopAfter && ( totalClients >= stopAfter )) { exit (0); } } } } } } }