/** * 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(); }
/** Release a connection immediately (abortive shutdown) */ public void release() { p(this, 3, "Release()"); // TODO(syu) send a FIN this.state = State.CLOSED; tcpMan.sendFIN(tsid); if (isReceiver()) tcpMan.remove(tsid); }
/** * Accept a connection on a socket * * <p>Needs to trigger sending an ACK * * @return TCPSock The first established connection on the request queue remove from welcomeQueue * adds recvSocket to socketSpace sends Ack */ public TCPSock accept() { aa(this, this.sockType == SocketType.WELCOME, "accept() called by non-welcome socket"); aa(this, this.state == State.LISTEN, "accept() called when not listening"); if (welcomeQueue.isEmpty()) return null; p(this, 3, "accept()"); TCPSock recvSock = welcomeQueue.remove(0); recvSock.state = State.ESTABLISHED; p(recvSock, 4, "established"); tcpMan.add(recvSock.tsid, recvSock); tcpMan.sendACK(recvSock.tsid); return recvSock; }
/** * Initiate connection to a remote socket * * @param destAddr int Destination node address * @param destPort int Destination port * @return int 0 on success, -1 otherwise */ public int connect(int destAddr, int destPort) { // if not starting from a closed state, connect should fail. if (!isClosed() || !isSender()) { pe(this, " connect() called on inappropriated"); return -1; } p(this, 3, "Connect() to: " + destAddr + ":" + destPort); this.tsid.remoteAddr = destAddr; this.tsid.remotePort = destPort; tcpMan.add(this.tsid, this); tcpMan.sendSYN(this.tsid); this.state = State.SYN_SENT; return 0; }
/** * Listen for connections on a socket * * @param backlog int Maximum number of pending connections * @return int 0 on success, -1 otherwise */ public int listen(int backlog) { if (sockType != SocketType.WELCOME) { die(this, "not a welcome socket"); return -1; } this.state = State.LISTEN; p(this, 3, "listening. backlog: " + backlog); this.backlog = backlog; welcomeQueue = new ArrayList<TCPSock>(backlog); tcpMan.addWelcomeSocket(this); return 0; }
public void dataReceived(Transport t) { aa(this, isReceiver(), "DATA received by non receiver socket"); aa(this, isConnected(), "DATA received by invalid socket state"); int inSeqNum = t.getSeqNum(); p(this, 3, "dataReceived() seqnum: " + inSeqNum); transportBuffer.put(inSeqNum, t); deliverToBuffer(); dumpState(4); p(this, 3, "ending dataReceived"); tcpMan.sendACK(this.tsid); }
public TCPSock(TCPManager tcpMan, SocketType type) { this.tcpMan = tcpMan; this.tsid = new TCPSockID(); this.tsid.localAddr = tcpMan.getAddr(); this.state = State.CLOSED; this.sockType = type; switch (sockType) { case SENDER: initSender(); break; case RECEIVER: initReceiver(); break; case WELCOME: initWelcome(); break; } this.seqNum = 0; }