Initial commit
This commit is contained in:
292
libsst-net/SST_NetAddress.c
Normal file
292
libsst-net/SST_NetAddress.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
SST_NetAddress.h
|
||||
Author: Patrick Baggett <ptbaggett@762studios.com>
|
||||
Created: 8/7/2012
|
||||
|
||||
Purpose:
|
||||
|
||||
Address storage manipulation
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#include "PlatformPrivate.h"
|
||||
#include <SST/SST_NetAddress.h>
|
||||
#include <string.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_NetResult SST_Net_InitAddress(SST_NetAddress* addr, SST_NetAddressFamily family, unsigned short port)
|
||||
{
|
||||
unsigned short nboPort; /* Port in network byte order */
|
||||
size_t addrSize;
|
||||
uint8_t* asBytes = (uint8_t*)addr;
|
||||
|
||||
nboPort = htons(port);
|
||||
|
||||
/* Avoid strict aliasing violations by setting up a temporary structure and memcpy()ing. */
|
||||
|
||||
switch(family)
|
||||
{
|
||||
case SSTNETADDRFAM_IPV4:
|
||||
{
|
||||
struct sockaddr_in addr4;
|
||||
|
||||
addr4.sin_family = AF_INET;
|
||||
addr4.sin_port = nboPort;
|
||||
addr4.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&addr4.sin_zero, 0, sizeof(addr4.sin_zero));
|
||||
|
||||
addrSize = sizeof(struct sockaddr_in);
|
||||
memcpy(addr, &addr4, addrSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case SSTNETADDRFAM_IPV6:
|
||||
{
|
||||
struct sockaddr_in6 addr6;
|
||||
|
||||
addr6.sin6_family = AF_INET;
|
||||
addr6.sin6_port = nboPort;
|
||||
addr6.sin6_flowinfo = 0;
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
addr6.sin6_scope_id = 0;
|
||||
|
||||
addrSize = sizeof(struct sockaddr_in6);
|
||||
memcpy(addr, &addr6, addrSize);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Default: return error */
|
||||
default:
|
||||
return SSTNETRESULT_ADDRFAMNOTSUPPORTED;
|
||||
}
|
||||
|
||||
/* memset() the rest of the address storage to all-bits-zero. */
|
||||
memset(asBytes + addrSize, 0, sizeof(SST_NetAddress) - addrSize);
|
||||
|
||||
return SSTNETRESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_NetAddressFamily SST_Net_GetAddressFamily(const SST_NetAddress* addr)
|
||||
{
|
||||
switch(addr->ss_family)
|
||||
{
|
||||
case AF_INET: return SSTNETADDRFAM_IPV4;
|
||||
case AF_INET6: return SSTNETADDRFAM_IPV6;
|
||||
default: return SSTNETADDRFAM_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
unsigned short SST_Net_GetAddressPort(const SST_NetAddress* addr)
|
||||
{
|
||||
|
||||
switch(addr->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
const struct sockaddr_in* addr4 = (const struct sockaddr_in*)addr;
|
||||
|
||||
return ntohs(addr4->sin_port);
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)addr;
|
||||
|
||||
return ntohs(addr6->sin6_port);
|
||||
}
|
||||
|
||||
default: return UINT16_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Net_AddressCompare(const SST_NetAddress* addr1, const SST_NetAddress* addr2)
|
||||
{
|
||||
|
||||
if(addr1->ss_family != addr2->ss_family)
|
||||
return (addr1->ss_family < addr2->ss_family ? -1 : 1);
|
||||
|
||||
switch(addr1->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
const struct sockaddr_in* A = (const struct sockaddr_in*)addr1;
|
||||
const struct sockaddr_in* B = (const struct sockaddr_in*)addr2;
|
||||
|
||||
/* Are the addresses different? */
|
||||
if(A->sin_addr.s_addr != B->sin_addr.s_addr)
|
||||
return (A->sin_addr.s_addr < B->sin_addr.s_addr ? -1 : 1);
|
||||
|
||||
/* Are the ports different? */
|
||||
if(A->sin_port != B->sin_port)
|
||||
return (A->sin_port < B->sin_port ? -1 : 1);
|
||||
|
||||
/* Address/port are the same, so OK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
const struct sockaddr_in6* A = (const struct sockaddr_in6*)addr1;
|
||||
const struct sockaddr_in6* B = (const struct sockaddr_in6*)addr2;
|
||||
int result;
|
||||
|
||||
result = memcmp(&A->sin6_addr, &B->sin6_addr, sizeof(struct in6_addr));
|
||||
|
||||
/* Are the addresses different? */
|
||||
if(result != 0)
|
||||
return result;
|
||||
|
||||
/* Are the ports different? */
|
||||
if(A->sin6_port != B->sin6_port)
|
||||
return (A->sin6_port < B->sin6_port ? -1 : 1);
|
||||
|
||||
/* Address/port are the same, so OK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Undefined structure -> useless result */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
int SST_Net_AddressIsLocalhost(const SST_NetAddress* addr)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
switch(addr->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in* addr4 = (struct sockaddr_in*)addr;
|
||||
|
||||
uint32_t localhost = (uint32_t)inet_addr("127.0.0.1");
|
||||
uint32_t myaddr = (uint32_t)addr4->sin_addr.s_addr;
|
||||
|
||||
/* Compare address to loopback */
|
||||
retval = (myaddr == localhost);
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)addr;
|
||||
|
||||
/* Compare address to loopback */
|
||||
retval = (memcmp(&addr6->sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback)) == 0);
|
||||
}
|
||||
|
||||
default: retval = -1; /* Error code*/
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
void SST_Net_AddressSetToLocalhost(SST_NetAddress* addr)
|
||||
{
|
||||
switch(addr->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in* addr4 = (struct sockaddr_in*)addr;
|
||||
|
||||
addr4->sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)addr;
|
||||
|
||||
addr6->sin6_addr = in6addr_loopback;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_NetResult SST_Net_SetAddressFromAddress(SST_NetAddress* dst, const SST_NetAddress* src)
|
||||
{
|
||||
switch(src->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in* dstAddr = (struct sockaddr_in*)dst;
|
||||
const struct sockaddr_in* srcAddr = (const struct sockaddr_in*)src;
|
||||
|
||||
memcpy(&dstAddr->sin_addr, &srcAddr->sin_addr, sizeof(struct in_addr));
|
||||
break;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6* dstAddr = (struct sockaddr_in6*)dst;
|
||||
const struct sockaddr_in6* srcAddr = (const struct sockaddr_in6*)src;
|
||||
|
||||
memcpy(&dstAddr->sin6_addr, &srcAddr->sin6_addr, sizeof(struct in6_addr));
|
||||
break;
|
||||
}
|
||||
/* Default: return error */
|
||||
default:
|
||||
return SSTNETRESULT_ADDRFAMNOTSUPPORTED;
|
||||
}
|
||||
|
||||
return SSTNETRESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
SST_NetResult SST_Net_SetAddressFromString(SST_NetAddress* addr, const char* addrString)
|
||||
{
|
||||
int result;
|
||||
char buf[sizeof(SST_NetAddress)];
|
||||
result = inet_pton(addr->ss_family, addrString, buf);
|
||||
|
||||
if(result > 0)
|
||||
{
|
||||
switch(addr->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in* dst = (struct sockaddr_in*)addr;
|
||||
|
||||
memcpy(&dst->sin_addr, buf, sizeof(dst->sin_addr));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6* dst = (struct sockaddr_in6*)addr;
|
||||
|
||||
memcpy(&dst->sin6_addr, buf, sizeof(dst->sin6_addr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SSTNETRESULT_SUCCESS;
|
||||
}
|
||||
else if(result == 0)
|
||||
return SSTNETRESULT_BADADDRESSSTRING;
|
||||
|
||||
//Other error
|
||||
return NativeDecodeError();
|
||||
}
|
||||
Reference in New Issue
Block a user