Skip to content

Commit

Permalink
allow ipv4 and 6 connections
Browse files Browse the repository at this point in the history
  • Loading branch information
andy5995 committed Aug 15, 2022
1 parent e63d814 commit c20ff46
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 62 deletions.
2 changes: 2 additions & 0 deletions source/shared_lib/include/platform/posix/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ class Socket {

static int getBroadCastPort() { return broadcast_portno; }
static void setBroadCastPort(int value) { broadcast_portno = value; }
static int getIpStr(struct addrinfo *ptr, char *buf);
struct addrinfo *getAddrInfo(const int port);
static std::vector<std::string> getLocalIPAddressList();

// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
Expand Down
179 changes: 117 additions & 62 deletions source/shared_lib/sources/platform/posix/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ string getNetworkInterfaceBroadcastAddress(string ipAddress)
//printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
if(strcmp(ifaAddrStr,ipAddress.c_str()) == 0) {
broadCastAddress = dstAddrStr;
}
}
}

if(pAdapterInfo) free(pAdapterInfo);
Expand All @@ -661,44 +661,103 @@ string getNetworkInterfaceBroadcastAddress(string ipAddress)
return broadCastAddress;
}

int Socket::getIpStr(struct addrinfo *ptr, char *buf) {
void *addr;
if (ptr->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *) ptr->ai_addr;
addr = &(ipv4->sin_addr);
}
else {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
addr = &(ipv6->sin6_addr);
}

if (inet_ntop(ptr->ai_family, addr, buf, INET6_ADDRSTRLEN) == NULL) {
perror("inet_ntop:");
return -1;
}

return 0;
}

uint32 Socket::getConnectedIPAddress(string IP) {
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
unsigned char addr[sizeof(struct in6_addr)];
if(IP == "") {
IP = connectedIpAddress;
}
int r = inet_pton(AF_INET, IP.c_str(), addr);
if (r != 0) {
// handle error
}
return SockAddrToUint32((struct in_addr *)&addr);;
}

addr.sin_family= AF_INET;
if(IP == "") {
IP = connectedIpAddress;
}
addr.sin_addr.s_addr= inet_addr(IP.c_str());
//addr.sin_port= htons(port);
// TODO: This may be too inefficient because it's called multiple
// times. It may be adequate to store 'result' and reuse it later. Note
// that the 4th argument ('&result) of getaddrinfo() is normally
// malloc'ed and needs to be freed later with freeaddrinfo(). One way to
// work around that may be to declare it statically.
//
// Returns a pointer to a memory-allocated addrinfo struct which must
// be freed later with freeaddrinfo()
struct addrinfo *Socket::getAddrInfo(const int port) {
struct addrinfo hints, *result;

/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
hints.ai_protocol = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;

char strPort[BUFSIZ];
size_t n = snprintf (strPort, sizeof strPort, "%d", port);
if (n > sizeof strPort) {
fprintf (stderr, "strPort truncated. This should not happen.");
throw megaglest_runtime_error(strPort);
}

char myhostname[HOST_NAME_MAX]="";
int r=gethostname(myhostname,HOST_NAME_MAX);
if (r != 0) {
fputs("gethostname failed.", stderr);
throw megaglest_runtime_error(myhostname);
}

int s = getaddrinfo(myhostname, strPort, &hints, &result);
if (s != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
throw megaglest_runtime_error(myhostname);
}

return SockAddrToUint32((struct sockaddr *)&addr);
return result;
}

