comparison packet.c @ 728:f27058078d61

Try using writev() for writing packets out to tcp
author Matt Johnston <matt@ucc.asn.au>
date Sun, 31 Mar 2013 23:15:35 +0800
parents f4232b65b316
children 9a5438271556
comparison
equal deleted inserted replaced
727:00bc3df3a9c3 728:f27058078d61
53 53
54 int len, written; 54 int len, written;
55 buffer * writebuf = NULL; 55 buffer * writebuf = NULL;
56 time_t now; 56 time_t now;
57 unsigned packet_type; 57 unsigned packet_type;
58 int all_ignore = 1;
59 #ifdef HAVE_WRITEV
60 struct iovec *iov = NULL;
61 int i;
62 struct Link *l;
63 #endif
58 64
59 TRACE(("enter write_packet")) 65 TRACE(("enter write_packet"))
60 dropbear_assert(!isempty(&ses.writequeue)); 66 dropbear_assert(!isempty(&ses.writequeue));
61 67
68 #ifdef HAVE_WRITEV
69 iov = m_malloc(sizeof(*iov) * ses.writequeue.count);
70 for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
71 {
72 writebuf = (buffer*)l->item;
73 packet_type = writebuf->data[writebuf->len-1];
74 len = writebuf->len - 1 - writebuf->pos;
75 dropbear_assert(len > 0);
76 all_ignore &= (packet_type == SSH_MSG_IGNORE);
77 iov[i].iov_base = buf_getptr(writebuf, len);
78 iov[i].iov_len = len;
79 }
80 written = writev(ses.sock_out, iov, ses.writequeue.count);
81 if (written < 0) {
82 if (errno == EINTR) {
83 m_free(iov);
84 TRACE(("leave writepacket: EINTR"))
85 return;
86 } else {
87 dropbear_exit("Error writing");
88 }
89 }
90
91 if (written == 0) {
92 ses.remoteclosed();
93 }
94
95 while (written > 0) {
96 writebuf = (buffer*)examine(&ses.writequeue);
97 len = writebuf->len - 1 - writebuf->pos;
98 if (len > written) {
99 // partial buffer write
100 buf_incrpos(writebuf, written);
101 written = 0;
102 } else {
103 written -= len;
104 dequeue(&ses.writequeue);
105 buf_free(writebuf);
106 }
107 }
108
109 m_free(iov);
110
111 #else
62 /* Get the next buffer in the queue of encrypted packets to write*/ 112 /* Get the next buffer in the queue of encrypted packets to write*/
63 writebuf = (buffer*)examine(&ses.writequeue); 113 writebuf = (buffer*)examine(&ses.writequeue);
64 114
65 /* The last byte of the buffer is not to be transmitted, but is 115 /* The last byte of the buffer is not to be transmitted, but is
66 * a cleartext packet_type indicator */ 116 * a cleartext packet_type indicator */
76 return; 126 return;
77 } else { 127 } else {
78 dropbear_exit("Error writing"); 128 dropbear_exit("Error writing");
79 } 129 }
80 } 130 }
81 131 all_ignore = (packet_type == SSH_MSG_IGNORE);
82 now = time(NULL);
83 ses.last_trx_packet_time = now;
84
85 if (packet_type != SSH_MSG_IGNORE) {
86 ses.last_packet_time = now;
87 }
88 132
89 if (written == 0) { 133 if (written == 0) {
90 ses.remoteclosed(); 134 ses.remoteclosed();
91 } 135 }
92 136
96 buf_free(writebuf); 140 buf_free(writebuf);
97 writebuf = NULL; 141 writebuf = NULL;
98 } else { 142 } else {
99 /* More packet left to write, leave it in the queue for later */ 143 /* More packet left to write, leave it in the queue for later */
100 buf_incrpos(writebuf, written); 144 buf_incrpos(writebuf, written);
145 }
146
147 #endif
148 now = time(NULL);
149 ses.last_trx_packet_time = now;
150
151 if (!all_ignore) {
152 ses.last_packet_time = now;
101 } 153 }
102 154
103 TRACE(("leave write_packet")) 155 TRACE(("leave write_packet"))
104 } 156 }
105 157