Name | Executed | Routines | % | Executed | Lines | % | Unexecuted |
/home/matt/eu/rds/include/std/socket.e | 12 | 19 | 63.16% | 120 | 141 | 85.11% | 21 |
Routine | Executed | Lines | Unexecuted | |
bind() | 0 | 3 | 0.00% | 3 |
select() | 8 | 11 | 72.73% | 3 |
send_to() | 0 | 3 | 0.00% | 3 |
accept() | 0 | 2 | 0.00% | 2 |
delete_socket() | 5 | 7 | 71.43% | 2 |
error_code() | 0 | 2 | 0.00% | 2 |
listen() | 0 | 2 | 0.00% | 2 |
receive_from() | 0 | 2 | 0.00% | 2 |
shutdown() | 0 | 2 | 0.00% | 2 |
close() | 2 | 2 | 100.00% | 0 |
connect() | 3 | 3 | 100.00% | 0 |
create() | 4 | 4 | 100.00% | 0 |
get_option() | 2 | 2 | 100.00% | 0 |
receive() | 2 | 2 | 100.00% | 0 |
send() | 2 | 2 | 100.00% | 0 |
service_by_name() | 2 | 2 | 100.00% | 0 |
service_by_port() | 2 | 2 | 100.00% | 0 |
set_option() | 2 | 2 | 100.00% | 0 |
socket() | 6 | 6 | 100.00% | 0 |
# | Executed | |
1 | namespace sockets | |
2 | ||
3 | --**** | |
4 | -- == Core Sockets | |
5 | -- | |
6 | -- < | |
7 | -- | |
8 | ||
9 | include std/get.e | |
10 | include std/regex.e as re | |
11 | include std/machine.e as mem | |
12 | include std/sequence.e as seq | |
13 | include std/net/common.e | |
14 | ||
15 | 3 | enum M_SOCK_GETSERVBYNAME=77, M_SOCK_GETSERVBYPORT, M_SOCK_SOCKET=81, M_SOCK_CLOSE, M_SOCK_SHUTDOWN, |
16 | 3 | M_SOCK_CONNECT, M_SOCK_SEND, M_SOCK_RECV, M_SOCK_BIND, M_SOCK_LISTEN, |
17 | 3 | M_SOCK_ACCEPT, M_SOCK_SETSOCKOPT, M_SOCK_GETSOCKOPT, M_SOCK_SELECT, M_SOCK_SENDTO, |
18 | 3 | M_SOCK_RECVFROM, M_SOCK_ERROR_CODE=96 |
19 | ||
20 | --**** | |
21 | -- === Error Information | |
22 | -- | |
23 | ||
24 | --** | |
25 | -- Get the error code. | |
26 | -- | |
27 | -- Returns: | |
28 | -- Integer [[:OK]] on no error, otherwise any one of the ##ERR_## constants to | |
29 | -- follow. | |
30 | -- | |
31 | ||
32 | 0 | |
33 | 0 | return machine_func(M_SOCK_ERROR_CODE, {}) |
34 | end function | |
35 | ||
36 | ||
37 | --** | |
38 | -- No error occurred. | |
39 | ||
40 | 3 | public constant OK = 0 |
41 | ||
42 | --** | |
43 | -- Permission has been denied. This can happen when using a send_to call on a broadcast | |
44 | -- address without setting the socket option SO_BROADCAST. Another, possibly more common, | |
45 | -- reason is you have tried to bind an address that is already exclusively bound by | |
46 | -- another application. | |
47 | -- | |
48 | -- May occur on a Unix Domain Socket when the socket directory or file could not be | |
49 | -- accessed due to security. | |
50 | ||
51 | 3 | public constant ERR_ACCESS = -1 |
52 | ||
53 | --** | |
54 | -- Address is already in use. | |
55 | ||
56 | 3 | public constant ERR_ADDRINUSE = -2 |
57 | ||
58 | --** | |
59 | -- The specified address is not a valid local IP address on this computer. | |
60 | ||
61 | 3 | public constant ERR_ADDRNOTAVAIL = -3 |
62 | ||
63 | --** | |
64 | -- Address family not supported by the protocol family. | |
65 | ||
66 | 3 | public constant ERR_AFNOSUPPORT = -4 |
67 | ||
68 | --** | |
69 | -- Kernel resources to complete the request are temporarly unavailable. | |
70 | ||
71 | 3 | public constant ERR_AGAIN = -5 |
72 | ||
73 | --** | |
74 | -- Operation is already in progress. | |
75 | ||
76 | 3 | public constant ERR_ALREADY = -6 |
77 | ||
78 | --** | |
79 | -- Software has caused a connection to be aborted. | |
80 | ||
81 | 3 | public constant ERR_CONNABORTED = -7 |
82 | ||
83 | --** | |
84 | -- Connection was refused. | |
85 | ||
86 | 3 | public constant ERR_CONNREFUSED = -8 |
87 | ||
88 | --** | |
89 | -- An incomming connection was supplied however it was terminated by the remote peer. | |
90 | ||
91 | 3 | public constant ERR_CONNRESET = -9 |
92 | ||
93 | --** | |
94 | -- Destination address required. | |
95 | ||
96 | 3 | public constant ERR_DESTADDRREQ = -10 |
97 | ||
98 | --** | |
99 | -- Address creation has failed internally. | |
100 | ||
101 | 3 | public constant ERR_FAULT = -11 |
102 | ||
103 | --** | |
104 | -- No route to the host specified could be found. | |
105 | ||
106 | 3 | public constant ERR_HOSTUNREACH = -12 |
107 | ||
108 | --** | |
109 | -- A blocking call is inprogress. | |
110 | ||
111 | 3 | public constant ERR_INPROGRESS = -13 |
112 | ||
113 | --** | |
114 | -- A blocking call was cancelled or interrupted. | |
115 | ||
116 | 3 | public constant ERR_INTR = -14 |
117 | ||
118 | --** | |
119 | -- An invalid sequence of command calls were made, for instance trying to ##accept## | |
120 | -- before an actual ##listen## was called. | |
121 | ||
122 | 3 | public constant ERR_INVAL = -15 |
123 | ||
124 | --** | |
125 | -- An I/O error occurred while making the directory entry or allocating the | |
126 | -- inode. (Unix Domain Socket). | |
127 | ||
128 | 3 | public constant ERR_IO = -16 |
129 | ||
130 | --** | |
131 | -- Socket is already connected. | |
132 | ||
133 | 3 | public constant ERR_ISCONN = -17 |
134 | ||
135 | --** | |
136 | -- An empty pathname was specified. (Unix Domain Socket). | |
137 | ||
138 | 3 | public constant ERR_ISDIR = -18 |
139 | ||
140 | --** | |
141 | -- Too many symbolic links were encountered. (Unix Domain Socket). | |
142 | ||
143 | 3 | public constant ERR_LOOP = -19 |
144 | ||
145 | --** | |
146 | -- The queue is not empty upon routine call. | |
147 | ||
148 | 3 | public constant ERR_MFILE = -20 |
149 | ||
150 | --** | |
151 | -- Message is too long for buffer size. This would indicate an internal error to | |
152 | -- Euphoria as Euphoria sets a dynamic buffer size. | |
153 | ||
154 | 3 | public constant ERR_MSGSIZE = -21 |
155 | ||
156 | --** | |
157 | -- Component of the path name exceeded 255 characters or the entire path | |
158 | -- exceeded 1023 characters. (Unix Domain Socket). | |
159 | ||
160 | 3 | public constant ERR_NAMETOOLONG = -22 |
161 | ||
162 | --** | |
163 | -- The network subsystem is down or has failed | |
164 | ||
165 | 3 | public constant ERR_NETDOWN = -23 |
166 | ||
167 | --** | |
168 | -- Network has dropped it's connection on reset. | |
169 | ||
170 | 3 | public constant ERR_NETRESET = -24 |
171 | ||
172 | --** | |
173 | -- Network is unreachable. | |
174 | ||
175 | 3 | public constant ERR_NETUNREACH = -25 |
176 | ||
177 | --** | |
178 | -- Not a file. (Unix Domain Sockets). | |
179 | ||
180 | 3 | public constant ERR_NFILE = -26 |
181 | ||
182 | --** | |
183 | -- No buffer space is available. | |
184 | ||
185 | 3 | public constant ERR_NOBUFS = -27 |
186 | ||
187 | --** | |
188 | -- Named socket does not exist. (Unix Domain Socket). | |
189 | ||
190 | 3 | public constant ERR_NOENT = -28 |
191 | ||
192 | --** | |
193 | -- Socket is not connected. | |
194 | ||
195 | 3 | public constant ERR_NOTCONN = -29 |
196 | ||
197 | --** | |
198 | -- Component of the path prefix is not a directory. (Unix Domain Socket). | |
199 | ||
200 | 3 | public constant ERR_NOTDIR = -30 |
201 | ||
202 | --** | |
203 | -- Socket system is not initialized (Windows only) | |
204 | ||
205 | 3 | public constant ERR_NOTINITIALISED = -31 |
206 | ||
207 | --** | |
208 | -- The descriptor is not a socket. | |
209 | ||
210 | 3 | public constant ERR_NOTSOCK = -32 |
211 | ||
212 | --** | |
213 | -- Operation is not supported on this type of socket. | |
214 | ||
215 | 3 | public constant ERR_OPNOTSUPP = -33 |
216 | ||
217 | --** | |
218 | -- Protocol not supported. | |
219 | ||
220 | 3 | public constant ERR_PROTONOSUPPORT = -34 |
221 | ||
222 | --** | |
223 | -- Protocol is the wrong type for the socket. | |
224 | ||
225 | 3 | public constant ERR_PROTOTYPE = -35 |
226 | ||
227 | --** | |
228 | -- The name would reside on a read-only file system. (Unix Domain Socket). | |
229 | ||
230 | 3 | public constant ERR_ROFS = -36 |
231 | ||
232 | --** | |
233 | -- The socket has been shutdown. Possibly a send/receive call after a shutdown took | |
234 | -- place. | |
235 | ||
236 | 3 | public constant ERR_SHUTDOWN = -37 |
237 | ||
238 | --** | |
239 | -- Socket type is not supported. | |
240 | ||
241 | 3 | public constant ERR_SOCKTNOSUPPORT = -38 |
242 | ||
243 | --** | |
244 | -- Connection has timed out. | |
245 | ||
246 | 3 | public constant ERR_TIMEDOUT = -39 |
247 | ||
248 | --** | |
249 | -- The operation would block on a socket marked as non-blocking. | |
250 | ||
251 | 3 | public constant ERR_WOULDBLOCK = -40 |
252 | ||
253 | --**** | |
254 | -- === Socket Type Constants | |
255 | -- | |
256 | -- These values are passed as the ##family## and ##sock_type## parameters of | |
257 | -- the [[:create]] function. | |
258 | -- | |
259 | ||
260 | 3 | ifdef WIN32 then |
261 | public constant | |
262 | --** | |
263 | -- Address family is unspecified | |
264 | AF_UNSPEC=0, | |
265 | --** | |
266 | -- Local communications | |
267 | AF_UNIX=-1, | |
268 | --** | |
269 | -- IPv4 Internet protocols | |
270 | AF_INET=2, | |
271 | --** | |
272 | -- IPv6 Internet protocols | |
273 | AF_INET6=23, | |
274 | --** | |
275 | -- Appletalk | |
276 | AF_APPLETALK=17, | |
277 | --** | |
278 | -- Bluetooth | |
279 | AF_BTH=32, | |
280 | --** | |
281 | -- Provides sequenced, reliable, two-way, connection-based byte streams. | |
282 | -- An out-of-band data transmission mechanism may be supported. | |
283 | SOCK_STREAM=1, | |
284 | --** | |
285 | -- Supports datagrams (connectionless, unreliable messages of a | |
286 | -- fixed maximum length). | |
287 | SOCK_DGRAM=2, | |
288 | --** | |
289 | -- Provides raw network protocol access. | |
290 | SOCK_RAW=3, | |
291 | --** | |
292 | -- Provides a reliable datagram layer that does not guarantee ordering. | |
293 | SOCK_RDM=4, | |
294 | --** | |
295 | -- Obsolete and should not be used in new programs | |
296 | SOCK_SEQPACKET=5 | |
297 | ||
298 | elsifdef LINUX then | |
299 | public constant | |
300 | 3 | AF_UNSPEC=0, AF_UNIX=1, AF_INET=2, AF_APPLETALK=5, AF_INET6=10, |
301 | 3 | SOCK_STREAM=1, SOCK_DGRAM=2, SOCK_RAW=3, SOCK_RDM=4, SOCK_SEQPACKET=5 |
302 | ||
303 | elsifdef SUNOS then | |
304 | public constant | |
305 | AF_UNSPEC=0, AF_UNIX=1, AF_INET=2, AF_APPLETALK=16, AF_INET6=26, | |
306 | SOCK_STREAM=2, SOCK_DGRAM=1, SOCK_RAW=4, SOCK_RDM=5, SOCK_SEQPACKET=6 | |
307 | ||
308 | elsifdef OSX then | |
309 | public constant | |
310 | AF_UNSPEC=0, AF_UNIX=1, AF_INET=2, AF_APPLETALK=16, AF_INET6=30, | |
311 | SOCK_STREAM=1, SOCK_DGRAM=2, SOCK_RAW=3, SOCK_RDM=4, SOCK_SEQPACKET=5 | |
312 | ||
313 | elsifdef FREEBSD then | |
314 | public constant | |
315 | AF_UNSPEC=0, AF_UNIX=1, AF_INET=2, AF_APPLETALK=16, AF_INET6=28, | |
316 | SOCK_STREAM=1, SOCK_DGRAM=2, SOCK_RAW=3, SOCK_RDM=4, SOCK_SEQPACKET=5 | |
317 | end ifdef | |
318 | ||
319 | --**** | |
320 | -- === Select Accessor Constants | |
321 | -- | |
322 | -- Use with the result of [[:select]]. | |
323 | -- | |
324 | ||
325 | public enum | |
326 | --** | |
327 | -- The socket | |
328 | 3 | SELECT_SOCKET, |
329 | ||
330 | --** | |
331 | -- Boolean (1/0) value indicating the readability. | |
332 | 3 | SELECT_IS_READABLE, |
333 | ||
334 | --** | |
335 | -- Boolean (1/0) value indicating the writeability. | |
336 | 3 | SELECT_IS_WRITABLE, |
337 | ||
338 | --** | |
339 | -- Boolean (1/0) value indicating the error state. | |
340 | 3 | SELECT_IS_ERROR |
341 | ||
342 | --**** | |
343 | -- === Shutdown Options | |
344 | -- | |
345 | -- Pass one of the following to the ##method## parameter of [[:shutdown]]. | |
346 | -- | |
347 | ||
348 | public constant | |
349 | --** | |
350 | -- Shutdown the send operations. | |
351 | 3 | SD_SEND = 0, |
352 | ||
353 | --** | |
354 | -- Shutdown the receive operations. | |
355 | 3 | SD_RECEIVE = 1, |
356 | ||
357 | --** | |
358 | -- Shutdown both send and receive operations. | |
359 | 3 | SD_BOTH = 2 |
360 | ||
361 | --**** | |
362 | -- === Socket Options | |
363 | -- | |
364 | -- Pass to the ##optname## parameter of the functions [[:get_option]] | |
365 | -- and [[:set_option]]. | |
366 | -- | |
367 | -- These options are highly OS specific and are normally not needed for most | |
368 | -- socket communication. They are provided here for your convenience. If you should | |
369 | -- need to set socket options, please refer to your OS reference material. | |
370 | -- | |
371 | -- There may be other values that your OS defines and some defined here are not | |
372 | -- supported on all operating systems. | |
373 | ||
374 | 3 | ifdef WINDOWS then |
375 | public constant | |
376 | SOL_SOCKET = #FFFF, | |
377 | SO_DEBUG = #0001, | |
378 | SO_ACCEPTCONN = #0002, | |
379 | SO_REUSEADDR = #0004, | |
380 | SO_KEEPALIVE = #0008, | |
381 | SO_DONTROUTE = #0010, | |
382 | SO_BROADCAST = #0020, | |
383 | SO_USELOOPBACK = #0040, | |
384 | SO_LINGER = #0080, | |
385 | SO_DONTLINGER = not_bits(SO_LINGER), | |
386 | SO_OOBINLINE = #0100, | |
387 | SO_REUSEPORT = #9999, | |
388 | SO_SNDBUF = #1001, | |
389 | SO_RCVBUF = #1002, | |
390 | SO_SNDLOWAT = #1003, | |
391 | SO_RCVLOWAT = #1004, | |
392 | SO_SNDTIMEO = #1005, | |
393 | SO_RCVTIMEO = #1006, | |
394 | SO_ERROR = #1007, | |
395 | SO_TYPE = #1008, | |
396 | SO_CONNDATA = #7000, | |
397 | SO_CONNOPT = #7001, | |
398 | SO_DISCDATA = #7002, | |
399 | SO_DISCOPT = #7003, | |
400 | SO_CONNDATALEN = #7004, | |
401 | SO_CONNOPTLEN = #7005, | |
402 | SO_DISCDATALEN = #7006, | |
403 | SO_DISCOPTLEN = #7007, | |
404 | SO_OPENTYPE = #7008, | |
405 | SO_MAXDG = #7009, | |
406 | SO_MAXPATHDG = #700A, | |
407 | SO_SYNCHRONOUS_ALTERT = #10, | |
408 | SO_SYNCHRONOUS_NONALERT = #20 | |
409 | elsifdef LINUX then | |
410 | 3 | public constant SOL_SOCKET = 1, |
411 | 3 | SO_REUSEADDR = 2, |
412 | 3 | SO_TYPE = 3, |
413 | 3 | SO_KEEPALIVE = 9 |
414 | end ifdef | |
415 | --**** | |
416 | -- === Send Flags | |
417 | -- | |
418 | -- Pass to the ##flags## parameter of [[:send]] and [[:receive]] | |
419 | -- | |
420 | ||
421 | public constant | |
422 | --** | |
423 | -- Sends out-of-band data on sockets that support this notion (e.g., of | |
424 | -- type [[:SOCK_STREAM]]); the underlying protocol must also support | |
425 | -- out-of-band data. | |
426 | ||
427 | 3 | MSG_OOB = #1, |
428 | ||
429 | --** | |
430 | -- This flag causes the receive operation to return data from the | |
431 | -- beginning of the receive queue without removing that data from the | |
432 | -- queue. Thus, a subsequent receive call will return the same data. | |
433 | ||
434 | 3 | MSG_PEEK = #2, |
435 | ||
436 | --** | |
437 | -- Don't use a gateway to send out the packet, only send to hosts on | |
438 | -- directly connected networks. This is usually used only by diagnostic | |
439 | -- or routing programs. This is only defined for protocol families that | |
440 | -- route; packet sockets don't. | |
441 | ||
442 | 3 | MSG_DONTROUTE = #4, |
443 | ||
444 | 3 | MSG_TRYHARD = #4, |
445 | ||
446 | --** | |
447 | -- indicates that some control data were discarded due to lack of space in | |
448 | -- the buffer for ancillary data. | |
449 | ||
450 | 3 | MSG_CTRUNC = #8, |
451 | ||
452 | 3 | MSG_PROXY = #10, |
453 | ||
454 | --** | |
455 | -- indicates that the trailing portion of a datagram was discarded because | |
456 | -- the datagram was larger than the buffer supplied. | |
457 | ||
458 | 3 | MSG_TRUNC = #20, |
459 | ||
460 | --** | |
461 | -- Enables non-blocking operation; if the operation would block, EAGAIN | |
462 | -- or EWOULDBLOCK is returned. | |
463 | ||
464 | 3 | MSG_DONTWAIT = #40, |
465 | ||
466 | --** | |
467 | -- Terminates a record (when this notion is supported, as for sockets of | |
468 | -- type [[:SOCK_SEQPACKET]]). | |
469 | ||
470 | 3 | MSG_EOR = #80, |
471 | ||
472 | --** | |
473 | -- This flag requests that the operation block until the full request is | |
474 | -- satisfied. However, the call may still return less data than requested | |
475 | -- if a signal is caught, an error or disconnect occurs, or the next data | |
476 | -- to be received is of a different type than that returned. | |
477 | ||
478 | 3 | MSG_WAITALL = #100, |
479 | ||
480 | 3 | MSG_FIN = #200, |
481 | ||
482 | 3 | MSG_SYN = #400, |
483 | ||
484 | --** | |
485 | -- Tell the link layer that forward progress happened: you got a | |
486 | -- successful reply from the other side. If the link layer doesn't get | |
487 | -- this it will regularly reprobe the neighbor (e.g., via a unicast ARP). | |
488 | -- Only valid on [[:SOCK_DGRAM]] and [[:SOCK_RAW]] sockets and currently only | |
489 | -- implemented for IPv4 and IPv6. | |
490 | ||
491 | 3 | MSG_CONFIRM = #800, |
492 | ||
493 | 3 | MSG_RST = #1000, |
494 | ||
495 | --** | |
496 | -- indicates that no data was received but an extended error from the | |
497 | -- socket error queue. | |
498 | ||
499 | 3 | MSG_ERRQUEUE = #2000, |
500 | ||
501 | --** | |
502 | -- Requests not to send SIGPIPE on errors on stream oriented sockets when | |
503 | -- the other end breaks the connection. The EPIPE error is still | |
504 | -- returned. | |
505 | ||
506 | 3 | MSG_NOSIGNAL = #4000, |
507 | ||
508 | --** | |
509 | -- The caller has more data to send. This flag is used with TCP sockets | |
510 | -- to obtain the same effect as the TCP_CORK socket option, with the | |
511 | -- difference that this flag can be set on a per-call basis. | |
512 | ||
513 | 3 | MSG_MORE = #8000 |
514 | ||
515 | --**** | |
516 | -- === Server and Client sides | |
517 | -- | |
518 | ||
519 | -- Not made public as the end user should have no need of accessing one value | |
520 | -- or the other. | |
521 | export enum | |
522 | --** | |
523 | -- Accessor index for socket handle of a socket type | |
524 | ||
525 | 3 | SOCKET_SOCKET, |
526 | ||
527 | --** | |
528 | -- Accessor index for the sockaddr_in pointer of a socket type | |
529 | ||
530 | 3 | SOCKET_SOCKADDR_IN |
531 | ||
532 | --** | |
533 | -- Socket type | |
534 | -- | |
535 | ||
536 | 37 | |
537 | 37 | if not sequence(o) then return 0 end if |
538 | 37 | if not length(o) = 2 then return 0 end if |
539 | 37 | if not atom(o[1]) then return 0 end if |
540 | 37 | if not atom(o[2]) then return 0 end if |
541 | ||
542 | 37 | return 1 |
543 | end type | |
544 | ||
545 | 2 | |
546 | 2 | if not socket(o) then |
547 | 0 | return |
548 | end if | |
549 | 2 | if o[SOCKET_SOCKADDR_IN] = 0 then |
550 | 0 | return |
551 | end if | |
552 | ||
553 | 2 | mem:free(o[SOCKET_SOCKADDR_IN]) |
554 | 2 | end procedure |
555 | 3 | integer delete_socket_rid = routine_id("delete_socket") |
556 | ||
557 | --** | |
558 | -- Create a new socket | |
559 | -- | |
560 | -- Parameters: | |
561 | -- # ##family##: an integer | |
562 | -- # ##sock_type##: an integer, the type of socket to create | |
563 | -- # ##protocol##: an integer, the communication protocol being used | |
564 | -- | |
565 | -- ##family## options: | |
566 | -- * [[:AF_UNIX]] | |
567 | -- * [[:AF_INET]] | |
568 | -- * [[:AF_INET6]] | |
569 | -- * [[:AF_APPLETALK]] | |
570 | -- * [[:AF_BTH]] | |
571 | -- | |
572 | -- ##sock_type## options: | |
573 | -- * [[:SOCK_STREAM]] | |
574 | -- * [[:SOCK_DGRAM]] | |
575 | -- * [[:SOCK_RAW]] | |
576 | -- * [[:SOCK_RDM]] | |
577 | -- * [[:SOCK_SEQPACKET]] | |
578 | -- | |
579 | -- Returns: | |
580 | -- An **object**, -1 on failure, else a supposedly valid socket id. | |
581 | -- | |
582 | -- Example 1: | |
583 | -- | |
584 | -- socket = create(AF_INET, SOCK_STREAM, 0) | |
585 | -- | |
586 | ||
587 | 4 | |
588 | 4 | object o = machine_func(M_SOCK_SOCKET, { family, sock_type, protocol }) |
589 | 4 | if atom(o) then return o end if |
590 | 4 | return delete_routine(o, delete_socket_rid) |
591 | end function | |
592 | ||
593 | --** | |
594 | -- Closes a socket. | |
595 | -- | |
596 | -- Parameters: | |
597 | -- # ##sock##: the socket to close | |
598 | -- | |
599 | -- Returns: | |
600 | -- An **integer**, 0 on success and -1 on error. | |
601 | -- | |
602 | -- Comments: | |
603 | -- It may take several minutes for the OS to declare the socket as closed. | |
604 | -- | |
605 | ||
606 | 4 | |
607 | 4 | return machine_func(M_SOCK_CLOSE, { sock }) |
608 | end function | |
609 | ||
610 | --** | |
611 | -- Partially or fully close a socket. | |
612 | -- | |
613 | -- Parameters: | |
614 | -- # ##sock## : the socket to shutdown | |
615 | -- # ##method## : the method used to close the socket | |
616 | -- | |
617 | -- Returns: | |
618 | -- An **integer**, 0 on success and -1 on error. | |
619 | -- | |
620 | -- Comments: | |
621 | -- Three constants are defined that can be sent to ##method##: | |
622 | -- * [[:SD_SEND]] - shutdown the send operations. | |
623 | -- * [[:SD_RECEIVE]] - shutdown the receive operations. | |
624 | -- * [[:SD_BOTH]] - shutdown both send and receive operations. | |
625 | -- | |
626 | -- It may take several minutes for the OS to declare the socket as closed. | |
627 | -- | |
628 | ||
629 | 0 | |
630 | 0 | return machine_func(M_SOCK_SHUTDOWN, { sock, method }) |
631 | end function | |
632 | ||
633 | --** | |
634 | -- Determine the read, write and error status of one or more sockets. | |
635 | -- | |
636 | -- Using select, you can check to see if a socket has data waiting and | |
637 | -- is read to be read, if a socket can be written to and if a socket has | |
638 | -- an error status. | |
639 | -- | |
640 | -- select allows for fine-grained control over your sockets, allow you | |
641 | -- to specify that a given socket only be checked for reading or for only | |
642 | -- reading and writing, etc. | |
643 | -- | |
644 | -- Parameters: | |
645 | -- # ##sockets_read## : either one socket or a sequence of sockets to check for reading. | |
646 | -- # ##sockets_write## : either one socket or a sequence of sockets to check for writing. | |
647 | -- # ##sockets_err## : either one socket or a sequence of sockets to check for errors. | |
648 | -- # ##timeout## : maximum time to wait to determine a sockets status, seconds part | |
649 | -- # ##timeout_micro## : maximum time to wait to determine a sockets status, microsecond part | |
650 | -- | |
651 | -- Returns: | |
652 | -- A **sequence**, of the same size of all unique sockets containing | |
653 | -- { socket, read_status, write_status, error_status } for each socket passed | |
654 | -- 2 to the function. | |
655 | -- Note that the sockets returned are not guaranteed to be in any particular order. | |
656 | -- | |
657 | ||
658 | 3 | |
659 | object sockets_err, integer timeout=0, | |
660 | integer timeout_micro=0) | |
661 | sequence sockets_all | |
662 | ||
663 | 3 | if length(sockets_read) and socket(sockets_read) then |
664 | 3 | sockets_read = { sockets_read } |
665 | end if | |
666 | 3 | if length(sockets_write) and socket(sockets_write) then |
667 | 0 | sockets_write = { sockets_write } |
668 | end if | |
669 | 3 | if length(sockets_err) and socket(sockets_err) then |
670 | 0 | sockets_err = { sockets_err } |
671 | end if | |
672 | ||
673 | -- if the user has passed in one socket (or set of sockets) for | |
674 | -- all three lists, then save time by not bothering to sort the list | |
675 | -- or remove duplicates | |
676 | 3 | if equal(sockets_err, sockets_read) and |
677 | equal(sockets_write, sockets_read) then | |
678 | 0 | sockets_all = sockets_read |
679 | else | |
680 | 3 | sockets_all = remove_dups(sockets_read & sockets_write |
681 | & sockets_err, RD_SORT) | |
682 | end if | |
683 | ||
684 | 3 | return machine_func(M_SOCK_SELECT, { sockets_read, sockets_write, |
685 | sockets_err, sockets_all, timeout_micro, timeout }) | |
686 | end function | |
687 | ||
688 | --** | |
689 | -- Send TCP data to a socket connected remotely. | |
690 | -- | |
691 | -- Parameters: | |
692 | -- # ##sock## : the socket to send data to | |
693 | -- # ##data## : a sequence of atoms, what to send | |
694 | -- # ##flags## : flags (see [[:Send Flags]]) | |
695 | -- | |
696 | -- Returns: | |
697 | -- An **integer**, the number of characters sent, or -1 for an error. | |
698 | -- | |
699 | ||
700 | 7 | |
701 | 7 | return machine_func(M_SOCK_SEND, { sock, data, flags }) |
702 | end function | |
703 | ||
704 | --** | |
705 | -- Receive data from a bound socket. | |
706 | -- | |
707 | -- Parameters: | |
708 | -- # ##sock## : the socket to get data from | |
709 | -- # ##flags## : flags (see [[:Send Flags]]) | |
710 | -- | |
711 | -- Returns: | |
712 | -- A **sequence**, either a full string of data on success, or an atom indicating | |
713 | -- the error code. | |
714 | -- | |
715 | -- Comments: | |
716 | -- This function will not return until data is actually received on the socket, | |
717 | -- unless the flags parameter contains [[:MSG_DONTWAIT]]. | |
718 | -- | |
719 | -- [[:MSG_DONTWAIT]] only works on Linux kernels 2.4 and above. To be cross-platform | |
720 | -- you should use [[:select]] to determine if a socket is readable, i.e. has data | |
721 | -- waiting. | |
722 | -- | |
723 | ||
724 | 6 | |
725 | 6 | return machine_func(M_SOCK_RECV, { sock, flags }) |
726 | end function | |
727 | ||
728 | --** | |
729 | -- Get options for a socket. | |
730 | -- | |
731 | -- Parameters: | |
732 | -- # ##sock## : the socket | |
733 | -- # ##level## : an integer, the option level | |
734 | -- # ##optname## : requested option (See [[:Socket Options]]) | |
735 | -- | |
736 | -- Returns: | |
737 | -- An **object**, either: | |
738 | -- * On error, {"ERROR",error_code}. | |
739 | -- * On success, either an atom or a sequence containing the option value, depending on the option. | |
740 | -- | |
741 | -- Comments: | |
742 | -- Primarily for use in multicast or more advanced socket | |
743 | -- applications. Level is the option level, and option_name is the | |
744 | -- option for which values are being sought. Level is usually | |
745 | -- [[:SOL_SOCKET]]. | |
746 | -- | |
747 | -- Returns: | |
748 | -- An **atom**, On error, an atom indicating the error code.\\ | |
749 | -- A **sequence** or **atom**, On success, either an atom or | |
750 | -- a sequence containing the option value. | |
751 | -- | |
752 | -- See also: | |
753 | -- [[:get_option]] | |
754 | -- | |
755 | ||
756 | 5 | |
757 | 5 | return machine_func(M_SOCK_GETSOCKOPT, { sock, level, optname }) |
758 | end function | |
759 | ||
760 | --** | |
761 | -- Set options for a socket. | |
762 | -- | |
763 | -- Parameters: | |
764 | -- # ##sock## : an atom, the socket id | |
765 | -- # ##level## : an integer, the option level | |
766 | -- # ##optname## : requested option (See [[:Socket Options]]) | |
767 | -- # ##val## : an object, the new value for the option | |
768 | -- | |
769 | -- Returns: | |
770 | -- An **integer**, 0 on success, -1 on error. | |
771 | -- | |
772 | -- Comments: | |
773 | -- Primarily for use in multicast or more advanced socket | |
774 | -- applications. Level is the option level, and option_name is the | |
775 | -- option for which values are being set. Level is usually | |
776 | -- [[:SOL_SOCKET]]. | |
777 | -- | |
778 | -- See Also: | |
779 | -- [[:get_option]] | |
780 | ||
781 | 2 | |
782 | 2 | return machine_func(M_SOCK_SETSOCKOPT, { sock, level, optname, val }) |
783 | end function | |
784 | ||
785 | --**** | |
786 | -- === Client side only | |
787 | ||
788 | --** | |
789 | -- Establish an outgoing connection to a remote computer. Only works with TCP sockets. | |
790 | -- | |
791 | -- Parameters: | |
792 | -- # ##sock## : the socket | |
793 | -- # ##address## : ip address to connect, optionally with :PORT at the end | |
794 | -- # ##port## : port number | |
795 | -- | |
796 | -- Returns: | |
797 | -- An **integer**, 0 for success and -1 on failure. | |
798 | -- | |
799 | -- Comments: | |
800 | -- ##address## can contain a port number. If it does not, it has to be supplied | |
801 | -- to the ##port## parameter. | |
802 | -- | |
803 | -- Example 1: | |
804 | -- | |
805 | -- success = connect(sock, "11.1.1.1") -- uses default port 80 | |
806 | -- success = connect(sock, "11.1.1.1:110") -- uses port 110 | |
807 | -- success = connect(sock, "11.1.1.1", 345) -- uses port 345 | |
808 | -- | |
809 | ||
810 | 4 | |
811 | 4 | object sock_data = parse_ip_address(address, port) |
812 | ||
813 | 4 | return machine_func(M_SOCK_CONNECT, { sock, sock_data[1], sock_data[2] }) |
814 | end function | |
815 | ||
816 | --**** | |
817 | -- === Server side only | |
818 | ||
819 | --** | |
820 | -- Joins a socket to a specific local internet address and port so | |
821 | -- later calls only need to provide the socket. | |
822 | -- | |
823 | -- Parameters: | |
824 | -- # ##sock## : the socket | |
825 | -- # ##address## : the address to bind the socket to | |
826 | -- # ##port## : optional, if not specified you must include :PORT in | |
827 | -- the address parameter. | |
828 | -- | |
829 | -- Returns: | |
830 | -- An **integer**, 0 on success and -1 on failure. | |
831 | -- | |
832 | -- Example 1: | |
833 | -- | |
834 | -- -- Bind to all interfaces on the default port 80. | |
835 | -- success = bind(socket, "0.0.0.0") | |
836 | -- -- Bind to all interfaces on port 8080. | |
837 | -- success = bind(socket, "0.0.0.0:8080") | |
838 | -- -- Bind only to the 243.17.33.19 interface on port 345. | |
839 | -- success = bind(socket, "243.17.33.19", 345) | |
840 | -- | |
841 | ||
842 | 0 | |
843 | 0 | object sock_data = parse_ip_address(address, port) |
844 | ||
845 | 0 | return machine_func(M_SOCK_BIND, { sock, sock_data[1], sock_data[2] }) |
846 | end function | |
847 | ||
848 | --** | |
849 | -- Start monitoring a connection. Only works with TCP sockets. | |
850 | -- | |
851 | -- Parameters: | |
852 | -- # ##sock## : the socket | |
853 | -- # ##backlog## : the number of connection requests that | |
854 | -- can be kept waiting before the OS refuses to hear any more. | |
855 | -- | |
856 | -- Returns: | |
857 | -- An **integer**, 0 on success and an error code on failure. | |
858 | -- | |
859 | -- Comments: | |
860 | -- Once the socket is created and bound, this will indicate to the | |
861 | -- operating system that you are ready to being listening for connections. | |
862 | -- | |
863 | -- The value of ##backlog## is strongly dependent on both the hardware | |
864 | -- and the amount of time it takes the program to process each | |
865 | -- connection request. | |
866 | -- | |
867 | -- This function must be executed after [[:bind]](). | |
868 | -- | |
869 | ||
870 | 0 | |
871 | 0 | return machine_func(M_SOCK_LISTEN, { sock, backlog }) |
872 | end function | |
873 | ||
874 | --** | |
875 | -- Produces a new socket for an incoming connection. | |
876 | -- | |
877 | -- Parameters: | |
878 | -- # ##sock##: the server socket | |
879 | -- | |
880 | -- Returns: | |
881 | -- An **atom**, on error\\ | |
882 | -- A **sequence**, | |
883 | -- ##{socket client, sequence client_ip_address}## | |
884 | -- on success. | |
885 | -- | |
886 | -- Comments: | |
887 | -- Using this function allows communication to occur on a | |
888 | -- "side channel" while the main server socket remains available | |
889 | -- for new connections. | |
890 | -- | |
891 | -- ##accept##() must be called after ##bind##() and ##listen##(). | |
892 | -- | |
893 | ||
894 | 0 | |
895 | 0 | return machine_func(M_SOCK_ACCEPT, { sock }) |
896 | end function | |
897 | ||
898 | --**** | |
899 | -- === UDP only | |
900 | -- | |
901 | ||
902 | --** | |
903 | -- Send a UDP packet to a given socket | |
904 | -- | |
905 | -- Parameters: | |
906 | -- # ##sock##: the server socket | |
907 | -- # ##data##: the data to be sent | |
908 | -- # ##ip##: the ip where the data is to be sent to (ip:port) | |
909 | -- is acceptable | |
910 | -- # ##port##: the port where the data is to be sent on (if not supplied with the ip) | |
911 | -- # ##flags## : flags (see [[:Send Flags]]) | |
912 | -- | |
913 | -- Returns: | |
914 | -- An ##integer## status code. | |
915 | -- | |
916 | -- See Also: | |
917 | -- [[:receive_from]] | |
918 | -- | |
919 | ||
920 | 0 | |
921 | atom flags=0) | |
922 | 0 | object sock_data = parse_ip_address(address, port) |
923 | ||
924 | 0 | return machine_func(M_SOCK_SENDTO, { sock, data, flags, sock_data[1], sock_data[2] }) |
925 | end function | |
926 | ||
927 | --** | |
928 | -- Receive a UDP packet from a given socket | |
929 | -- | |
930 | -- Parameters: | |
931 | -- # ##sock##: the server socket | |
932 | -- # ##flags## : flags (see [[:Send Flags]]) | |
933 | -- | |
934 | -- Returns: | |
935 | -- A ##sequence## containing { client_ip, client_port, data } or an ##atom## error code. | |
936 | -- | |
937 | -- See Also: | |
938 | -- [[:send_to]] | |
939 | -- | |
940 | ||
941 | 0 | |
942 | 0 | return machine_func(M_SOCK_RECVFROM, { sock, flags }) |
943 | end function | |
944 | ||
945 | --**** | |
946 | -- === Information | |
947 | ||
948 | --** | |
949 | -- Get service information by name. | |
950 | -- | |
951 | -- Parameters: | |
952 | -- # ##name## : service name. | |
953 | -- # ##protocol## : protocol. Default is not to search by protocol. | |
954 | -- | |
955 | -- Returns: | |
956 | -- A **sequence**, containing { official protocol name, protocol, port number } or | |
957 | -- an atom indicating the error code. | |
958 | -- | |
959 | -- Example 1: | |
960 | -- | |
961 | -- object result = getservbyname("http") | |
962 | -- -- result = { "http", "tcp", 80 } | |
963 | -- | |
964 | -- | |
965 | -- See Also: | |
966 | -- [[:service_by_port]] | |
967 | ||
968 | 3 | |
969 | 3 | return machine_func(M_SOCK_GETSERVBYNAME, { name, protocol }) |
970 | end function | |
971 | ||
972 | --** | |
973 | -- Get service information by port number. | |
974 | -- | |
975 | -- Parameters: | |
976 | -- # ##port## : port number. | |
977 | -- # ##protocol## : protocol. Default is not to search by protocol. | |
978 | -- | |
979 | -- Returns: | |
980 | -- A **sequence**, containing { official protocol name, protocol, port number } or | |
981 | -- an atom indicating the error code. | |
982 | -- | |
983 | -- Example 1: | |
984 | -- | |
985 | -- object result = getservbyport(80) | |
986 | -- -- result = { "http", "tcp", 80 } | |
987 | -- | |
988 | -- | |
989 | -- See Also: | |
990 | -- [[:service_by_name]] | |
991 | ||
992 | 3 | |
993 | 3 | return machine_func(M_SOCK_GETSERVBYPORT, { port, protocol }) |
994 | end function |