Merge pull request #338 from svost/c++11
[novacoin.git] / src / stun.cpp
index 30da395..4a34a8c 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-#ifdef WIN32
-#include <winsock2.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
 #ifndef WIN32
 #include <unistd.h>
 #endif
 #include <errno.h>
 
 #include "ministun.h"
+#include "netbase.h"
+
+using namespace std;
 
-extern int GetRandInt(int nMax);
 extern uint64_t GetRand(uint64_t nMax);
+extern void FillRand(uint8_t *buffer, size_t nCount);
 
 /*---------------------------------------------------------------------*/
 
@@ -338,14 +333,11 @@ static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
 }
 
 /* helper function to generate a random request id */
-static uint64_t randfiller = GetRand(std::numeric_limits<uint64_t>::max());
+static uint64_t randfiller = GetRand(numeric_limits<uint64_t>::max());
 static void stun_req_id(struct stun_header *req)
 {
-    const uint64_t *S_block = (const uint64_t *)StunSrvList;
-    req->id.id[0] = GetRandInt(std::numeric_limits<int32_t>::max());
-    req->id.id[1] = GetRandInt(std::numeric_limits<int32_t>::max());
-    req->id.id[2] = GetRandInt(std::numeric_limits<int32_t>::max());
-    req->id.id[3] = GetRandInt(std::numeric_limits<int32_t>::max());
+    auto S_block = (const uint64_t *)StunSrvList;
+    FillRand((uint8_t*)&req->id.id[0], sizeof(req->id.id));
 
     req->id.id[0] |= 0x55555555;
     req->id.id[1] &= 0x55555555;
@@ -374,10 +366,9 @@ typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
 static int stun_handle_packet(int s, struct sockaddr_in *src,
                               unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
 {
-    struct stun_header *hdr = (struct stun_header *)data;
+    auto hdr = (struct stun_header *)data;
     struct stun_attr *attr;
     int ret = len;
-    unsigned int x;
 
     /* On entry, 'len' is the length of the udp payload. After the
    * initial checks it becomes the size of unprocessed options,
@@ -388,7 +379,7 @@ static int stun_handle_packet(int s, struct sockaddr_in *src,
 
     len -= sizeof(struct stun_header);
     data += sizeof(struct stun_header);
-    x = ntohs(hdr->msglen); /* len as advertised in the message */
+    uint32_t x = ntohs(hdr->msglen); /* len as advertised in the message */
     if(x < len)
         len = x;
 
@@ -437,8 +428,8 @@ static int stun_handle_packet(int s, struct sockaddr_in *src,
  */
 static int stun_get_mapped(struct stun_attr *attr, void *arg)
 {
-    struct stun_addr *addr = (struct stun_addr *)(attr + 1);
-    struct sockaddr_in *sa = (struct sockaddr_in *)arg;
+    auto addr = (struct stun_addr *)(attr + 1);
+    auto sa = (struct sockaddr_in *)arg;
 
     if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
         return 1; /* not us. */
@@ -456,7 +447,7 @@ static int StunRequest2(int sock, struct sockaddr_in *server, struct sockaddr_in
 
     req = (struct stun_header *)reqdata;
     stun_req_id(req);
-    int reqlen = 0;
+    unsigned short reqlen = 0;
     req->msgtype = 0;
     req->msglen = 0;
     req->msglen = htons(reqlen);
@@ -465,12 +456,6 @@ static int StunRequest2(int sock, struct sockaddr_in *server, struct sockaddr_in
     unsigned char reply_buf[1024];
     fd_set rfds;
     struct timeval to = { STUN_TIMEOUT, 0 };
-    struct sockaddr_in src;
-#ifdef WIN32
-    int srclen;
-#else
-    socklen_t srclen;
-#endif
 
     int res = stun_send(sock, server, req);
     if(res < 0)
@@ -480,56 +465,45 @@ static int StunRequest2(int sock, struct sockaddr_in *server, struct sockaddr_in
     res = select(sock + 1, &rfds, NULL, NULL, &to);
     if (res <= 0)  /* timeout or error */
         return -11;
-    memset(&src, 0, sizeof(src));
-    srclen = sizeof(src);
-    /* XXX pass -1 in the size, because stun_handle_packet might
-   * write past the end of the buffer.
-   */
+    struct sockaddr_in src = {};
+    socklen_t srclen = sizeof(src);
+
+    // XXX pass -1 in the size, because stun_handle_packet might
+    // write past the end of the buffer.
     res = recvfrom(sock, (char *)reply_buf, sizeof(reply_buf) - 1,
                    0, (struct sockaddr *)&src, &srclen);
     if (res <= 0)
         return -12;
-    memset(mapped, 0, sizeof(struct sockaddr_in));
     return stun_handle_packet(sock, &src, reply_buf, res, stun_get_mapped, mapped);
 } // StunRequest2
 
-/*---------------------------------------------------------------------*/
 static int StunRequest(const char *host, uint16_t port, struct sockaddr_in *mapped) {
     struct hostent *hostinfo = gethostbyname(host);
-    if(hostinfo == NULL)
+    if (hostinfo == NULL)
         return -1;
 
-    struct sockaddr_in server, client;
-    memset(&server, 0, sizeof(server));
-    memset(&client, 0, sizeof(client));
-    server.sin_family = client.sin_family = AF_INET;
+    SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (sock == INVALID_SOCKET)
+        return -2;
+
+    struct sockaddr_in server = {}, client = {};
 
+    server.sin_family = client.sin_family = AF_INET;
     server.sin_addr = *(struct in_addr*) hostinfo->h_addr;
     server.sin_port = htons(port);
-
-    int sock = socket(AF_INET, SOCK_DGRAM, 0);
-    if(sock < 0)
-        return -2;
-
     client.sin_addr.s_addr = htonl(INADDR_ANY);
 
     int rc = -3;
-    if(bind(sock, (struct sockaddr*)&client, sizeof(client)) >= 0)
+    if (::bind(sock, (struct sockaddr*)&client, sizeof(client)) != SOCKET_ERROR)
         rc = StunRequest2(sock, &server, mapped);
-#ifndef WIN32
-    close(sock);
-#else
-    closesocket(sock);
-#endif
+    CloseSocket(sock);
     return rc;
 } // StunRequest
 
-/*---------------------------------------------------------------------*/
 // Input: two random values (pos, step) for generate uniuqe way over server
 // list
 // Output: populate struct struct mapped
 // Retval:
-
 int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv) {
     randfiller    = rnd;
     uint16_t pos  = rnd;
@@ -539,14 +513,11 @@ int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **s
         step = rnd % StunSrvListQty;
     } while(step == 0);
 
-    uint16_t attempt;
-    for(attempt = 1; attempt < StunSrvListQty * 2; attempt++) {
+    for(uint16_t attempt = 1; attempt < StunSrvListQty * 2; attempt++) {
         pos = (pos + step) % StunSrvListQty;
         int rc = StunRequest(*srv = StunSrvList[pos].name, StunSrvList[pos].port, mapped);
         if(rc >= 0)
             return attempt;
-        // fprintf(stderr, "Lookup: %s:%u\t%s\t%d\n", StunSrvList[pos].name,
-        // StunSrvList[pos].port, inet_ntoa(mapped->sin_addr), rc);
     }
     return -1;
 }