Merge: Better error handling in Socket
authorJean Privat <jean@pryen.org>
Wed, 3 Jun 2015 02:00:01 +0000 (22:00 -0400)
committerJean Privat <jean@pryen.org>
Wed, 3 Jun 2015 02:00:01 +0000 (22:00 -0400)
Errors on both finding a host by its name and on connection are reported with all available details as an `Error`.

Pull-Request: #1428
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Jean Privat <jean@pryen.org>

lib/socket/socket.nit
lib/socket/socket_c.nit

index 4885805..a40cc5d 100644 (file)
@@ -71,14 +71,29 @@ class TCPStream
                        closed = true
                        return
                end
-               var hostname = socket.gethostbyname(host)
-               addrin = new NativeSocketAddrIn.with_hostent(hostname, port)
 
+               var hostname = sys.gethostbyname(host.to_cstring)
+               if hostname.address_is_null then
+                       # Error in name lookup
+                       var err = sys.h_errno
+                       last_error = new IOError(err.to_s)
+
+                       closed = true
+                       end_reached = true
+
+                       return
+               end
+
+               addrin = new NativeSocketAddrIn.with_hostent(hostname, port)
                address = addrin.address
                init(addrin.port, hostname.h_name)
 
                closed = not internal_connect
                end_reached = closed
+               if closed then
+                       # Connection failed
+                       last_error = new IOError(errno.strerror)
+               end
        end
 
        # Creates a client socket, this is meant to be used by accept only
index d9056d6..94eecd7 100644 (file)
@@ -121,8 +121,6 @@ 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));
        `}
@@ -482,3 +480,52 @@ extern class NativeSocketPollValues `{ int `}
                return self | other;
        `}
 end
+
+redef class Sys
+       # Get network host entry
+       fun gethostbyname(name: NativeString): 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