(socket utility) move ix::getFreePort to ixwebsocket library
This commit is contained in:
97
ixwebsocket/IXGetFreePort.cpp
Normal file
97
ixwebsocket/IXGetFreePort.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* IXGetFreePort.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
// Using inet_addr will trigger an error on uwp without this
|
||||
// FIXME: use a different api
|
||||
#ifdef _WIN32
|
||||
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "IXGetFreePort.h"
|
||||
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int getAnyFreePortRandom()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::uniform_int_distribution<int> dist(1024 + 1, 65535);
|
||||
|
||||
return dist(rd);
|
||||
}
|
||||
|
||||
int getAnyFreePort()
|
||||
{
|
||||
int sockfd;
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
return getAnyFreePortRandom();
|
||||
}
|
||||
|
||||
int enable = 1;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*) &enable, sizeof(enable)) < 0)
|
||||
{
|
||||
return getAnyFreePortRandom();
|
||||
}
|
||||
|
||||
// Bind to port 0. This is the standard way to get a free port.
|
||||
struct sockaddr_in server; // server address information
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(0);
|
||||
server.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if (bind(sockfd, (struct sockaddr*) &server, sizeof(server)) < 0)
|
||||
{
|
||||
Socket::closeSocket(sockfd);
|
||||
return getAnyFreePortRandom();
|
||||
}
|
||||
|
||||
struct sockaddr_in sa; // server address information
|
||||
socklen_t len = sizeof(sa);
|
||||
if (getsockname(sockfd, (struct sockaddr*) &sa, &len) < 0)
|
||||
{
|
||||
Socket::closeSocket(sockfd);
|
||||
return getAnyFreePortRandom();
|
||||
}
|
||||
|
||||
int port = ntohs(sa.sin_port);
|
||||
Socket::closeSocket(sockfd);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
int getFreePort()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
int port = getAnyFreePortRandom();
|
||||
#else
|
||||
int port = getAnyFreePort();
|
||||
#endif
|
||||
#else
|
||||
int port = getAnyFreePort();
|
||||
#endif
|
||||
//
|
||||
// Only port above 1024 can be used by non root users, but for some
|
||||
// reason I got port 7 returned with macOS when binding on port 0...
|
||||
//
|
||||
if (port > 1024)
|
||||
{
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
} // namespace ix
|
12
ixwebsocket/IXGetFreePort.h
Normal file
12
ixwebsocket/IXGetFreePort.h
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* IXGetFreePort.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int getFreePort();
|
||||
} // namespace ix
|
@ -6,4 +6,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IX_WEBSOCKET_VERSION "10.0.0"
|
||||
#define IX_WEBSOCKET_VERSION "10.0.1"
|
||||
|
Reference in New Issue
Block a user