99e948981a44d0bc544a8fd011c648acca6139e8
[feisty_meow.git] / octopi / library / sockets / raw_socket.h
1 #ifndef RAW_SOCKET_CLASS
2 #define RAW_SOCKET_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : raw_socket                                                        *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1991-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 //! Provides access to the operating system's socket methods.
19
20 /*!
21   NOTE: This class does not provide any sort of synchronization of the
22   sockets involved.  If you have multiple threads arbitrarily calling select
23   and read, then some selects will claim the socket was disconnected (since
24   the other thread might have grabbed the data that seemed to be ready but
25   then wasn't--a sign of a disconnect).  Ensure that your accesses of the
26   socket are serialized.
27 */
28
29 #include <basis/array.h>
30 #include <basis/astring.h>
31 #include <basis/contracts.h>
32
33 namespace sockets {
34
35 // forward declarations.
36 class fd_set_wrapper;
37 class tcpip_stack;
38
39 //////////////
40
41 // sockets can be intrigued by the occurrence of the following conditions:
42 enum socket_interests {
43   SI_READABLE      = 0x1,   // the socket is readable; there's data there.
44   SI_WRITABLE      = 0x2,   // the socket will accept data if it's sent.
45   SI_CONNECTED     = 0x4,   // the socket is connected.
46   SI_DISCONNECTED  = 0x8,   // the socket is disconnected.
47   SI_ERRONEOUS     = 0x10,  // the socket is in an erroneous state.
48   SI_BASELINE      = 0x20,  // the socket seems okay but not interesting.
49
50   SI_ALL_SOCK_INT  = 0xFF   // all socket interests are active.
51 };
52
53 //////////////
54
55 class raw_socket : public virtual basis::root_object
56 {
57 public:
58   raw_socket();
59
60   ~raw_socket();
61
62   DEFINE_CLASS_NAME("raw_socket");
63
64   int close(basis::un_int &socket);
65     // disconnects, destroys and resets the "socket" to zero.
66
67   int ioctl(basis::un_int socket, int request, void *argp) const;
68     // manipulates the device parameters for the "socket".
69
70   bool set_non_blocking(basis::un_int socket, bool non_blocking = true);
71     // makes the "socket" into a non-blocking socket if "non_blocking" is true.
72     // if "non_blocking" is false, then the socket is reset to blocking mode.
73
74   bool set_nagle_algorithm(basis::un_int socket, bool use_nagle = true);
75     // sets the nagle algorithm on "socket" if "use_nagle" is true.  note that
76     // true is the default when a socket is created; to change that for the
77     // socket, "use_nagle" should be false.
78
79   bool set_broadcast(basis::un_int socket, bool broadcasting = true);
80     // sets broadcast mode on the socket so that it can receive packets that
81     // are broadcast to the network.
82
83   bool set_reuse_address(basis::un_int socket, bool reuse = true);
84     // sets the socket to allow an address to be re-used when it's already
85     // in use, rather than getting a bind error.
86
87   bool set_keep_alive(basis::un_int socket, bool keep_alive = true);
88     // marks a connected-mode socket so that keep alive packets will be sent
89     // occasionally to ensure that a disconnection is noticed.
90
91   static basis::astring interest_name(int to_name);
92     // returns the textual form for the interests set in "to_name".
93
94   // outlines any special constraints on the select invocation.
95   enum select_types {
96     SELECTING_JUST_WRITE = 0x1,
97     SELECTING_JUST_READ = 0x2
98   };
99
100   int select(basis::un_int socket, int selection_mode, int timeout = 0) const;
101     // this is similar to the low-level select on a bsd socket.  usually this
102     // will return events of any type--read, write and exception.  exceptions
103     // will always be cause for a return, but if you just want to look at a
104     // read condition, include the JUST_READ flag in the "selection_mode".  to
105     // just check for write, add the JUST_WRITE flag.  this function returns a
106     // bitwise ORed value from the different types of 'socket_interests' (see
107     // tcpip definitions, which is where the enum is currently stored).  if
108     // there are no special conditions noted on the socket, then zero is
109     // returned.  if the "timeout" is zero, the function will return right
110     // away.  if "timeout" (measured in milliseconds) is non-zero, then the
111     // function will wait until the condition becomes true or the "timeout"
112     // elapses.  note: no infinite timeouts are provided here.
113
114   int select(basis::int_array &read_sox, basis::int_array &write_sox, int timeout = 0) const;
115     // similar to select above, but operates on a list of sockets in the
116     // "read_sox" and "write_sox".  the "read_sox" are checked to see whether
117     // those sockets have data pending that could be read.  the "write_sox" are
118     // checked to see if the sockets are currently writable without blocking.
119     // if any sockets have events applicable to the "selection_mode", then they
120     // will still be present in the lists when the call returns.  zero is
121     // returned if absolutely nothing happened during the "timeout" period;
122     // otherwise, a non-zero number is returned but the individual sockets
123     // must still be inspected to determine what happened.
124
125   int analyze_select_result(basis::un_int socket, int mode, fd_set_wrapper &read_list,
126           fd_set_wrapper &write_list, fd_set_wrapper &exceptions) const;
127     // examines the "socket" in the fd_sets passed in and returns a result
128     // based on those sets and the "mode".
129
130 private:
131   tcpip_stack *_stack;
132
133   int test_readability(basis::un_int socket) const;
134     // checks on the readability state for the "socket", assuming that select()
135     // reported the socket as readable, and returns either SI_ERRONEOUS,
136     // SI_READABLE or SI_DISCONNECTED based on what ioctl() says about it.
137
138   int inner_select(basis::un_int socket, int selection_mode, int timeout,
139           fd_set_wrapper &read_list, fd_set_wrapper &write_list,
140           fd_set_wrapper &exceptions) const;
141     // intermediate function that doesn't attempt to fully analyze the select
142     // result.  the returned value will be non-zero if something interesting
143     // is happening on the socket.  if that value is SI_ERRONEOUS, then
144     // something bad happened to the socket.  the other non-zero value is
145     // SI_BASELINE, which means the socket has something to report in the
146     // fd_set parameters.
147 };
148
149 //////////////
150
151 #ifdef __UNIX__
152   // provide some unifying definitions.
153   #define INVALID_SOCKET -1
154   #define SOCKET_ERROR -1
155   typedef void sock_hop;
156
157   // provide synonyms for errors so we don't conflict with the windows
158   // brain-deadness.  they define error values like EACCESS but they're not
159   // the real values you need to use with tcp/ip.  french fried gates time.
160   #define SOCK_EACCES EACCES
161   #define SOCK_EADDRINUSE EADDRINUSE
162   #define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
163   #define SOCK_EAFNOSUPPORT EAFNOSUPPORT
164   #define SOCK_EALREADY EALREADY
165   #define SOCK_EBADF EBADF
166   #define SOCK_ECONNABORTED ECONNABORTED
167   #define SOCK_ECONNREFUSED ECONNREFUSED
168   #define SOCK_ECONNRESET ECONNRESET
169   #define SOCK_EDESTADDRREQ EDESTADDRREQ
170   #define SOCK_EDQUOT EDQUOT
171   #define SOCK_EFAULT EFAULT
172   #define SOCK_EHOSTDOWN EHOSTDOWN
173   #define SOCK_EHOSTUNREACH EHOSTUNREACH
174   #define SOCK_EINPROGRESS EINPROGRESS
175   #define SOCK_EINTR EINTR
176   #define SOCK_EINVAL EINVAL
177   #define SOCK_EISCONN EISCONN
178   #define SOCK_ELOOP ELOOP
179   #define SOCK_EMFILE EMFILE
180   #define SOCK_EMSGSIZE EMSGSIZE
181   #define SOCK_ENAMETOOLONG ENAMETOOLONG
182   #define SOCK_ENETDOWN ENETDOWN
183   #define SOCK_ENETUNREACH ENETUNREACH
184   #define SOCK_ENETRESET ENETRESET
185   #define SOCK_ENOBUFS ENOBUFS
186   #define SOCK_ENOPROTOOPT ENOPROTOOPT
187   #define SOCK_ENOTCONN ENOTCONN
188   #define SOCK_ENOTEMPTY ENOTEMPTY
189   #define SOCK_ENOTSOCK ENOTSOCK
190   #define SOCK_EOPNOTSUPP EOPNOTSUPP
191   #define SOCK_EPFNOSUPPORT EPFNOSUPPORT
192   #define SOCK_EPROCLIM EPROCLIM
193   #define SOCK_EPROTOTYPE EPROTOTYPE
194   #define SOCK_EPROTONOSUPPORT EPROTONOSUPPORT
195   #define SOCK_EREMOTE EREMOTE
196   #define SOCK_ESHUTDOWN ESHUTDOWN
197   #define SOCK_ESOCKTNOSUPPORT ESOCKTNOSUPPORT
198   #define SOCK_ESTALE ESTALE
199   #define SOCK_ETIMEDOUT ETIMEDOUT
200   #define SOCK_ETOOMANYREFS ETOOMANYREFS
201   #define SOCK_EWOULDBLOCK EWOULDBLOCK
202   #define SOCK_EUSERS EUSERS
203 #endif //unix.
204
205 //////////////
206
207 #ifdef __WIN32__
208   typedef char sock_hop;
209   typedef int socklen_t;
210
211   // provide close to the real BSD error names using windows values.
212   #define SOCK_EACCES WSAEACCES
213   #define SOCK_EADDRINUSE WSAEADDRINUSE
214   #define SOCK_EADDRNOTAVAIL WSAEADDRNOTAVAIL
215   #define SOCK_EAFNOSUPPORT WSAEAFNOSUPPORT
216   #define SOCK_EALREADY WSAEALREADY
217   #define SOCK_EBADF WSAEBADF
218   #define SOCK_ECONNABORTED WSAECONNABORTED
219   #define SOCK_ECONNREFUSED WSAECONNREFUSED
220   #define SOCK_ECONNRESET WSAECONNRESET
221   #define SOCK_EDESTADDRREQ WSAEDESTADDRREQ
222   #define SOCK_EDQUOT WSAEDQUOT
223   #define SOCK_EFAULT WSAEFAULT
224   #define SOCK_EHOSTDOWN WSAEHOSTDOWN
225   #define SOCK_EHOSTUNREACH WSAEHOSTUNREACH
226   #define SOCK_EINPROGRESS WSAEINPROGRESS
227   #define SOCK_EINTR WSAEINTR
228   #define SOCK_EINVAL WSAEINVAL
229   #define SOCK_EISCONN WSAEISCONN
230   #define SOCK_ELOOP WSAELOOP
231   #define SOCK_EMFILE WSAEMFILE
232   #define SOCK_EMSGSIZE WSAEMSGSIZE
233   #define SOCK_ENAMETOOLONG WSAENAMETOOLONG
234   #define SOCK_ENETDOWN WSAENETDOWN
235   #define SOCK_ENETUNREACH WSAENETUNREACH
236   #define SOCK_ENETRESET WSAENETRESET
237   #define SOCK_ENOBUFS WSAENOBUFS
238   #define SOCK_ENOPROTOOPT WSAENOPROTOOPT
239   #define SOCK_ENOTCONN WSAENOTCONN
240   #define SOCK_ENOTEMPTY WSAENOTEMPTY
241   #define SOCK_ENOTSOCK WSAENOTSOCK
242   #define SOCK_EOPNOTSUPP WSAEOPNOTSUPP
243   #define SOCK_EPFNOSUPPORT WSAEPFNOSUPPORT
244   #define SOCK_EPROCLIM WSAEPROCLIM
245   #define SOCK_EPROTOTYPE WSAEPROTOTYPE
246   #define SOCK_EPROTONOSUPPORT WSAEPROTONOSUPPORT
247   #define SOCK_EREMOTE WSAEREMOTE
248   #define SOCK_ESHUTDOWN WSAESHUTDOWN
249   #define SOCK_ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
250   #define SOCK_ESTALE WSAESTALE
251   #define SOCK_ETIMEDOUT WSAETIMEDOUT
252   #define SOCK_ETOOMANYREFS WSAETOOMANYREFS
253   #define SOCK_EUSERS WSAEUSERS
254
255   // windows specific names.
256   #define SOCK_EWOULDBLOCK WSAEWOULDBLOCK
257   #define SOCK_HOST_NOT_FOUND WSAHOST_NOT_FOUND
258   #define SOCK_NO_DATA WSANO_DATA
259   #define SOCK_NO_RECOVERY WSANO_RECOVERY
260   #define SOCK_NOTINITIALISED WSANOTINITIALISED
261   #define SOCK_SYSNOTREADY WSASYSNOTREADY
262   #define SOCK_TRY_AGAIN WSATRY_AGAIN
263   #define SOCK_VERNOTSUPPORTED WSAVERNOTSUPPORTED
264 #endif //win32.
265
266 //////////////
267
268 } //namespace.
269
270 #endif // outer guard.
271