/** * sends data from buffer. * * <p>precondition: sendbb is in put mode post condition: sendbb is in put mode */ private void sendFromBuffer() { aa(this, isSender(), "nonsender can't write"); aa(this, isConnected() || isClosurePending(), "needs to be established can't write"); // switch sendbb to get mode sendbb.flip(); p(this, 3, "Sending from buffer. bb flipped."); int payloadLength = Math.min(Transport.MAX_PAYLOAD_SIZE, sendbb.limit()); p(this, 4, "Max Payload size: " + Transport.MAX_PAYLOAD_SIZE); p(this, 4, "payloadlen: " + payloadLength); dumpState(4); if (roomForPacket(payloadLength) && payloadLength > 0) { byte[] payload = new byte[payloadLength]; sendbb.get(payload); Transport t = makeTransport(Transport.DATA, seqNum, payload); tcpMan.sendData(this.tsid, t); p(this, 3, "Write: converting to packet: " + TCPManager.bytesToString(payload)); // only increment the seqNum if a packet is sent seqNum += payloadLength; } // switch back to put mode sendbb.compact(); dumpState(4); if (isClosurePending() && sendbb.position() == 0) release(); }
/** * Read from the socket up to len bytes into the buffer buf starting at position pos. * * @param buf byte[] the buffer * @param pos int starting position in buffer * @param len int number of bytes to read * @return int on success, the number of bytes read, which may be smaller than len; on failure, -1 */ public int read(byte[] buf, int pos, int len) { aa(this, isReceiver(), "nonreceiver socket reading"); aa(this, state == State.ESTABLISHED, "attempting to read from closed socket"); recvbb.flip(); int bytesCopied = Math.min(recvbb.limit(), len); recvbb.get(buf, pos, bytesCopied); recvbb.compact(); return bytesCopied; }
private void initSender() { aa(this, sockType == SocketType.SENDER, ""); sendWindow = 3 * Transport.MAX_PAYLOAD_SIZE; sendBase = 0; seqNum = 0; sendbb = ByteBuffer.allocate(SEND_BUFFER_SIZE); }
private void deliverToBuffer() { while (transportBuffer.containsKey(recvBase)) { p(this, 4, "coalescing at recvBase: " + recvBase); dumpState(6); byte[] payload = transportBuffer.get(recvBase).getPayload(); if (recvbb.remaining() >= payload.length) { recvbb.put(payload); recvBase += payload.length; p(this, 5, "coalesced: recvBase incremented to " + recvBase); } else { p(this, 5, "coalesce ending: buffer full"); break; } } }
/** * Write to the socket up to len bytes from the buffer buf starting at position pos. * * @param buf byte[] the buffer to write from * @param pos int starting position in buffer * @param len int number of bytes to write * @return int on success, the number of bytes written, which may be smaller than len; on failure, * -1 */ public int write(byte[] buf, int pos, int len) { aa(this, isSender(), "nonsender can't write"); aa(this, isConnected(), "nonsender can't write"); // fill buffer p( this, 3, "write called"); // \n\t buf = " + TCPManager.bytesToString(buf)); p(this, 4, "sendbb // position: " + sendbb.position()); dumpState(4); // p(this, 4, "sendbb limit: " + sendbb.limit()); // p(this, 4, "sendbb remaining: " + sendbb.remaining()); // p(this, 4, "sendbb size: " + sendbb.capacity()); int bytesCopied = Math.min(sendbb.remaining(), len); sendbb.put(buf, pos, bytesCopied); p(this, 3, "bytes copied: " + bytesCopied); // try to send as much as possible sendFromBuffer(); return bytesCopied; }
/** Initiate closure of a connection (graceful shutdown) */ public void close() { p(this, 3, "Close()"); switch (sockType) { case SENDER: state = State.SHUTDOWN; if (sendbb.position() == 0) release(); break; case RECEIVER: release(); break; case WELCOME: release(); } }
private void initReceiver() { aa(this, sockType == SocketType.RECEIVER, ""); recvBase = 0; recvbb = ByteBuffer.allocate(RECV_BUFFER_SIZE); transportBuffer = new HashMap<Integer, Transport>(); }