--- orig/src/SSF/OS/TCP/Rcv_WndManager.java
+++ mod/src/SSF/OS/TCP/Rcv_WndManager.java
@@ -55,7 +55,7 @@
   /**
    * Maximum number of packets in receive buffer
    */
-  public static final int SIZE = 64;
+  public static final int SIZE = 512;
   
   public int MSS;
 
--- orig/src/SSF/OS/TCP/SendQueue.java
+++ mod/src/SSF/OS/TCP/SendQueue.java
@@ -9,6 +9,7 @@
 import SSF.OS.*;
 import SSF.OS.Socket.*;
 import java.io.*;
+import java.util.*;
 
 /**
  * SendQueue contains all the unsent and sent-but-unacknowledged TCP data segments.
@@ -142,32 +143,26 @@
       if(space() == 0 || data_size == 0)
         return 0;
       tcp_h.flags = 0;
-      //1/25/02 TCP_Header tcp_header = new TCP_Header(tcp_h);
-      newitem = new SendItem();
-      segSize = Math.min(Math.min(MSS, data_size), space());
-      //1/25/02 newitem.msg = new TCP_Message(tcp_header,SrcIPAddr,DestIPAddr,segSize);
-      newitem.msg = new TCP_Message(tcp_h,SrcIPAddr,DestIPAddr,segSize);
-
-      if(((dataMessage)msg).data != null)
-        newitem.msg.carryPayload(msg);
-      if (len==0) { // queue is empty
-        dummyItem.next = newitem;
-        newitem.prev = dummyItem;
-      } else {
-        newitem.prev = dummyItem.prev;
-        newitem.prev.next = newitem;
-      }
-      newitem.next = dummyItem;
-      dummyItem.prev = newitem;
-      len += segSize;
-      data_size -= segSize;
+
+      Object payload=((dataMessage)msg).data;
 
       // fill up any small leftover segment from previous append()
       if(data_size > 0) {
-        if((currentItem.next != dummyItem) &&
-	  (dummyItem.prev.msg.payload() == null)){
+        if((currentItem.next != dummyItem)) {
+		//&& (dummyItem.prev.msg.payload() == null)){
 	  int n = MSS - (dummyItem.prev.msg).seglen;
+	  n=Math.min(n,space());
 	  if (n > 0) {
+        if(payload != null) {
+		  ArrayList l;
+		  if (dummyItem.prev.msg.payload() == null) {
+		    l=new ArrayList(1);
+            dummyItem.prev.msg.carryPayload(new dataMessage(l,-1));
+		  } else 
+		    l=(ArrayList)((dataMessage)dummyItem.prev.msg.payload()).data;
+		  l.add(msg);
+		  payload = null;
+		}
 	    segSize = Math.min(n, data_size);
 	    (dummyItem.prev.msg).seglen += segSize;
 	    data_size -= segSize;
@@ -182,6 +177,12 @@
         segSize = Math.min(MSS, data_size);
         //1/25/02 newitem.msg = new TCP_Message(tcp_header,SrcIPAddr,DestIPAddr,segSize);
         newitem.msg = new TCP_Message(tcp_h,SrcIPAddr,DestIPAddr,segSize);
+        if(payload != null) {
+		  ArrayList l=new ArrayList(1);
+          newitem.msg.carryPayload(new dataMessage(l,-1));
+		  l.add(msg);
+		  payload = null;
+		}
         newitem.prev = dummyItem.prev;
         newitem.prev.next = newitem;
         newitem.next = dummyItem;


--- orig/src/SSF/OS/TCP/tcpSession.java
+++ mod/src/SSF/OS/TCP/tcpSession.java
@@ -735,16 +735,33 @@
   // change ato 5/28/01: write returns success when all written bytes
   // are acked. Previous versions returned success when send buffer was drained.
 
+  private static final int maxpending=1000;
+  private Vector pending=new Vector();
+  private int pendingBytes=0;
+  private boolean fresh=false;
+
   public void write(dataMessage dmsg, Continuation caller){
     if (writeCont != null){
       System.err.println(sessionInfo("write error - socket already in blocking write"));
       caller.failure(socketMaster.EBUSY);
       return;
     }
-    writeMsg = dmsg;
-    writeCont = caller;
-    writeSize = dmsg.size;
-    dataFeed();
+	if (writeSize>0 || pendingBytes>0) {
+		pending.add(dmsg);
+		pendingBytes+=dmsg.size;
+	} else {
+    	writeMsg = dmsg;
+    	writeSize = dmsg.size;
+		fresh=true;
+	}
+	if (pendingBytes<maxpending)
+		caller.success();
+	else
+    	writeCont = caller;
+
+	if (fresh)
+    	dataFeed();
+
     if(DEBUG)
       INSTR.takeSnapshot(getSimTime(), INSTR.EVT_SOCKWRITE);
   }
@@ -755,34 +772,41 @@
   // be accessed by read().
 
   void dataFeed(){
-    if(writeCont == null)
-      return;
+	while(writeSize!=0 || !pending.isEmpty()) {
+    if(writeSize == 0) {
+		writeMsg = (dataMessage)pending.remove(0);
+		writeSize = writeMsg.size;
+		pendingBytes-=writeSize;
+	}
     tcpHdr.flags = 0;
-    int size = snd.SendBuffer.append(writeMsg, writeMsg.size, tcpHdr,
+    int size = snd.SendBuffer.append(writeMsg, writeSize, tcpHdr,
                                      ipHdr.SOURCE_IP, ipHdr.DEST_IP, false);
     if(DEBUG)
       INSTR.takeSnapshot(getSimTime(), INSTR.EVT_PKSND);
 
-    snd.Send_Data_Process();
-    writeMsg.size -= size;
-  }
+	if (size==0)
+		break;
 
-  // Callback from Send_WndManager.Rcv_Ack_Process() when
-  // a segment was acked. added ato 5/28/01.
+    writeSize -= size;
+	}
 
-  void dataAcked(int nbytes) {
-    if(writeCont == null) return;
-    //System.err.println(sessionInfo("dataAcked: "+nbytes));
-    writeSize -= nbytes;
+    snd.Send_Data_Process();
 
-    // return success when all data were acked
-    if(writeSize <= 0){
+    // return success when queue is not full
+    if(pendingBytes<maxpending && writeCont!=null){
       Continuation app_call_waiting = writeCont;
       writeCont = null;
       mySocket.appCallWaiting = false;
       //mySocket.socketInfo("wrote data");
       app_call_waiting.success();
-    }
+    } 
+  }
+
+  // Callback from Send_WndManager.Rcv_Ack_Process() when
+  // a segment was acked. added ato 5/28/01.
+
+  void dataAcked(int nbytes) {
+	// I don't care
   }
 
   // change ato 5/28/01: allow for data arrival before a read().
@@ -806,7 +830,12 @@
     // if requested data is in the buffer, get it from buffer
     // We use the fact that a data object arrives in the first TCP segment.
 
-    if(nbytes <= dataReceived) {
+	if(nbytes<0 && objBuffer.size()!=0) {
+      dataMessage dmsg = (dataMessage)objBuffer.get(0);
+	  nbytes = dmsg.size;
+	}
+
+    if(nbytes>=0 && nbytes <= dataReceived) {
       dataReceived -= nbytes;
 
       if(obj != null) {
@@ -816,7 +845,8 @@
                         " but only virtual data arrived, no Object"));
           System.exit(-1);
         }
-        obj[0] = objBuffer.get(0);
+        dataMessage dmsg = (dataMessage)objBuffer.get(0);
+        obj[0] = dmsg.data;
         objBuffer.remove(0);
       }
       caller.success();
@@ -838,15 +868,25 @@
   private ArrayList objBuffer = new ArrayList(1);
 
   void dataCollect(dataMessage dmsg, int size){
-    if(dmsg != null)
-        objBuffer.add(dmsg.data);
+    if(dmsg != null) {
+		Iterator i=((ArrayList)dmsg.data).iterator();
+		while(i.hasNext())
+        	objBuffer.add((dataMessage)i.next());
+	}
 
     dataReceived += size;
     //System.err.println(sessionInfo("dataReceive: obj= "+dmsg+" size= "+size+
     //                               ", waiting for= "+(readSize - dataReceived)));
 
     // We use the fact that a data object arrives in the first TCP segment.
-    if((readCont != null) && (dataReceived >= readSize)) {
+    if (readCont == null)
+        return;
+    if (readSize < 0 && isReadingObject && objBuffer.size()!=0) {
+      // If the user asks for -1 bytes, we guess the size of the object
+      dmsg = (dataMessage)objBuffer.get(0);
+      readSize=dmsg.size;
+    }
+    if (readSize >= 0 && dataReceived >= readSize) {
       if(isReadingObject) {
         if (objBuffer.size() == 0) {
           System.err.println(
@@ -854,7 +894,8 @@
                         " but only virtual data arrived, no Object"));
           System.exit(-1);
         }
-        readObj[0] = objBuffer.get(0);
+        dmsg = (dataMessage)objBuffer.get(0);
+        readObj[0] = dmsg.data;
         objBuffer.remove(0);
         isReadingObject = false;
       }



