📄 plainsocketimpl.c
字号:
/* * java.net.PlainSocketImpl.c * * Copyright (c) 1996, 1997 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "config-std.h"#include "config-io.h"#include "config-mem.h"#include "config-net.h"#include "support.h"#include "java_lang_Integer.h"#include "java_net_SocketImpl.h"#include "java_net_InetAddress.h"#include "gnu_java_net_PlainSocketImpl.h"#include "java_net_SocketOptions.h"#include "java_io_InterruptedIOException.h"#include "nets.h"#include <jsyscall.h>#include <jthread.h>#include "debug.h"#include "object.h"#include "itypes.h"#include "exception.h"#include "locks.h"#include "dummyin6.h"#define IPV4_ADDRESS_SIZE 4#define IPV6_ADDRESS_SIZE 16#if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)#include "getaddrinfo.h"#endif /* !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) *//* * Supported socket options */ static const struct { int jopt; int level; int copt; } socketOptions[] = {#if defined(SO_SNDBUF) { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },#endif /* defined(SO_SNDBUF) */#if defined(SO_RCVBUF) { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },#endif /* defined(SO_RCVBUF) */#if defined(SO_LINGER) { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },#endif /* defined(SO_LINGER) */#if defined(SO_REUSEADDR) { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },#endif /* defined(SO_REUSEADDR) */#if defined(TCP_NODELAY) { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },#endif /* defined(TCP_NODELAY) */ };#if defined(KAFFE_VMDEBUG) && !defined(NDEBUG)/* * Option names (for debugging only) */ static const struct { int opt; const char *name; } optionNames[] = {#if defined(SO_SNDBUF) { java_net_SocketOptions_SO_SNDBUF, "SO_SNDBUF" },#endif /* defined(SO_SNDBUF) */#if defined(SO_RCVBUF) { java_net_SocketOptions_SO_RCVBUF, "SO_RCVBUF" },#endif /* defined(SO_RCVBUF) */#if defined(SO_LINGER) { java_net_SocketOptions_SO_LINGER, "SO_LINGER" },#endif /* defined(SO_LINGER) */#if defined(SO_REUSEADDR) { java_net_SocketOptions_SO_REUSEADDR, "SO_REUSEADDR" },#endif /* defined(SO_REUSEADDR) */#if defined(TCP_NODELAY) { java_net_SocketOptions_TCP_NODELAY, "TCP_NODELAY" },#endif /* defined(TCP_NODELAY) */ { java_net_SocketOptions_SO_BINDADDR, "SO_BINDADDR" }, { java_net_SocketOptions_SO_TIMEOUT, "SO_TIMEOUT" }, { java_net_SocketOptions_IP_MULTICAST_IF, "IP_MULTICAST_IF" } };static char *ip2str(uint32 addr) { static char addrbuf[16]; addr = ntohl(addr); sprintf(addrbuf, "%u.%u.%u.%u", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr ) & 0xff); return addrbuf;}#if defined(HAVE_STRUCT_SOCKADDR_IN6)/* Generate a string for an inet6 addr (in host form). */static char *ip62str(struct in6_addr *addr) { static char addrbuf[255]; int i, count; for (count=0,i=0;i<16;i++) { count += sprintf(&addrbuf[count], i == 0 && addr->s6_addr[i] != 0 ? "%x" : addr->s6_addr[i] != 0 ? "%x:" : i != 0 ? ":" : "", addr->s6_addr[i]); } return addrbuf;}#endif /* defined(HAVE_STRUCT_SOCKADDR_IN6) */#endif /* defined(KAFFE_VMDEBUG) && !defined(NDEBUG) *//** * This is a helper functions to obtain safely a file descriptor which represents * the socket. * * @param this A valid socket implementation. * @return A valid file descriptor if available. */static intgetFileFromSocket(struct Hgnu_java_net_PlainSocketImpl* this){ int fd; lockObject((struct Hjava_lang_Object *)this); fd = (int)unhand(this)->native_fd; if (fd < 0) { unlockObject((struct Hjava_lang_Object *)this); SignalError("java.net.SocketException", "fd invalid"); } unhand(this)->fdUsed++; unlockObject((struct Hjava_lang_Object*)this); return fd;}/** * This is a helper functions to return safely a file descriptor to * the socket. * * @param this A valid socket implementation. */static voidreleaseFileToSocket(struct Hgnu_java_net_PlainSocketImpl* this){ lockObject((struct Hjava_lang_Object*)this); unhand(this)->fdUsed--; if (unhand(this)->fdUsed == 0) { KSOCKCLOSE(unhand(this)->native_fd); unhand(this)->native_fd = -1; } unlockObject((struct Hjava_lang_Object*)this);}/* * Create a stream or datagram socket. */voidgnu_java_net_PlainSocketImpl_socketCreate(struct Hgnu_java_net_PlainSocketImpl* this, jboolean stream){ int fd; int type; int rc; if (stream == 0) { type = SOCK_DGRAM; } else { type = SOCK_STREAM; } DBG(NATIVENET, dprintf("socketCreate(%p, %s)\n", this, stream ? "stream" : "datagram"); ); rc = KSOCKET(AF_INET, type, 0, &fd); if (rc) { unhand(this)->native_fd = -1; SignalError("java.io.IOException", SYS_ERROR(rc)); } DBG(NATIVENET, dprintf("socketCreate(%p, %s) -> fd=%d\n", this, stream ? "stream" : "datagram", fd); ); unhand(this)->fdUsed++; unhand(this)->native_fd = fd;}/* * Connect the socket to someone. */voidgnu_java_net_PlainSocketImpl_socketConnect(struct Hgnu_java_net_PlainSocketImpl* this, struct Hjava_net_InetAddress* daddr, jint dport, jint timeout){ int fd; int r; KaffeSocketAddr addr; socklen_t alen; memset(&addr, 0, sizeof(addr)); if (obj_length(unhand(daddr)->addr) == IPV4_ADDRESS_SIZE) { alen = sizeof(addr.addr4); #if defined(BSD44) addr.addr4.sin_len = sizeof(addr.addr4);#endif /* defined(BSD44) */ addr.addr4.sin_family = AF_INET; addr.addr4.sin_port = htons(dport); memcpy(&addr.addr4.sin_addr, unhand_byte_array(unhand(daddr)->addr), sizeof(addr.addr4.sin_addr));#if defined(HAVE_STRUCT_SOCKADDR_IN6) } else if (obj_length(unhand(daddr)->addr) == IPV6_ADDRESS_SIZE) { alen = sizeof(addr.addr6);#if defined(BSD44) addr.addr6.sin6_len = sizeof(addr.addr6);#endif /* defined(BSD44) */ addr.addr6.sin6_family = AF_INET6; addr.addr6.sin6_port = htons(dport); memcpy(&addr.addr6.sin6_addr, unhand_byte_array(unhand(daddr)->addr), sizeof(addr.addr6.sin6_addr));#endif /* defined(HAVE_STRUCT_SOCKADDR_IN6) */ } else { SignalError("java.net.SocketException", "Unsupported address family"); } DBG(NATIVENET, dprintf("socketConnect(%p, %s, %d, %d)\n", this, ip2str(addr.addr4.sin_addr.s_addr), dport, timeout); ); fd = getFileFromSocket(this); r = KCONNECT(fd, (struct sockaddr*)&addr, alen, timeout); if (r == EINTR) { releaseFileToSocket(this); SignalError("java.io.InterruptedIOException", "Connect was interrupted"); } if (r == ETIMEDOUT) { releaseFileToSocket(this); SignalError("java.net.SocketTimeoutException", "Connect timed out"); } if (r == EWOULDBLOCK && unhand(this)->blocking) { unhand(this)->connecting = true; return; } if (r) { releaseFileToSocket(this); SignalError("java.io.IOException", SYS_ERROR(r)); } /* Enter information into socket object */ alen = sizeof(addr); r = KGETSOCKNAME(fd, (struct sockaddr*)&addr, &alen); releaseFileToSocket(this); if (r) { SignalError("java.io.IOException", SYS_ERROR(r)); } DBG(NATIVENET, dprintf("socketConnect(%p, %s, %d) -> (lport: %d)\n", this, ip2str(addr.addr4.sin_addr.s_addr), dport, ntohs(addr.addr4.sin_port) ); ); unhand(this)->address = daddr; unhand(this)->port = dport; unhand(this)->localport = ntohs(addr.addr4.sin_port);}/* * Bind this socket to an address. */voidgnu_java_net_PlainSocketImpl_socketBind(struct Hgnu_java_net_PlainSocketImpl* this, struct Hjava_net_InetAddress* laddr, jint lport){ int r; KaffeSocketAddr addr; int fd; int on = 1; socklen_t alen; DBG(NATIVENET, dprintf("socketBind(%p, %s, %d)\n", this, ip2str(unhand(laddr)->address), lport); ); memset(&addr, 0, sizeof(addr)); if (obj_length(unhand(laddr)->addr) == IPV4_ADDRESS_SIZE) { alen = sizeof(addr.addr4);#if defined(BSD44) addr.addr4.sin_len = sizeof(addr.addr4);#endif /* defined(BSD44) */ addr.addr4.sin_family = AF_INET; addr.addr4.sin_port = htons(lport); memcpy(&addr.addr4.sin_addr, unhand_byte_array(unhand(laddr)->addr), sizeof(addr.addr4.sin_addr)); DBG(NATIVENET, dprintf("socketBind(%p, %s, -) -> (lport: %d)\n", this, ip2str(addr.addr4.sin_addr.s_addr), lport); );#if defined(HAVE_STRUCT_SOCKADDR_IN6) } else if (obj_length(unhand(laddr)->addr) == IPV6_ADDRESS_SIZE) { alen = sizeof(addr.addr6);#if defined(BSD44) addr.addr6.sin6_len = sizeof(addr.addr6);#endif /* defined(BSD44) */ addr.addr6.sin6_family = AF_INET6; addr.addr6.sin6_port = htons(lport); memcpy(&addr.addr6.sin6_addr, unhand_byte_array(unhand(laddr)->addr), sizeof(addr.addr6.sin6_addr)); DBG(NATIVENET, dprintf("socketBind(%p, %s, -) -> (lport: %d)\n", this, ip62str(&addr.addr6.sin6_addr), lport); );#endif /* defined(HAVE_STRUCT_SOCKADDR_IN6) */ } else { SignalError("java.net.SocketException", "Unsupported address family"); } fd = getFileFromSocket(this); /* Allow rebinding to socket - ignore errors */ (void)KSETSOCKOPT(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); r = KBIND(fd, (struct sockaddr*)&addr, alen); switch( r ) { case 0: break; case EADDRNOTAVAIL: case EADDRINUSE: case EACCES: releaseFileToSocket(this); SignalError("java.net.BindException", SYS_ERROR(r)); break; default: releaseFileToSocket(this); SignalError("java.net.SocketException", SYS_ERROR(r)); break; } /* Enter information into socket object */ unhand(this)->address = laddr; if (lport == 0) { alen = sizeof(addr); r = KGETSOCKNAME(fd, (struct sockaddr*)&addr, &alen); releaseFileToSocket(this); if (r) { SignalError("java.io.IOException", SYS_ERROR(r)); }#if defined(HAVE_STRUCT_SOCKADDR_IN6) if (obj_length(unhand(laddr)->addr) == IPV6_ADDRESS_SIZE) { lport = ntohs(addr.addr6.sin6_port); } else#endif { lport = ntohs(addr.addr4.sin_port); } } unhand(this)->localport = lport;}/* * Turn this socket into a listener. */voidgnu_java_net_PlainSocketImpl_socketListen(struct Hgnu_java_net_PlainSocketImpl* this, jint count){ int r; DBG(NATIVENET, dprintf("socketListen(%p, count=%d)\n", this, count); ); r = KLISTEN(getFileFromSocket(this), count); releaseFileToSocket(this); if (r) { SignalError("java.io.IOException", SYS_ERROR(r)); }}/* * Accept a connection. */voidgnu_java_net_PlainSocketImpl_socketAccept(struct Hgnu_java_net_PlainSocketImpl* this, struct Hjava_net_SocketImpl* sock){ int fd; int r; int rc, rc1; socklen_t alen; struct sockaddr_in addr; HArrayOfByte *remote_addr; struct Hgnu_java_net_PlainSocketImpl* accepted_socket = (struct Hgnu_java_net_PlainSocketImpl *)sock; jvalue jv; fd = getFileFromSocket(this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -