1: #line 31 "./lpsrc/flx_demuxconfig.pak"
2:
3: DEMUXRTL_INTERFACES = [
4: 'demux/demux_demuxer.hpp',
5: 'demux/demux_posix_demuxer.hpp',
6: 'demux/demux_timer_queue.hpp',
7: 'demux/demux_quitter.hpp',
8: 'demux/demux_posix_timer_queue.hpp',
9: 'demux/demux_pfileio.hpp',
10: 'demux/demux_select_demuxer.hpp',
11: 'demux/demux_iocp_demuxer.hpp',
12: 'demux/demux_overlapped.hpp',
13: 'demux/demux_win_timer_queue.hpp',
14: 'demux/demux_kqueue_demuxer.hpp',
15: 'demux/demux_evtport_demuxer.hpp',
16: 'demux/demux_epoll_demuxer.hpp',
17: 'demux/demux_sockety.hpp',
18: 'demux/demux_self_piper.hpp',
19: 'demux/demux_wself_piper.hpp',
20: 'demux/demux_ts_select_demuxer.hpp',
21: 'demux/demux_poll_demuxer.hpp',
22: 'demux/demux_ts_poll_demuxer.hpp',
23: ]
24:
25: DEMUX_CPPS = [
26: "demux/demux_demuxer",
27: "demux/demux_quitter",
28: ]
29:
30: POSIX_DEMUX_CPPS = [
31: "demux/demux_posix_demuxer",
32: "demux/demux_select_demuxer",
33: "demux/demux_posix_timer_queue",
34: "demux/demux_sockety",
35: "demux/demux_self_piper",
36: "demux/demux_pfileio",
37: 'demux/demux_ts_select_demuxer',
38: ]
39:
40: POLL_DEMUX_CPPS = [
41:
42:
43: 'demux/demux_poll_demuxer',
44: 'demux/demux_ts_poll_demuxer',
45: ]
46:
47: WINDOWS_DEMUX_CPPS = [
48: "demux/demux_iocp_demuxer",
49: "demux/demux_overlapped",
50: "demux/demux_wself_piper",
51: "demux/demux_win_timer_queue",
52: ]
53:
54: EXTRA_SYS_LIBS = ""
55: if WIN32:
56: DEMUX_CPPS = DEMUX_CPPS + WINDOWS_DEMUX_CPPS
57: if HAVE_MSVC:
58: EXTRA_SYS_LIBS = "/DEFAULTLIB:ws2_32 /DEFAULTLIB:mswsock "
59: else:
60:
61: EXTRA_SYS_LIBS = "-lws2_32 -lmswsock "
62:
63:
64: if POSIX:
65: DEMUX_CPPS = DEMUX_CPPS + POSIX_DEMUX_CPPS
66:
67: if HAVE_KQUEUE_DEMUXER:
68: DEMUX_CPPS = DEMUX_CPPS + [ "demux/demux_kqueue_demuxer" ]
69:
70: if HAVE_POLL:
71: DEMUX_CPPS = DEMUX_CPPS + POLL_DEMUX_CPPS
72:
73: if HAVE_EPOLL:
74: DEMUX_CPPS = DEMUX_CPPS + [ "demux/demux_epoll_demuxer" ]
75:
76: if HAVE_EVTPORTS:
77: DEMUX_CPPS = DEMUX_CPPS + [ "demux/demux_evtport_demuxer"]
78:
79: if SOLARIS:
80:
81: EXTRA_SYS_LIBS = "-lsocket -lnsl "
82:
83: cpp_cpps = DEMUX_CPPS
84: rtl_interfaces = DEMUXRTL_INTERFACES
85: pkg_requires = ['flx_pthread', 'flx_rtl']
86: lib_requires = ['libflx_pthread']
87: dflags = EXTRA_SYS_LIBS
88: sflags = EXTRA_SYS_LIBS
89: iscr_source = [
90: "lpsrc/flx_demux.pak",
91: "lpsrc/flx_demuxconfig.pak",
92: ]
93: build_macro = "DEMUX"
94: weaver_directory = 'doc/rtl/flx_demux/'
95:
1: #line 127 "./lpsrc/flx_demuxconfig.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: typedef socklen_t FLX_SOCKLEN_T;
22:
23: namespace flx { namespace demux {
24:
25: /*
26: returns a socket ready for listening (AF_INET, SOCK_STREAM for now).
27: 0 in for port means let kernel decide, result in *io_port
28: portable, can be factored out. listens on all NICs.
29: returns -1 on failure, sometimes eats errno.
30: p.s. sets SO_REUSEADDR.
31: */
32: int
33: create_listener_socket(int* io_port, int q_len)
34: {
35: int listener;
36: int yes = 1; /* for address reuse */
37:
38: if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
39: return -1;
40:
41: /* get rid of those *pesky* "address already in use" errors. */
42: /* for when you don't cleanly shutdown the server */
43: if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
44: goto listener_fail;
45:
46: /* bind listener to local interface (ANY) */
47: if(bind_sock(listener, io_port) == -1)
48: goto listener_fail;
49:
50: /* set listen queue length for socket */
51: if(listen(listener, q_len) == -1)
52: goto listener_fail;
53:
54: return listener;
55:
56: listener_fail:
57: perror("create_listener_socket"); /* eats errno! */
58: if(close(listener) == -1)
59: perror("create_listener_socket close");
60: return -1;
61: }
62:
63: /* create listener, make it non-blocking */
64: /* duh, sometimes eats errno...*/
65: int
66: create_async_listener(int* io_port, int q_len)
67: {
68: int listener;
69:
70: listener = create_listener_socket(io_port, q_len);
71:
72: if(-1 == listener) return -1;
73:
74: if(make_nonblock(listener) == -1)
75: {
76: if(close(listener) != 0)
77: perror("create_async_listener close");
78: return -1;
79: }
80:
81: return listener;
82: }
83:
84: /* ps, sets resulting socket to non-block. some people would say that */
85: /* this WASN'T nice, so change the name some time. returns socket or -1 */
86: /* on failure, with *err containing the error code. on success returns 0 */
87: /* with zero (= no error) in *err */
88: int
89: nice_accept(int listener, int* err)
90: {
91: struct sockaddr_in remoteaddr;
92: /*socklen_t addrlen = sizeof(remoteaddr);*/
93: /* os x 10.2.8 doesn't have socklen_t. will this work elsewhere? */
94: /* 10.4 (gcc 4.0) complains about signedeness, so now unsigned */
95: FLX_SOCKLEN_T addrlen = sizeof(remoteaddr);
96: int newfd;
97:
98: *err = 0; /* assume all good */
99:
100: newfd = accept(listener, (struct sockaddr*)&remoteaddr, &addrlen);
101: if(-1 == newfd) {
102: *err = errno;
103: return -1;
104: }
105: else
106: {
107: /*I think 0's the result I want*/
108: if(make_nonblock(newfd) == -1)
109: {
110: *err = errno;
111:
112: /* bizarre case, note that close's errno is lost */
113: if(close(newfd) == -1)
114: perror("nice_accept close");
115: newfd = -1;
116: }
117: }
118: return newfd;
119: }
120:
121: /* call this connect_ipv4? would its interface work for ipv6? */
122: /* this connect can be either asynchronous or synchronous, */
123: /* depending on whether or not the socket is non blocking */
124: /* returns -1 with err in errno on failure */
125: int
126: connect_sock(int s, const char* addr, int port)
127: {
128: struct sockaddr_in sock_addr;
129:
130: memset(&sock_addr, 0, sizeof(sock_addr));
131: sock_addr.sin_family = AF_INET; /* host byte order */
132: sock_addr.sin_addr.s_addr = inet_addr(addr);
133: sock_addr.sin_port = htons(port);
134:
135: return connect(s, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
136: }
137:
138: /* bind s to local address with given port number, or zero to let OS */
139: /* choose. can you bind to non-local addresses? not sure, but you might */
140: /* like to choose which local interface... (ADD OTHER INTERFACES HERE) */
141: /* returns -1 on failure with error code in errno */
142: int
143: bind_sock(int s, int* io_port)
144: {
145: struct sockaddr_in addr;
146: FLX_SOCKLEN_T namelen = sizeof(addr);
147:
148: memset(&addr, 0, sizeof(addr));
149: addr.sin_family = AF_INET; /* host byte order */
150: /* make the NIC an argument */
151: addr.sin_addr.s_addr = htonl(INADDR_ANY); /* allow multihomed */
152: addr.sin_port = htons(*io_port);
153:
154: /* bind to port */
155: if (bind(s, (struct sockaddr *)&addr, namelen) < 0)
156: {
157: return -1;
158: }
159:
160: /* we don't need to do this when the port was specified */
161: if(0 == *io_port)
162: {
163: /* Find out what port number was chosen */
164: if (getsockname(s, (struct sockaddr *)&addr, &namelen) < 0)
165: {
166: return -1;
167: }
168:
169: *io_port = ntohs(addr.sin_port);
170: }
171:
172: return 0; /* success! */
173: }
174:
175: /* simple wrapper for fcntl for those too lazy to look it up */
176: /* returns -1 on failure with errno set or non -1 otherwise */
177: int
178: make_nonblock(int s)
179: {
180: return fcntl(s, F_SETFL, O_NONBLOCK);
181: }
182:
183: /* returns -1 on failure with errno set or 0 otherwise */
184: int
185: set_tcp_nodelay(int s, int disable_nagle)
186: {
187: return setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
188: (char*)&disable_nagle, sizeof(disable_nagle));
189: }
190:
191: /*
192: Getting the determining if the async connect succeeded and if not,
193: its error, can actually be quite hairy on some systems, see
194: http:
195: for suggestions (none of which I follow at this point)
196: returns 0 on success and socket error in *socket_err
197: on failure returns -1 and *socket_err errno
198: */
199: int
200: get_socket_error(int s, int* socket_err)
201: {
202: int res;
203: FLX_SOCKLEN_T len = sizeof(*socket_err);
204: /* god knows what the level should be. socket level seems sensible. */
205: res = getsockopt(s, SOL_SOCKET, SO_ERROR, socket_err, &len);
206:
207: /* I've heard of impls of getsockopt(SO_ERROR) acting as they they */
208: /* had the socket error (i.e. returning -1 and the sock err in errno) */
209: if(-1 == res)
210: {
211: *socket_err = errno;
212: fprintf(stderr, "getsockopt failed - is that our error? (%i)\n",
213: *socket_err);
214: }
215:
216: return res;
217: }
218:
219: /* also make non-blocking AFTER connect, that is, */
220: /* this is a synchronous connect */
221: /* is eating errno, fix */
222: int
223: nice_connect(const char* addr, int port)
224: {
225: int s;
226:
227: if((s = socket(AF_INET, SOCK_STREAM, 0)) != -1
228: && connect_sock(s, addr, port) == 0
229: && make_nonblock(s) != -1)
230: {
231: return s; /* success! */
232: }
233:
234: /* something happened (not as good as catch 22) */
235: perror("nice_connect");
236:
237: if(-1 != s && close(s) != 0)
238: perror("nice close");
239:
240: return -1;
241: }
242:
243: /* makes the socket non-blocking BEFORE connect, returns result */
244: /* from which can be determined if it finished immediately */
245: /* returns the socket & finished flag or -1 on failure, with the */
246: /* error returned in *err */
247: int
248: async_connect(const char* addr, int port, int* finished, int* err)
249: {
250: int s = -1;
251:
252: if((s = socket(AF_INET, SOCK_STREAM, 0)) != -1 && make_nonblock(s) != -1)
253: {
254: /* no error we now have s, a non-blocking socket */
255: if(connect_sock(s, addr, port) == 0)
256: {
257: *err = 0; /* no error */
258: *finished = 1; /* finished */
259: return s;
260: }
261:
262: *err = errno; /* connect failed or in-progress */
263:
264: /* this can apparently be EWOULDBLOCK or even EAGAIN on some systems */
265: /* any info? on some systems they're the same, on some they're not */
266: if(EINPROGRESS == *err)
267: {
268: *finished = 0; /* not finished, in progress */
269: return s;
270: }
271: /* some other failure, fall through and clean up */
272: }
273:
274: /* hope you can read same errno twice in threaded apps! */
275: *err = errno; /* pass back error */
276:
277: if(-1 != s && close(s) != 0) /* we lose the close error */
278: perror("async_connect close");
279:
280: *finished = 1; /* for completeness */
281: return -1;
282: }
283: }}
284: