/** * See pcsl_serversocket.h for definition. */ int pcsl_serversocket_open( int port, void **pHandle) { int truebuf = 1; int fd = -1; struct sockaddr_in addr; int status; int flags; fd = socket(AF_INET, SOCK_STREAM, 0); lastError = errno; if (fd == INVALID_SOCKET) { return PCSL_NET_IOERROR; } status = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &truebuf, sizeof(truebuf)); lastError = errno; if (status == -1) { /* printf("setsockopt failed errno=%d\n", errno); */ (void)close(fd); return PCSL_NET_IOERROR; } flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); addr.sin_family = AF_INET; addr.sin_port = htons((unsigned short)port); addr.sin_addr.s_addr = htonl(INADDR_ANY); status = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); lastError = errno; if (status == -1) { /* printf("bind failed errno=%d\n", errno); */ (void)close(fd); return PCSL_NET_IOERROR; } status = listen(fd, SERVERSOCKET_BACKLOG); if (status == 0) { *pHandle = na_create(fd); return PCSL_NET_SUCCESS; } /* printf("listen failed errno=%d\n", errno); */ (void)close(fd); return PCSL_NET_IOERROR; }
/** * Common functionality for accept start and finish */ static int pcsl_serversocket_accept_common( void *handle, void **pConnectionHandle, void **pContext) { int connfd; int flags; struct sockaddr_in sa; int saLen = sizeof (sa); int listenfd = na_get_fd(handle); connfd = accept(listenfd, (struct sockaddr *)&sa, (socklen_t *)&saLen); if (connfd == SOCKET_ERROR) { if (errno == EWOULDBLOCK || errno == ECONNABORTED) { /* * The "listenfd" is marked as non-blocking and no connections * are present to be accepted. */ na_register_for_read((void *)handle); *pContext = NULL; return PCSL_NET_WOULDBLOCK; } else { na_unregister_for_read((void *)handle); return PCSL_NET_IOERROR; } } else { na_unregister_for_read((void *)handle); /* * Linux accept does _not_ inherit socket flags like O_NONBLOCK. * So, irrespective of the blocking or non-blockimg mode of listenfd, * connfd, must be set to non-blocking mode; otherwise VM will * be blocked for any I/O operation on this new socket descriptor. */ flags = fcntl(connfd, F_GETFL, 0); fcntl(connfd, F_SETFL, flags | O_NONBLOCK); *pConnectionHandle = na_create(connfd); return PCSL_NET_SUCCESS; } }
/** * See pcsl_datagram.h for definition. */ int pcsl_datagram_open_start( int port, void **pHandle, void **pContext) { struct sockaddr_in addr; int fd; int res; int i; int flags; int result; fd = socket(AF_INET, SOCK_DGRAM, 0); lastError = errno; if (fd == INVALID_SOCKET) { return PCSL_NET_IOERROR; } i = port; /* * Here is a total mystery to me. If I give solaris a port number of zero * then it allocated one somewhere above 50000. The problem is that when I * do a recvfrom() on a socket that is bound to a port > 32767 it never sees * any data. * * Temporary solution (seems to work all the time): * Start at port 6000 and just go upwards until a free port is found */ if (i <= 0) { i = 6000; } res = EADDRINUSE; do { addr.sin_family = AF_INET; addr.sin_port = htons((short)i++); addr.sin_addr.s_addr = htonl(INADDR_ANY); res = bind(fd, (struct sockaddr*)&addr, sizeof( addr )); lastError = errno; } while ((res == SOCKET_ERROR) && (errno == EADDRINUSE) && (port == 0) && (i < 32767)); if (res != SOCKET_ERROR) { *pHandle = na_create(fd); /* printf("creating SMS datagram handle, handle = %d, fd = %d, port = %d\n", (int)(*pHandle), fd, (i-1)); */ /* Set the datagram socket to non-blocking mode */ flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); return PCSL_NET_SUCCESS; } close(fd); return PCSL_NET_IOERROR; }
/** * See pcsl_socket.h for definition. */ int pcsl_socket_open_start( unsigned char *ipBytes, int port, void **pHandle, void **pContext) { int truebuf = 1; int fd = -1; struct sockaddr_in addr; int status; int flags; fd = socket(AF_INET, SOCK_STREAM, 0); lastError = errno; if (fd == INVALID_SOCKET) { return PCSL_NET_IOERROR; } status = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &truebuf, sizeof(truebuf)); lastError = errno; if (status == -1) { /* * DEBUG: * printf("setsockopt failed errno=%d\n", errno); */ (void)close(fd); return PCSL_NET_IOERROR; } addr.sin_family = AF_INET; addr.sin_port = htons((unsigned short)port); memcpy(&addr.sin_addr.s_addr, ipBytes, sizeof(addr.sin_addr.s_addr)); flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); status = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); lastError = errno; /* connect() may return 0 in case of non-blocking sockets if server is on the same host as client. No need to create a a blocked handle if connection is successfully established */ if (status == 0) { *pHandle = na_create(fd); return PCSL_NET_SUCCESS; } if ((status == SOCKET_ERROR) && (errno == EINPROGRESS || errno == EALREADY)) { *pContext = NULL; *pHandle = na_create(fd); na_register_for_write(*pHandle); return PCSL_NET_WOULDBLOCK; } close(fd); return PCSL_NET_CONNECTION_NOTFOUND; }