static void PR_CALLBACK reader(void *arg) { PRUintn i = 0; size_t nbytes; do { (void) PR_WaitSem(emptyBufs); nbytes = dread(0, buf[i].data, BSIZE); buf[i].nbytes = nbytes; PR_PostSem(fullBufs); i = (i + 1) % 2; } while (nbytes > 0); }
static void writer(void) { PRUintn i = 0; size_t nbytes; do { (void) PR_WaitSem(fullBufs); nbytes = buf[i].nbytes; if (nbytes > 0) { nbytes = dwrite(1, buf[i].data, nbytes); PR_PostSem(emptyBufs); i = (i + 1) % 2; } } while (nbytes > 0); }
static void PR_CALLBACK writer(void *arg) { PRUintn i = 0; PRInt32 nbytes; do { (void) PR_WaitSem(fullBufs); nbytes = buf[i].nbytes; if (nbytes > 0) { nbytes = PR_Write((PRFileDesc*)arg, buf[i].data, nbytes); PR_PostSem(emptyBufs); i = (i + 1) % 2; } } while (nbytes > 0); }
static void PR_CALLBACK reader(void *arg) { PRUintn i = 0; PRInt32 nbytes; do { (void) PR_WaitSem(emptyBufs); nbytes = PR_Read((PRFileDesc*)arg, buf[i].data, BSIZE); if (nbytes >= 0) { buf[i].nbytes = nbytes; PR_PostSem(fullBufs); i = (i + 1) % 2; } } while (nbytes > 0); }
/* * UDP Server * Server Thread * Bind an address to a socket, read data from clients and send data * back to clients */ static void PR_CALLBACK UDP_Server(void *arg) { Server_Param *sp = (Server_Param *) arg; PRFileDesc *sockfd; buffer *in_buf; PRNetAddr netaddr; PRInt32 bytes, i, rv; bytes = sp->datalen; /* * Create a udp socket */ if ((sockfd = PR_NewUDPSocket()) == NULL) { fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); failed_already=1; return; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = AF_INET; netaddr.inet.port = PR_htons(UDP_SERVER_PORT); netaddr.inet.ip = PR_htonl(INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); failed_already=1; return; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; return; } if (netaddr.inet.port != PR_htons(UDP_SERVER_PORT)) { fprintf(stderr,"prsocket_test: ERROR - tried to bind to UDP " "port %hu, but was bound to port %hu\n", UDP_SERVER_PORT, PR_ntohs(netaddr.inet.port)); failed_already=1; return; } DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); udp_server_addr = netaddr; /* * We can't use the IP address returned by PR_GetSockName in * netaddr.inet.ip because netaddr.inet.ip is returned * as 0 (= INADDR_ANY). */ udp_server_addr.inet.ip = PR_htonl(INADDR_LOOPBACK); /* * Wake up parent thread because server address is bound and made * available in the global variable 'udp_server_addr' */ PR_PostSem(sp->addr_sem); bytes = sp->datalen; in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } /* * Receive datagrams from clients and send them back, unmodified, to the * clients */ memset(&netaddr, 0 , sizeof(netaddr)); for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) { DPRINTF(("UDP_Server: calling PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data, in_buf->data[0])); rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data, in_buf->data[0])); if (rv != bytes) { return; } rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } } PR_DELETE(in_buf); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread())); }
/* * TCP Server * Server Thread * Bind an address to a socket and listen for incoming connections * Start a Serve_Client thread for each incoming connection. */ static void PR_CALLBACK TCP_Server(void *arg) { PRThread *t; Server_Param *sp = (Server_Param *) arg; Serve_Client_Param *scp; PRFileDesc *sockfd, *newsockfd; PRNetAddr netaddr; PRInt32 i; /* * Create a tcp socket */ if ((sockfd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); goto exit; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = AF_INET; netaddr.inet.port = PR_htons(TCP_SERVER_PORT); netaddr.inet.ip = PR_htonl(INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); failed_already=1; goto exit; } if (PR_Listen(sockfd, 32) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); failed_already=1; goto exit; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; goto exit; } DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); tcp_server_addr.inet.family = netaddr.inet.family; tcp_server_addr.inet.port = netaddr.inet.port; tcp_server_addr.inet.ip = netaddr.inet.ip; /* * Wake up parent thread because server address is bound and made * available in the global variable 'tcp_server_addr' */ PR_PostSem(sp->addr_sem); for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) { if ((newsockfd = PR_Accept(sockfd, &netaddr, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n"); goto exit; } scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); goto exit; } /* * Start a Serve_Client thread for each incoming connection */ scp->sockfd = newsockfd; scp->datalen = sp->datalen; t = PR_CreateThread(PR_USER_THREAD, Serve_Client, (void *)scp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; goto exit; } DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t)); } exit: if (sockfd) { PR_Close(sockfd); } /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread())); }
/* * TransmitFile Server * Server Thread * Bind an address to a socket and listen for incoming connections * Create worker threads to service clients */ static void TransmitFile_Server(void *arg) { PRThread **t = NULL; /* an array of PRThread pointers */ Server_Param *sp = (Server_Param *) arg; Serve_Client_Param *scp; PRFileDesc *sockfd = NULL, *newsockfd; PRNetAddr netaddr; PRInt32 i; PRThreadScope scope; t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *)); if (t == NULL) { fprintf(stderr, "prsocket_test: run out of memory\n"); failed_already=1; goto exit; } /* * Create a tcp socket */ if ((sockfd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); failed_already=1; goto exit; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = AF_INET; netaddr.inet.port = PR_htons(TCP_SERVER_PORT); netaddr.inet.ip = PR_htonl(INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); failed_already=1; perror("PR_Bind"); goto exit; } if (PR_Listen(sockfd, 32) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); failed_already=1; goto exit; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr, "prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; goto exit; } DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); tcp_server_addr.inet.family = netaddr.inet.family; tcp_server_addr.inet.port = netaddr.inet.port; tcp_server_addr.inet.ip = netaddr.inet.ip; /* * Wake up parent thread because server address is bound and made * available in the global variable 'tcp_server_addr' */ PR_PostSem(sp->addr_sem); for (i = 0; i < num_transmitfile_clients ; i++) { if ((newsockfd = PR_Accept(sockfd, &netaddr, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr, "prsocket_test: ERROR - PR_Accept failed\n"); failed_already=1; goto exit; } scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; goto exit; } /* * Start a Serve_Client thread for each incoming connection */ scp->sockfd = newsockfd; scp->datalen = sp->datalen; /* * create LOCAL and GLOBAL threads alternately */ if (i & 1) scope = PR_LOCAL_THREAD; else scope = PR_GLOBAL_THREAD; t[i] = PR_CreateThread(PR_USER_THREAD, Serve_TransmitFile_Client, (void *)scp, PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (t[i] == NULL) { fprintf(stderr, "prsocket_test: PR_CreateThread failed\n"); failed_already=1; goto exit; } DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t)); } /* * Wait for all the worker threads to end, so that we know * they are no longer using the small and large file fd's. */ for (i = 0; i < num_transmitfile_clients; i++) { PR_JoinThread(t[i]); } exit: if (t) { PR_DELETE(t); } if (sockfd) { PR_Close(sockfd); } /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("TransmitFile_Server [0x%lx] exiting\n", PR_GetCurrentThread())); }