summaryrefslogtreecommitdiffhomepage
path: root/NetEx/NetSock.cpp
diff options
context:
space:
mode:
authorFWoltermann@gmail.com <FWoltermann@gmail.com@076cb2c4-205e-83fd-5cf3-1be9aa105544>2011-12-08 14:53:40 +0000
committerFWoltermann@gmail.com <FWoltermann@gmail.com@076cb2c4-205e-83fd-5cf3-1be9aa105544>2011-12-08 14:53:40 +0000
commite33e19d0587146859d48a134ec9fd94e7b7ba5cd (patch)
tree69d048c8801858d2756ab3a487090a7a1b74bf14 /NetEx/NetSock.cpp
downloadstarshatter-e33e19d0587146859d48a134ec9fd94e7b7ba5cd.zip
starshatter-e33e19d0587146859d48a134ec9fd94e7b7ba5cd.tar.gz
starshatter-e33e19d0587146859d48a134ec9fd94e7b7ba5cd.tar.bz2
Initial upload
Diffstat (limited to 'NetEx/NetSock.cpp')
-rw-r--r--NetEx/NetSock.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/NetEx/NetSock.cpp b/NetEx/NetSock.cpp
new file mode 100644
index 0000000..47c50d8
--- /dev/null
+++ b/NetEx/NetSock.cpp
@@ -0,0 +1,342 @@
+/* Project nGenEx
+ Destroyer Studios LLC
+ Copyright © 1997-2004. All Rights Reserved.
+
+ SUBSYSTEM: NetEx.lib
+ FILE: NetSock.cpp
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Network (IP) Socket Wrapper Implementation
+*/
+
+
+// WINSOCK2.H MUST COME FIRST!!
+#include <winsock2.h>
+
+#include "MemDebug.h"
+#include "NetSock.h"
+#include "NetLayer.h"
+
+// +-------------------------------------------------------------------+
+
+/**
+ * Server-side socket constructor
+ */
+NetSock::NetSock(bool str)
+ : stream(str), closed(false), stat(0), current_timeout(9999)
+{
+ if (stream)
+ s = ::socket(AF_INET, SOCK_STREAM, 0);
+ else
+ s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+}
+
+/**
+ * Server-side socket constructor
+ *
+ * PRIVATE: used only by the accept call to build a socket for
+ * a client connection to this server
+ */
+NetSock::NetSock(SOCKET sock, bool str)
+ : s(sock), stream(str), closed(false), stat(0), current_timeout(9999)
+{ }
+
+/**
+ * Client-side socket constructor
+ *
+ * Will connect to server at "addr"
+ */
+NetSock::NetSock(const NetAddr& addr, bool str)
+ : stream(str), closed(false), stat(0), current_timeout(9999)
+{
+ if (stream)
+ s = ::socket(AF_INET, SOCK_STREAM, 0);
+ else
+ s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ connect(addr);
+}
+
+NetSock::~NetSock()
+{
+ close();
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::bind(const NetAddr& addr)
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ return stat = ::bind(s, addr.GetSockAddr(), addr.GetSockAddrLength());
+}
+
+int
+NetSock::connect(const NetAddr& addr)
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ return stat = ::connect(s, addr.GetSockAddr(), addr.GetSockAddrLength());
+}
+
+int
+NetSock::listen(int max_connections)
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ return stat = ::listen(s, max_connections);
+}
+
+NetSock*
+NetSock::accept(NetAddr* addr)
+{
+ if (closed || s == INVALID_SOCKET) return 0;
+
+ SOCKET conn = INVALID_SOCKET;
+
+ if (addr) {
+ sockaddr a;
+ int asize = sizeof(a);
+
+ conn = ::accept(s, &a, &asize);
+
+ if (conn != INVALID_SOCKET && asize > 0) {
+ addr->SetSockAddr(&a, asize);
+ }
+ }
+ else {
+ conn = ::accept(s, 0, 0);
+ }
+
+ if (conn == INVALID_SOCKET)
+ return 0;
+
+ return new(__FILE__,__LINE__) NetSock(conn, stream);
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::available()
+{
+ if (closed || s == INVALID_SOCKET) return 0;
+
+ DWORD nbytes = 0;
+ if (::ioctlsocket(s, FIONREAD, &nbytes) == 0)
+ return (int) nbytes;
+
+ return 0;
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::send(Text msg)
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ return stat = ::send(s, msg.data(), msg.length(), 0);
+}
+
+Text
+NetSock::recv()
+{
+ if (closed || s == INVALID_SOCKET) return "";
+
+ static char rbuf[8192];
+ int rlen = -1;
+
+ if (stream) {
+ rlen = ::recv(s, rbuf, sizeof(rbuf), 0);
+ }
+ else {
+ rlen = ::recvfrom(s, rbuf, sizeof(rbuf), 0, 0, 0);
+ }
+
+ if (rlen < 0) {
+ stat = NetLayer::GetLastError();
+
+ switch (stat) {
+ case WSAENETDOWN:
+ case WSAENETRESET:
+ case WSAEINTR:
+ case WSAESHUTDOWN:
+ case WSAECONNABORTED:
+ case WSAECONNRESET:
+ case WSAETIMEDOUT:
+ close();
+ break;
+
+ case WSAEWOULDBLOCK:
+ stat = WSAEWOULDBLOCK;
+ break;
+ }
+
+ return Text();
+ }
+
+ else if (rlen == 0) {
+ return Text();
+ }
+
+ return Text(rbuf, rlen);
+}
+
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::sendto(Text msg, const NetAddr& dest)
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ return stat = ::sendto(s, msg.data(), msg.length(),
+ 0, dest.GetSockAddr(), dest.GetSockAddrLength());
+}
+
+Text
+NetSock::recvfrom(NetAddr* a)
+{
+ if (closed || s == INVALID_SOCKET) return "";
+
+ static char rbuf[4096];
+ int rlen = 0;
+
+ if (a) {
+ int addrlen = a->GetSockAddrLength();
+ rlen = ::recvfrom(s, rbuf, sizeof(rbuf), 0, a->GetSockAddr(), &addrlen);
+ a->InitFromSockAddr();
+ }
+ else {
+ rlen = ::recvfrom(s, rbuf, sizeof(rbuf), 0, 0, 0);
+ }
+
+ if (rlen < 0) {
+ stat = NetLayer::GetLastError();
+ return Text();
+ }
+
+ else if (rlen == 0) {
+ return Text();
+ }
+
+ return Text(rbuf, rlen);
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::select(SELECT_TYPE t, long seconds, long microseconds)
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+
+ FD_SET fd;
+ ZeroMemory(&fd, sizeof(fd));
+
+ FD_SET(s, &fd);
+ TIMEVAL timeval = {seconds, microseconds};
+ TIMEVAL* timeout = &timeval;
+
+ if (t == SELECT_READ)
+ return stat = ::select(1, &fd, 0, 0, timeout);
+
+ else if (t == SELECT_WRITE)
+ return stat = ::select(1, 0, &fd, 0, timeout);
+
+ else if (t == (SELECT_READ|SELECT_WRITE))
+ return stat = ::select(1, &fd, &fd, 0, timeout);
+
+ return 0;
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::set_timeout(int msecs)
+{
+ if (closed || s == INVALID_SOCKET) return 0;
+ if (msecs == current_timeout) return 1;
+
+ // zero timeout means non-blocking
+ if (msecs == 0) {
+ u_long nonblocking = 1;
+ if (::ioctlsocket(s, FIONBIO, &nonblocking) == SOCKET_ERROR) {
+ stat = NetLayer::GetLastError();
+ return stat;
+ }
+ }
+
+ // non-zero timeout means blocking
+ else {
+ if (current_timeout == 0) {
+ u_long nonblocking = 0; // disable non-blocking
+ if (::ioctlsocket(s, FIONBIO, &nonblocking) == SOCKET_ERROR) {
+ stat = NetLayer::GetLastError();
+ return stat;
+ }
+ }
+
+ // max timeout means infinite wait
+ if (msecs >= NET_MAX_TIMEOUT) {
+ int maxto = 0;
+ ::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*) &maxto, sizeof(maxto));
+ ::setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*) &maxto, sizeof(maxto));
+ }
+
+ // otherwise, set the timeout
+ else {
+ ::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*) &msecs, sizeof(msecs));
+ ::setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*) &msecs, sizeof(msecs));
+ }
+ }
+
+ current_timeout = msecs;
+ return 1;
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::shutdown_input()
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ ::shutdown(s, SD_RECEIVE);
+ return 0;
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::shutdown_output()
+{
+ if (closed || s == INVALID_SOCKET) return INVALID_SOCKET;
+ ::shutdown(s, SD_SEND);
+ return 0;
+}
+
+// +--------------------------------------------------------------------+
+
+int
+NetSock::close()
+{
+ if (s != INVALID_SOCKET && !closed) {
+ ::shutdown(s, SD_BOTH);
+ ::closesocket(s);
+
+ closed = true;
+ }
+
+ return 0;
+}
+
+// +--------------------------------------------------------------------+
+
+DWORD
+NetSock::max_packet_size() const
+{
+ DWORD size = 0;
+ int len = sizeof(size);
+
+ ::getsockopt(s, SOL_SOCKET, 0x2003, (char*) &size, &len);
+
+ return size;
+} \ No newline at end of file