summaryrefslogtreecommitdiff
path: root/Runtime/Network/ServerSocket.cpp
blob: a89782fb416b7de0fb6a273785a97a52c41cfc77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "UnityPrefix.h"

#if ENABLE_SOCKETS
#include "ServerSocket.h"
#include "SocketUtils.h"

ServerSocket::ServerSocket(int domain, int type, int protocol)
: Socket(domain, type, protocol)
, m_IsListening(false)
{
	SetReuseAddress(true);
}

#if !UNITY_WINRT

// Metro does not support BSD sockets, so these methods are reimplemented
// in Metro platform specific codebase

bool ServerSocket::StartListening(unsigned short port, bool block)
{
	struct sockaddr_in addr;
	SetupAddress(htonl(INADDR_ANY), htons(port), &addr);
	return StartListening((const sockaddr*) &addr, sizeof(addr), block);
}

bool ServerSocket::StartListening(const char* ip, unsigned short port, bool block)
{
	struct sockaddr_in addr;
	SetupAddress(inet_addr(ip), htons(port), &addr);
	return StartListening((const sockaddr*) &addr, sizeof(addr), block);
}

bool ServerSocket::StartListening(const sockaddr* addr, socklen_t addr_len, bool block)
{
	if (!m_IsListening)
	{
		if (!SetBlocking(block))
			return false;

		if (CheckError(bind(m_SocketHandle, addr, addr_len), "bind failed"))
			return false;

		if (CheckError(listen(m_SocketHandle, 5), "listen failed"))
			return false;

		m_IsListening = true;
		return true;
	}
	ErrorStringMsg("already listening");
	return false;
}

int ServerSocket::GetPort()
{
	sockaddr_in addr;
	socklen_t addr_len = sizeof(addr);
	if (CheckError(getsockname(m_SocketHandle, (struct sockaddr *) &addr, &addr_len)))
		return -1;
	return ntohs(addr.sin_port);
}

TSocketHandle ServerSocket::Accept()
{
	return Accept(NULL, NULL);
}

TSocketHandle ServerSocket::Accept(sockaddr* addr, socklen_t* addr_len)
{
	int socketHandle = accept(m_SocketHandle, addr, addr_len);
	if (CheckError(socketHandle, "accept failed", kPlatformAcceptWouldBlock))
		return socketHandle; // Shutdown?
	return socketHandle;
}


#undef Error
#undef SocketError

// ---------------------------------------------------------------------------
#if ENABLE_UNIT_TESTS && !UNITY_XENON

#include "External/UnitTest++/src/UnitTest++.h"
#include "NetworkUtility.h"
SUITE (ServerSocketTests)
{
	struct SocketFixture
	{
		SocketFixture()
		{
			NetworkInitialize();
		};

		~SocketFixture()
		{
			NetworkCleanup();
		}
	};

	TEST_FIXTURE(SocketFixture, ServerSocket_Connect)
	{
		int socketHandle, port;

		ServerSocket socket;
		CHECK((socket.StartListening("127.0.0.1", 0, false)) == true);
		CHECK((port = socket.GetPort()) > 0);
		CHECK((socketHandle = Socket::Connect("127.0.0.1", port)) >= 0);

		Socket::Close(socketHandle);
		CHECK(socket.IsListening());
	}
}

#endif //ENABLE_UNIT_TESTS

#endif // UNITY_WINRT

#endif // ENABLE_SOCKETS