int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds; PRIntn nfds; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRThread *clientThread; PRInt32 retVal; PRIntn i, j; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. Timeout, error\n"); printf("reporting, and normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); printf("%s", buf); /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* Testing timeout */ if (debug_mode) printf("PR_Select should time out in 5 seconds\n"); retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Select should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); if (!debug_mode) Test_Result(FAIL); } exit(1); } if (debug_mode) printf("PR_Select timed out. Test passed.\n\n"); else Test_Result(PASS); /* Testing bad fd */ printf("PR_Select should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); exit(1); } PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); PR_FD_SET(badFD, &readFdSet); PR_Close(badFD); /* make the fd bad */ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Select returns %d\n", retVal); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); } exit(1); } printf("PR_Select detected a bad fd. Test passed.\n\n"); PR_FD_CLR(badFD, &readFdSet); clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); /* set up the fd array */ fds = fds0; other_fds = fds1; fds[0] = listenSock1; fds[1] = listenSock2; nfds = 2; PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* 20 events total */ i = 0; while (i < 20) { PRFileDesc **tmp; int nextIndex; int nEvents = 0; retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_fds[j] = fds[j]; if (PR_FD_ISSET(fds[j], &readFdSet)) { PRFileDesc *sock; nEvents++; sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); exit(1); } other_fds[nextIndex] = sock; PR_FD_SET(sock, &readFdSet); nextIndex++; } PR_FD_SET(fds[j], &readFdSet); } for (j = 2; j < nfds; j++) { if (PR_FD_ISSET(fds[j], &readFdSet)) { PRInt32 nBytes; PR_FD_CLR(fds[j], &readFdSet); nEvents++; nBytes = PR_Read(fds[j], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read() failed\n"); exit(1); } /* Just to be safe */ buf[127] = '\0'; PR_Close(fds[j]); printf("The server received \"%s\" from a client\n", buf); } else { PR_FD_SET(fds[j], &readFdSet); other_fds[nextIndex] = fds[j]; nextIndex++; } } PR_ASSERT(retVal == nEvents); /* swap */ tmp = fds; fds = other_fds; other_fds = tmp; nfds = nextIndex; i += nEvents; } printf("All tests finished\n"); PR_Cleanup(); return 0; }
static void RunTest(PRInt32 acceptType, PRInt32 clientAction) { int i; /* First bind to the socket */ listenSock = PR_NewTCPSocket(); if (!listenSock) { failed_already=1; if (debug_mode) PR_fprintf(output, "unable to create listen socket\n"); return; } memset(&listenAddr, 0 , sizeof(listenAddr)); listenAddr.inet.family = PR_AF_INET; listenAddr.inet.port = PR_htons(BASE_PORT); listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(listenSock, &listenAddr) == PR_FAILURE) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { listenAddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } failed_already=1; if (debug_mode) PR_fprintf(output,"accept: ERROR - PR_Bind failed\n"); return; } rv = PR_Listen(listenSock, 100); if (rv == PR_FAILURE) { failed_already=1; if (debug_mode) PR_fprintf(output, "unable to listen\n"); return; } clientCommand = clientAction; clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread, (void *)&clientCommand, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (!clientThread) { failed_already=1; if (debug_mode) PR_fprintf(output, "error creating client thread\n"); return; } iterations = count; for (;iterations--;) { switch (acceptType) { case ACCEPT_NORMAL: clientSock = PR_Accept(listenSock, &clientAddr, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: TEST_ASSERT(clientSock == 0); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; case ACCEPT_READ: status = PR_AcceptRead(listenSock, &clientSock, &raddr, buf, CLIENT_DATA, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: /* Invalid test case */ TEST_ASSERT(0); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); TEST_ASSERT(status == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(status == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; #ifdef WINNT case ACCEPT_FAST: clientSock = PR_NTFast_Accept(listenSock, &clientAddr, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: TEST_ASSERT(clientSock == 0); if (debug_mode) PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError()); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; break; case ACCEPT_READ_FAST: status = PR_NTFast_AcceptRead(listenSock, &clientSock, &raddr, buf, 4096, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: /* Invalid test case */ TEST_ASSERT(0); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); TEST_ASSERT(status == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(clientSock == NULL); TEST_ASSERT(status == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; case ACCEPT_READ_FAST_CB: status = PR_NTFast_AcceptRead_WithTimeoutCallback( listenSock, &clientSock, &raddr, buf, 4096, timeoutTime, timeout_callback, (void *)CALLBACK_MAGIC); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: /* Invalid test case */ TEST_ASSERT(0); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); TEST_ASSERT(status == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: if (debug_mode) PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock); TEST_ASSERT(clientSock == NULL); TEST_ASSERT(status == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; #endif } if (clientSock != NULL) { PR_Close(clientSock); clientSock = NULL; } } PR_Close(listenSock); PR_JoinThread(clientThread); }
PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[]) { #if defined(XP_UNIX) || defined(XP_AMIGAOS) PRInt32 rv, osfd[2]; if (!_pr_initialized) _PR_ImplicitInitialization(); rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd); if (rv == -1) { return PR_FAILURE; } f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); if (!f[0]) { _PR_MD_CLOSE_SOCKET(osfd[0]); _PR_MD_CLOSE_SOCKET(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); if (!f[1]) { PR_Close(f[0]); _PR_MD_CLOSE_SOCKET(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } _PR_MD_MAKE_NONBLOCK(f[0]); _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); _PR_MD_MAKE_NONBLOCK(f[1]); _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); return PR_SUCCESS; #elif defined(WINNT) /* * A socket pair is often used for interprocess communication, * so we need to make sure neither socket is associated with * the I/O completion port; otherwise it can't be used by a * child process. * * The default implementation below cannot be used for NT * because PR_Accept would have associated the I/O completion * port with the listening and accepted sockets. */ SOCKET listenSock; SOCKET osfd[2]; struct sockaddr_in selfAddr, peerAddr; int addrLen; if (!_pr_initialized) _PR_ImplicitInitialization(); osfd[0] = osfd[1] = INVALID_SOCKET; listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock == INVALID_SOCKET) { goto failed; } selfAddr.sin_family = AF_INET; selfAddr.sin_port = 0; selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */ addrLen = sizeof(selfAddr); if (bind(listenSock, (struct sockaddr *) &selfAddr, addrLen) == SOCKET_ERROR) { goto failed; } if (getsockname(listenSock, (struct sockaddr *) &selfAddr, &addrLen) == SOCKET_ERROR) { goto failed; } if (listen(listenSock, 5) == SOCKET_ERROR) { goto failed; } osfd[0] = socket(AF_INET, SOCK_STREAM, 0); if (osfd[0] == INVALID_SOCKET) { goto failed; } selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that connect returns * successfully as soon as the connect request is put * into the listen queue (but before accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (connect(osfd[0], (struct sockaddr *) &selfAddr, addrLen) == SOCKET_ERROR) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket osfd[0]. */ if (getsockname(osfd[0], (struct sockaddr *) &selfAddr, &addrLen) == SOCKET_ERROR) { goto failed; } osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen); if (osfd[1] == INVALID_SOCKET) { goto failed; } if (peerAddr.sin_port != selfAddr.sin_port) { /* the connection we accepted is not from osfd[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } closesocket(listenSock); f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); if (!f[0]) { closesocket(osfd[0]); closesocket(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); if (!f[1]) { PR_Close(f[0]); closesocket(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); return PR_SUCCESS; failed: if (listenSock != INVALID_SOCKET) { closesocket(listenSock); } if (osfd[0] != INVALID_SOCKET) { closesocket(osfd[0]); } if (osfd[1] != INVALID_SOCKET) { closesocket(osfd[1]); } return PR_FAILURE; #else /* not Unix or NT */ /* * default implementation */ PRFileDesc *listenSock; PRNetAddr selfAddr, peerAddr; PRUint16 port; f[0] = f[1] = NULL; listenSock = PR_NewTCPSocket(); if (listenSock == NULL) { goto failed; } PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */ if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } port = ntohs(selfAddr.inet.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { goto failed; } f[0] = PR_NewTCPSocket(); if (f[0] == NULL) { goto failed; } #ifdef _PR_CONNECT_DOES_NOT_BIND /* * If connect does not implicitly bind the socket (e.g., on * BeOS), we have to bind the socket so that we can get its * port with getsockname later. */ PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) { goto failed; } #endif PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that PR_Connect returns * successfully as soon as the connect request is put * into the listen queue (but before PR_Accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket f[0]. */ if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) { goto failed; } f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT); if (f[1] == NULL) { goto failed; } if (peerAddr.inet.port != selfAddr.inet.port) { /* the connection we accepted is not from f[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } PR_Close(listenSock); return PR_SUCCESS; failed: if (listenSock) { PR_Close(listenSock); } if (f[0]) { PR_Close(f[0]); } if (f[1]) { PR_Close(f[1]); } return PR_FAILURE; #endif }
static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { PRFileDesc *listenSock, *sock; PRUint16 listenPort; PRNetAddr addr; char buf[CHUNK_SIZE]; PRThread *clientThread; PRInt32 retVal; PRSocketOptionData optval; PRIntn i; PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME); /* Create a listening socket */ if ((listenSock = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } PR_snprintf(buf, sizeof(buf), "The server thread is listening on port %hu\n\n", listenPort); printf("%s", buf); clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("client thread created.\n"); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock, &optval); /* time 0 */ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock != NULL || PR_GetError() != PR_WOULD_BLOCK_ERROR) { PL_PrintError("First Accept\n"); fprintf(stderr, "First PR_Accept() xxx\n" ); exit(1); } printf("accept: EWOULDBLOCK, good\n"); fflush(stdout); /* time 2 */ PR_Sleep(2 * unitTime); sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { PL_PrintError("Second Accept\n"); fprintf(stderr, "Second PR_Accept() failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("accept: succeeded, good\n"); fflush(stdout); PR_Close(listenSock); PR_SetSocketOption(sock, &optval); /* time 3, 5, 6, 8, etc. */ for (i = 0; i < NUMBER_ROUNDS; i++) { PR_Sleep(unitTime); retVal = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_WOULD_BLOCK_ERROR) { PL_PrintError("First Receive:\n"); fprintf(stderr, "First PR_Recv: retVal: %ld, Error: %ld\n", retVal, PR_GetError()); exit(1); } printf("read: EWOULDBLOCK, good\n"); fflush(stdout); PR_Sleep(2 * unitTime); retVal = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (retVal != CHUNK_SIZE) { PL_PrintError("Second Receive:\n"); fprintf(stderr, "Second PR_Recv: retVal: %ld, Error: %ld\n", retVal, PR_GetError()); exit(1); } printf("read: %d bytes, good\n", retVal); fflush(stdout); } PR_Close(sock); printf("All tests finished\n"); printf("PASS\n"); return 0; }
int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRThread *clientThread; PRPollDesc pds0[20], pds1[20], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRIntn i, j; PRSocketOptionData optval; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock1, &optval); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); PR_SetSocketOption(listenSock2, &optval); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; /* Add some unused entries to test if they are ignored by PR_Poll() */ memset(&pds[2], 0, sizeof(pds[2])); memset(&pds[3], 0, sizeof(pds[3])); memset(&pds[4], 0, sizeof(pds[4])); npds = 5; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } if (debug_mode) { printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); } /* two clients, three events per iteration: accept, read, close */ i = 0; while (i < 2 * 3 * NUM_ITERATIONS) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); failed_already=1; goto exit_now; } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); failed_already=1; goto exit_now; } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); failed_already=1; goto exit_now; } } for (j = 2; j < npds; j++) { if (NULL == pds[j].fd) { /* * Keep the unused entries in the poll descriptor array * for testing purposes. */ other_pds[nextIndex] = pds[j]; nextIndex++; continue; } PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nAvail; PRInt32 nRead; nEvents++; nAvail = PR_Available(pds[j].fd); nRead = PR_Read(pds[j].fd, buf, sizeof(buf)); PR_ASSERT(nAvail == nRead); if (nRead == -1) { fprintf(stderr, "PR_Read() failed\n"); failed_already=1; goto exit_now; } else if (nRead == 0) { PR_Close(pds[j].fd); continue; } else { /* Just to be safe */ buf[127] = '\0'; if (debug_mode) printf("The server received \"%s\" from a client\n", buf); } } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); failed_already=1; goto exit_now; } other_pds[nextIndex] = pds[j]; nextIndex++; } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } if (debug_mode) printf("Tests passed\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; }
int FileSSLDoublePoint_main(char * strUserPin, char * strNickName) { #if 1 int isServer = 0; SECStatus rv = SECSuccess; char * buffer = malloc(1024 * 1024); PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); PK11_SetPasswordFunc(GetModulePassword); rv = NSS_Initialize(GetSystemDBDir(), "", "", "secmod.db", 0); rv = SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE); rv = SSL_OptionSetDefault(SSL_SOCKS, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_FDX, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); rv = NSS_SetDomesticPolicy(); rv = NSS_SetExportPolicy(); rv = NSS_SetFrancePolicy(); // rv = SSL_CipherPolicySet(); SSL_ClearSessionCache(); rv = SSL_ConfigServerSessionIDCache(10, 30 , 30, "."); PRFileDesc * tcp_socket = PR_NewTCPSocket(); PRFileDesc * ssl_socket = SSL_ImportFD(NULL,tcp_socket); if (isServer) { CERTCertDBHandle *certHandle; certHandle = CERT_GetDefaultCertDB(); char * nickname = "4914afeedee988071490b98f1120ddac_e73f20c7-176d-4342-ac89-ea7c00bb570a";/*nickname*/ CERTCertificate* cert = NULL; cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickname); SECKEYPrivateKey *prvKey = NULL; prvKey = PK11_FindKeyByAnyCert(cert, NULL); rv = SSL_ConfigSecureServer(ssl_socket, cert,prvKey,ssl_kea_rsa); PRNetAddr netAddr; PRNetAddr netAddrLocal; rv = PR_InitializeNetAddr(0, 8888, &netAddr); rv = PR_StringToNetAddr("127.0.0.1", &netAddrLocal); rv = PR_Bind(tcp_socket,&netAddr); rv = PR_Listen(tcp_socket, 100); while (1) { PRFileDesc * client = PR_Accept(tcp_socket, &netAddr, 6000000); PRNetAddr addr; rv = PR_GetSockName(client, &addr); rv = SSL_ForceHandshake(client); rv = PR_Write(client,"123", 4); sleep(1); } } else { rv = SSL_AuthCertificateHook(ssl_socket, OwnAuthCertHandler, NULL); char * nickname = "nickname";/*nickname*/ rv = SSL_SetURL(ssl_socket, "192.168.18.22"); char * str = malloc(1024) ; memset(str, 0, 1024); strcpy(str ,"GET /test/test2.html HTTP/1.1\r\n");//注意\r\n为回车换行 // str = [str stringByAppendingString:@"Accept-Language: zh-cn\r\n"]; // str = [str stringByAppendingString:@"Connection: Keep-Alive\r\n"]; //str = [str stringByAppendingString:@"Host: 192.168.0.106\r\n"]; strcat(str ,"Host: 192.168.18.22:8443\r\n"); // str = [str stringByAppendingString:@"Content-Length: 0\r\n"]; strcat(str ,"\r\n"); // str = [str stringByAppendingString:@"userName=liqiangqiang&password=new_andy\r\n"]; // str = [str stringByAppendingString:@"\r\n"]; PRNetAddr netAddr; rv = PR_StringToNetAddr("192.168.18.22", &netAddr); rv = PR_InitializeNetAddr(0, 8443, &netAddr); // rv = PR_GetHostByName(); // PR_EnumerateHostEnt rv = PR_Connect(tcp_socket,&netAddr, 300000); FILE_LOG_NUMBER("/sdcard/ssl.log", rv); rv = SSL_GetClientAuthDataHook(ssl_socket,NSS_GetClientAuthData,strNickName); FILE_LOG_NUMBER("/sdcard/ssl.log", rv); rv = SSL_ForceHandshake(ssl_socket); FILE_LOG_NUMBER("/sdcard/ssl.log", rv); rv = PR_Write(tcp_socket, str, strlen(str)); FILE_LOG_NUMBER("/sdcard/ssl.log", rv); rv = PR_Read(tcp_socket,buffer, 1024 * 1024); FILE_LOG_NUMBER("/sdcard/ssl.log", rv); FILE * file = fopen("/sdcard/ssl_read.txt", "wb"); //fwrite(buffer, 1, rv, file); //rv = PR_Read(tcp_socket,buffer, 1024 * 1024); fwrite(buffer, 1, rv, file); fclose(file); sleep(1); rv = SSL_InvalidateSession(ssl_socket); rv = PR_Shutdown(tcp_socket, PR_SHUTDOWN_BOTH); rv = PR_Close(tcp_socket); rv = ssl_FreeSessionCacheLocks(); rv = NSS_Shutdown(); } #endif return 0; }
int StartServer(const char *nssCertDBDir, SSLSNISocketConfig sniSocketConfig, void *sniSocketConfigArg) { const char *debugLevel = PR_GetEnv("MOZ_TLS_SERVER_DEBUG_LEVEL"); if (debugLevel) { int level = atoi(debugLevel); switch (level) { case DEBUG_ERRORS: gDebugLevel = DEBUG_ERRORS; break; case DEBUG_WARNINGS: gDebugLevel = DEBUG_WARNINGS; break; case DEBUG_VERBOSE: gDebugLevel = DEBUG_VERBOSE; break; default: PrintPRError("invalid MOZ_TLS_SERVER_DEBUG_LEVEL"); return 1; } } const char *callbackPort = PR_GetEnv("MOZ_TLS_SERVER_CALLBACK_PORT"); if (callbackPort) { gCallbackPort = atoi(callbackPort); } if (NSS_Init(nssCertDBDir) != SECSuccess) { PrintPRError("NSS_Init failed"); return 1; } if (NSS_SetDomesticPolicy() != SECSuccess) { PrintPRError("NSS_SetDomesticPolicy failed"); return 1; } if (SSL_ConfigServerSessionIDCache(0, 0, 0, nullptr) != SECSuccess) { PrintPRError("SSL_ConfigServerSessionIDCache failed"); return 1; } ScopedPRFileDesc serverSocket(PR_NewTCPSocket()); if (!serverSocket) { PrintPRError("PR_NewTCPSocket failed"); return 1; } PRSocketOptionData socketOption; socketOption.option = PR_SockOpt_Reuseaddr; socketOption.value.reuse_addr = true; PR_SetSocketOption(serverSocket, &socketOption); PRNetAddr serverAddr; PR_InitializeNetAddr(PR_IpAddrLoopback, LISTEN_PORT, &serverAddr); if (PR_Bind(serverSocket, &serverAddr) != PR_SUCCESS) { PrintPRError("PR_Bind failed"); return 1; } if (PR_Listen(serverSocket, 1) != PR_SUCCESS) { PrintPRError("PR_Listen failed"); return 1; } ScopedPRFileDesc rawModelSocket(PR_NewTCPSocket()); if (!rawModelSocket) { PrintPRError("PR_NewTCPSocket failed for rawModelSocket"); return 1; } ScopedPRFileDesc modelSocket(SSL_ImportFD(nullptr, rawModelSocket.forget())); if (!modelSocket) { PrintPRError("SSL_ImportFD of rawModelSocket failed"); return 1; } if (SECSuccess != SSL_SNISocketConfigHook(modelSocket, sniSocketConfig, sniSocketConfigArg)) { PrintPRError("SSL_SNISocketConfigHook failed"); return 1; } // We have to configure the server with a certificate, but it's not one // we're actually going to end up using. In the SNI callback, we pick // the right certificate for the connection. if (SECSuccess != ConfigSecureServerWithNamedCert(modelSocket, DEFAULT_CERT_NICKNAME, nullptr, nullptr)) { return 1; } if (gCallbackPort != 0) { if (DoCallback()) { return 1; } } while (true) { PRNetAddr clientAddr; PRFileDesc *clientSocket = PR_Accept(serverSocket, &clientAddr, PR_INTERVAL_NO_TIMEOUT); HandleConnection(clientSocket, modelSocket); } return 0; }
static void PR_CALLBACK Worker(void *arg) { PRStatus rv; PRNetAddr from; PRFileDesc *fd = NULL; PRThread *me = PR_GetCurrentThread(); CSWorker_t *worker = (CSWorker_t*)arg; CSServer_t *server = worker->server; CSPool_t *pool = &server->pool; TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1)); PR_Lock(server->ml); PR_APPEND_LINK(&worker->element, &server->list); pool->workers += 1; /* define our existance */ while (cs_run == server->state) { while (pool->accepting >= server->workers.accepting) { TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): waiting for accept slot[%d]\n", me, pool->accepting)); rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT); if (Aborted(rv) || (cs_run != server->state)) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tWorker(0x%p): has been %s\n", me, (Aborted(rv) ? "interrupted" : "stopped"))); goto exit; } } pool->accepting += 1; /* how many are really in accept */ PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): calling accept\n", me)); fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT); PR_Lock(server->ml); pool->accepting -= 1; PR_NotifyCondVar(pool->acceptComplete); if ((NULL == fd) && Aborted(PR_FAILURE)) { if (NULL != server->listener) { PR_Close(server->listener); server->listener = NULL; } goto exit; } if (NULL != fd) { /* ** Create another worker of the total number of workers is ** less than the minimum specified or we have none left in ** accept() AND we're not over the maximum. ** This sort of presumes that the number allowed in accept ** is at least as many as the minimum. Otherwise we'll keep ** creating new threads and deleting them soon after. */ PRBool another = ((pool->workers < server->workers.minimum) || ((0 == pool->accepting) && (pool->workers < server->workers.maximum))) ? PR_TRUE : PR_FALSE; pool->active += 1; PR_Unlock(server->ml); if (another) (void)CreateWorker(server, pool); rv = ProcessRequest(fd, server); if (PR_SUCCESS != rv) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tWorker(0x%p): server process ended abnormally\n", me)); (void)PR_Close(fd); fd = NULL; PR_Lock(server->ml); pool->active -= 1; } } exit: PR_ClearInterrupt(); PR_Unlock(server->ml); if (NULL != fd) { (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH); (void)PR_Close(fd); } TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): exiting [%u]\n", PR_GetCurrentThread(), pool->workers)); PR_Lock(server->ml); pool->workers -= 1; /* undefine our existance */ PR_REMOVE_AND_INIT_LINK(&worker->element); PR_NotifyCondVar(pool->exiting); PR_Unlock(server->ml); PR_DELETE(worker); /* destruction of the "worker" object */ } /* Worker */
static void TCP_Server_Accept(void *arg) { Server_Param *sp = (Server_Param *) arg; PRThreadPool *tp = sp->tp; Serve_Client_Param *scp; PRFileDesc *newsockfd; PRJob *jobp; if ((newsockfd = PR_Accept(sp->iod.socket, &sp->netaddr, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"%s: ERROR - PR_Accept failed\n", program_name); failed_already=1; goto exit; } scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"%s: PR_NEW failed\n", program_name); failed_already=1; goto exit; } /* * Start a Serve_Client job for each incoming connection */ scp->iod.socket = newsockfd; scp->iod.timeout = PR_SecondsToInterval(60); scp->datalen = tcp_mesg_size; scp->exit_mon = sp->exit_mon; scp->job_counterp = sp->job_counterp; scp->tp = sp->tp; PR_EnterMonitor(sp->exit_mon); (*sp->job_counterp)++; PR_ExitMonitor(sp->exit_mon); jobp = PR_QueueJob(tp, Serve_Client, scp, PR_FALSE); PR_ASSERT(NULL != jobp); DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", jobp)); /* * single-threaded update; no lock needed */ sp->conn_counter++; if (sp->conn_counter < (num_tcp_clients * num_tcp_connections_per_client)) { jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500), print_stats, sp, PR_FALSE); PR_ASSERT(NULL != jobp); DPRINTF(("TCP_Server: Created print_stats timer job = 0x%lx\n", jobp)); exit: PR_EnterMonitor(sp->exit_mon); /* Wait for server jobs to finish */ while (0 != *sp->job_counterp) { PR_Wait(sp->exit_mon, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("TCP_Server: conn_counter = %d\n", *sp->job_counterp)); } PR_ExitMonitor(sp->exit_mon); if (sp->iod.socket) { PR_Close(sp->iod.socket); } PR_DestroyMonitor(sp->exit_mon); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); DPRINTF(("%s: calling PR_ShutdownThreadPool\n", program_name)); PR_ShutdownThreadPool(sp->tp); PR_DELETE(sp); }
int FileSSL_main(int argc, char * argv[]) { bool isServer = true; SECStatus rv = SECSuccess; char buffer[32] = {0}; PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); PK11_SetPasswordFunc(GetModulePassword); rv = NSS_Initialize(GetSystemDBDir(), "", "", "secmod.db", 0); rv = SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE); rv = SSL_OptionSetDefault(SSL_SOCKS, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_FDX, PR_TRUE); rv = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); rv = NSS_SetDomesticPolicy(); rv = NSS_SetExportPolicy(); rv = NSS_SetFrancePolicy(); // rv = SSL_CipherPolicySet(); SSL_ClearSessionCache(); rv = SSL_ConfigServerSessionIDCache(10, 30 , 30, "."); PRFileDesc * socket = PR_NewTCPSocket(); socket = SSL_ImportFD(NULL,socket); if (isServer) { CERTCertDBHandle *certHandle; certHandle = CERT_GetDefaultCertDB(); char * nickname = "itrus Certificate DB:2013-11-15 12:44:10";/*nickname*/ CERTCertificate* cert = NULL; cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickname); SECKEYPrivateKey *prvKey = NULL; prvKey = PK11_FindKeyByAnyCert(cert, NULL); rv = SSL_ConfigSecureServer(socket, cert,prvKey,ssl_kea_rsa); PRNetAddr netAddr; PRNetAddr netAddrLocal; rv = PR_InitializeNetAddr(0, 8888, &netAddr); rv = PR_StringToNetAddr("127.0.0.1", &netAddrLocal); rv = PR_Bind(socket,&netAddr); rv = PR_Listen(socket, 100); while (1) { PRFileDesc * client = PR_Accept(socket, &netAddr, 6000000); PRNetAddr addr; rv = PR_GetSockName(client, &addr); rv = SSL_ForceHandshake(client); rv = PR_Write(client,"123", 4); sleep(1); } } else { rv = SSL_SetURL(socket, "127.0.0.1"); PRNetAddr netAddr; PRNetAddr netAddrLocal; rv = PR_InitializeNetAddr(0, 8888, &netAddr); rv = PR_StringToNetAddr("127.0.0.1", &netAddrLocal); // rv = PR_GetHostByName(); // PR_EnumerateHostEnt rv = PR_Connect(socket,&netAddr, 300000); rv = SSL_AuthCertificateHook(socket, OwnAuthCertHandler, NULL); rv = SSL_ForceHandshake(socket); while (1) { rv = PR_Read(socket,buffer, 32); sleep(1); } } return 0; }
static void ServerThread(void *arg) { PRFileDesc *listenSock = (PRFileDesc *) arg; PRFileDesc *acceptSock; PRFileDesc *file; PRSendFileData sfd; char header[1024], trailer[1024]; PRInt32 nbytes; /* Create a zero-length file */ file = PR_Open(ZERO_LEN_FILE_NAME, PR_CREATE_FILE|PR_TRUNCATE|PR_RDWR, 0666); if (NULL == file) { fprintf(stderr, "PR_Open failed\n"); exit(1); } sfd.fd = file; sfd.file_offset = 0; sfd.file_nbytes = 0; memcpy(header, HEADER_STR, HEADER_LEN); memcpy(trailer, TRAILER_STR, TRAILER_LEN); sfd.header = header; sfd.hlen = HEADER_LEN; sfd.trailer = trailer; sfd.tlen = TRAILER_LEN; acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == acceptSock) { fprintf(stderr, "PR_Accept failed\n"); exit(1); } /* Send both header and trailer */ nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (HEADER_LEN+TRAILER_LEN != nbytes) { fprintf(stderr, "PR_SendFile should return %d but returned %d\n", HEADER_LEN+TRAILER_LEN, nbytes); exit(1); } /* Trailer only, no header */ sfd.hlen = 0; nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (TRAILER_LEN != nbytes) { fprintf(stderr, "PR_SendFile should return %d but returned %d\n", TRAILER_LEN, nbytes); exit(1); } /* Header only, no trailer */ sfd.hlen = HEADER_LEN; sfd.tlen = 0; nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (HEADER_LEN != nbytes) { fprintf(stderr, "PR_SendFile should return %d but returned %d\n", HEADER_LEN, nbytes); exit(1); } /* Try PR_TransmitFile */ nbytes = PR_TransmitFile(acceptSock, file, header, HEADER_LEN, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (HEADER_LEN != nbytes) { fprintf(stderr, "PR_TransmitFile should return %d but returned %d\n", HEADER_LEN, nbytes); exit(1); } if (PR_Close(acceptSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Close(file) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Delete(ZERO_LEN_FILE_NAME) == PR_FAILURE) { fprintf(stderr, "PR_Delete failed\n"); exit(1); } }
static bool NewTCPSocketPair(PRFileDesc *fd[], bool aSetRecvBuff) { // this is a replacement for PR_NewTCPSocketPair that manually // sets the recv buffer to 64K. A windows bug (1248358) // can result in using an incompatible rwin and window // scale option on localhost pipes if not set before connect. SOCKET_LOG(("NewTCPSocketPair %s a recv buffer tuning\n", aSetRecvBuff ? "with" : "without")); PRFileDesc *listener = nullptr; PRFileDesc *writer = nullptr; PRFileDesc *reader = nullptr; PRSocketOptionData recvBufferOpt; recvBufferOpt.option = PR_SockOpt_RecvBufferSize; recvBufferOpt.value.recv_buffer_size = 65535; PRSocketOptionData nodelayOpt; nodelayOpt.option = PR_SockOpt_NoDelay; nodelayOpt.value.no_delay = true; PRSocketOptionData noblockOpt; noblockOpt.option = PR_SockOpt_Nonblocking; noblockOpt.value.non_blocking = true; listener = PR_OpenTCPSocket(PR_AF_INET); if (!listener) { goto failed; } if (aSetRecvBuff) { PR_SetSocketOption(listener, &recvBufferOpt); } PR_SetSocketOption(listener, &nodelayOpt); PRNetAddr listenAddr; memset(&listenAddr, 0, sizeof(listenAddr)); if ((PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &listenAddr) == PR_FAILURE) || (PR_Bind(listener, &listenAddr) == PR_FAILURE) || (PR_GetSockName(listener, &listenAddr) == PR_FAILURE) || // learn the dynamic port (PR_Listen(listener, 5) == PR_FAILURE)) { goto failed; } writer = PR_OpenTCPSocket(PR_AF_INET); if (!writer) { goto failed; } if (aSetRecvBuff) { PR_SetSocketOption(writer, &recvBufferOpt); } PR_SetSocketOption(writer, &nodelayOpt); PR_SetSocketOption(writer, &noblockOpt); PRNetAddr writerAddr; if (PR_InitializeNetAddr(PR_IpAddrLoopback, ntohs(listenAddr.inet.port), &writerAddr) == PR_FAILURE) { goto failed; } if (PR_Connect(writer, &writerAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { if ((PR_GetError() != PR_IN_PROGRESS_ERROR) || (PR_ConnectContinue(writer, PR_POLL_WRITE) == PR_FAILURE)) { goto failed; } } reader = PR_Accept(listener, &listenAddr, PR_MillisecondsToInterval(200)); if (!reader) { goto failed; } if (aSetRecvBuff) { PR_SetSocketOption(reader, &recvBufferOpt); } PR_SetSocketOption(reader, &nodelayOpt); PR_SetSocketOption(reader, &noblockOpt); PR_Close(listener); fd[0] = reader; fd[1] = writer; return true; failed: if (listener) { PR_Close(listener); } if (reader) { PR_Close(reader); } if (writer) { PR_Close(writer); } return false; }
static void NativeSelectTest(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); return; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address\n"); PR_Close(listenSocket); return; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); PR_Close(listenSocket); return; } if (debug_mode) printf("Listening on port %d\n", PORT); { PRIntn osfd; char buf[11]; fd_set rdset; PRNetAddr rAddr; PRFileDesc *newSock; struct timeval timeout; PRInt32 bytesRead, rv, loops = 0; loops++; if (debug_mode) printf("Going into accept\n"); newSock = PR_Accept(listenSocket, &rAddr, PR_INTERVAL_NO_TIMEOUT); if (newSock) { if (debug_mode) printf("Got connection!\n"); } else { if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError()); else Test_Result (FAIL); } osfd = PR_FileDesc2NativeHandle(newSock); FD_ZERO(&rdset); FD_SET(osfd, &rdset); if (debug_mode) printf("Going into select \n"); timeout.tv_sec = 2; timeout.tv_usec = 0; rv = select(osfd + 1, &rdset, NULL, NULL, &timeout); if (debug_mode) printf("return from select is %d\n", rv); if (FD_ISSET(osfd, &rdset)) if (debug_mode) printf("I can't believe it- the socket is ready okay!\n"); else if (debug_mode) printf("Damn; the select test failed...\n"); else Test_Result (FAIL); strcpy(buf, "XXXXXXXXXX"); bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT); buf[10] = '\0'; if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf); PR_Close(newSock); } } /* NativeSelectTest */
static void AcceptThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) struct _timeb end_time_tb; #endif PRFileDesc *sock; PRNetAddr addr; PRFileDesc *accepted; sock = PR_NewTCPSocket(); if (sock == NULL) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_ANY); if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } accepted = PR_Accept(sock, NULL, timeout); if (accepted != NULL || PR_GetError() != PR_IO_TIMEOUT_ERROR) { fprintf(stderr, "PR_Accept did not time out\n"); exit(1); } elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (debug_mode) { fprintf(stderr, "Accept thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } }