To future googlers: It turns out this is a bad idea--you can have a packet 
sitting in session->packets but still not be able to process the data until 
more packets are available.

I added a "count" property to the list_head struct, incrementing it in 
_libssh2_list_add() and decrementing in _libssh2_list_remove(). In 
_libssh2_channel_read() instead of calling _libssh2_transport_read() once if 
session->packets is empty, I  and session->packets->count is below a constant 
limit. (8 seems reasonable..?) A better solution might be to track the total 
size of the buffered data and place a limit on that instead.


diff -ru /Users/dave/Desktop/libssh2-1.4.2/src/channel.c 
libssh2-1.4.2/src/channel.c
--- /Users/dave/Desktop/libssh2-1.4.2/src/channel.c     2012-05-18 
14:29:03.000000000 -0700
+++ libssh2-1.4.2/src/channel.c 2012-08-15 16:57:53.000000000 -0700
@@ -1760,10 +1760,12 @@
 
     rc = 1; /* set to >0 to let the while loop start */
 
+#define MAX_BUFFERED_PACKETS 8
+
     /* Process all pending incoming packets in all states in order to "even
        out" the network readings. Tests prove that this way produces faster
        transfers. */
-    while (rc > 0)
+    while (rc > 0 && _libssh2_list_count(&session->packets) < 
MAX_BUFFERED_PACKETS)
         rc = _libssh2_transport_read(session);
 
     if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
diff -ru /Users/dave/Desktop/libssh2-1.4.2/src/misc.c libssh2-1.4.2/src/misc.c
--- /Users/dave/Desktop/libssh2-1.4.2/src/misc.c        2011-08-25 
10:59:47.000000000 -0700
+++ libssh2-1.4.2/src/misc.c    2012-08-15 15:47:00.000000000 -0700
@@ -474,6 +474,7 @@
 /* init the list head */
 void _libssh2_list_init(struct list_head *head)
 {
+       head->count = 0;
     head->first = head->last = NULL;
 }
 
@@ -498,6 +499,8 @@
         entry->prev->next = entry;
     else
         head->first = entry;
+       
+       ++head->count;
 }
 
 /* return the "first" node in the list this head points to */
@@ -518,9 +521,16 @@
     return node->prev;
 }
 
+int _libssh2_list_count(struct list_head *head)
+{
+    return head->count;
+}
+
 /* remove this node from the list */
 void _libssh2_list_remove(struct list_node *entry)
 {
+       --entry->head->count;
+       
     if(entry->prev)
         entry->prev->next = entry->next;
     else
diff -ru /Users/dave/Desktop/libssh2-1.4.2/src/misc.h libssh2-1.4.2/src/misc.h
--- /Users/dave/Desktop/libssh2-1.4.2/src/misc.h        2012-05-14 
10:50:53.000000000 -0700
+++ libssh2-1.4.2/src/misc.h    2012-08-15 15:09:34.000000000 -0700
@@ -39,6 +39,7 @@
  */
 
 struct list_head {
+       int count;
     struct list_node *last;
     struct list_node *first;
 };
@@ -66,6 +67,8 @@
 /* return the prev node in the list */
 void *_libssh2_list_prev(struct list_node *node);
 
+int _libssh2_list_count(struct list_head *head);
+
 /* remove this node from the list */
 void _libssh2_list_remove(struct list_node *entry);
 


On Jun 27, 2012, at 5:09 PM, Dave Hayden wrote:

> At the head of _libssh2_channel_read(), a while loop calls 
> _libssh2_transport_read(), after this comment:
> 
>>      Process all pending incoming packets in all states in order to "even 
>> out" the network readings. Tests prove that this way produces faster 
>> transfers.
> 
> 
> That makes sense for file transfers where the server will wait for an 
> acknowledgement, but in the case of a terminal session that's firehosing data 
> at us faster than we can process, that winds up filling up all available 
> memory--instead of just the network buffer. I changed that code to
> 
>       read_packet = _libssh2_list_first(&session->packets);
> 
>       while ( read_packet == NULL && rc > 0 )
>       {
>               rc = _libssh2_transport_read(session);
>               read_packet = _libssh2_list_first(&session->packets);
>       }
> 
> and it appears to fix this problem. Maybe there should be a channel or 
> session setting, choosing between the two? Or a limit on the number of 
> packets the session will buffer?
> 
> Thanks!
> -Dave
> 
> 
> _______________________________________________
> libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel


_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Reply via email to