]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - sshshare.c
first pass
[PuTTY.git] / sshshare.c
index 873f3581878ce0878256bbef9e5d98014d6aa139..82c4bd31ed8867755fcad1b467356450c3df5410 100644 (file)
 #include <stdlib.h>
 #include <assert.h>
 #include <limits.h>
+#include <errno.h>
 
 #include "putty.h"
 #include "tree234.h"
@@ -914,8 +915,25 @@ static int share_closing(Plug plug, const char *error_msg, int error_code,
                          int calling_back)
 {
     struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
-    if (error_msg)
-        ssh_sharing_logf(cs->parent->ssh, cs->id, "%s", error_msg);
+
+    if (error_msg) {
+#ifdef BROKEN_PIPE_ERROR_CODE
+        /*
+         * Most of the time, we log what went wrong when a downstream
+         * disappears with a socket error. One exception, though, is
+         * receiving EPIPE when we haven't received a protocol version
+         * string from the downstream, because that can happen as a result
+         * of plink -shareexists (opening the connection and instantly
+         * closing it again without bothering to read our version string).
+         * So that one case is not treated as a log-worthy error.
+         */
+        if (error_code == BROKEN_PIPE_ERROR_CODE && !cs->got_verstring)
+            /* do nothing */;
+        else
+#endif
+            ssh_sharing_logf(cs->parent->ssh, cs->id,
+                             "Socket error: %s", error_msg);
+    }
     share_begin_cleanup(cs);
     return 1;
 }
@@ -1810,6 +1828,7 @@ static int share_receive(Plug plug, int urgent, char *data, int len)
     ssh_sharing_logf(cs->parent->ssh, cs->id,
                      "Downstream version string: %.*s",
                      cs->recvlen, cs->recvbuf);
+    cs->got_verstring = TRUE;
 
     /*
      * Loop round reading packets.
@@ -2026,6 +2045,55 @@ char *ssh_share_sockname(const char *host, int port, Conf *conf)
     return sockname;
 }
 
+static void nullplug_socket_log(Plug plug, int type, SockAddr addr, int port,
+                                const char *error_msg, int error_code) {}
+static int nullplug_closing(Plug plug, const char *error_msg, int error_code,
+                            int calling_back) { return 0; }
+static int nullplug_receive(Plug plug, int urgent, char *data,
+                            int len) { return 0; }
+static void nullplug_sent(Plug plug, int bufsize) {}
+
+int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
+{
+    static const struct plug_function_table fn_table = {
+       nullplug_socket_log,
+       nullplug_closing,
+       nullplug_receive,
+       nullplug_sent,
+       NULL
+    };
+    struct nullplug {
+        const struct plug_function_table *fn;
+    } np;
+
+    char *sockname, *logtext, *ds_err, *us_err;
+    int result;
+    Socket sock;
+
+    np.fn = &fn_table;
+
+    sockname = ssh_share_sockname(host, port, conf);
+
+    sock = NULL;
+    logtext = ds_err = us_err = NULL;
+    result = platform_ssh_share(sockname, conf, (Plug)&np, (Plug)NULL, &sock,
+                                &logtext, &ds_err, &us_err, FALSE, TRUE);
+
+    sfree(logtext);
+    sfree(ds_err);
+    sfree(us_err);
+    sfree(sockname);
+
+    if (result == SHARE_NONE) {
+        assert(sock == NULL);
+        return FALSE;
+    } else {
+        assert(result == SHARE_DOWNSTREAM);
+        sk_close(sock);
+        return TRUE;
+    }
+}
+
 /*
  * Init function for connection sharing. We either open a listening
  * socket and become an upstream, or connect to an existing one and