lib/socket: intro `TCPSocket`
[nit.git] / lib / socket / socket.nit
index 3cd18ff..7e9018f 100644 (file)
@@ -20,12 +20,21 @@ module socket
 private import socket_c
 intrude import standard::stream
 
-# A general TCP socket, either a `TCPStream` or a `TCPServer`
+# A general Socket, either TCP or UDP
 abstract class Socket
 
        # Underlying C socket
        private var native: NativeSocket is noinit
 
+       # Is this socket closed?
+       var closed = false
+
+end
+
+# A general TCP socket, either a `TCPStream` or a `TCPServer`
+abstract class TCPSocket
+       super Socket
+
        # Port used by the socket
        var port: Int
 
@@ -33,14 +42,11 @@ abstract class Socket
        #
        # Formatted as xxx.xxx.xxx.xxx.
        var address: String is noinit
-
-       # Is this socket closed?
-       var closed = false
 end
 
 # Simple communication stream with a remote socket
 class TCPStream
-       super Socket
+       super TCPSocket
        super BufferedReader
        super Writer
        super PollableReader
@@ -72,8 +78,8 @@ class TCPStream
                        return
                end
 
-               var hostname = sys.gethostbyname(host.to_cstring)
-               if hostname.address_is_null then
+               var hostent = sys.gethostbyname(host.to_cstring)
+               if hostent.address_is_null then
                        # Error in name lookup
                        var err = sys.h_errno
                        last_error = new IOError(err.to_s)
@@ -84,9 +90,12 @@ class TCPStream
                        return
                end
 
-               addrin = new NativeSocketAddrIn.with_hostent(hostname, port)
-               address = addrin.address
-               init(addrin.port, hostname.h_name)
+               addrin = new NativeSocketAddrIn
+               addrin.fill_from_hostent hostent
+               addrin.port = port
+
+               address = addrin.address.to_s
+               init(addrin.port, hostent.h_name.to_s)
 
                closed = not internal_connect
                end_reached = closed
@@ -94,18 +103,20 @@ class TCPStream
                        # Connection failed
                        last_error = new IOError(errno.strerror)
                end
+
+               prepare_buffer(1024)
        end
 
        # Creates a client socket, this is meant to be used by accept only
        private init server_side(h: SocketAcceptResult)
        do
-               _buffer = new NativeString(1024)
-               _buffer_pos = 0
                native = h.socket
                addrin = h.addr_in
-               address = addrin.address
+               address = addrin.address.to_s
 
                init(addrin.port, address)
+
+               prepare_buffer(1024)
        end
 
        redef fun poll_in do return ready_to_read(0)
@@ -159,7 +170,7 @@ class TCPStream
        redef fun write(msg)
        do
                if closed then return
-               native.write(msg.to_s)
+               native.write(msg.to_cstring, msg.length)
        end
 
        redef fun write_byte(value)
@@ -168,36 +179,37 @@ class TCPStream
                native.write_byte value
        end
 
-       redef fun write_bytes(s) do
+       redef fun write_bytes(bytes) do
                if closed then return
-               native.write(s.to_s)
+               var s = bytes.to_s
+               native.write(s.to_cstring, s.length)
        end
 
        fun write_ln(msg: Text)
        do
-               if end_reached then return
-               write(msg.to_s)
-               write("\n")
+               if closed then return
+               write msg.to_s
+               write "\n"
        end
 
        redef fun fill_buffer
        do
-               _buffer_length = 0
-               _buffer_pos = 0
                if not connected then return
-               var read = native.read
-               if read.length == 0 then
+
+               var read = native.read(_buffer, _buffer_capacity)
+               if read == -1 then
                        close
                        end_reached = true
                end
-               enlarge(_buffer_length + read.length)
-               read.copy_to_native(_buffer, read.length, 0, 0)
-               _buffer_length = read.length
+
+               _buffer_length = read
+               _buffer_pos = 0
        end
 
        fun enlarge(len: Int) do
                if _buffer_capacity >= len then return
-               while _buffer_capacity < len do _buffer_capacity = _buffer_capacity * 2 + 2
+               _buffer_capacity = len
+
                var ns = new NativeString(_buffer_capacity)
                _buffer.copy_to(ns, _buffer_length - _buffer_pos, _buffer_pos, 0)
                _buffer = ns
@@ -226,7 +238,7 @@ end
 #
 # Create streams to communicate with clients using `accept`.
 class TCPServer
-       super Socket
+       super TCPSocket
 
        private var addrin: NativeSocketAddrIn is noinit
 
@@ -240,8 +252,13 @@ class TCPServer
                        closed = true
                        return
                end
-               addrin = new NativeSocketAddrIn.with_port(port, new NativeSocketAddressFamilies.af_inet)
-               address = addrin.address
+
+               addrin = new NativeSocketAddrIn
+               addrin.family = new NativeSocketAddressFamilies.af_inet
+               addrin.port = port
+               addrin.address_any
+
+               address = addrin.address.to_s
 
                # Bind it
                closed = not bind