/** * See pcsl_network.h for definition. */ int pcsl_network_getremoteport( void *handle, int *pPortNumber) { int status; int peerPort; struct sockaddr_in sa; socklen_t saLen = sizeof (sa); int fd = na_get_fd(handle); status = getpeername(fd, (struct sockaddr*)&sa, &saLen); lastError = errno; if (status < 0) { return PCSL_NET_IOERROR; } /* * DEBUG: * printf("get ip number family=%x port=%d addr=%s\n", * sa.sin_family, sa.sin_port, inet_ntoa(sa.sin_addr) ); */ peerPort = (int) ntohs(sa.sin_port); *pPortNumber = peerPort; return PCSL_NET_SUCCESS; }
/** * See pcsl_socket.h for definition. */ int pcsl_socket_getremoteaddr( void *handle, char *pAddress) { int status; struct sockaddr_in sa; socklen_t saLen = sizeof (sa); int fd = na_get_fd(handle); sa.sin_family = AF_INET; status = getpeername(fd, (struct sockaddr*)&sa, &saLen); lastError = errno; if (status < 0) { return PCSL_NET_IOERROR; } /* * DEBUG: * printf("get ip number port=%d addr=%s\n", * sa.sin_port, inet_ntoa(sa.sin_addr) ); */ strcpy(pAddress, (char *)inet_ntoa(sa.sin_addr)); return PCSL_NET_SUCCESS; }
/** * See pcsl_socket.h for definition. */ int pcsl_network_setsockopt( void *handle, int flag, int optval) { int level = SOL_SOCKET; int optsize = sizeof(optval); int optname; struct linger lbuf ; void * opttarget = (void *) & optval ; int fd = na_get_fd(handle); switch (flag) { case 0: /* DELAY */ level = IPPROTO_TCP; optname = TCP_NODELAY; break; case 1: /* LINGER */ opttarget = (void *) &lbuf ; optsize = sizeof (struct linger); optname = SO_LINGER; if (optval == 0) { lbuf.l_onoff = 0; lbuf.l_linger = 0; } else { lbuf.l_onoff = 1; lbuf.l_linger = optval; } break; case 2: /* KEEPALIVE */ optname = SO_KEEPALIVE; break; case 3: /* RCVBUF */ optname = SO_RCVBUF; break; case 4: /* SNDBUF */ optname = SO_SNDBUF; break; default: return PCSL_NET_INVALID; } /* * DEBUG: * printf("setSockopt option=%d value=%d\n", optname, optval); */ if (setsockopt(fd, level, optname, opttarget, optsize) != 0) { lastError = errno; /* * DEBUG: * printf("setsockopt errno=%d\n", errno); */ return PCSL_NET_INVALID; } lastError = 0; return PCSL_NET_SUCCESS; }
/** * See pcsl_socket.h for definition. */ int pcsl_socket_open_finish( void *handle, void *context) { int err; socklen_t err_size = sizeof(err); int fd = na_get_fd(handle); int status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_size); /* * DEBUG: * printf( "pcsl_socket_open_finish::handle=%d err=%d\n", fd, err); */ lastError = err; if (err == 0) { na_unregister_for_write(handle); /* * DEBUG: * printf("opened fd: %d\n", fd); */ return PCSL_NET_SUCCESS; } else { na_destroy(handle); close(fd); return PCSL_NET_IOERROR; } }
/** * See pcsl_socket.h for definition. * * Note that this function NEVER returns PCSL_NET_WOULDBLOCK. Therefore, the * finish() function should never be called and does nothing. */ int pcsl_socket_close_start( void *handle, void **pContext) { int status; int fd = na_get_fd(handle); /* * DEBUG: * printf("closing fd: %d\n", fd); */ status = close(fd); lastError = errno; /* * If PCSL_NET_WOULDBLOCk is detected, the notification adapter must not be * destroyed. */ na_destroy(handle); if (status == 0) { return PCSL_NET_SUCCESS; } return PCSL_NET_IOERROR; }
/** * See pcsl_socket.h for definition. */ int pcsl_network_getsockopt( void *handle, int flag, int *pOptval) { int level = SOL_SOCKET; int optname; socklen_t optsize = sizeof(optname); struct linger lbuf ; void * opttarget = (void *) pOptval ; int fd = na_get_fd(handle); switch (flag) { case 0: /* DELAY */ level = IPPROTO_TCP; optname = TCP_NODELAY; break; case 1: /* LINGER */ opttarget = (void *) &lbuf ; optsize = sizeof (struct linger); optname = SO_LINGER; break; case 2: /* KEEPALIVE */ optname = SO_KEEPALIVE; break; case 3: /* RCVBUF */ optname = SO_RCVBUF; break; case 4: /* SNDBUF */ optname = SO_SNDBUF; break; default: return PCSL_NET_INVALID; } if (getsockopt(fd, level, optname, opttarget, &optsize) == 0 ) { lastError = 0; if (optname == SO_LINGER) { /* If linger is on return the number of seconds. */ *pOptval = (lbuf.l_onoff == 0 ? 0 : lbuf.l_linger) ; } /* * DEBUG: * printf("getSockopt option=%d value=%d size=%d\n", * optname, *pOptval, optsize); */ return PCSL_NET_SUCCESS; } else { lastError = errno; /* * DEBUG: * printf("getsockopt errno=%d option=%d level=%d\n", * errno, optname, level ); */ return PCSL_NET_IOERROR; } }
/** * See pcsl_socket.h for definition. */ int pcsl_socket_shutdown_output(void *handle) { int fd = na_get_fd(handle); int status; status = shutdown(fd, 1); lastError = errno; /* Return value of shutdown() need not be checked */ return PCSL_NET_SUCCESS; }
/** * Common implementation between pcsl_socket_read_start() * and pcsl_socket_read_finish(). */ static int pcsl_socket_read_common( void *handle, unsigned char *pData, int len, int *pBytesRead) { int status; int fd; if (na_get_status(handle) == PCSL_NET_INTERRUPTED) { /* * VMSocket status need not be set to any value at this point * as the VMSocket is deleted and corresponding BSD socket is * also closed after emitting an interrupted IO exception */ return PCSL_NET_INTERRUPTED; } fd = na_get_fd(handle); status = recv(fd, pData, len, 0); lastError = errno; if (SOCKET_ERROR == status) { if (EWOULDBLOCK == errno || EINPROGRESS == errno) { /* * DEBUG: * printf("read_start from : fd :%d\n", fd); */ return PCSL_NET_WOULDBLOCK; } else if (EINTR == errno) { return PCSL_NET_INTERRUPTED; } else { return PCSL_NET_IOERROR; } } if (status == 0) { /* * DEBUG: * printf("Bytes read are 0\n"); */ } /* * DEBUG: * printf("read_finish from : fd :%d\n", fd); */ *pBytesRead = status; return PCSL_NET_SUCCESS; }
/** * See pcsl_socket.h for definition. */ int pcsl_socket_available(void *handle, int *pBytesAvailable) { int fd = na_get_fd(handle); int status; status = ioctl(fd, FIONREAD, pBytesAvailable); lastError = errno; if (status < 0) { return PCSL_NET_IOERROR; } else { return PCSL_NET_SUCCESS; } }
/** * Common implementation between pcsl_datagram_read_start() * and pcsl_datagram_read_finish(). */ static int pcsl_datagram_read_common( void *handle, unsigned char *pAddress, int *port, char *buffer, int length, int *pBytesRead) { struct sockaddr_in addr; int len = sizeof(struct sockaddr_in); int status; int fd; if (na_get_status(handle) == PCSL_NET_INTERRUPTED) { /* * VMSocket status need not be set to any value at this point * as the VMSocket is deleted and corresponding BSD socket is * also closed */ return PCSL_NET_INTERRUPTED; } fd = na_get_fd(handle); status = recvfrom(fd, buffer, length, 0, (struct sockaddr*)&addr, (socklen_t *)&len); lastError = errno; if (SOCKET_ERROR == status) { if (EWOULDBLOCK == errno || EINPROGRESS == errno) { /* printf("datagram read_start from : fd :%d\n", fd); */ return PCSL_NET_WOULDBLOCK; } else if (EINTR == errno) { return PCSL_NET_INTERRUPTED; } else { return PCSL_NET_IOERROR; } } memcpy(pAddress, &addr.sin_addr.s_addr, sizeof(pAddress)); //*ipnumber = (long)addr.sin_addr.s_addr; *port = ntohs(addr.sin_port); *pBytesRead = status; return PCSL_NET_SUCCESS; }
/** * Common implementation between pcsl_socket_write_start() * and pcsl_socket_write_finish(). */ static int pcsl_socket_write_common( void *handle, char *pData, int len, int *pBytesWritten) { int status; int fd; if (na_get_status(handle) == PCSL_NET_INTERRUPTED) { /* * VMSocket status need not be set to any value at this point * as the VMSocket is deleted and corresponding BSD socket is * also closed */ return PCSL_NET_INTERRUPTED; } fd = na_get_fd(handle); status = send(fd, pData, len, 0); lastError = errno; if (SOCKET_ERROR == status) { if (EWOULDBLOCK == errno || EINPROGRESS == errno) { /* * DEBUG: * printf("write_start from : fd :%d\n", fd); */ return PCSL_NET_WOULDBLOCK; } else if (EINTR == errno) { return PCSL_NET_INTERRUPTED; } else { return PCSL_NET_IOERROR; } } /* * DEBUG: * printf("writing : %s : to fd :%d\n", pData, fd); * printf("write_finish from : fd :%d\n", fd); */ *pBytesWritten = status; return PCSL_NET_SUCCESS; }
/** * Common implementation between pcsl_datagram_write_start() * and pcsl_datagram_write_finish(). */ static int pcsl_datagram_write_common( void *handle, unsigned char *ipBytes, int port, char *buffer, int length, int *pBytesWritten) { struct sockaddr_in addr; int status; int fd; if (na_get_status(handle) == PCSL_NET_INTERRUPTED) { /* * VMSocket status need not be set to any value at this point * as the VMSocket is deleted and corresponding BSD socket is * also closed */ return PCSL_NET_INTERRUPTED; } fd = na_get_fd(handle); addr.sin_family = AF_INET; addr.sin_port = htons((short)port); memcpy(&addr.sin_addr.s_addr, ipBytes, sizeof(addr.sin_addr.s_addr)); status = sendto(fd, buffer, length, 0, (struct sockaddr*)&addr, sizeof(addr)); lastError = errno; if (SOCKET_ERROR == status) { if (EWOULDBLOCK == errno || EINPROGRESS == errno) { /* printf("write_start from : fd :%d\n", fd); */ return PCSL_NET_WOULDBLOCK; } else if (EINTR == errno) { return PCSL_NET_INTERRUPTED; } else { return PCSL_NET_IOERROR; } } *pBytesWritten = status; return PCSL_NET_SUCCESS; }
/** * See pcsl_datagram.h for definition. * * Note that this function NEVER returns PCSL_NET_WOULDBLOCK. Therefore, the * finish() function should never be called and does nothing. */ int pcsl_datagram_close_start( void *handle, void **pContext) { int status; int fd = na_get_fd(handle); /* printf("closing fd: %d\n", fd); */ (void)pContext; na_destroy(handle); status = close(fd); lastError = errno; if (status == 0) { return PCSL_NET_SUCCESS; } 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; } }