From 2b89388c5c17717c98e3c044d445018e0389ed4e Mon Sep 17 00:00:00 2001
From: xjoaalm <joao.almeida@blue-tc.com>
Date: Thu, 10 Jul 2014 11:25:49 +0200
Subject: [PATCH] Patch to solve IPv4 vs IPv6 issue

Signed-off-by: Joao Pedro Almeida Pereira <joao.almeida@blue-tc.com>
---
 src/connect.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 68 insertions(+), 2 deletions(-)

diff --git a/src/connect.c b/src/connect.c
index 5ddd149..b42d18a 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <arpa/inet.h>
 
 #include "libssh/libssh.h"
 #include "libssh/misc.h"
@@ -64,12 +65,17 @@
 #include <wspiapi.h>
 #endif
 
+#define INET_NTOP InetNtop
+
 #else /* _WIN32 */
 
 #include <netdb.h>
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define INET_NTOP inet_ntop
 
 #endif /* _WIN32 */
 
@@ -306,6 +312,23 @@ socket_t ssh_connect_host(ssh_session session, const char *host,
 
 /**
  * @internal
+ * @brief The function used on connect but do not do anything
+ *
+ */
+void on_connect_do_nothing(int code, int errno_code, void *user){
+    return;
+}
+
+struct ssh_socket_callbacks_struct callbacks={
+        NULL,
+        NULL,
+        NULL,
+        on_connect_do_nothing,
+        NULL
+};
+
+/**
+ * @internal
  *
  * @brief Launches a nonblocking connect to an IPv4 or IPv6 host
  * specified by its IP address or hostname.
@@ -319,6 +342,13 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
   int rc;
   struct addrinfo *ai;
   struct addrinfo *itr;
+  ssh_socket my_socket;
+  int tm = 50;
+  const int max_retries = 100;
+  int iter = 0;
+  ssh_poll_ctx ctx;
+  struct sockaddr *sockaddr_;
+  char ipaddr_[INET6_ADDRSTRLEN];
 
   rc = getai(host, port, &ai);
   if (rc != 0) {
@@ -328,6 +358,9 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
     return -1;
   }
 
+
+
+
   for (itr = ai; itr != NULL; itr = itr->ai_next){
     /* create socket */
     s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
@@ -382,10 +415,43 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
         continue;
     }
 
-    connect(s, itr->ai_addr, itr->ai_addrlen);
-    break;
+    my_socket = ssh_socket_new(session);
+	ssh_socket_set_callbacks(my_socket, &callbacks);
+	ssh_socket_set_fd(my_socket, s);
+	ctx=ssh_poll_ctx_new(2);
+	ssh_poll_ctx_add_socket(ctx,my_socket);
+
+    do{
+        rc = connect(s, itr->ai_addr, itr->ai_addrlen);
+        if(rc == -1 && ( errno == EINPROGRESS || errno == EALREADY ) ){
+            ssh_poll_ctx_dopoll(ctx, tm);
+        }else
+            break;
+    }while(iter++ < max_retries);
+    if(rc == 0){
+		break;
+	}
+    sockaddr_ = (struct sockaddr *)itr->ai_addr;
+	switch(itr->ai_addr->sa_family){
+		case AF_INET:
+			INET_NTOP(AF_INET, &(((struct sockaddr_in *)sockaddr_)->sin_addr),
+					ipaddr_, INET_ADDRSTRLEN);
+			break;
+
+		case AF_INET6:
+			INET_NTOP(AF_INET6, &(((struct sockaddr_in6 *)sockaddr_)->sin6_addr),
+					ipaddr_, INET6_ADDRSTRLEN);
+			break;
+
+		default:
+			strncpy(ipaddr_, "Unknown AF", INET6_ADDRSTRLEN);
+	}
+	ssh_socket_free(my_socket);
+	SSH_LOG(SSH_LOG_PACKET, "Unable to connect '%s' with error '%s', tried: '%d' times, trying next address!", ipaddr_, strerror(errno), iter);
+
   }
 
+
   freeaddrinfo(ai);
 
   return s;
-- 
1.8.5.5

