diff --git a/stratum/socket.cpp b/stratum/socket.cpp index b708f96..c829c6a 100644 --- a/stratum/socket.cpp +++ b/stratum/socket.cpp @@ -8,6 +8,48 @@ bool socket_connected(YAAMP_SOCKET *s) return s->sock > 0; } +void socket_real_ip(YAAMP_SOCKET *s) +{ + // get real ip if we are using haproxy or similar that use PROXY protocol + // https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt + int size, ret; + const char v2sig[] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"; + + do { + ret = recv(s->sock, &hdr, sizeof(hdr), MSG_PEEK); + } while (ret == -1 && errno == EINTR); + + if (ret >= (16 + ntohs(hdr.v2.len)) && + memcmp(&hdr.v2, v2sig, 12) == 0 && + ((hdr.v2.ver_cmd & 0xF0) == 0x20) && + hdr.v2.fam == 0x11) { + // we received a proxy v2 header + inet_ntop(AF_INET, &hdr.v2.addr.ip4.src_addr, s->ip, 64); + s->port = ntohs(hdr.v2.addr.ip4.src_port); + + // we need to consume the appropriate amount of data from the socket + // read the buffer without PEEK'ing so that we begin at the real data later in socket_nextjson + size = 16 + ntohs(hdr.v2.len); + do { + ret = recv(s->sock, &hdr, size, 0); + } while (ret == -1 && errno == EINTR); + return; + } + else { + // not received any proxy header + struct sockaddr_in name; + socklen_t len = sizeof(name); + memset(&name, 0, len); + + int res = getpeername(s->sock, (struct sockaddr *)&name, &len); + inet_ntop(AF_INET, &name.sin_addr, s->ip, 64); + + res = getsockname(s->sock, (struct sockaddr *)&name, &len); + s->port = ntohs(name.sin_port); + return; + } +} + YAAMP_SOCKET *socket_initialize(int sock) { YAAMP_SOCKET *s = new YAAMP_SOCKET; @@ -19,15 +61,7 @@ YAAMP_SOCKET *socket_initialize(int sock) // yaamp_create_mutex(&s->mutex); // pthread_mutex_lock(&s->mutex); - struct sockaddr_in name; - socklen_t len = sizeof(name); - memset(&name, 0, len); - - int res = getpeername(s->sock, (struct sockaddr *)&name, &len); - inet_ntop(AF_INET, &name.sin_addr, s->ip, 64); - - res = getsockname(s->sock, (struct sockaddr *)&name, &len); - s->port = ntohs(name.sin_port); + socket_real_ip(s); return s; } diff --git a/stratum/socket.h b/stratum/socket.h index c169e33..f992fa5 100644 --- a/stratum/socket.h +++ b/stratum/socket.h @@ -18,6 +18,8 @@ struct YAAMP_SOCKET bool socket_connected(YAAMP_SOCKET *s); +void socket_real_ip(YAAMP_SOCKET *s); + YAAMP_SOCKET *socket_initialize(int sock); void socket_close(YAAMP_SOCKET *s); @@ -26,3 +28,32 @@ int socket_send(YAAMP_SOCKET *s, const char *format, ...); int socket_send_raw(YAAMP_SOCKET *s, const char *buffer, int size); +static union { + struct { + char line[108]; + } v1; + struct { + uint8_t sig[12]; + uint8_t ver_cmd; + uint8_t fam; + uint16_t len; + union { + struct { /* for TCP/UDP over IPv4, len = 12 */ + uint32_t src_addr; + uint32_t dst_addr; + uint16_t src_port; + uint16_t dst_port; + } ip4; + struct { /* for TCP/UDP over IPv6, len = 36 */ + uint8_t src_addr[16]; + uint8_t dst_addr[16]; + uint16_t src_port; + uint16_t dst_port; + } ip6; + struct { /* for AF_UNIX sockets, len = 216 */ + uint8_t src_addr[108]; + uint8_t dst_addr[108]; + } unx; + } addr; + } v2; +} hdr;