diff --git a/Makefile.am b/Makefile.am
index c92b79e9..20c12607 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -64,6 +64,14 @@ UTIL_FILES = \
matrix.hpp \
memory.cpp \
memory.hpp \
+ net/address.cpp \
+ net/address.hpp \
+ net/except.cpp \
+ net/except.hpp \
+ net/types.cpp \
+ net/types.hpp \
+ net/socket.cpp \
+ net/socket.hpp \
nocopy.hpp \
noise.cpp \
noise.hpp \
diff --git a/net/address.cpp b/net/address.cpp
new file mode 100644
index 00000000..67f644c6
--- /dev/null
+++ b/net/address.cpp
@@ -0,0 +1,139 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#include "address.hpp"
+
+#include "except.hpp"
+#include "../debug.hpp"
+#include "../endian.hpp"
+#include "../types.hpp"
+
+#ifdef __WIN32
+#else
+ #include
+#endif
+
+//-----------------------------------------------------------------------------
+using namespace net;
+using namespace std;
+
+
+//-----------------------------------------------------------------------------
+#ifdef __WIN32
+const char* inet_ntop(int af, const void* src, char* dst, int size){
+ struct sockaddr_in srcaddr;
+ memset(&srcaddr, 0, sizeof(struct sockaddr_in));
+ memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
+ srcaddr.sin_family = af;
+
+ if (WSAAddressToString ((struct sockaddr*) &srcaddr, sizeof (struct sockaddr_in), 0, dst, (LPDWORD) &size) != 0)
+ net::error::throw_code ();
+
+ return dst;
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+namespace net {
+ template <>
+ address::address (const sockaddr_type &addr):
+ m_ip (addr.sin_addr.s_addr),
+ m_mask (0),
+ m_port (ntoh (addr.sin_port))
+ {
+ CHECK (addr.sin_family == (int)domain::INET);
+ }
+
+
+ template
+ address::address (const std::string &_ip,
+ port_type _port):
+ m_ip (_ip),
+ m_mask ( 0),
+ m_port (_port)
+ { ; }
+
+
+ template <>
+ address::sockaddr_type
+ address::to_sockaddr (void) const {
+ sockaddr_type addr;
+
+ addr.sin_family = (int)domain::INET;
+ addr.sin_port = hton (m_port);
+ addr.sin_addr.s_addr = m_ip.m_integer;
+
+ return addr;
+ }
+
+
+ template <>
+ std::string
+ address::to_string (void) const {
+ char dest[INET_ADDRSTRLEN + 1];
+ sockaddr_type addr = to_sockaddr ();
+
+ if (NULL == inet_ntop ((int)domain::INET, &addr.sin_addr, dest, sizeof (dest)))
+ net::error::throw_code ();
+ return dest;
+ }
+
+
+ template <>
+ bool
+ address::operator ==(const address &rhs) {
+ return m_ip == rhs.m_ip &&
+ m_mask == rhs.m_mask &&
+ m_port == rhs.m_port;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+std::ostream&
+net::operator<< (std::ostream &os, const address &addr) {
+ os << addr.to_string () << ":" << addr.port ();
+ return os;
+}
+
+
+//-----------------------------------------------------------------------------
+template <>
+const address
+address::LOOPBACK ("127.0.0.1", 0);
+
+
+template <>
+const address
+address::ANY ("0.0.0.0", 0);
+
+
+template <>
+const address
+address::LOOPBACK ("::1", 0);
+
+
+template <>
+const address
+address::ANY ("::0", 0);
+
+template class address;
+template class address;
+
diff --git a/net/address.hpp b/net/address.hpp
new file mode 100644
index 00000000..0cd4569c
--- /dev/null
+++ b/net/address.hpp
@@ -0,0 +1,109 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#ifndef __NET_ADDRESS_HPP
+#define __NET_ADDRESS_HPP
+
+#include "types.hpp"
+#include "../ip.hpp"
+
+#if defined(HAVE_WINSOCK2_H)
+ #include "ws2tcpip.h"
+#endif
+
+#include
+#include
+
+
+//-----------------------------------------------------------------------------
+namespace net {
+ /// Supporting types used for defining addresses in various domains
+ template
+ struct address_types;
+
+
+ template <>
+ struct address_types {
+ typedef ipv4::ip ip;
+ typedef ipv4::mask mask;
+ typedef ipv4::port port;
+ typedef sockaddr_in sockaddr;
+ };
+
+
+ template <>
+ struct address_types {
+ typedef ipv6::ip ip;
+ typedef ipv6::mask mask;
+ typedef ipv6::port port;
+ typedef sockaddr_in6 sockaddr;
+ };
+
+
+ /// A full endpoint specification for a domain. Must be usable for bind/listen and send/recv.
+ template
+ class address {
+ public:
+ typedef typename address_types::ip ip_type;
+ typedef typename address_types::mask mask_type;
+ typedef typename address_types::port port_type;
+ typedef typename address_types::sockaddr sockaddr_type;
+
+ protected:
+ ip_type m_ip;
+ mask_type m_mask;
+ port_type m_port;
+
+ public:
+ static const address LOOPBACK;
+ static const address ANY;
+
+ address (const sockaddr_type &);
+ address (const std::string&,
+ port_type);
+
+ port_type
+ port (void) const
+ { return m_port; }
+
+ void
+ set_port (const port_type &_port)
+ { m_port = _port; }
+
+ ip_type
+ ip (void) const
+ { return m_ip; }
+
+ sockaddr_type
+ to_sockaddr (void) const;
+
+ std::string
+ to_string (void) const;
+
+ bool operator ==(const address &rhs);
+ };
+
+ std::ostream&
+ operator<< (std::ostream &os, const net::address &addr);
+}
+
+
+
+#endif // __NET_ADDRESS_HPP
+
diff --git a/net/except.cpp b/net/except.cpp
new file mode 100644
index 00000000..398389d2
--- /dev/null
+++ b/net/except.cpp
@@ -0,0 +1,119 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#include "except.hpp"
+
+#include "../debug.hpp"
+
+
+//-----------------------------------------------------------------------------
+using namespace std;
+using namespace net;
+
+
+//-----------------------------------------------------------------------------
+net::error::error (const std::string &_what):
+ runtime_error (_what)
+{ ; }
+
+
+net::error::error (int _code):
+ runtime_error (strerror (_code))
+{ CHECK (_code != 0); }
+
+
+std::string
+net::error::code_to_string (int code) {
+#ifdef __WIN32
+ char message[256];
+ int output = FormatMessage (0, NULL, code, 0, message, sizeof (message), NULL);
+ CHECK_HARD (output != 0);
+
+ return std::string (message);
+#else
+ return strerror (code);
+#endif
+}
+
+
+void
+net::error::throw_code (int code) {
+#ifdef __WIN32
+ throw net::error (code);
+#else
+
+ CHECK (code != 0);
+ switch (code) {
+#define ERROR_CODE(c) \
+ case c: \
+ throw net::error_code (); \
+ break;
+
+ ERROR_CODE(ECONNREFUSED);
+ ERROR_CODE(ECONNRESET);
+ ERROR_CODE(EINVAL);
+ ERROR_CODE(ENOTCONN);
+
+ default:
+ unreachable ();
+#undef ERROR_CODE
+ }
+#endif
+}
+
+
+void
+net::error::try_code (int err) {
+ if (err == 0)
+ return;
+
+ throw_code (err);
+}
+
+
+void
+net::error::try_code (void)
+ { try_code (last_code ()); }
+
+
+void
+net::error::throw_code (void)
+ { throw_code (last_code ()); }
+
+
+int
+net::error::last_code (void) {
+#ifdef __WIN32
+ return WSAGetLastError ();
+#else
+ return errno;
+#endif
+}
+
+
+template
+net::error_code::error_code (void):
+ net::error (CODE)
+{ ; }
+
+
+template
+int
+net::error_code::code (void) const
+ { return CODE; }
diff --git a/net/except.hpp b/net/except.hpp
new file mode 100644
index 00000000..a5bafcaf
--- /dev/null
+++ b/net/except.hpp
@@ -0,0 +1,79 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#ifndef __NET_EXCEPT_HPP
+#define __NET_EXCEPT_HPP
+
+#if defined(HAVE_WINSOCK2_H)
+ #include
+#else
+ #include
+ #include
+#endif
+
+#include
+#include
+
+#include "../annotations.hpp"
+
+
+//-----------------------------------------------------------------------------
+namespace net {
+ class error : public std::runtime_error {
+ protected:
+ error (const std::string &);
+ error (int code);
+
+ static std::string
+ code_to_string (int code);
+
+ public:
+ /// Throw an error corresponding the a given code. Code must be a valid error code,
+ /// not success otherwise the application will (at best) abort.
+ static void
+ throw_code (int code) terminal;
+
+ /// Throw an error corresponding to the most recent error condition. This will check
+ /// the current error condition in a platform agnostic manner, and pass on to
+ /// throw_code(int). This should be used whenever an error has been detected, rather
+ /// than the more normal try_code(errno) due to Windows error reporting quirks.
+ static void
+ throw_code (void) terminal;
+
+ static void
+ try_code (int code);
+
+ static void
+ try_code (void);
+
+ static int
+ last_code (void);
+ };
+
+
+ template
+ class error_code : public error {
+ public:
+ error_code ();
+
+ int code (void) const;
+ };
+}
+
+#endif // __NET_EXCEPT_HPP
diff --git a/net/socket.cpp b/net/socket.cpp
new file mode 100644
index 00000000..f9982f7b
--- /dev/null
+++ b/net/socket.cpp
@@ -0,0 +1,297 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#include "socket.hpp"
+
+#include "../debug.hpp"
+#include "../except.hpp"
+#include "../types/casts.hpp"
+#include "../log.hpp"
+#include "except.hpp"
+
+#if !defined(HAVE_WINSOCK2_H)
+ #include
+#endif
+
+#include
+#include
+
+using namespace net;
+
+//-----------------------------------------------------------------------------
+template
+socket_domain::socket_domain (socket_t _fd):
+ m_fd (_fd)
+{
+#ifdef __WIN32
+#else
+ CHECK_HARD (m_fd >= 0);
+#endif
+}
+
+
+#if defined(HAVE_WINSOCK2_H)
+ // TODO: Make this not retarded. Fucking Windows.
+ #define dup(X) (X)
+
+ static_assert(sizeof(int) == sizeof(ssize_t), "int != ssize_t");
+ static_assert(sizeof(int) == sizeof( size_t), "int != size_t");
+
+ ssize_t recv(socket_t _socket, void *_buf, size_t _len, int _flags)
+ { return (ssize_t)::recv(_socket, (char*)_buf, (int)_len, _flags); }
+
+ ssize_t recvfrom(socket_t _socket, void *_buf, size_t _len, int _flags, struct sockaddr *_sockaddr, socklen_t *_socklen)
+ { return (ssize_t)::recvfrom(_socket, (char*)_buf, (int)_len, _flags, _sockaddr, (int*)_socklen); }
+
+ ssize_t sendto(socket_t _socket, const void *_buf, size_t _len, int _flags, const struct sockaddr *_sockaddr, socklen_t _socklen)
+ { return (ssize_t)::sendto(_socket, (const char*)_buf, (int)_len, _flags, _sockaddr, (int)_socklen); }
+
+ ssize_t send(socket_t _socket, const void *_buf, size_t _len, int _flags)
+ { return (ssize_t)::send(_socket, (const char*)_buf, (int)_len, _flags); }
+#else
+ #define closesocket(X) close(X)
+#endif
+
+
+template
+socket_domain::socket_domain (const socket_domain &rhs):
+ m_fd (dup (rhs.m_fd))
+{ ; }
+
+
+template
+socket_domain::~socket_domain () {
+ if (closesocket (m_fd) < 0) {
+ LOG_DEBUG ("closesocket: %s", strerror (errno));
+ }
+}
+
+
+template
+socket_t
+socket_domain::native (void) const
+ { return m_fd; }
+
+
+template
+void
+socket_domain::shutdown (void) {
+#if defined(HAVE_WINSOCK2_H)
+ #define SHUT_SEND SD_SEND
+ #define SHUT_RECV SD_RECEIVE
+ #define SHUT_RDWR SD_BOTH
+#endif
+
+ if (::shutdown (m_fd, SHUT_RDWR) < 0)
+ net::error::throw_code ();
+}
+
+
+template
+template
+T
+socket_domain::get_option (level, option) {
+ not_implemented ();
+ return T ();
+}
+
+
+template
+void
+socket_domain::set_option (level _level, option _option) {
+ if (setsockopt (this->m_fd, (int)_level, (int)_option, NULL, 0))
+ net::error::throw_code ();
+}
+
+
+template
+template
+void
+socket_domain::set_option (level _level, option _option, const T &value) {
+ if (setsockopt (this->m_fd, (int)_level, (int)_option, (const char*)&value, sizeof (value)))
+ net::error::throw_code ();
+}
+
+
+template
+void
+socket_domain::bind (const address_type &addr) {
+ typename address_type::sockaddr_type addr_in = addr.to_sockaddr ();
+
+ if (::bind (m_fd, (sockaddr *)&addr_in, sizeof (addr_in)) != 0)
+ net::error::throw_code ();
+}
+
+//-----------------------------------------------------------------------------
+template
+net::socket::socket (socket_t _fd):
+ net::socket_domain (_fd)
+{ ; }
+
+
+template
+net::socket::socket ():
+ net::socket_domain (::socket ((int)D, (int)type::STREAM, (int)protocol::DEFAULT))
+{ ; }
+
+
+template
+net::socket::socket (const socket_type &rhs):
+ socket_domain (rhs)
+{ ; }
+
+
+template
+void
+net::socket::send (const uint8_t *restrict data, size_t len) {
+ CHECK_HARD (data != NULL);
+ CHECK (len > 0);
+
+ for (size_t sent = 0; sent < len; ) {
+ ssize_t result = ::send (this->m_fd, static_cast(data + sent), len - sent, 0);
+
+ if (result < 0)
+ net::error::throw_code ();
+
+ sent += sign_cast (result);
+ }
+}
+
+
+template
+size_t
+net::socket::recv (uint8_t *restrict data, size_t len) {
+ CHECK_HARD (data != NULL);
+ CHECK (len > 0);
+
+ ssize_t received = ::recv (this->m_fd, data, len, 0);
+ if (received < 0)
+ net::error::throw_code ();
+
+ return sign_cast (received);
+}
+
+
+template
+void
+net::socket::connect (const address_type &_addr) {
+ typename address_type::sockaddr_type addr (_addr.to_sockaddr ());
+
+ if (::connect (this->m_fd, reinterpret_cast (&addr), sizeof (addr)) < 0)
+ net::error::throw_code ();
+}
+
+
+template
+void
+net::socket::listen (const address_type &_addr, unsigned int _backlog) {
+ this->bind (_addr);
+
+ if (::listen (this->m_fd, sign_cast(_backlog)) != 0)
+ net::error::throw_code ();
+}
+
+
+template
+typename net::socket::socket_ptr
+net::socket::accept (void) {
+ int newfd = ::accept (this->m_fd, NULL, 0);
+ if (newfd < 0)
+ net::error::throw_code ();
+
+ return socket_ptr(new socket (newfd));
+}
+
+
+template
+typename net::socket::address_type
+net::socket::get_peer (void) const {
+ typename address_type::sockaddr_type addr;
+ socklen_t addr_len;
+
+ if (getpeername (this->m_fd, (sockaddr*)&addr, &addr_len))
+ net::error::throw_code ();
+
+ CHECK (addr_len == sizeof (addr));
+ return addr;
+}
+
+
+//-----------------------------------------------------------------------------
+template
+net::socket::socket (socket_t _fd):
+ net::socket_domain (_fd)
+{ ; }
+
+
+template
+net::socket::socket ():
+ net::socket_domain (::socket ((int)D, (int)type::DGRAM, (int)protocol::DEFAULT))
+{ ; }
+
+
+template
+net::socket::socket (const socket_type &rhs):
+ net::socket_domain (rhs)
+{ ; }
+
+
+template
+void
+net::socket::send_addr (const address_type &addr,
+ const uint8_t *restrict data,
+ size_t len) {
+ CHECK_HARD (data != NULL);
+ CHECK (len > 0);
+
+ typename address_type::sockaddr_type addr_in = addr.to_sockaddr ();
+
+ ssize_t sent = ::sendto (this->m_fd, data, len, 0, (sockaddr *)&addr_in, sizeof (addr_in));
+ if (sent < 0)
+ net::error::throw_code ();
+
+ CHECK_HARD (sign_cast(sent) == len);
+}
+
+
+template
+typename net::socket::address_type
+net::socket::recv_addr (uint8_t *restrict data,
+ size_t len) {
+ CHECK_HARD (data != NULL);
+ CHECK (len > 0);
+
+ typename address_type::sockaddr_type addr_in;
+ socklen_t addr_len = sizeof (addr_in);
+
+ ssize_t recvd = recvfrom (this->m_fd, data, len, 0, (sockaddr *)&addr_in, &addr_len);
+ CHECK_HARD (sizeof (addr_in) == addr_len);
+ if (recvd < 0)
+ net::error::throw_code ();
+
+ return addr_in;
+}
+
+//-----------------------------------------------------------------------------
+template class net::socket_domain;
+template void net::socket_domain::set_option(level, option, const int&);
+
+template class net::socket;
+template class net::socket;
+
diff --git a/net/socket.hpp b/net/socket.hpp
new file mode 100644
index 00000000..8c971909
--- /dev/null
+++ b/net/socket.hpp
@@ -0,0 +1,109 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#ifndef __NET_SOCKET_HPP
+#define __NET_SOCKET_HPP
+
+#include "types.hpp"
+#include "address.hpp"
+
+
+//-----------------------------------------------------------------------------
+namespace net {
+ template
+ class socket_domain {
+ public:
+ typedef address address_type;
+
+ protected:
+ socket_t m_fd;
+
+ socket_domain (socket_t _fd);
+ socket_domain (const socket_domain&);
+ ~socket_domain ();
+
+ public:
+ socket_t native (void) const;
+
+ void shutdown (void);
+
+ template
+ T get_option (level, option);
+
+ void set_option (level, option);
+ template
+ void set_option (level, option, const T &value);
+
+ protected:
+ void bind (const address_type&);
+ };
+
+
+ template
+ class socket;
+
+
+ template
+ class socket: public socket_domain {
+ public:
+ typedef socket socket_type;
+ typedef std::unique_ptr socket_ptr;
+ typedef address address_type;
+
+ protected:
+ static const unsigned int DEFAULT_BACKLOG = 5;
+
+ socket (socket_t _fd);
+
+ public:
+ socket ();
+ socket (const socket_type &);
+
+ void send (const uint8_t *restrict, size_t);
+ size_t recv (uint8_t *restrict, size_t);
+
+ void connect (const address_type&);
+
+ void listen (const address_type&, unsigned int backlog = DEFAULT_BACKLOG);
+ socket_ptr accept (void);
+
+ address_type get_peer (void) const;
+ };
+
+
+ template
+ class socket : public socket_domain {
+ public:
+ typedef socket socket_type;
+ typedef address address_type;
+
+ socket (socket_t _fd);
+
+ public:
+ socket ();
+ socket (const socket_type &);
+
+ void send_addr (const address_type&, const uint8_t *restrict, size_t);
+ address_type recv_addr (uint8_t *restrict, size_t);
+ };
+}
+
+
+#endif // __NET_SOCKET_HPP
+
diff --git a/net/types.cpp b/net/types.cpp
new file mode 100644
index 00000000..50199e28
--- /dev/null
+++ b/net/types.cpp
@@ -0,0 +1,53 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#include "types.hpp"
+#include "../debug.hpp"
+
+#if defined(HAVE_WINSOCK2_H)
+#else
+ #include
+#endif
+
+//-----------------------------------------------------------------------------
+using namespace net;
+
+
+//-----------------------------------------------------------------------------
+protocol
+net::string_to_protocol (const std::string &_name)
+ { return net::string_to_protocol (_name.c_str ()); }
+
+
+protocol
+net::string_to_protocol (const char *_name) {
+ struct protoent *entry = getprotobyname (_name);
+ // TODO: Throw an exception...
+ CHECK_HARD (entry);
+ return (protocol)entry->p_proto;
+}
+
+
+std::string
+net::protocol_to_string (protocol _protocol) {
+ struct protoent *entry = getprotobynumber ((int)_protocol);
+ CHECK_HARD (entry);
+ return entry->p_name;
+}
+
diff --git a/net/types.hpp b/net/types.hpp
new file mode 100644
index 00000000..30b61eee
--- /dev/null
+++ b/net/types.hpp
@@ -0,0 +1,182 @@
+/*
+ * This file is part of libgim.
+ *
+ * libgim is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libgim is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libgim. If not, see .
+ *
+ * Copyright 2011 Danny Robson
+ */
+
+#ifndef __NET_TYPES_HPP
+#define __NET_TYPES_HPP
+
+
+#if defined(HAVE_WINSOCK2_H)
+ #include
+#else
+ #include
+ #include
+ #include
+ #include
+ #include
+#endif
+
+#include
+#include
+
+
+namespace net {
+ /// Cross platform socket type to deal with Winsock2
+#if defined(HAVE_WINSOCK2_H)
+ typedef SOCKET socket_t;
+#else
+ typedef int socket_t;
+#endif
+
+ /// Defines the protocol family, or communication domain of a socket (see `man socket').
+ enum class domain : int {
+#define DEFINE_DOMAIN(V) \
+ V = AF_##V
+
+ DEFINE_DOMAIN(UNIX),
+ //DEFINE_DOMAIN(LOCAL),
+ DEFINE_DOMAIN(INET),
+ DEFINE_DOMAIN(INET6),
+ DEFINE_DOMAIN(IPX),
+ //DEFINE_DOMAIN(NETLINK),
+ //DEFINE_DOMAIN(X25),
+ //DEFINE_DOMAIN(AX25),
+ //DEFINE_DOMAIN(ATMPVC),
+ DEFINE_DOMAIN(APPLETALK)
+ //DEFINE_DOMAIN(PACKET)
+
+#undef DEFINE_DOMAIN
+ };
+
+
+ /// Specifies the communication semantics of a socket; how a socket deals with data.
+ enum class type : int {
+#define DEFINE_TYPE(V) \
+ V = SOCK_##V
+
+ DEFINE_TYPE(STREAM),
+ DEFINE_TYPE(DGRAM),
+ DEFINE_TYPE(SEQPACKET),
+ DEFINE_TYPE(RAW),
+ DEFINE_TYPE(RDM)
+ //DEFINE_TYPE(PACKET)
+
+#undef DEFINE_TYPE
+ };
+
+
+ /// Indicates the wire transmission protocol to use.
+ ///
+ /// This DOES NOT mean what you think it does! It is included for completeness sake, and unless
+ /// you're doing something funky with the C API you really just want DEFAULT.
+ /// Values retrieved from /etc/protocols
+ enum class protocol : int {
+ DEFAULT = 0,
+
+ IP = 0,
+ ICMP = 1,
+ TCP = 6,
+ UDP = 17,
+ IPV6 = 41
+ };
+
+
+ protocol
+ string_to_protocol (const std::string&);
+
+ protocol
+ string_to_protocol (const char *name);
+
+ std::string
+ protocol_to_string (protocol);
+
+
+ enum class option : int {
+#define DEFINE_OPTION(V) \
+ V = SO_##V
+
+ DEFINE_OPTION(DEBUG),
+ DEFINE_OPTION(REUSEADDR),
+ DEFINE_OPTION(TYPE),
+ //DEFINE_OPTION(ERROR),
+ DEFINE_OPTION(DONTROUTE),
+ DEFINE_OPTION(BROADCAST),
+ //DEFINE_OPTION(SNDBUF),
+ DEFINE_OPTION(RCVBUF),
+ //DEFINE_OPTION(SNDBUFFORCE),
+ //DEFINE_OPTION(RCVBUFFORCE),
+ DEFINE_OPTION(KEEPALIVE),
+ DEFINE_OPTION(OOBINLINE),
+ //DEFINE_OPTION(NO_CHECK),
+ //DEFINE_OPTION(PRIORITY),
+ DEFINE_OPTION(LINGER),
+ //DEFINE_OPTION(BSDCOMPAT),
+
+ //DEFINE_OPTION(PASSCRED),
+ //DEFINE_OPTION(PEERCRED),
+ DEFINE_OPTION(RCVLOWAT),
+ DEFINE_OPTION(SNDLOWAT),
+ DEFINE_OPTION(RCVTIMEO),
+ DEFINE_OPTION(SNDTIMEO),
+
+ //DEFINE_OPTION(BINDTODEVICE),
+
+ //DEFINE_OPTION(ATTACH_FILTER),
+ //DEFINE_OPTION(DETACH_FILTER),
+
+ //DEFINE_OPTION(PEERNAME),
+ //DEFINE_OPTION(TIMESTAMP),
+
+ DEFINE_OPTION(ACCEPTCONN),
+
+ //DEFINE_OPTION(PEERSEC),
+ //DEFINE_OPTION(PASSSEC),
+ //DEFINE_OPTION(TIMESTAMPNS),
+
+ //DEFINE_OPTION(MARK),
+
+ //DEFINE_OPTION(TIMESTAMPING)
+#undef DEFINE_OPTION
+
+#define DEFINE_OPTION(V) \
+ V = TCP_##V
+
+ //DEFINE_OPTION(CORK),
+ //DEFINE_OPTION(DEFER_ACCEPT),
+ //DEFINE_OPTION(INFO),
+ //DEFINE_OPTION(KEEPCNT),
+ //DEFINE_OPTION(KEEPIDLE),
+ //DEFINE_OPTION(KEEPINTVL),
+ //DEFINE_OPTION(LINGER2),
+ //DEFINE_OPTION(MAXSEG),
+ DEFINE_OPTION(NODELAY)
+ //DEFINE_OPTION(QUICKACK),
+ //DEFINE_OPTION(SYNCNT),
+ //DEFINE_OPTION(WINDOW_CLAMP)
+#undef DEFINE_OPTION
+ };
+
+
+ enum class level : int {
+ SOCKET = SOL_SOCKET,
+ TCP = IPPROTO_TCP
+ };
+}
+
+#endif // __NET_TYPES_HPP
+