-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsocket.h
140 lines (106 loc) · 4.56 KB
/
socket.h
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#pragma once
#include <one/arcus/c_platform.h>
#include <array>
#if defined(ONE_WINDOWS)
#if defined(ONE_UNREAL_WINDOWS)
#include <Windows/AllowWindowsPlatformTypes.h>
#endif
#include <winsock2.h>
#include <WS2tcpip.h>
#if defined(ONE_UNREAL_WINDOWS)
#include <Windows/HideWindowsPlatformTypes.h>
#endif
#else
typedef int SOCKET;
#ifndef INVALID_SOCKET
const int INVALID_SOCKET = -1;
#endif
#endif
#include <one/arcus/error.h>
#include <one/arcus/types.h>
namespace i3d {
namespace one {
// Must be called before using Socket. Safe to call multiple times. Calls to
// init_socket_system must have matching calls to shutdown_socket_system.
// The first init call does the initializing. Any calls after the first init
// call only serve to increment a counter to track the number of shutdowns
// needed before the actual shutdown is performed.
OneError init_socket_system();
// Call when finished using sockets. Safe to call multiple times.
// Must have a matching call to init_socket_subsystem, called first. Only the
// final matching shutdown call actually performs cleanup, the preceding
// calls decrement counters matching the number of times init was called.
OneError shutdown_socket_system();
// A limited, cross-platform, low level TCP socket interface.
class Socket final {
public:
//------------
// Life cycle.
// Creates an uninitialized socket. init must be called.
Socket();
// Destroys the socket. Closes active connection, if any.
~Socket();
// Note that the system socket ownership is transferred when sockets are
// copied or assigned. Be careful when using the socket in data structures,
// if the socket is automatically copied during use, behavior may be
// undefined.
explicit Socket(const Socket &other);
void operator=(const Socket &other);
// Initializes as a TCP socket. Must be called before listen or connect.
OneError init();
bool is_initialized() const {
return _socket != INVALID_SOCKET;
}
// Closes active socket, if active.
OneError close();
//--------
// Server.
// Assigns the given IP and port to the socket. Use "" for any ip address
// and 0 for any port.
OneError bind(const char *ip, unsigned int port);
// Assigns the port to the socket. Use 0 for any port.
OneError bind(unsigned int port);
// Returns the address of this socket.
OneError address(String &ip, unsigned int &port) const;
// A decent default for the listen queue length for production. Ensure
// the listen socket is serviced by accept to keep the queue free.
static constexpr int default_queue_length = 32;
// Listens for incoming connections. Socket must have bind called
// beforehand.
OneError listen(int queueLength);
// Process incoming listen connections. Returns < 0 if an error occurred
// during processing. If a new client connection was accepted, then the
// given client socket's IsInitialized will be true.
OneError accept(Socket &client, String &ip, unsigned int &port);
//--------
// Client.
OneError connect(const char *ip, const unsigned int port);
//--------
// IO.
// Sets is_ready to true if the socket is ready for reading (accept or receive).
OneError ready_for_read(float timeout, bool &is_ready);
// Sets is_ready to true if the socket is ready for sending.
OneError ready_for_send(float timeout, bool &is_ready);
// Sends data on the socket, setting the given length_sent to the number of
// bytes sent. A failure to due to the socket not being ready, e.g.
// due to EAGAIN on Linux, is not considered to be an error and returns
// ONE_ERROR_NONE.
OneError send(const void *data, size_t length, size_t &length_sent);
// Puts number of bytes available for reading into the given length.
OneError available(size_t &length);
// Receives data on the socket into the given buffer, setting the given
// length_received to the number of bytes received. A failure to due to the
// socket not being ready, e.g. due to EAGAIN on Linux, is not considered
// to be an error and returns ONE_ERROR_NONE.
OneError receive(void *data, size_t length, size_t &length_received);
// Error reporting.
const char *last_error_text() const;
private:
mutable SOCKET _socket; // Mutable so that the copy constructor and operator can take
// ownership of the system socket.
public:
void set_last_error_text();
std::array<char, 256> _last_error_string;
};
} // namespace one
} // namespace i3d