libevent :: Connection :: defaultinit
# Spawned to manage a specific connection
class Connection
super Writer
# Closing this connection has been requested, but may not yet be `closed`
var close_requested = false
# This connection is closed
var closed = false
# The native libevent linked to `self`
var native_buffer_event: NativeBufferEvent
# Close this connection if possible, otherwise mark it to be closed later
redef fun close
do
if closed then return
var i = native_buffer_event.input_buffer
var o = native_buffer_event.output_buffer
if i.length > 0 or o.length > 0 then
close_requested = true
else
force_close
end
end
# Force closing this connection and freeing `native_buffer_event`
fun force_close
do
if closed then return
native_buffer_event.free
closed = true
end
# Callback method on a write event
fun write_callback
do
if close_requested then close
end
private fun read_callback_native(bev: NativeBufferEvent)
do
var evbuffer = bev.input_buffer
var len = evbuffer.length
var buf = new CString(len)
evbuffer.remove(buf, len)
var str = buf.to_s_with_length(len)
read_callback str
end
# Callback method when data is available to read
fun read_callback(content: String)
do
if close_requested then close
end
# Callback method on events: EOF, user-defined timeout and unrecoverable errors
#
# Returns `true` if the native handles to `self` can be released.
fun event_callback(events: Int): Bool
do
if events & bev_event_error != 0 or events & bev_event_eof != 0 then
if events & bev_event_error != 0 then
var sock_err = evutil_socket_error
# Ignore some normal errors and print the others for debugging
if sock_err == 110 then
# Connection timed out (ETIMEDOUT)
else if sock_err == 104 then
# Connection reset by peer (ECONNRESET)
else
print_error "libevent error event: {evutil_socket_error_to_string(sock_err)} ({sock_err})"
end
end
force_close
return true
end
return false
end
# Write a string to the connection
redef fun write(str)
do
if close_requested then return
native_buffer_event.write(str.to_cstring, str.byte_length)
end
redef fun write_byte(byte)
do
if close_requested then return
native_buffer_event.write_byte(byte)
end
redef fun write_bytes_from_cstring(ns, len)
do
if close_requested then return
native_buffer_event.write(ns, len)
end
# Write a file to the connection
#
# If `not path.file_exists`, the method returns.
fun write_file(path: String)
do
if close_requested then return
var file = new FileReader.open(path)
if file.last_error != null then
var error = new IOError("Failed to open file at '{path}'")
error.cause = file.last_error
self.last_error = error
file.close
return
end
var stat = file.file_stat
if stat == null then
last_error = new IOError("Failed to stat file at '{path}'")
file.close
return
end
var err = native_buffer_event.output_buffer.add_file(file.fd, 0, stat.size)
if err then
last_error = new IOError("Failed to add file at '{path}'")
file.close
end
end
end
lib/libevent/libevent.nit:150,1--280,3