diff --git a/cli-main.c b/cli-main.c index 6834d1d..80ff557 100644 --- a/cli-main.c +++ b/cli-main.c @@ -47,6 +47,7 @@ int main(int argc, char ** argv) { int sock_in, sock_out; char* error = NULL; + struct dropbear_progress_connection *progress = NULL; _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; @@ -72,11 +73,11 @@ int main(int argc, char ** argv) { } else #endif { - connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, NULL); + progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, NULL); sock_in = sock_out = -1; } - cli_session(sock_in, sock_out); + cli_session(sock_in, sock_out, progress); /* not reached */ return -1; diff --git a/cli-session.c b/cli-session.c index a5ae728..c2e4863 100644 --- a/cli-session.c +++ b/cli-session.c @@ -102,15 +102,20 @@ void cli_connected(int result, int sock, void* userdata, const char *errstring) ses.sock_in = ses.sock_out = sock; } -void cli_session(int sock_in, int sock_out) { +void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress) { common_session_init(sock_in, sock_out); + if (progress) { + connect_set_writequeue(progress, &ses.writequeue); + } + chaninitialise(cli_chantypes); /* Set up cli_ses vars */ cli_session_init(); + /* Ready to go */ sessinitdone = 1; diff --git a/dbutil.c b/dbutil.c index 7b3a664..01b541c 100644 --- a/dbutil.c +++ b/dbutil.c @@ -1049,9 +1049,11 @@ static void connect_try_next(struct dropbear_progress_connection *c) { setnonblocking(c->sock); #if defined(__linux__) && defined(TCP_DEFER_ACCEPT) - set_piggyback_ack(sock); + //set_piggyback_ack(c->sock); #endif +#ifdef PROGRESS_CONNECT_FALLBACK +#if 0 if (connect(c->sock, r->ai_addr, r->ai_addrlen) < 0) { if (errno == EINPROGRESS) { TRACE(("Connect in progress")) @@ -1065,8 +1067,43 @@ static void connect_try_next(struct dropbear_progress_connection *c) { } break; /* Success. Treated the same as EINPROGRESS */ +#endif +#else + { + struct msghdr message = {0}; + int flags; + int res; + message.msg_name = r->ai_addr; + message.msg_namelen = r->ai_addrlen; + + if (c->writequeue) { + int iovlen; /* Linux msg_iovlen is a size_t */ + message.msg_iov = packet_queue_to_iovec(c->writequeue, &iovlen); + message.msg_iovlen = iovlen; + res = sendmsg(c->sock, &message, MSG_FASTOPEN); + if (res < 0 && errno == EOPNOTSUPP) { + TRACE(("Fastopen not supported")); + /* No kernel MSG_FASTOPEN support. Fall back below */ + c->writequeue = NULL; + } + } + + if (!c->writequeue) { + res = connect(c->sock, r->ai_addr, r->ai_addrlen); + } + if (res < 0 && errno != EINPROGRESS) { + err = errno; + close(c->sock); + c->sock = -1; + continue; + } else { + break; + } + } +#endif } + if (r) { c->res_iter = r->ai_next; } else { @@ -1130,9 +1167,6 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons c->res_iter = c->res; - /* Set one going */ - connect_try_next(c); - return c; } @@ -1202,3 +1236,7 @@ void handle_connect_fds(fd_set *writefd) { } TRACE(("leave handle_connect_fds - end iter")) } + +void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue) { + c->writequeue = writequeue; +} diff --git a/dbutil.h b/dbutil.h index e05b249..c82e494 100644 --- a/dbutil.h +++ b/dbutil.h @@ -28,6 +28,7 @@ #include "includes.h" #include "buffer.h" +#include "queue.h" #ifndef DISABLE_SYSLOG void startsyslog(); @@ -132,4 +133,6 @@ void handle_connect_fds(fd_set *writefd); /* Doesn't actually stop the connect, but adds a dummy callback instead */ void cancel_connect(struct dropbear_progress_connection *c); +void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue); + #endif /* _DBUTIL_H_ */ diff --git a/packet.c b/packet.c index 7b2b865..bdc3613 100644 --- a/packet.c +++ b/packet.c @@ -108,8 +108,6 @@ void write_packet() { unsigned packet_type; #ifdef HAVE_WRITEV struct iovec *iov = NULL; - int i; - struct Link *l; int iov_count; #endif diff --git a/packet.h b/packet.h index 4645b14..ac14eca 100644 --- a/packet.h +++ b/packet.h @@ -27,6 +27,7 @@ #define _PACKET_H_ #include "includes.h" +#include "queue.h" void write_packet(); void read_packet(); @@ -46,4 +47,8 @@ typedef struct PacketType { #define INIT_READBUF 128 +/* TODO: writev #ifdef guard */ +struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count); +void packet_queue_consume(struct Queue *queue, ssize_t written); + #endif /* _PACKET_H_ */ diff --git a/session.h b/session.h index 3786346..28c2cae 100644 --- a/session.h +++ b/session.h @@ -60,7 +60,7 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_N void svr_dropbear_log(int priority, const char* format, va_list param); /* Client */ -void cli_session(int sock_in, int sock_out); +void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress); void cli_connected(int result, int sock, void* userdata, const char *errstring); void cleantext(unsigned char* dirtytext);