/** @inheritDoc */ public int writeBuf(int fd, byte buffer[], int off, int len) throws IOException { int result = 0; byte[] buf = buffer; if (off != 0) { buf = new byte[len]; System.arraycopy(buffer, off, buf, 0, len); } if (DEBUG) { System.err.println("writeBuf(" + fd + ") before write."); } result = libc.write(fd, buf, len); // We rely on open0() for setting the socket to non-blocking if (result < 0) { int err_code = LibCUtil.errno(); if (err_code == LibC.EWOULDBLOCK) { VMThread.getSystemEvents().waitForWriteEvent(fd); if (DEBUG) { System.err.println("writeBuf(" + fd + ") returned from select. retry."); } result = libc.write(fd, buf, len); // We rely on open0() for setting the socket to non-blocking } if (DEBUG) { System.err.println("writeBuf(" + fd + ") error:"); } LibCUtil.errCheckNeg(result); } return result; }
/** @inheritDoc */ public int readBuf(int fd, byte b[], int offset, int length) throws IOException { byte[] buf = b; if (offset != 0) { buf = new byte[length]; } int result = libc.read(fd, buf, length); // We rely on open0() for setting the socket to non-blocking if (result < 0) { int err_code = LibCUtil.errno(); if (err_code == LibC.EWOULDBLOCK) { VMThread.getSystemEvents().waitForReadEvent(fd); result = libc.read(fd, buf, length); // We rely on open0() for setting the socket to non-blocking } LibCUtil.errCheckNeg(result); } if (result == 0) { // If remote side has shut down the connection gracefully, and all // data has been received, recv() will complete immediately with // zero bytes received. // // This is true for Win32/CE and Linux result = -1; } return result; }
/** * Accept client connections on server socket fd. Blocks until a client connects. * * @param fd open server socket. See {@link #openServer}. * @return a native handle to the network connection. * @throws IOException */ public int accept(int fd) throws IOException { VMThread.getSystemEvents().waitForReadEvent(fd); Socket.sockaddr_in remote_sin = new Socket.sockaddr_in(); IntByReference address_len = new IntByReference(4); int newSocket = sockets.accept(fd, remote_sin, address_len); if (newSocket < 0) { throw newError(fd, "accept"); } address_len.free(); set_blocking_flags(newSocket, /*is_blocking*/ false); // we could read info about client from remote_sin, but don't need to. return newSocket; }
/** @inheritDoc */ public int open(String hostname, int port, int mode) throws IOException { // init_sockets(); win32 only int fd = -1; fd = sockets.socket(Socket.AF_INET, Socket.SOCK_STREAM, 0); if (DEBUG) { System.err.println("Socket.socket() = " + fd); } if (fd < 0) { throw newError(fd, "socket create"); } set_blocking_flags(fd, /*is_blocking*/ false); NetDB.hostent phostent; // hostname is always NUL terminated. See socket/Protocol.java for detail. phostent = NetDB.INSTANCE.gethostbyname(hostname); if (phostent == null) { throw newError(fd, "gethostbyname (herrono = " + NetDB.INSTANCE.h_errno() + ")"); } Socket.sockaddr_in destination_sin = new Socket.sockaddr_in(); destination_sin.sin_family = Socket.AF_INET; destination_sin.sin_port = Inet.htons((short) port); destination_sin.sin_addr = phostent.h_addr_list[0]; if (DEBUG) { System.err.println("Socket.sockaddr_in: " + destination_sin); System.err.println("connect: hostname: " + hostname + " port: " + port + " mode: " + mode); } if (sockets.connect(fd, destination_sin, destination_sin.size()) < 0) { int err_code = LibCUtil.errno(); if (err_code == LibC.EINPROGRESS || err_code == LibC.EWOULDBLOCK) { // When the socket is ready for connect, it becomes *writable* // (according to BSD socket spec of select()) VMThread.getSystemEvents().waitForWriteEvent(fd); } else { throw newError(fd, "connect"); } } return fd; }
/** * Accept client connections on server socket fd. Blocks until a client connects. * * @param fd open server socket. See {@link #openServer}. * @return a native handle to the network connection. * @throws IOException */ public int accept(int fd) throws IOException { Socket.sockaddr_in remote_sin = new Socket.sockaddr_in(); IntByReference address_len = new IntByReference(4); int newSocket; try { if (DEBUG) { System.err.println("Socket.accept(" + fd + ", " + remote_sin + ")..."); } newSocket = sockets.accept(fd, remote_sin, address_len); if (newSocket < 0) { if (DEBUG) { System.err.println("Need to block for accept..."); } int err_code = LibCUtil.errno(); if (err_code == LibC.EAGAIN || err_code == LibC.EWOULDBLOCK) { VMThread.getSystemEvents().waitForReadEvent(fd); newSocket = sockets.accept(fd, remote_sin, address_len); if (newSocket < 0) { throw newError(fd, "accept"); } } else { // BUG! throw newError(fd, "accept"); } } } finally { address_len.free(); } set_blocking_flags(newSocket, /*is_blocking*/ false); // we could read info about client from remote_sin, but don't need to. if (DEBUG) { System.err.println(" Socket.accept(...) = " + newSocket); } return newSocket; }
/** * Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting * on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the * discretion of the implementation. A thread waits on an object's monitor by calling one of the * <code>wait</code> methods. * * <p>The awakened thread will not be able to proceed until the current thread relinquishes the * lock on this object. The awakened thread will compete in the usual manner with any other * threads that might be actively competing to synchronize on this object; for example, the * awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock * this object. * * <p>This method should only be called by a thread that is the owner of this object's monitor. A * thread becomes the owner of the object's monitor in one of three ways: * * <ul> * <li>By executing a synchronized instance method of that object. * <li>By executing the body of a <code>synchronized</code> statement that synchronizes on the * object. * <li>For objects of type <code>Class,</code> by executing a synchronized static method of that * class. * </ul> * * <p>Only one thread at a time can own an object's monitor. * * @exception IllegalMonitorStateException if the current thread is not the owner of this object's * monitor. * @see java.lang.Object#notifyAll() * @see java.lang.Object#wait() */ public final void notify() { com.sun.squawk.VMThread.monitorNotify(this, false); }
/** * Causes current thread to wait until either another thread invokes the {@link * java.lang.Object#notify()} method or the {@link java.lang.Object#notifyAll()} method for this * object, or a specified amount of time has elapsed. * * <p>The current thread must own this object's monitor. * * <p>This method causes the current thread (call it <var>T</var>) to place itself in the wait set * for this object and then to relinquish any and all synchronization claims on this object. * Thread <var>T</var> becomes disabled for thread scheduling purposes and lies dormant until one * of four things happens: * * <ul> * <li>Some other thread invokes the <tt>notify</tt> method for this object and thread * <var>T</var> happens to be arbitrarily chosen as the thread to be awakened. * <li>Some other thread invokes the <tt>notifyAll</tt> method for this object. * <li>The specified amount of real time has elapsed, more or less. If <tt>timeout</tt> is zero, * however, then real time is not taken into consideration and the thread simply waits until * notified. * </ul> * * The thread <var>T</var> is then removed from the wait set for this object and re-enabled for * thread scheduling. It then competes in the usual manner with other threads for the right to * synchronize on the object; once it has gained control of the object, all its synchronization * claims on the object are restored to the status quo ante - that is, to the situation as of the * time that the <tt>wait</tt> method was invoked. Thread <var>T</var> then returns from the * invocation of the <tt>wait</tt> method. Thus, on return from the <tt>wait</tt> method, the * synchronization state of the object and of thread <tt>T</tt> is exactly as it was when the * <tt>wait</tt> method was invoked. * * <p>Note that the <tt>wait</tt> method, as it places the current thread into the wait set for * this object, unlocks only this object; any other objects on which the current thread may be * synchronized remain locked while the thread waits. * * <p>This method should only be called by a thread that is the owner of this object's monitor. * See the <code>notify</code> method for a description of the ways in which a thread can become * the owner of a monitor. * * @param timeout the maximum time to wait in milliseconds. * @exception IllegalArgumentException if the value of timeout is negative. * @exception IllegalMonitorStateException if the current thread is not the owner of the object's * monitor. * @exception InterruptedException if another thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is cleared when this exception is thrown. * @see java.lang.Object#notify() * @see java.lang.Object#notifyAll() */ public final void wait(long timeout) throws InterruptedException { if (timeout < 0) { throw new IllegalArgumentException(/*"timeout value is negative"*/ ); } com.sun.squawk.VMThread.monitorWait(this, timeout); }
/** * Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's * monitor by calling one of the <code>wait</code> methods. * * <p>The awakened threads will not be able to proceed until the current thread relinquishes the * lock on this object. The awakened threads will compete in the usual manner with any other * threads that might be actively competing to synchronize on this object; for example, the * awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock * this object. * * <p>This method should only be called by a thread that is the owner of this object's monitor. * See the <code>notify</code> method for a description of the ways in which a thread can become * the owner of a monitor. * * @exception IllegalMonitorStateException if the current thread is not the owner of this object's * monitor. * @see java.lang.Object#notify() * @see java.lang.Object#wait() */ public final void notifyAll() { com.sun.squawk.VMThread.monitorNotify(this, true); }
/** @inheritDoc */ public int readBuf(int fd, byte b[], int offset, int length) throws IOException { byte[] buf = b; int result; if (offset != 0) { if (DEBUG) { System.err.println("readBuf() into temp buf"); } buf = new byte[length]; } if (NBIO_WORKS) { result = libc.read(fd, buf, length); // We rely on open0() for setting the socket to non-blocking if (result < 0) { int err_code = LibCUtil.errno(); if (err_code == LibC.EWOULDBLOCK) { if (DEBUG) { System.err.println("Wait for read in select..."); } VMThread.getSystemEvents().waitForReadEvent(fd); result = libc.read( fd, buf, length); // We rely on open0() for setting the socket to non-blocking } LibCUtil.errCheckNeg(result); } } else { // If non-blocking IO doesn't seems to be working, try this hack... int bAvail = available(fd); // may throw IOException if (bAvail == 0) { if (DEBUG) { System.err.println("Wait for read in select..."); } VMThread.getSystemEvents().waitForReadEvent(fd); bAvail = available(fd); if (bAvail == 0) { // woke up because connection is closed if (DEBUG) { System.err.println("readBuf(" + fd + ") signalling EOF."); } return -1; // signal EOF } } if (DEBUG) { System.err.println("readBuf(" + fd + ") returned from select. retry."); } int n = Math.min(bAvail, length); // don't read more than is asked for... result = libc.read(fd, buf, n); // only read what we know is there... LibCUtil.errCheckNeg(result); } if (result == 0) { // If remote side has shut down the connection gracefully, and all // data has been received, recv() will complete immediately with // zero bytes received. // // This is true for Win32/CE and Linux if (DEBUG) { System.err.println("readBuf(" + fd + ") saw remote side shutdown."); } result = -1; } if (offset != 0 && result > 0) { System.arraycopy(buf, 0, b, offset, result); } if (DEBUG) { System.out.println("readBuf(" + fd + ") = " + result); } return result; }