# Simple communication stream with a remote socket
class TCPStream
super Socket
- super BufferedIStream
- super OStream
- super PollableIStream
+ super BufferedReader
+ super Writer
+ super PollableReader
# Real canonical name of the host to which `self` is connected
var host: String
# Creates a socket connection to host `host` on port `port`
init connect(host: String, port: Int)
do
- _buffer = new FlatBuffer
+ _buffer = new NativeString(1024)
_buffer_pos = 0
socket = new NativeSocket.socket(new NativeSocketAddressFamilies.af_inet,
new NativeSocketTypes.sock_stream, new NativeSocketProtocolFamilies.pf_null)
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
private init server_side(h: SocketAcceptResult)
do
- _buffer = new FlatBuffer
+ _buffer = new NativeString(1024)
_buffer_pos = 0
socket = h.socket
addrin = h.addr_in
# timeout : Time in milliseconds before stopping to wait for events
fun ready_to_read(timeout: Int): Bool
do
- if _buffer_pos < _buffer.length then return true
+ if _buffer_pos < _buffer_length then return true
if end_reached then return false
var events = [new NativeSocketPollValues.pollin]
return pollin(events, timeout).length != 0
end
# If socket.end_reached, nothing will happen
- redef fun write(msg: Text)
+ redef fun write(msg)
do
if closed then return
socket.write(msg.to_s)
end
+ redef fun write_byte(value)
+ do
+ if closed then return
+ socket.write_byte value
+ end
+
+ redef fun write_bytes(s) do
+ if closed then return
+ socket.write(s.to_s)
+ end
+
fun write_ln(msg: Text)
do
if end_reached then return
redef fun fill_buffer
do
- _buffer.clear
+ _buffer_length = 0
_buffer_pos = 0
if not connected then return
var read = socket.read
close
end_reached = true
end
- _buffer.append(read)
+ enlarge(_buffer_length + read.length)
+ read.copy_to_native(_buffer, read.length, 0, 0)
+ _buffer_length = read.length
+ end
+
+ fun enlarge(len: Int) do
+ if _buffer_capacity >= len then return
+ while _buffer_capacity < len do _buffer_capacity = _buffer_capacity * 2 + 2
+ var ns = new NativeString(_buffer_capacity)
+ _buffer.copy_to(ns, _buffer_length - _buffer_pos, _buffer_pos, 0)
+ _buffer = ns
end
redef fun close
closed = true
return
end
- addrin = new NativeSocketAddrIn.with(port, new NativeSocketAddressFamilies.af_inet)
+ addrin = new NativeSocketAddrIn.with_port(port, new NativeSocketAddressFamilies.af_inet)
address = addrin.address
# Bind it