std::vector<std::string> Socket::getLocalIPAddressList() {
std::vector<std::string>Socket::getLocalIPAddressList() {
std::vector<std::string> ipList;
/* get my host name */
char myhostname[101]="";
gethostname(myhostname,100);

struct hostent* myhostent = gethostbyname(myhostname);
if(myhostent) {
// get all host IP addresses (Except for loopback)
char myhostaddr[101] = "";
for(int ipIdx = 0; myhostent->h_addr_list[ipIdx] != NULL; ++ipIdx) {
Ip::Inet_NtoA(SockAddrToUint32((struct in_addr *)myhostent->h_addr_list[ipIdx]), myhostaddr);

//printf("ipIdx = %d [%s]\n",ipIdx,myhostaddr);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] myhostaddr = [%s]\n",__FILE__,__FUNCTION__,__LINE__,myhostaddr);

if(strlen(myhostaddr) > 0 &&
strncmp(myhostaddr,"127.",4) != 0 &&
strncmp(myhostaddr,"0.",2) != 0) {
ipList.push_back(myhostaddr);
}
Socket tmp;
struct addrinfo *result = tmp.getAddrInfo(61357);
char ipStr[INET6_ADDRSTRLEN];
struct addrinfo *ptr = result;

for (ptr; ptr != NULL; ptr = ptr->ai_next)
{
if (tmp.getIpStr(ptr, ipStr) != 0)
throw megaglest_runtime_error("getLocalIPAddressList");

if(strlen(ipStr) > 0 &&
strncmp(ipStr,"127.",4) != 0 &&
strncmp(ipStr,"0.",2) != 0) {
ipList.push_back(ipStr);
}
}

freeaddrinfo(result);

Socket::getLocalIPAddressListForPlatform(ipList);
return ipList;
}
Expand Down Expand Up @@ -905,7 +964,7 @@ Socket::Socket() {

this->connectedIpAddress = "";

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(isSocketValid() == false) {
throwException("Error creating socket");
}
Expand Down Expand Up @@ -1381,7 +1440,7 @@ int Socket::send(const void *data, int dataSize) {
int totalBytesSent = bytesSent;
int attemptCount = 0;


time_t tStartTimer = time(NULL);
while(((bytesSent > 0 && totalBytesSent < dataSize) ||
(bytesSent < 0 && lastSocketError == PLATFORM_SOCKET_TRY_AGAIN)) &&
Expand Down Expand Up @@ -2392,49 +2451,45 @@ bool ServerSocket::isBroadCastThreadRunning() {

void ServerSocket::bind(int port) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d port = %d, portBound = %d START\n",__FILE__,__FUNCTION__,__LINE__,port,portBound);

boundPort = port;

if(isSocketValid() == false) {
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(isSocketValid() == false) {
throwException("Error creating socket");
}
setBlock(false);
}
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_flowinfo = 0;
addr.sin6_port=htons(boundPort);
addr.sin6_addr = in6addr_any;

//sockaddr structure
sockaddr_in addr;
addr.sin_family= AF_INET;
if(this->bindSpecificAddress != "") {
addr.sin_addr.s_addr= inet_addr(this->bindSpecificAddress.c_str());
sock = socket(addr.sin6_family, SOCK_STREAM, 0);
if(sock == -1) {
throw megaglest_runtime_error("socket failed");
}
else {
addr.sin_addr.s_addr= INADDR_ANY;
}
addr.sin_port= htons(port);
addr.sin_zero[0] = 0;

setBlock(false);
int val = 1;

#ifndef WIN32
int opt_result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
int opt_result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
#else
int opt_result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
int opt_result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
#endif

int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if(err < 0) {
char szBuf[8096]="";
snprintf(szBuf, 8096,"In [%s::%s] Error binding socket sock = " PLATFORM_SOCKET_FORMAT_TYPE ", address [%s] port = %d err = %d, error = %s opt_result = %d\n",__FILE__,__FUNCTION__,sock,this->bindSpecificAddress.c_str(),port,err,getLastSocketErrorFormattedText().c_str(),opt_result);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"%s",szBuf);
//char ipStr[INET6_ADDRSTRLEN];
//if (Socket::getIpStr(ptr, ipStr) != 0) {
//throw megaglest_runtime_error("");
//}

//printf("Binding to %s:%d...", ipStr, boundPort);

snprintf(szBuf, 8096,"Error binding socket sock = " PLATFORM_SOCKET_FORMAT_TYPE ", address [%s] port = %d err = %d, error = %s\n",sock,this->bindSpecificAddress.c_str(),port,err,getLastSocketErrorFormattedText().c_str());
throw megaglest_runtime_error(szBuf);
if ((::bind (sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6))) < 0) {
puts("fail");
perror("bind");
close(sock);
exit(EXIT_FAILURE);
}
portBound = true;
puts("ok");

if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d port = %d, portBound = %d END\n",__FILE__,__FUNCTION__,__LINE__,port,portBound);
portBound = true;
}

void ServerSocket::disconnectSocket() {
Expand All @@ -2449,7 +2504,7 @@ void ServerSocket::listen(int connectionQueueSize) {
if(isSocketValid() == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(isSocketValid() == false) {
throwException("Error creating socket");
}
Expand Down

0 comments on commit c20ff46

Please sign in to comment.