comparison packet.c @ 1026:59a1146e8b9d fastopen

generalise write iovec handling
author Matt Johnston <matt@ucc.asn.au>
date Wed, 18 Feb 2015 23:02:49 +0800
parents 02baa0b334e8
children daf21fd50abf
comparison
equal deleted inserted replaced
1025:02baa0b334e8 1026:59a1146e8b9d
50 #ifndef DISABLE_ZLIB 50 #ifndef DISABLE_ZLIB
51 static buffer* buf_decompress(buffer* buf, unsigned int len); 51 static buffer* buf_decompress(buffer* buf, unsigned int len);
52 static void buf_compress(buffer * dest, buffer * src, unsigned int len); 52 static void buf_compress(buffer * dest, buffer * src, unsigned int len);
53 #endif 53 #endif
54 54
55 #if 0 55 struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count) {
56 struct iovec * dropbear_queue_to_iovec(struct Queue *queue) {
57
58 struct iovec *iov = NULL; 56 struct iovec *iov = NULL;
59 struct Link *l; 57 struct Link *l;
60 int iov_max_count; 58 unsigned int i, packet_type;
59 int len;
60 buffer *writebuf;
61 61
62 #ifndef IOV_MAX 62 #ifndef IOV_MAX
63 #define IOV_MAX UIO_MAXIOV 63 #define IOV_MAX UIO_MAXIOV
64 #endif 64 #endif
65 65
66 #error incomplete 66 *ret_iov_count = MIN(queue->count, IOV_MAX);
67 67
68 } 68 iov = m_malloc(sizeof(*iov) * *ret_iov_count);
69 69 for (l = queue->head, i = 0; l; l = l->link, i++)
70 void dropbear_queue_consume(struct Queue *queue, ssize_t written) {
71
72 }
73 #endif
74
75 /* non-blocking function writing out a current encrypted packet */
76 void write_packet() {
77
78 ssize_t written;
79 int len;
80 buffer * writebuf = NULL;
81 unsigned packet_type;
82 #ifdef HAVE_WRITEV
83 struct iovec *iov = NULL;
84 int i;
85 struct Link *l;
86 int iov_max_count;
87 #endif
88
89 TRACE2(("enter write_packet"))
90 dropbear_assert(!isempty(&ses.writequeue));
91
92 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
93
94 #ifndef IOV_MAX
95 #define IOV_MAX UIO_MAXIOV
96 #endif
97
98 /* Make sure the size of the iov is below the maximum allowed by the OS. */
99 iov_max_count = ses.writequeue.count;
100 if (iov_max_count > IOV_MAX)
101 {
102 iov_max_count = IOV_MAX;
103 }
104
105 iov = m_malloc(sizeof(*iov) * iov_max_count);
106 for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
107 { 70 {
108 writebuf = (buffer*)l->item; 71 writebuf = (buffer*)l->item;
109 packet_type = writebuf->data[writebuf->len-1]; 72 packet_type = writebuf->data[writebuf->len-1];
110 len = writebuf->len - 1 - writebuf->pos; 73 len = writebuf->len - 1 - writebuf->pos;
111 dropbear_assert(len > 0); 74 dropbear_assert(len > 0);
112 TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type, 75 TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type,
113 len, writebuf->len-1)) 76 len, writebuf->len-1))
114 iov[i].iov_base = buf_getptr(writebuf, len); 77 iov[i].iov_base = buf_getptr(writebuf, len);
115 iov[i].iov_len = len; 78 iov[i].iov_len = len;
116 } 79 }
117 /* This may return EAGAIN. The main loop sometimes 80
118 calls write_packet() without bothering to test with select() since 81 return iov;
119 it's likely to be necessary */ 82 }
120 written = writev(ses.sock_out, iov, iov_max_count); 83
121 if (written < 0) { 84 void packet_queue_consume(struct Queue *queue, ssize_t written) {
122 if (errno == EINTR || errno == EAGAIN) { 85 buffer *writebuf;
123 m_free(iov); 86 int len;
124 TRACE2(("leave write_packet: EINTR"))
125 return;
126 } else {
127 dropbear_exit("Error writing: %s", strerror(errno));
128 }
129 }
130
131 if (written == 0) {
132 ses.remoteclosed();
133 }
134
135 while (written > 0) { 87 while (written > 0) {
136 writebuf = (buffer*)examine(&ses.writequeue); 88 writebuf = (buffer*)examine(queue);
137 len = writebuf->len - 1 - writebuf->pos; 89 len = writebuf->len - 1 - writebuf->pos;
138 if (len > written) { 90 if (len > written) {
139 /* partial buffer write */ 91 /* partial buffer write */
140 buf_incrpos(writebuf, written); 92 buf_incrpos(writebuf, written);
141 written = 0; 93 written = 0;
142 } else { 94 } else {
143 written -= len; 95 written -= len;
144 dequeue(&ses.writequeue); 96 dequeue(queue);
145 buf_free(writebuf); 97 buf_free(writebuf);
146 } 98 }
147 } 99 }
148 100 }
101
102 /* non-blocking function writing out a current encrypted packet */
103 void write_packet() {
104
105 ssize_t written;
106 int len;
107 buffer * writebuf = NULL;
108 unsigned packet_type;
109 #ifdef HAVE_WRITEV
110 struct iovec *iov = NULL;
111 int i;
112 struct Link *l;
113 int iov_count;
114 #endif
115
116 TRACE2(("enter write_packet"))
117 dropbear_assert(!isempty(&ses.writequeue));
118
119 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
120
121 iov = packet_queue_to_iovec(&ses.writequeue, &iov_count);
122 /* This may return EAGAIN. The main loop sometimes
123 calls write_packet() without bothering to test with select() since
124 it's likely to be necessary */
125 written = writev(ses.sock_out, iov, iov_count);
126 if (written < 0) {
127 if (errno == EINTR || errno == EAGAIN) {
128 TRACE2(("leave write_packet: EINTR"))
129 m_free(iov);
130 return;
131 } else {
132 dropbear_exit("Error writing: %s", strerror(errno));
133 }
134 }
149 m_free(iov); 135 m_free(iov);
136
137 packet_queue_consume(&ses.writequeue, written);
138
139 if (written == 0) {
140 ses.remoteclosed();
141 }
142
150 #else /* No writev () */ 143 #else /* No writev () */
151 /* Get the next buffer in the queue of encrypted packets to write*/ 144 /* Get the next buffer in the queue of encrypted packets to write*/
152 writebuf = (buffer*)examine(&ses.writequeue); 145 writebuf = (buffer*)examine(&ses.writequeue);
153 146
154 /* The last byte of the buffer is not to be transmitted, but is 147 /* The last byte of the buffer is not to be transmitted, but is