X-Git-Url: http://nitlanguage.org diff --git a/lib/socket/socket_c.nit b/lib/socket/socket_c.nit index 000e9f7..8758cdf 100644 --- a/lib/socket/socket_c.nit +++ b/lib/socket/socket_c.nit @@ -28,15 +28,16 @@ in "C Header" `{ #include #include #include +`} - typedef struct sockaccept_result { - struct sockaddr_in addr_in; - int s_desc; - } S_ACCEPT_RESULT; +in "C" `{ + #include + #include `} # Wrapper for the data structure PollFD used for polling on a socket class PollFD + super FinalizableOnce # The PollFD object private var poll_struct: NativeSocketPollFD @@ -76,27 +77,30 @@ class PollFD return response & mask; `} + redef fun finalize_once + do + poll_struct.free + end end # Data structure used by the poll function -private extern class NativeSocketPollFD `{ struct pollfd `} +private extern class NativeSocketPollFD `{ struct pollfd * `} - # File descriptor id - private fun fd: Int `{ return recv.fd; `} + # File descriptor + fun fd: Int `{ return recv->fd; `} # List of events to be watched - private fun events: Int `{ return recv.events; `} + fun events: Int `{ return recv->events; `} # List of events received by the last poll function - private fun revents: Int `{ return recv.revents; `} + fun revents: Int `{ return recv->revents; `} new (pid: Int, events: NativeSocketPollValues) `{ - struct pollfd poll; - poll.fd = pid; - poll.events = events; + struct pollfd *poll = malloc(sizeof(struct pollfd)); + poll->fd = pid; + poll->events = events; return poll; `} - end extern class NativeSocket `{ int* `} @@ -141,12 +145,14 @@ extern class NativeSocket `{ int* `} `} # Sets an option for the socket - fun setsockopt(level: NativeSocketOptLevels, option_name: NativeSocketOptNames, option_value: Int) `{ + # + # Returns `true` on success. + fun setsockopt(level: NativeSocketOptLevels, option_name: NativeSocketOptNames, option_value: Int): Bool `{ int err = setsockopt(*recv, level, option_name, &option_value, sizeof(int)); if(err != 0){ - perror("Error on setsockopts: "); - exit(1); + return 0; } + return 1; `} fun bind(addrIn: NativeSocketAddrIn): Int `{ return bind(*recv, (struct sockaddr*)addrIn, sizeof(*addrIn)); `} @@ -177,40 +183,52 @@ extern class NativeSocket `{ int* `} # The array's members are pollfd structures within which fd specifies an open file descriptor and events and revents are bitmasks constructed by # OR'ing a combination of the pollfd flags. private fun native_poll(filedesc: NativeSocketPollFD, timeout: Int): Int `{ - int poll_return = poll(&filedesc, 1, timeout); + int poll_return = poll(filedesc, 1, timeout); return poll_return; `} - private fun native_accept(addrIn: NativeSocketAddrIn): NativeSocket `{ + private fun native_accept(addr_in: NativeSocketAddrIn): NativeSocket `{ socklen_t s = sizeof(struct sockaddr); - int *d = NULL; - d = malloc(sizeof(int)); - *d = accept(*recv,(struct sockaddr*)addrIn, &s); - return d; + int socket = accept(*recv, (struct sockaddr*)addr_in, &s); + if (socket == -1) return NULL; + + int *ptr = malloc(sizeof(int)); + *ptr = socket; + return ptr; `} - fun accept: NativeSocketAcceptResult + fun accept: nullable SocketAcceptResult do var addrIn = new NativeSocketAddrIn var s = native_accept(addrIn) - return new NativeSocketAcceptResult(s, addrIn) + if s.address_is_null then return null + return new SocketAcceptResult(s, addrIn) end -end -extern class NativeSocketAcceptResult `{ S_ACCEPT_RESULT* `} - new (socket: NativeSocket, addrIn: NativeSocketAddrIn) `{ - S_ACCEPT_RESULT *sar = NULL; - sar = malloc(sizeof(S_ACCEPT_RESULT)); - sar->s_desc = *socket; - sar->addr_in = *addrIn; - return sar; + # Set wether this socket is non blocking + fun non_blocking=(value: Bool) `{ + int flags = fcntl(*recv, F_GETFL, 0); + if (flags == -1) flags = 0; + + if (value) { + flags = flags | O_NONBLOCK; + } else if (flags & O_NONBLOCK) { + flags = flags - O_NONBLOCK; + } else { + return; + } + fcntl(*recv, F_SETFL, flags); `} +end - fun socket: NativeSocket `{ return &recv->s_desc; `} +# Result of a call to `NativeSocket::accept` +class SocketAcceptResult - fun addrIn: NativeSocketAddrIn `{ return &recv->addr_in; `} + # Opened socket + var socket: NativeSocket - fun destroy `{ free(recv); `} + # Address of the remote client + var addr_in: NativeSocketAddrIn end extern class NativeSocketAddrIn `{ struct sockaddr_in* `} @@ -220,7 +238,7 @@ extern class NativeSocketAddrIn `{ struct sockaddr_in* `} return sai; `} - new with(port: Int, family: NativeSocketAddressFamilies) `{ + new with_port(port: Int, family: NativeSocketAddressFamilies) `{ struct sockaddr_in *sai = NULL; sai = malloc(sizeof(struct sockaddr_in)); sai->sin_family = family; @@ -308,6 +326,8 @@ extern class NativeSocketSet `{ fd_set* `} end class NativeSocketObserver + # FIXME this implementation is broken. `reads`, `write` and `except` + # are boxed objects, passing them to a C function is illegal. fun select(max: NativeSocket, reads: nullable NativeSocketSet, write: nullable NativeSocketSet, except: nullable NativeSocketSet, timeout: NativeTimeval): Int `{ fd_set *rds, *wts, *exs = NULL; @@ -354,9 +374,6 @@ extern class NativeSocketAddressFamilies `{ int `} # Novell Internet Protocol new af_ipx `{ return AF_IPX; `} - # Integrated Services Digital Network - new af_isdn `{ return AF_ISDN; `} - # IPv6 new af_inet6 `{ return AF_INET6; `} @@ -373,7 +390,6 @@ extern class NativeSocketProtocolFamilies `{ int `} new pf_decnet `{ return PF_DECnet; `} new pf_route `{ return PF_ROUTE; `} new pf_ipx `{ return PF_IPX; `} - new pf_isdn `{ return PF_ISDN; `} new pf_key `{ return PF_KEY; `} new pf_inet6 `{ return PF_INET6; `} new pf_max `{ return PF_MAX; `} @@ -409,6 +425,9 @@ extern class NativeSocketOptNames `{ int `} # Authorizes the use of keep-alive packets in a connection new keepalive `{ return SO_KEEPALIVE; `} + + # Disable the Nagle algorithm and send data as soon as possible, in smaller packets + new tcp_nodelay `{ return TCP_NODELAY; `} end # Used for the poll function of a socket, mix several Poll values to check for events on more than one type of event