From d06ae1629513e0a8ab8c1a24566226dddc93e8e1 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 16 Aug 2021 12:34:52 +0200 Subject: net.server: Add a predrain callaback just before writes Allows sneaking in things in the write buffer just before it's sent to the network stack. For example ack requests, compression flushes or other things that make sense to send after stanzas or other things. This ensures any additional trailing data sent is included in the same write, and possibly the same TCP packet. Other methods used such as timers or nextTick might not have the same effect as it depends on scheduling. --- net/server_epoll.lua | 1 + net/server_event.lua | 5 +++++ net/server_select.lua | 5 +++++ 3 files changed, 11 insertions(+) (limited to 'net') diff --git a/net/server_epoll.lua b/net/server_epoll.lua index b737ee59..60ecb687 100644 --- a/net/server_epoll.lua +++ b/net/server_epoll.lua @@ -472,6 +472,7 @@ end function interface:onwritable() self:onconnect(); if not self.conn then return; end -- could have been closed in onconnect + self:on("predrain"); local buffer = self.writebuffer; local data = buffer or ""; if type(buffer) == "table" then diff --git a/net/server_event.lua b/net/server_event.lua index f7e1f448..139c7e5f 100644 --- a/net/server_event.lua +++ b/net/server_event.lua @@ -449,6 +449,7 @@ function interface_mt:setlistener(listener, data) self.onstatus = listener.onstatus; self.ondetach = listener.ondetach; self.onattach = listener.onattach; + self.onpredrain = listener.onpredrain; self.ondrain = listener.ondrain; self:onattach(data); end @@ -464,6 +465,8 @@ function interface_mt:ontimeout() end function interface_mt:onreadtimeout() end +function interface_mt:onpredrain() +end function interface_mt:ondrain() end function interface_mt:ondetach() @@ -490,6 +493,7 @@ local function handleclient( client, ip, port, server, pattern, listener, sslctx onincoming = listener.onincoming; -- will be called when client sends data ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs onreadtimeout = listener.onreadtimeout; -- called when socket inactivity timeout occurs + onpredrain = listener.onpredrain; -- called before writes ondrain = listener.ondrain; -- called when writebuffer is empty ondetach = listener.ondetach; -- called when disassociating this listener from this connection onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS) @@ -540,6 +544,7 @@ local function handleclient( client, ip, port, server, pattern, listener, sslctx interface.eventwritetimeout = false end end + interface:onpredrain(); interface.writebuffer = { t_concat(interface.writebuffer) } local succ, err, byte = interface.conn:send( interface.writebuffer[1], 1, interface.writebufferlen ) --vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte ) diff --git a/net/server_select.lua b/net/server_select.lua index 09c1c027..eea850ce 100644 --- a/net/server_select.lua +++ b/net/server_select.lua @@ -294,6 +294,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local dispatch = listeners.onincoming local status = listeners.onstatus local disconnect = listeners.ondisconnect + local predrain = listeners.onpredrain local drain = listeners.ondrain local onreadtimeout = listeners.onreadtimeout; local detach = listeners.ondetach @@ -338,6 +339,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport dispatch = listeners.onincoming disconnect = listeners.ondisconnect status = listeners.onstatus + predrain = listeners.onpredrain drain = listeners.ondrain handler.onreadtimeout = listeners.onreadtimeout detach = listeners.ondetach @@ -552,6 +554,9 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport listeners.onconnect(handler); end end + if predrain then + predrain(handler); + end buffer = table_concat( bufferqueue, "", 1, bufferqueuelen ) succ, err, byte = send( socket, buffer, 1, bufferlen ) count = ( succ or byte or 0 ) * STAT_UNIT -- cgit v1.2.3