1 #ifndef NETWORK_SOCKET_HH |
1 #ifndef NETWORK_SOCKET_HH |
2 #define NETWORK_SOCKET_HH |
2 #define NETWORK_SOCKET_HH |
3 |
3 |
|
4 /** |
|
5 * @file |
|
6 * |
|
7 * Network sockets |
|
8 */ |
|
9 |
4 // forward-declare |
10 // forward-declare |
5 class NetworkSocket; |
11 class NetworkSocket; |
6 |
12 |
7 #include "../Error.hh" |
13 #include "../Error.hh" |
|
14 #include "Platform.hh" |
8 #include "Address.hh" |
15 #include "Address.hh" |
9 #include "Reactor.hh" |
16 #include "Reactor.hh" |
10 |
17 |
11 /* |
18 /** |
12 * Platform-specific includes |
19 * This is a socket class that wraps an OS socket filedescriptor and provides the more important socket operations |
13 */ |
20 * as methods. The implementation aims to be address-family agnostic, and should thence work with both IPv6 and IPv4. |
14 #ifndef WIN32 |
21 * |
15 // linux |
22 * Network addresses are abstracted into the NetworkEndpoint and derived NetworkAddress classes. The bind() and |
16 #include <sys/types.h> |
23 * connect() methods accept a NetworkEndpoint as an argument, which allows them to handle hosts with multiple |
17 #include <sys/socket.h> |
24 * addresses (such as all dual-stack IPv6/IPv4 hosts). Other methods such as accept(), recv() and send() require a |
18 #include <unistd.h> |
25 * NetworkAddress, which encodes a single specific address. Note how these are also useable as arguments to |
19 #include <fcntl.h> |
26 * connect()/bind(). |
20 |
27 * |
21 #define closesocket close |
28 * The constructor accepts family/socktype/protocol arguments (as passed to the socket() syscall) which can be used to |
22 #else |
29 * limit which kinds of addresses/sockets will be used. Usually, family can be specified as AF_UNSPEC and socktype as |
23 #error "This network code won't compile on win32 :)" |
30 * either SOCK_STREAM or SOCK_DGRAM - this will let bind()/connect() pick the best IPv6/IPv4 address for use. |
24 #endif |
31 * |
25 |
32 * Note however that a call to bind()/connect() can result to multiple calls to the socket() syscall - this interaction |
26 /** |
33 * is slightly complicated. On a succesfull bind() operation, the resulting socket will be "locked down", meaning that |
27 * We use ClanLib's Socket API, but with our own extensions... |
34 * a later connect() operation will use the same local socket - this restricts the remote address families that are valid. |
|
35 * |
|
36 * The behaviour of send/recv differs from the behaviour of the similarly named syscalls. On failure, |
|
37 * NetworkSocketErrno is thrown, and on EOF, NetworkSocketEOFError. Zero is returned if the syscall returns EAGAIN - in |
|
38 * other words - if a socket is nonblocking and the operation would block. Otherwise, the return value is the same as |
|
39 * for the syscalls - the number of bytes send/received. |
|
40 * |
|
41 * NetworkSockets also support polling for non-blocking operations using NetworkReactor. A socket is associated with a |
|
42 * specific reactor (passed to the constructor, defaults to NetworkReactor::current). This is inherited by accept()'d |
|
43 * sockets. For read/write, NetworkSocket provides a sig_read()/sig_write() signal which will be fired if a socket is |
|
44 * registered using set_poll_read(true)/set_poll_write(true) and the NetworkReactor::poll is run. The internal logic |
|
45 * does not manipulate the poll states. Usually, sig_read will always be enabled (except to throttle incoming traffic), |
|
46 * and sig_write should be enabled after send() returns zero (XXX: provide an automatic mechanism for this?). |
28 */ |
47 */ |
29 class NetworkSocket { |
48 class NetworkSocket { |
30 private: |
49 private: |
31 /** |
50 /** |
32 * Socket family/type/protocol |
51 * Socket family/type/protocol |
49 socket_type sock_type; |
68 socket_type sock_type; |
50 |
69 |
51 /** The file descriptor */ |
70 /** The file descriptor */ |
52 int fd; |
71 int fd; |
53 |
72 |
54 /** Our current type, intialized via constructor, but updated by lazy_socket */ |
73 /** Our current type as used for fd, intialized via constructor, but updated by lazy_socket */ |
55 socket_type type; |
74 socket_type type; |
56 |
75 |
57 /** |
76 /** |
58 * Has the socket been explicitly bind()'d? If so, force ourselves to use this socket in connect(). |
77 * Has the socket been explicitly bind()'d? If so, force ourselves to use this socket in connect(). |
59 */ |
78 */ |