Mercurial > dropbear
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")) |