#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);
/*---------------------------------------------------------------------*/
}
/* 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;
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,
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;
*/
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. */
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);
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)
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;
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;
}