updates from orpheus for windoze build
[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 /* wow, an ancient screw-up, leaving these in here after they were abstracted to tcpip_definitions.h; yargh.
152 #ifdef __UNIX__
153   // provide some unifying definitions.
154   #define INVALID_SOCKET -1
155   #define SOCKET_ERROR -1
156   typedef void sock_hop;
157
158   // provide synonyms for errors so we don't conflict with the windows
159   // brain-deadness.  they define error values like EACCESS but they're not
160   // the real values you need to use with tcp/ip.  french fried gates time.
161   #define SOCK_EACCES EACCES
162   #define SOCK_EADDRINUSE EADDRINUSE
163   #define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
164   #define SOCK_EAFNOSUPPORT EAFNOSUPPORT
165   #define SOCK_EALREADY EALREADY
166   #define SOCK_EBADF EBADF
167   #define SOCK_ECONNABORTED ECONNABORTED
168   #define SOCK_ECONNREFUSED ECONNREFUSED
169   #define SOCK_ECONNRESET ECONNRESET
170   #define SOCK_EDESTADDRREQ EDESTADDRREQ
171   #define SOCK_EDQUOT EDQUOT
172   #define SOCK_EFAULT EFAULT
173   #define SOCK_EHOSTDOWN EHOSTDOWN
174   #define SOCK_EHOSTUNREACH EHOSTUNREACH
175   #define SOCK_EINPROGRESS EINPROGRESS
176   #define SOCK_EINTR EINTR
177   #define SOCK_EINVAL EINVAL
178   #define SOCK_EISCONN EISCONN
179   #define SOCK_ELOOP ELOOP
180   #define SOCK_EMFILE EMFILE
181   #define SOCK_EMSGSIZE EMSGSIZE
182   #define SOCK_ENAMETOOLONG ENAMETOOLONG
183   #define SOCK_ENETDOWN ENETDOWN
184   #define SOCK_ENETUNREACH ENETUNREACH
185   #define SOCK_ENETRESET ENETRESET
186   #define SOCK_ENOBUFS ENOBUFS
187   #define SOCK_ENOPROTOOPT ENOPROTOOPT
188   #define SOCK_ENOTCONN ENOTCONN
189   #define SOCK_ENOTEMPTY ENOTEMPTY
190   #define SOCK_ENOTSOCK ENOTSOCK
191   #define SOCK_EOPNOTSUPP EOPNOTSUPP
192   #define SOCK_EPFNOSUPPORT EPFNOSUPPORT
193   #define SOCK_EPROCLIM EPROCLIM
194   #define SOCK_EPROTOTYPE EPROTOTYPE
195   #define SOCK_EPROTONOSUPPORT EPROTONOSUPPORT
196   #define SOCK_EREMOTE EREMOTE
197   #define SOCK_ESHUTDOWN ESHUTDOWN
198   #define SOCK_ESOCKTNOSUPPORT ESOCKTNOSUPPORT
199   #define SOCK_ESTALE ESTALE
200   #define SOCK_ETIMEDOUT ETIMEDOUT
201   #define SOCK_ETOOMANYREFS ETOOMANYREFS
202   #define SOCK_EWOULDBLOCK EWOULDBLOCK
203   #define SOCK_EUSERS EUSERS
204 #endif //unix.
205
206 //////////////
207
208 #ifdef __WIN32__
209   typedef char sock_hop;
210   typedef int socklen_t;
211
212   // provide close to the real BSD error names using windows values.
213   #define SOCK_EACCES WSAEACCES
214   #define SOCK_EADDRINUSE WSAEADDRINUSE
215   #define SOCK_EADDRNOTAVAIL WSAEADDRNOTAVAIL
216   #define SOCK_EAFNOSUPPORT WSAEAFNOSUPPORT
217   #define SOCK_EALREADY WSAEALREADY
218   #define SOCK_EBADF WSAEBADF
219   #define SOCK_ECONNABORTED WSAECONNABORTED
220   #define SOCK_ECONNREFUSED WSAECONNREFUSED
221   #define SOCK_ECONNRESET WSAECONNRESET
222   #define SOCK_EDESTADDRREQ WSAEDESTADDRREQ
223   #define SOCK_EDQUOT WSAEDQUOT
224   #define SOCK_EFAULT WSAEFAULT
225   #define SOCK_EHOSTDOWN WSAEHOSTDOWN
226   #define SOCK_EHOSTUNREACH WSAEHOSTUNREACH
227   #define SOCK_EINPROGRESS WSAEINPROGRESS
228   #define SOCK_EINTR WSAEINTR
229   #define SOCK_EINVAL WSAEINVAL
230   #define SOCK_EISCONN WSAEISCONN
231   #define SOCK_ELOOP WSAELOOP
232   #define SOCK_EMFILE WSAEMFILE
233   #define SOCK_EMSGSIZE WSAEMSGSIZE
234   #define SOCK_ENAMETOOLONG WSAENAMETOOLONG
235   #define SOCK_ENETDOWN WSAENETDOWN
236   #define SOCK_ENETUNREACH WSAENETUNREACH
237   #define SOCK_ENETRESET WSAENETRESET
238   #define SOCK_ENOBUFS WSAENOBUFS
239   #define SOCK_ENOPROTOOPT WSAENOPROTOOPT
240   #define SOCK_ENOTCONN WSAENOTCONN
241   #define SOCK_ENOTEMPTY WSAENOTEMPTY
242   #define SOCK_ENOTSOCK WSAENOTSOCK
243   #define SOCK_EOPNOTSUPP WSAEOPNOTSUPP
244   #define SOCK_EPFNOSUPPORT WSAEPFNOSUPPORT
245   #define SOCK_EPROCLIM WSAEPROCLIM
246   #define SOCK_EPROTOTYPE WSAEPROTOTYPE
247   #define SOCK_EPROTONOSUPPORT WSAEPROTONOSUPPORT
248   #define SOCK_EREMOTE WSAEREMOTE
249   #define SOCK_ESHUTDOWN WSAESHUTDOWN
250   #define SOCK_ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
251   #define SOCK_ESTALE WSAESTALE
252   #define SOCK_ETIMEDOUT WSAETIMEDOUT
253   #define SOCK_ETOOMANYREFS WSAETOOMANYREFS
254   #define SOCK_EUSERS WSAEUSERS
255
256   // windows specific names.
257   #define SOCK_EWOULDBLOCK WSAEWOULDBLOCK
258   #define SOCK_HOST_NOT_FOUND WSAHOST_NOT_FOUND
259   #define SOCK_NO_DATA WSANO_DATA
260   #define SOCK_NO_RECOVERY WSANO_RECOVERY
261   #define SOCK_NOTINITIALISED WSANOTINITIALISED
262   #define SOCK_SYSNOTREADY WSASYSNOTREADY
263   #define SOCK_TRY_AGAIN WSATRY_AGAIN
264   #define SOCK_VERNOTSUPPORTED WSAVERNOTSUPPORTED
265 #endif //win32.
266 */
267
268 //////////////
269
270 } //namespace.
271
272 #endif // outer guard.
273