#include <stdlib.h>
#include <assert.h>
#include <limits.h>
+#include <errno.h>
#include "putty.h"
#include "tree234.h"
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;
}
ssh_sharing_logf(cs->parent->ssh, cs->id,
"Downstream version string: %.*s",
cs->recvlen, cs->recvbuf);
+ cs->got_verstring = TRUE;
/*
* Loop round reading packets.
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