Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ add_library(AthenaZelda EXCLUDE_FROM_ALL
include/Athena/SkywardSwordQuest.hpp
)

add_library(AthenaNet
src/sockwrap.c
src/Athena/Socket.cpp
src/Athena/OAuth.cpp
src/Athena/IPAddress.cpp

include/sockwrap.h
include/Athena/Socket.hpp
include/Athena/OAuth.hpp
include/Athena/IPAddress.hpp)

# Icon
set(ATHENA_ICO ${CMAKE_CURRENT_SOURCE_DIR}/Athena.ico)

Expand Down
44 changes: 44 additions & 0 deletions include/Athena/IPAddress.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef IPADDRESS_HPP
#define IPADDRESS_HPP

#include "Athena/Global.hpp"
#include <string.h>

#include <cstring>
#include <utility>

namespace Athena
{
namespace net
{
class IPAddress
{
public:

static const IPAddress None;
static const IPAddress Any;
static const IPAddress Localhost;
static const IPAddress Broadcast;

IPAddress() : m_address(~0u), m_valid(false) {}

IPAddress(const std::string& address);

IPAddress(atUint8 a, atUint8 b, atUint8 c, atUint8 d);

IPAddress(atUint32 address);

const std::string toString() const;
const atUint32 toInt() const;

static IPAddress localAddress();
private:

atUint32 m_address;
bool m_valid;
void resolve(const std::string& address);
};
}
}

#endif
17 changes: 17 additions & 0 deletions include/Athena/OAuth.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef OAUTH_HPP
#define OAUTH_HPP

#include <Athena/Global.hpp>

namespace Athena
{
namespace net
{
class OAuth
{

};
}
}

#endif
44 changes: 44 additions & 0 deletions include/Athena/Socket.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef SOCKET_HPP
#define SOCKET_HPP

#include "Athena/Global.hpp"
#include "sockwrap.h"

namespace Athena
{
namespace net
{

class Socket
{
// Disable copying
public:
enum Type
{
TCP,
UDP
};

explicit Socket(Type type = TCP);

virtual ~Socket() { close() ; }

void setBlocking(bool blocking);
bool isBlocking() const { return m_isBlocking; }
protected:
sockhandle_t handle() { return m_handle; }
void create();
void close();
private:
// Disable copying
Socket(const Socket&)=delete;
Socket& operator=(const Socket&)=delete;
Type m_type;
sockhandle_t m_handle;
bool m_isBlocking;
};

}
}

#endif
61 changes: 61 additions & 0 deletions include/sockwrap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef SOCKWRAP_H
#define SOCKWRAP_H

#include <stdint.h>
#include <stdbool.h>

#ifdef _WIN32
#ifdef _WIN32_WINDOWS
#undef _WIN32_WINDOWS
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINDOWS 0x0501
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <ws2tcpip.h>
#include <basetsd>

typedef UINT_PTR sockhandle_t;
typedef int addrlen_t;
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

typedef int32_t sockhandle_t;
typedef socklen_t addrlen_t;
#endif

#define ANY_PORT 0

#ifdef __cplusplus
extern "C" {
#endif

// TODO: More granular errors
typedef enum
{
SS_Done,
SS_NotReady,
SS_Partial,
SS_Disconnected,
SS_Error
} sockstatus_t;

struct sockaddr_in sock_create_address(uint32_t address, uint16_t port);
void sock_close_socket(sockhandle_t sock);
void sock_set_blocking(sockhandle_t sock, bool block);
sockstatus_t sock_error_status();
sockhandle_t sock_invalid_socket();

#ifdef __cplusplus
}
#endif

#endif
107 changes: 107 additions & 0 deletions src/Athena/IPAddress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "Athena/IPAddress.hpp"
#include "sockwrap.h" // To resolve local IP

namespace Athena
{
namespace net
{
const IPAddress IPAddress::Any;
const IPAddress IPAddress::None = IPAddress( 0, 0, 0, 0);
const IPAddress IPAddress::Localhost = IPAddress(127, 0, 0, 1);
const IPAddress IPAddress::Broadcast = IPAddress(255, 255, 255, 255);

IPAddress::IPAddress(const std::string& address)
: m_valid(false)
{
resolve(address);
}

IPAddress::IPAddress(atUint8 a, atUint8 b, atUint8 c, atUint8 d)
: m_address(htonl((a << 24)| (b << 16) | (c << 8) | d)),
m_valid(true)
{
}

IPAddress::IPAddress(atUint32 address)
: m_address(htonl(address)),
m_valid(true)
{
}

const std::string IPAddress::toString() const
{
in_addr address;
address.s_addr = m_address;
return inet_ntoa(address);
}

const atUint32 IPAddress::toInt() const
{
return ntohl(m_address);
}

IPAddress IPAddress::localAddress()
{
sockhandle_t sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == sock_invalid_socket())
return IPAddress();

struct sockaddr_in address = sock_create_address(ntohl(INADDR_LOOPBACK), 9);
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(struct sockaddr_in)) == -1)
{
sock_close_socket(sock);
return IPAddress();
}

addrlen_t size = sizeof(address);
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
{
sock_close_socket(sock);
return IPAddress();
}

sock_close_socket(sock);
return IPAddress(ntohl(address.sin_addr.s_addr));
}

void IPAddress::resolve(const std::string& address)
{
if (address == "0.0.0.0")
{
m_address = 0;
m_valid = true;
}
else if(address == "255.255.255.255")
{
m_address = ~0u;
m_valid = true;
}
else
{
atUint32 ip = inet_addr(address.c_str());
if (ip == INADDR_NONE)
{
addrinfo hints;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = AF_INET;
addrinfo* result = nullptr;
if (getaddrinfo(address.c_str(), nullptr, &hints, &result) == 0)
{
if (result)
{
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
m_address = ip;
m_valid = true;
}
}
}
else
{
m_address = ip;
m_valid = true;
}
}
}
}
}
1 change: 1 addition & 0 deletions src/Athena/OAuth.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "Athena/OAuth.hpp"
71 changes: 71 additions & 0 deletions src/Athena/Socket.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "Athena/Socket.hpp"

namespace Athena
{
namespace net
{

Socket::Socket(Socket::Type type)
: m_type(type),
m_handle(sock_invalid_socket()),
m_isBlocking(true)
{}

void Socket::create()
{
if (m_handle == sock_invalid_socket())
{
m_handle = socket(PF_INET, m_type == TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
setBlocking(m_isBlocking);

int yes = 1;
if (m_type == TCP)
{
// Disable Nagle algorithm
if (setsockopt(m_handle, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(int)) == -1)
atWarning("Failed to set socket option \"TCP_NODELAY\", TCP packets will be buffered");

#ifdef __APPLE__
if (setsockopt(m_handle, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(int)) == -1)
atWarning("Failed to set socket option \"SO_NOSIGPIPE\"");
#endif
}
else
{
if (setsockopt(m_handle, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(int)) == -1)
atWarning("Failed to enable broadcast on UDP socket");
}
}
}

void Socket::close()
{
sock_close_socket(m_handle);
m_handle = sock_invalid_socket();
}

void Socket::setBlocking(bool blocking)
{
sock_set_blocking(m_handle, blocking);
}

#if _WIN32
struct WSADerpHandler
{
WSADerpHandler()
{
WSADATA init;
WSAStartup(MAKEWORD(2, 2), &init);
}

~WSADerpHandler()
{
WSACleanup();
}
};

static const WSADerpHandler __wsaderp__;
#endif

}
}
Loading