📄 natplainsocketimplposix.cc
字号:
/* Copyright (C) 2003, 2004, 2005 Free Software Foundation This file is part of libgcj.This software is copyrighted work licensed under the terms of theLibgcj License. Please consult the file "LIBGCJ_LICENSE" fordetails. */#include <config.h>#include <platform.h>#ifdef HAVE_SYS_IOCTL_H#define BSD_COMP /* Get FIONREAD on Solaris2. */#include <sys/ioctl.h>#endif// Pick up FIONREAD on Solaris 2.5.#ifdef HAVE_SYS_FILIO_H#include <sys/filio.h>#endif#include <netinet/in.h>#include <netinet/tcp.h>#include <errno.h>#include <string.h>#if HAVE_BSTRING_H// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 #include <bstring.h>#endif#include <gcj/cni.h>#include <gcj/javaprims.h>#include <gnu/java/net/PlainSocketImpl.h>#include <gnu/java/net/PlainSocketImpl$SocketInputStream.h>#include <gnu/java/net/PlainSocketImpl$SocketOutputStream.h>#include <java/io/IOException.h>#include <java/io/InterruptedIOException.h>#include <java/net/BindException.h>#include <java/net/ConnectException.h>#include <java/net/InetAddress.h>#include <java/net/InetSocketAddress.h>#include <java/net/SocketException.h>#include <java/net/SocketTimeoutException.h>#include <java/lang/InternalError.h>#include <java/lang/Object.h>#include <java/lang/Boolean.h>#include <java/lang/Class.h>#include <java/lang/Integer.h>#include <java/lang/Thread.h>#include <java/lang/NullPointerException.h>#include <java/lang/ArrayIndexOutOfBoundsException.h>#include <java/lang/IllegalArgumentException.h>union SockAddr{ struct sockaddr_in address;#ifdef HAVE_INET6 struct sockaddr_in6 address6;#endif};voidgnu::java::net::PlainSocketImpl::create (jboolean stream){ int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0); if (sock < 0) { char* strerr = strerror (errno); throw new ::java::io::IOException (JvNewStringUTF (strerr)); } _Jv_platform_close_on_exec (sock); // We use native_fd in place of fd here. From leaving fd null we avoid // the double close problem in FileDescriptor.finalize. native_fd = sock;}voidgnu::java::net::PlainSocketImpl::bind (::java::net::InetAddress *host, jint lport){ union SockAddr u; struct sockaddr *ptr = (struct sockaddr *) &u.address; jbyteArray haddress = host->addr; jbyte *bytes = elements (haddress); int len = haddress->length; int i = 1; if (len == 4) { u.address.sin_family = AF_INET; if (host != NULL) memcpy (&u.address.sin_addr, bytes, len); else u.address.sin_addr.s_addr = htonl (INADDR_ANY); len = sizeof (struct sockaddr_in); u.address.sin_port = htons (lport); }#ifdef HAVE_INET6 else if (len == 16) { u.address6.sin6_family = AF_INET6; memcpy (&u.address6.sin6_addr, bytes, len); len = sizeof (struct sockaddr_in6); u.address6.sin6_port = htons (lport); }#endif else throw new ::java::net::SocketException (JvNewStringUTF ("invalid length")); // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT. ::setsockopt(native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i)); if (_Jv_bind (native_fd, ptr, len) == 0) { socklen_t addrlen = sizeof(u); if (lport != 0) localport = lport; else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0) localport = ntohs (u.address.sin_port); else goto error; return; } error: char* strerr = strerror (errno); throw new ::java::net::BindException (JvNewStringUTF (strerr));}voidgnu::java::net::PlainSocketImpl::connect (::java::net::SocketAddress *addr, jint timeout){ ::java::net::InetSocketAddress *tmp = (::java::net::InetSocketAddress*) addr; ::java::net::InetAddress *host = tmp->getAddress(); jint rport = tmp->getPort(); // Set the SocketImpl's address and port fields before we try to // connect. Note that the fact that these are set doesn't imply // that we're actually connected to anything. We need to record // this data before we attempt the connect, since non-blocking // SocketChannels will use this and almost certainly throw timeout // exceptions. address = host; port = rport; union SockAddr u; socklen_t addrlen = sizeof(u); jbyteArray haddress = host->addr; jbyte *bytes = elements (haddress); int len = haddress->length; struct sockaddr *ptr = (struct sockaddr *) &u.address; if (len == 4) { u.address.sin_family = AF_INET; memcpy (&u.address.sin_addr, bytes, len); len = sizeof (struct sockaddr_in); u.address.sin_port = htons (rport); }#ifdef HAVE_INET6 else if (len == 16) { u.address6.sin6_family = AF_INET6; memcpy (&u.address6.sin6_addr, bytes, len); len = sizeof (struct sockaddr_in6); u.address6.sin6_port = htons (rport); }#endif else throw new ::java::net::SocketException (JvNewStringUTF ("invalid length")); if (timeout > 0) { int flags = ::fcntl (native_fd, F_GETFL); ::fcntl (native_fd, F_SETFL, flags | O_NONBLOCK); if ((_Jv_connect (native_fd, ptr, len) != 0) && (errno != EINPROGRESS)) goto error; fd_set fset; struct timeval tv; FD_ZERO(&fset); FD_SET(native_fd, &fset); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; int retval; if ((retval = _Jv_select (native_fd + 1, &fset, &fset, NULL, &tv)) < 0) goto error; else if (retval == 0) throw new ::java::net::SocketTimeoutException (JvNewStringUTF ("Connect timed out")); // Set the socket back into a blocking state. ::fcntl (native_fd, F_SETFL, flags); } else { if (_Jv_connect (native_fd, ptr, len) != 0) goto error; } // A bind may not have been done on this socket; if so, set localport now. if (localport == 0) { if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0) localport = ntohs (u.address.sin_port); else goto error; } return; error: char* strerr = strerror (errno); throw new ::java::net::ConnectException (JvNewStringUTF (strerr));}voidgnu::java::net::PlainSocketImpl::listen (jint backlog){ if (::listen (native_fd, backlog) != 0) { char* strerr = strerror (errno); throw new ::java::io::IOException (JvNewStringUTF (strerr)); }}static void throw_on_sock_closed (gnu::java::net::PlainSocketImpl *soc_impl){ // Avoid races from asynchronous close(). JvSynchronize sync (soc_impl); if (soc_impl->native_fd == -1) { using namespace java::net; // Socket was closed. SocketException *se = new SocketException (JvNewStringUTF ("Socket Closed")); throw se; }}voidgnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl *s){ union SockAddr u; socklen_t addrlen = sizeof(u); int new_socket = 0; // Do timeouts via select since SO_RCVTIMEO is not always available. if (timeout > 0 && native_fd >= 0 && native_fd < FD_SETSIZE) { fd_set fset; struct timeval tv; FD_ZERO(&fset); FD_SET(native_fd, &fset); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; int retval; if ((retval = _Jv_select (native_fd + 1, &fset, &fset, NULL, &tv)) < 0) goto error; else if (retval == 0) throw new ::java::net::SocketTimeoutException ( JvNewStringUTF("Accept timed out")); } new_socket = _Jv_accept (native_fd, (sockaddr*) &u, &addrlen); if (new_socket < 0) goto error; _Jv_platform_close_on_exec (new_socket); jbyteArray raddr; jint rport; if (u.address.sin_family == AF_INET) { raddr = JvNewByteArray (4); memcpy (elements (raddr), &u.address.sin_addr, 4); rport = ntohs (u.address.sin_port); }#ifdef HAVE_INET6 else if (u.address.sin_family == AF_INET6) { raddr = JvNewByteArray (16); memcpy (elements (raddr), &u.address6.sin6_addr, 16); rport = ntohs (u.address6.sin6_port); }#endif else throw new ::java::net::SocketException (JvNewStringUTF ("invalid family")); s->native_fd = new_socket; s->localport = localport; s->address = new ::java::net::InetAddress (raddr, NULL); s->port = rport; return; error: char* strerr = strerror (errno); throw_on_sock_closed (this); throw new ::java::io::IOException (JvNewStringUTF (strerr));}// Close(shutdown) the socket.voidgnu::java::net::PlainSocketImpl::close(){ // Avoid races from asynchronous finalization. JvSynchronize sync (this); // Should we use shutdown here? Yes. // How would that effect so_linger? Uncertain. ::shutdown (native_fd, 2); // Ignore errors in shutdown as we are closing and all the same // errors are handled in the close. int res = _Jv_close (native_fd); if (res == -1) { // These three errors are not errors according to tests performed // on the reference implementation. if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF) throw new ::java::io::IOException (JvNewStringUTF (strerror (errno))); } // Safe place to reset the file pointer. native_fd = -1; timeout = 0;}static voidwrite_helper (jint native_fd, jbyte *bytes, jint len);// Write a byte to the socket.voidgnu::java::net::PlainSocketImpl$SocketOutputStream::write(jint b){ jbyte data = (jbyte) b; write_helper (this$0->native_fd, &data, 1);}// Write some bytes to the socket.voidgnu::java::net::PlainSocketImpl$SocketOutputStream::write(jbyteArray b, jint offset, jint len){ if (! b) throw new ::java::lang::NullPointerException; if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b)) throw new ::java::lang::ArrayIndexOutOfBoundsException; write_helper (this$0->native_fd, elements (b) + offset * sizeof (jbyte), len);}static voidwrite_helper(jint native_fd, jbyte *bytes, jint len){ int written = 0; while (len > 0) { int r = _Jv_write (native_fd, bytes, len); if (r == -1) { if (::java::lang::Thread::interrupted()) { ::java::io::InterruptedIOException *iioe = new ::java::io::InterruptedIOException (JvNewStringLatin1 (strerror (errno))); iioe->bytesTransferred = written; throw iioe; } // Some errors should not cause exceptions. if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF) throw new ::java::io::IOException (JvNewStringUTF (strerror (errno))); break; } written += r; len -= r; bytes += r; }}voidgnu::java::net::PlainSocketImpl::sendUrgentData (jint){ throw new ::java::net::SocketException (JvNewStringLatin1 ( "PlainSocketImpl: sending of urgent data not supported by this socket"));}static jintread_helper (gnu::java::net::PlainSocketImpl *soc_impl, jbyte *bytes, jint count);// Read a single byte from the socket.jintgnu::java::net::PlainSocketImpl$SocketInputStream::read(void){ jbyte data; if (read_helper (this$0, &data, 1) == 1) return data & 0xFF; return -1;}// Read count bytes into the buffer, starting at offset.jintgnu::java::net::PlainSocketImpl$SocketInputStream::read(jbyteArray buffer, jint offset, jint count){ if (! buffer) throw new ::java::lang::NullPointerException; jsize bsize = JvGetArrayLength (buffer); if (offset < 0 || count < 0 || offset + count > bsize) throw new ::java::lang::ArrayIndexOutOfBoundsException; return read_helper (this$0, elements (buffer) + offset * sizeof (jbyte), count);}static jint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -