ReChecker/common/netapi.cpp
2022-09-25 00:01:43 +07:00

209 lines
3.9 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include "winsock.h"
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif // _WIN32
#include "netapi.h"
class CNetAPI: public INetAPI {
public:
virtual void NetAdrToSockAddr(netadr_t *a, struct sockaddr *s);
virtual void SockAddrToNetAdr(struct sockaddr *s, netadr_t *a);
virtual char *AdrToString(netadr_t *a);
virtual bool StringToAdr(const char *s, netadr_t *a);
virtual void GetSocketAddress(int socket, netadr_t *a);
virtual bool CompareAdr(netadr_t *a, netadr_t *b);
virtual void GetLocalIP(netadr_t *a);
};
// Expose interface
CNetAPI g_NetAPI;
INetAPI *net = (INetAPI *)&g_NetAPI;
void CNetAPI::NetAdrToSockAddr(netadr_t *a, struct sockaddr *s)
{
memset(s, 0, sizeof(*s));
if (a->type == NA_BROADCAST)
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
}
else if (a->type == NA_IP)
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
((struct sockaddr_in *)s)->sin_port = a->port;
}
}
void CNetAPI::SockAddrToNetAdr(struct sockaddr *s, netadr_t *a)
{
if (s->sa_family == AF_INET)
{
a->type = NA_IP;
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port;
}
}
char *CNetAPI::AdrToString(netadr_t *a)
{
static char s[64];
memset(s, 0, sizeof(s));
if (a)
{
if (a->type == NA_LOOPBACK)
{
sprintf(s, "loopback");
}
else if (a->type == NA_IP)
{
sprintf(s, "%i.%i.%i.%i:%i", a->ip[0], a->ip[1], a->ip[2], a->ip[3], ntohs(a->port));
}
}
return s;
}
bool StringToSockaddr(const char *s, struct sockaddr *sadr)
{
struct hostent *h;
char *colon;
char copy[128];
struct sockaddr_in *p;
memset(sadr, 0, sizeof(*sadr));
p = (struct sockaddr_in *)sadr;
p->sin_family = AF_INET;
p->sin_port = 0;
strcpy(copy, s);
// strip off a trailing :port if present
for (colon = copy ; *colon ; colon++)
{
if (*colon == ':')
{
// terminate
*colon = '\0';
// Start at next character
p->sin_port = htons((short)atoi(colon + 1));
}
}
// Numeric IP, no DNS
if (copy[0] >= '0' && copy[0] <= '9' && strstr(copy, "."))
{
*(int *)&p->sin_addr = inet_addr(copy);
}
else
{
// DNS it
if (!(h = gethostbyname(copy)))
{
return false;
}
// Use first result
*(int *)&p->sin_addr = *(int *)h->h_addr_list[0];
}
return true;
}
bool CNetAPI::StringToAdr(const char *s, netadr_t *a)
{
struct sockaddr sadr;
if (!strcmp(s, "localhost"))
{
memset(a, 0, sizeof(*a));
a->type = NA_LOOPBACK;
return true;
}
if (!StringToSockaddr(s, &sadr))
{
return false;
}
SockAddrToNetAdr(&sadr, a);
return true;
}
// Lookup the IP address for the specified IP socket
void CNetAPI::GetSocketAddress(int socket, netadr_t *a)
{
char buff[512];
struct sockaddr_in address;
int namelen;
memset(a, 0, sizeof(*a));
gethostname(buff, sizeof(buff));
// Ensure that it doesn't overrun the buffer
buff[sizeof buff - 1] = '\0';
StringToAdr(buff, a);
namelen = sizeof(address);
if (getsockname(socket, (struct sockaddr *)&address, (int *)&namelen) == 0)
{
a->port = address.sin_port;
}
}
bool CNetAPI::CompareAdr(netadr_t *a, netadr_t *b)
{
if (a->type != b->type)
{
return false;
}
if (a->type == NA_LOOPBACK)
{
return true;
}
if (a->type == NA_IP &&
a->ip[0] == b->ip[0] &&
a->ip[1] == b->ip[1] &&
a->ip[2] == b->ip[2] &&
a->ip[3] == b->ip[3] &&
a->port == b->port)
{
return true;
}
return false;
}
void CNetAPI::GetLocalIP(netadr_t *a)
{
char s[64];
if(!::gethostname(s, 64))
{
struct hostent *localip = ::gethostbyname(s);
if(localip)
{
a->type = NA_IP;
a->port = 0;
memcpy(a->ip, localip->h_addr_list[0], 4);
}
}
}