comparison dbutil.c @ 1016:257f7d5fca97

piggyback data on acks when making connections on linux
author Matt Johnston <matt@ucc.asn.au>
date Fri, 13 Feb 2015 22:49:15 +0800
parents 6fb4c010c448
children cb148f8d3d22
comparison
equal deleted inserted replaced
1015:cb7b510b4dd2 1016:257f7d5fca97
148 va_end(param); 148 va_end(param);
149 } 149 }
150 150
151 151
152 #ifdef DEBUG_TRACE 152 #ifdef DEBUG_TRACE
153
154 static double time_since_start()
155 {
156 static double start_time = -1;
157 double nowf;
158 struct timeval tv;
159 gettimeofday(&tv, NULL);
160 nowf = tv.tv_sec + (tv.tv_usec / 1000000.0);
161 if (start_time < 0)
162 {
163 start_time = nowf;
164 return 0;
165 }
166 return nowf - start_time;
167 }
168
153 void dropbear_trace(const char* format, ...) { 169 void dropbear_trace(const char* format, ...) {
154 va_list param; 170 va_list param;
155 struct timeval tv;
156 171
157 if (!debug_trace) { 172 if (!debug_trace) {
158 return; 173 return;
159 } 174 }
160 175
161 gettimeofday(&tv, NULL);
162
163 va_start(param, format); 176 va_start(param, format);
164 fprintf(stderr, "TRACE (%d) %d.%d: ", getpid(), (int)tv.tv_sec, (int)tv.tv_usec); 177 fprintf(stderr, "TRACE (%d) %f: ", getpid(), time_since_start());
165 vfprintf(stderr, format, param); 178 vfprintf(stderr, format, param);
166 fprintf(stderr, "\n"); 179 fprintf(stderr, "\n");
167 va_end(param); 180 va_end(param);
168 } 181 }
169 182
170 void dropbear_trace2(const char* format, ...) { 183 void dropbear_trace2(const char* format, ...) {
171 static int trace_env = -1; 184 static int trace_env = -1;
172 va_list param; 185 va_list param;
173 struct timeval tv;
174 186
175 if (trace_env == -1) { 187 if (trace_env == -1) {
176 trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0; 188 trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
177 } 189 }
178 190
179 if (!(debug_trace && trace_env)) { 191 if (!(debug_trace && trace_env)) {
180 return; 192 return;
181 } 193 }
182 194
183 gettimeofday(&tv, NULL);
184
185 va_start(param, format); 195 va_start(param, format);
186 fprintf(stderr, "TRACE2 (%d) %d.%d: ", getpid(), (int)tv.tv_sec, (int)tv.tv_usec); 196 fprintf(stderr, "TRACE2 (%d) %f: ", getpid(), time_since_start());
187 vfprintf(stderr, format, param); 197 vfprintf(stderr, format, param);
188 fprintf(stderr, "\n"); 198 fprintf(stderr, "\n");
189 va_end(param); 199 va_end(param);
190 } 200 }
191 #endif /* DEBUG_TRACE */ 201 #endif /* DEBUG_TRACE */
388 } 398 }
389 return fd; 399 return fd;
390 } 400 }
391 #endif 401 #endif
392 402
403 #if defined(__linux__) && defined(TCP_DEFER_ACCEPT)
404 static void set_piggyback_ack(int sock) {
405 /* Undocumented Linux feature - set TCP_DEFER_ACCEPT and data will be piggybacked
406 on the 3rd packet (ack) of the TCP handshake. Saves a IP packet.
407 http://thread.gmane.org/gmane.linux.network/224627/focus=224727
408 "Piggyback the final ACK of the three way TCP connection establishment with the data" */
409 int val = 1;
410 /* No error checking, this is opportunistic */
411 int err = setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (void*)&val, sizeof(val));
412 if (err)
413 {
414 DEBUG_TRACE(("Failed setsockopt TCP_DEFER_ACCEPT: %s", strerror(errno)))
415 }
416 }
417 #endif
418
419
393 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will 420 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will
394 * return immediately if nonblocking is set. On failure, if errstring 421 * return immediately if nonblocking is set. On failure, if errstring
395 * wasn't null, it will be a newly malloced error message */ 422 * wasn't null, it will be a newly malloced error message */
396 423
397 /* TODO: maxfd */ 424 /* TODO: maxfd */
435 continue; 462 continue;
436 } 463 }
437 464
438 if (nonblocking) { 465 if (nonblocking) {
439 setnonblocking(sock); 466 setnonblocking(sock);
467
468 #if defined(__linux__) && defined(TCP_DEFER_ACCEPT)
469 set_piggyback_ack(sock);
470 #endif
440 } 471 }
441 472
442 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { 473 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
443 if (errno == EINPROGRESS && nonblocking) { 474 if (errno == EINPROGRESS && nonblocking) {
444 TRACE(("Connect in progress")) 475 TRACE(("Connect in progress"))