X-Git-Url: http://nitlanguage.org diff --git a/lib/socket/socket_c.nit b/lib/socket/socket_c.nit index d9056d6..1486752 100644 --- a/lib/socket/socket_c.nit +++ b/lib/socket/socket_c.nit @@ -121,31 +121,24 @@ extern class NativeSocket `{ int* `} fun descriptor: Int `{ return *self; `} - fun gethostbyname(n: String): NativeSocketHostent import String.to_cstring `{ return gethostbyname(String_to_cstring(n)); `} - fun connect(addrIn: NativeSocketAddrIn): Int `{ return connect(*self, (struct sockaddr*)addrIn, sizeof(*addrIn)); `} - fun write(buffer: String): Int - import String.to_cstring, String.length `{ - return write(*self, (char*)String_to_cstring(buffer), String_length(buffer)); + # Write `length` bytes from `buffer` + fun write(buffer: CString, length: Int): Int `{ + return write(*self, buffer, length); `} # Write `value` as a single byte - fun write_byte(value: Int): Int `{ + fun write_byte(value: Byte): Int `{ unsigned char byt = (unsigned char)value; return write(*self, &byt, 1); `} - fun read: String import NativeString.to_s_with_length, NativeString `{ - char *c = new_NativeString(1024); - int n = read(*self, c, 1023); - if(n < 0) { - return NativeString_to_s_with_length("",0); - } - c[n] = 0; - return NativeString_to_s_with_length(c, n); + # Read `length` bytes into `buffer`, returns the number of bytes read + fun read(buffer: CString, length: Int): Int `{ + return read(*self, buffer, length); `} # Sets an option for the socket @@ -171,6 +164,15 @@ extern class NativeSocket `{ int* `} return filedesc.check_response(result) end + # Poll this socket with `POLLHUP|POLLERR` + # + # A return value of 0 means there is no errors. + fun poll_hup_err: Int `{ + struct pollfd fd = {*self, POLLHUP|POLLERR, 0}; + int res = poll(&fd, 1, 0); + return res; + `} + # Call to the poll function of the C socket # # Signature: @@ -209,7 +211,7 @@ extern class NativeSocket `{ int* `} return new SocketAcceptResult(s, addrIn) end - # Set wether this socket is non blocking + # Set whether this socket is non blocking fun non_blocking=(value: Bool) `{ int flags = fcntl(*self, F_GETFL, 0); if (flags == -1) flags = 0; @@ -223,6 +225,22 @@ extern class NativeSocket `{ int* `} } fcntl(*self, F_SETFL, flags); `} + + # Send `len` bytes from `buf` to `dest_addr` + fun sendto(buf: CString, len: Int, flags: Int, dest_addr: NativeSocketAddrIn): Int `{ + return sendto(*self, buf, len, flags, (struct sockaddr*)dest_addr, sizeof(struct sockaddr_in)); + `} + + # Receive a message into `buf` of maximum `len` bytes + fun recv(buf: CString, len: Int, flags: Int): Int `{ + return recv(*self, buf, len, flags); + `} + + # Receive a message into `buf` of maximum `len` bytes and store sender info into `src_addr` + fun recvfrom(buf: CString, len: Int, flags: Int, src_addr: NativeSocketAddrIn): Int `{ + socklen_t srclen = sizeof(struct sockaddr_in); + return recvfrom(*self, buf, len, flags, (struct sockaddr*)src_addr, &srclen); + `} end # Result of a call to `NativeSocket::accept` @@ -235,64 +253,76 @@ class SocketAcceptResult var addr_in: NativeSocketAddrIn end +# Socket address in the Internet namespace, pointer to a `struct sockaddr_in` extern class NativeSocketAddrIn `{ struct sockaddr_in* `} + + # `NULL` pointer + new nul `{ return NULL; `} + + # `malloc` a new instance new `{ struct sockaddr_in *sai = NULL; sai = malloc(sizeof(struct sockaddr_in)); return sai; `} - new with_port(port: Int, family: NativeSocketAddressFamilies) `{ - struct sockaddr_in *sai = NULL; - sai = malloc(sizeof(struct sockaddr_in)); - sai->sin_family = family; - sai->sin_port = htons(port); - sai->sin_addr.s_addr = INADDR_ANY; - return sai; + # Set `address` and `family` from `hostent` (to use with `Sys::gethostbyname`) + fun fill_from_hostent(hostent: NativeSocketHostent) `{ + self->sin_family = hostent->h_addrtype; + memcpy((char*)&self->sin_addr.s_addr, + (char*)hostent->h_addr, + hostent->h_length); `} - new with_hostent(hostent: NativeSocketHostent, port: Int) `{ - struct sockaddr_in *sai = NULL; - sai = malloc(sizeof(struct sockaddr_in)); - sai->sin_family = hostent->h_addrtype; - sai->sin_port = htons(port); - memcpy((char*)&sai->sin_addr.s_addr, (char*)hostent->h_addr, hostent->h_length); - return sai; - `} + # Internet address as then IPV4 numbers-and-dots notation + fun address: CString `{ return (char*)inet_ntoa(self->sin_addr); `} + + # Set `address` to `INADDR_ANY` + fun address_any `{ self->sin_addr.s_addr = INADDR_ANY; `} - fun address: String import NativeString.to_s `{ return NativeString_to_s((char*)inet_ntoa(self->sin_addr)); `} + # Set `address` to `INADDR_BROADCAST` + fun address_broadcast `{ self->sin_addr.s_addr = INADDR_BROADCAST; `} + # Address family fun family: NativeSocketAddressFamilies `{ return self->sin_family; `} + # Address family + fun family=(value: NativeSocketAddressFamilies) `{ self->sin_family = value; `} + + # Port fun port: Int `{ return ntohs(self->sin_port); `} - fun destroy `{ free(self); `} + # Port + fun port=(value: Int) `{ self->sin_port = htons(value); `} end +# Host entry information, a pointer to a `struct hostent` extern class NativeSocketHostent `{ struct hostent* `} - private fun native_h_aliases(i: Int): String import NativeString.to_s `{ return NativeString_to_s(self->h_aliases[i]); `} - - private fun native_h_aliases_reachable(i: Int): Bool `{ return (self->h_aliases[i] != NULL); `} + private fun native_h_aliases(i: Int): CString `{ + return self->h_aliases[i]; + `} + # Alternative names for the host fun h_aliases: Array[String] do - var i=0 - var d=new Array[String] + var res = new Array[String] loop - d.add(native_h_aliases(i)) - if native_h_aliases_reachable(i+1) == false then break - i += 1 + var ha = native_h_aliases(res.length) + if ha.address_is_null then break + res.add ha.to_s end - return d + return res end - fun h_addr: String import NativeString.to_s `{ return NativeString_to_s((char*)inet_ntoa(*(struct in_addr*)self->h_addr)); `} + fun h_addr: CString `{ + return (char*)inet_ntoa(*(struct in_addr*)self->h_addr); + `} fun h_addrtype: Int `{ return self->h_addrtype; `} fun h_length: Int `{ return self->h_length; `} - fun h_name: String import NativeString.to_s `{ return NativeString_to_s(self->h_name); `} + fun h_name: CString `{ return self->h_name; `} end extern class NativeTimeval `{ struct timeval* `} @@ -334,7 +364,9 @@ class NativeSocketObserver # 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; + fd_set *rds = NULL, + *wts = NULL, + *exs = NULL; struct timeval *tm = NULL; if (reads != NULL) rds = (fd_set*)reads; if (write != NULL) wts = (fd_set*)write; @@ -397,6 +429,7 @@ extern class NativeSocketProtocolFamilies `{ int `} new pf_key `{ return PF_KEY; `} new pf_inet6 `{ return PF_INET6; `} new pf_max `{ return PF_MAX; `} + new ipproto_udp `{ return IPPROTO_UDP; `} end # Level on which to set options @@ -482,3 +515,52 @@ extern class NativeSocketPollValues `{ int `} return self | other; `} end + +redef class Sys + # Get network host entry + fun gethostbyname(name: CString): NativeSocketHostent `{ + return gethostbyname(name); + `} + + # Last error raised by `gethostbyname` + fun h_errno: HErrno `{ return h_errno; `} +end + +# Error code of `Sys::h_errno` +extern class HErrno `{ int `} + # The specified host is unknown + fun host_not_found: Bool `{ return self == HOST_NOT_FOUND; `} + + # The requested name is valid but does not have an IP address + # + # Same as `no_data`. + fun no_address: Bool `{ return self == NO_ADDRESS; `} + + # The requested name is valid byt does not have an IP address + # + # Same as `no_address`. + fun no_data: Bool `{ return self == NO_DATA; `} + + # A nonrecoverable name server error occurred + fun no_recovery: Bool `{ return self == NO_RECOVERY; `} + + # A temporary error occurred on an authoritative name server, try again later + fun try_again: Bool `{ return self == TRY_AGAIN; `} + + redef fun to_s + do + if host_not_found then + return "The specified host is unknown" + else if no_address then + return "The requested name is valid but does not have an IP address" + else if no_recovery then + return "A nonrecoverable name server error occurred" + else if try_again then + return "A temporary error occurred on an authoritative name server, try again later" + else + # This may happen if another call was made to `gethostbyname` + # before we fetch the error code. + return "Unknown error on `gethostbyname`" + end + end +end