Provide support for negotiating a stratum connection via http proxies.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
diff --git a/util.c b/util.c
index 0b33715..6c5d9c0 100644
--- a/util.c
+++ b/util.c
@@ -1719,6 +1719,70 @@ bool auth_stratum(struct pool *pool)
return ret;
}
+static int recv_byte(int sockd)
+{
+ unsigned char c;
+
+ if (recv(sockd, &c, 1, 0) != -1)
+ return c;
+
+ return -1;
+}
+
+static bool http_negotiate(struct pool *pool, int sockd, bool http0)
+{
+ char buf[1024];
+ int i, len;
+
+ if (http0) {
+ snprintf(buf, 1024, "CONNECT %s:%s HTTP/1.0\r\n\r\n",
+ pool->sockaddr_url, pool->stratum_port);
+ } else {
+ snprintf(buf, 1024, "CONNECT %s:%s HTTP/1.1\r\nHost: %s:%s\r\n\r\n",
+ pool->sockaddr_url, pool->stratum_port, pool->sockaddr_url,
+ pool->stratum_port);
+ }
+ applog(LOG_DEBUG, "Sending proxy %s:%s - %s",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port, buf);
+ send(sockd, buf, strlen(buf), 0);
+ len = recv(sockd, buf, 12, 0);
+ if (len <= 0) {
+ applog(LOG_WARNING, "Couldn't read from proxy %s:%s after sending CONNECT",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port);
+ return false;
+ }
+ buf[len] = '\0';
+ applog(LOG_DEBUG, "Received from proxy %s:%s - %s",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port, buf);
+ if (strcmp(buf, "HTTP/1.1 200") && strcmp(buf, "HTTP/1.0 200")) {
+ applog(LOG_WARNING, "HTTP Error from proxy %s:%s - %s",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port, buf);
+ return false;
+ }
+
+ /* Ignore unwanted headers till we get desired response */
+ for (i = 0; i < 4; i++) {
+ buf[i] = recv_byte(sockd);
+ if (buf[i] == -1) {
+ applog(LOG_WARNING, "Couldn't read HTTP byte from proxy %s:%s",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port);
+ return false;
+ }
+ }
+ while (strncmp(buf, "\r\n\r\n", 4)) {
+ for (i = 0; i < 3; i++)
+ buf[i] = buf[i + 1];
+ buf[3] = recv_byte(sockd);
+ if (buf[3] == -1) {
+ applog(LOG_WARNING, "Couldn't read HTTP byte from proxy %s:%s",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool setup_stratum_socket(struct pool *pool)
{
struct addrinfo servinfobase, *servinfo, *hints, pbase, *p;
@@ -1780,6 +1844,24 @@ static bool setup_stratum_socket(struct pool *pool)
}
freeaddrinfo(servinfo);
+ if (pool->rpc_proxy) {
+ switch (pool->rpc_proxytype) {
+ case CURLPROXY_HTTP_1_0:
+ if (!http_negotiate(pool, sockd, true))
+ return false;
+ break;
+ case CURLPROXY_HTTP:
+ if (!http_negotiate(pool, sockd, false))
+ return false;
+ break;
+ default:
+ applog(LOG_WARNING, "Unsupported proxy type for %s:%s",
+ pool->sockaddr_proxy_url, pool->sockaddr_proxy_port);
+ return false;
+ break;
+ }
+ }
+
if (!pool->sockbuf) {
pool->sockbuf = calloc(RBUFSIZE, 1);
if (!pool->sockbuf)