int sockets_readh(struct graphhost_t* inst, struct list_t* list, struct list_elem_t* elem) { struct socketconn_t* conn = elem->data; int error; if (conn->readbuflength == 0) { conn->readbufoffset = 0; conn->readbuflength = 16; /* This should be configurable somewhere */ conn->readbuf = malloc(conn->readbuflength); } error = recv(conn->fd, (char*)conn->readbuf, conn->readbuflength - conn->readbufoffset, 0); if (error < 1) { /* Clean up the socket here */ sockets_close(list, elem); return 0; } conn->readbufoffset += error; if (conn->readbufoffset == conn->readbuflength) { sockets_readdoneh(inst, conn->readbuf, conn->readbuflength, list, elem); conn->readbufoffset = 0; conn->readbuflength = 0; free(conn->readbuf); conn->readbuf = NULL; } return 0; }
int main(int argc, char *argv[]) { struct sockaddr *address; struct sockaddr_in address_in; struct sockaddr_in6 address_in6; socklen_t addrlen; uint8_t *address_start; int *socket_ids; char *data; int index; struct timeval time_before; struct timeval time_after; int rc; size = 28; verbose = false; type = SOCK_DGRAM; sockets = 10; messages = 10; family = PF_INET; port = 7; /* * Parse the command line arguments. * * Stop before the last argument if it does not start with dash ('-') */ for (index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++index) { /* Options should start with dash ('-') */ if (argv[index][0] == '-') { rc = nettest2_parse_opt(argc, argv, &index); if (rc != EOK) return rc; } else { nettest2_print_help(); return EINVAL; } } /* If not before the last argument containing the address */ if (index >= argc) { printf("Command line error: missing address\n"); nettest2_print_help(); return EINVAL; } /* Prepare the address buffer */ switch (family) { case PF_INET: address_in.sin_family = AF_INET; address_in.sin_port = htons(port); address = (struct sockaddr *) &address_in; addrlen = sizeof(address_in); address_start = (uint8_t *) &address_in.sin_addr.s_addr; break; case PF_INET6: address_in6.sin6_family = AF_INET6; address_in6.sin6_port = htons(port); address = (struct sockaddr *) &address_in6; addrlen = sizeof(address_in6); address_start = (uint8_t *) &address_in6.sin6_addr.s6_addr; break; default: fprintf(stderr, "Address family is not supported\n"); return EAFNOSUPPORT; } /* Parse the last argument which should contain the address. */ rc = inet_pton(family, argv[argc - 1], address_start); if (rc != EOK) { fprintf(stderr, "Address parse error %d\n", rc); return rc; } /* Check data buffer size. */ if (size <= 0) { fprintf(stderr, "Data buffer size too small (%zu). Using 1024 " "bytes instead.\n", size); size = 1024; } /* * Prepare the buffer. Allocate size bytes plus one for terminating * null character. */ data = (char *) malloc(size + 1); if (!data) { fprintf(stderr, "Failed to allocate data buffer.\n"); return ENOMEM; } /* Fill buffer with a pattern. */ nettest2_fill_buffer(data, size); /* Check socket count. */ if (sockets <= 0) { fprintf(stderr, "Socket count too small (%d). Using " "2 instead.\n", sockets); sockets = 2; } /* * Prepare the socket buffer. * Allocate count entries plus the terminating null (\0) */ socket_ids = (int *) malloc(sizeof(int) * (sockets + 1)); if (!socket_ids) { fprintf(stderr, "Failed to allocate receive buffer.\n"); return ENOMEM; } socket_ids[sockets] = 0; if (verbose) printf("Starting tests\n"); rc = sockets_create(verbose, socket_ids, sockets, family, type); if (rc != EOK) return rc; if (type == SOCK_STREAM) { rc = sockets_connect(verbose, socket_ids, sockets, address, addrlen); if (rc != EOK) return rc; } if (verbose) printf("\n"); rc = gettimeofday(&time_before, NULL); if (rc != EOK) { fprintf(stderr, "Get time of day error %d\n", rc); return rc; } rc = sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages); if (rc != EOK) return rc; rc = gettimeofday(&time_after, NULL); if (rc != EOK) { fprintf(stderr, "Get time of day error %d\n", rc); return rc; } if (verbose) printf("\tOK\n"); printf("sendto + recvfrom tested in %ld microseconds\n", tv_sub(&time_after, &time_before)); rc = gettimeofday(&time_before, NULL); if (rc != EOK) { fprintf(stderr, "Get time of day error %d\n", rc); return rc; } rc = sockets_sendto(verbose, socket_ids, sockets, address, addrlen, data, size, messages); if (rc != EOK) return rc; rc = sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages); if (rc != EOK) return rc; rc = gettimeofday(&time_after, NULL); if (rc != EOK) { fprintf(stderr, "Get time of day error %d\n", rc); return rc; } if (verbose) printf("\tOK\n"); printf("sendto, recvfrom tested in %ld microseconds\n", tv_sub(&time_after, &time_before)); rc = sockets_close(verbose, socket_ids, sockets); if (rc != EOK) return rc; if (verbose) printf("\nExiting\n"); return EOK; }
void* sockets_threadmain(void* arg) { int listenfd; struct graphhost_t* inst = arg; struct socketconn_t* conn; struct list_elem_t* elem; int maxfd; int fd; uint8_t ipccmd; fd_set readfds; fd_set writefds; fd_set errorfds; pthread_mutex_init(&inst->mutex, NULL); /* Create a list to store all the open connections */ inst->connlist = list_create(); inst->graphlist = list_create(); /* Listen on a socket */ listenfd = sockets_listen_int(inst->port, AF_INET, 0x00000000); if (listenfd == -1) { pthread_mutex_destroy(&inst->mutex); list_destroy(inst->graphlist); list_destroy(inst->connlist); pthread_exit(NULL); return NULL; } /* Set the running flag after we've finished initializing everything */ inst->running = 1; while (1) { /* Clear the fdsets */ FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errorfds); /* Reset the maxfd */ maxfd = listenfd; /* Add the file descriptors to the list */ pthread_mutex_lock(&inst->mutex); for (elem = inst->connlist->start; elem != NULL; elem = elem->next) { conn = elem->data; fd = conn->fd; if (conn->orphan == 1) continue; if (maxfd < fd) maxfd = fd; if (conn->selectflags & SOCKET_READ) FD_SET(fd, &readfds); if (conn->selectflags & SOCKET_WRITE) FD_SET(fd, &writefds); if (conn->selectflags & SOCKET_ERROR) FD_SET(fd, &errorfds); } pthread_mutex_unlock(&inst->mutex); /* Select on the listener fd */ FD_SET(listenfd, &readfds); /* ipcfd will recieve data when the thread needs to exit */ FD_SET(inst->ipcfd_r, &readfds); /* Select on the file descrpitors */ select(maxfd + 1, &readfds, &writefds, &errorfds, NULL); pthread_mutex_lock(&inst->mutex); for (elem = inst->connlist->start; elem != NULL; elem = elem->next) { conn = elem->data; fd = conn->fd; if (conn->orphan == 1) continue; if (FD_ISSET(fd, &readfds)) { /* Handle reading */ sockets_readh(inst, inst->connlist, elem); } if (FD_ISSET(fd, &writefds)) { /* Handle writing */ sockets_writeh(inst, inst->connlist, elem); } if (FD_ISSET(fd, &errorfds)) { /* Handle errors */ sockets_close(inst->connlist, elem); } } /* Close all the file descriptors marked for closing */ sockets_clear_orphans(inst->connlist); pthread_mutex_unlock(&inst->mutex); /* Check for listener condition */ if (FD_ISSET(listenfd, &readfds)) { /* Accept connections */ sockets_accept(inst->connlist, listenfd); } /* Handle IPC commands */ if (FD_ISSET(inst->ipcfd_r, &readfds)) { read(inst->ipcfd_r, (char*)&ipccmd, 1); if (ipccmd == 'x') { break; } } } /* We're done, clear the running flag and clean up */ inst->running = 0; pthread_mutex_lock(&inst->mutex); /* Mark all the open file descriptors for closing */ for (elem = inst->connlist->start; elem != NULL; elem = elem->next) { sockets_close(inst->connlist, elem); /* We don't need to delete the element form the because we just delete all of them below. */ } /* Actually close all the open file descriptors */ sockets_clear_orphans(inst->connlist); /* Free the list of connections */ list_destroy(inst->connlist); /* Close the listener file descriptor */ close(listenfd); /* Clean up & free the global dataset list */ for (elem = inst->graphlist->start; elem != NULL; elem = elem->next) { free(elem->data); } list_destroy(inst->graphlist); /* Destroy the mutex */ pthread_mutex_unlock(&inst->mutex); pthread_mutex_destroy(&inst->mutex); pthread_exit(NULL); return NULL; }
static int nettest1_test(int *socket_ids, int nsockets, int nmessages) { int rc; if (verbose) printf("%d sockets, %d messages\n", nsockets, nmessages); rc = sockets_create(verbose, socket_ids, nsockets, family, type); if (rc != EOK) return rc; if (type == SOCK_STREAM) { rc = sockets_connect(verbose, socket_ids, nsockets, address, addrlen); if (rc != EOK) return rc; } rc = sockets_sendto_recvfrom(verbose, socket_ids, nsockets, address, &addrlen, data, size, nmessages); if (rc != EOK) return rc; rc = sockets_close(verbose, socket_ids, nsockets); if (rc != EOK) return rc; if (verbose) printf("\tOK\n"); /****/ rc = sockets_create(verbose, socket_ids, nsockets, family, type); if (rc != EOK) return rc; if (type == SOCK_STREAM) { rc = sockets_connect(verbose, socket_ids, nsockets, address, addrlen); if (rc != EOK) return rc; } rc = sockets_sendto(verbose, socket_ids, nsockets, address, addrlen, data, size, nmessages); if (rc != EOK) return rc; rc = sockets_recvfrom(verbose, socket_ids, nsockets, address, &addrlen, data, size, nmessages); if (rc != EOK) return rc; rc = sockets_close(verbose, socket_ids, nsockets); if (rc != EOK) return rc; if (verbose) printf("\tOK\n"); return EOK; }