Changeset

5625:e67891ad18d6

net.server_event: Add support for listener.onreadtimeout(conn), which can return true to prevent the connection from being closed when a read timeout occurs
author Matthew Wild <mwild1@gmail.com>
date Fri, 24 May 2013 14:46:16 +0100
parents 5624:187f734bc996
children 5626:8416d4619d80
files net/server_event.lua
diffstat 1 files changed, 52 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/net/server_event.lua	Fri May 24 13:59:59 2013 +0100
+++ b/net/server_event.lua	Fri May 24 14:46:16 2013 +0100
@@ -437,10 +437,11 @@
 	end
 	
 	function interface_mt:setlistener(listener)
-		self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onstatus
-			= listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout, listener.onstatus;
+		self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onreadtimeout, self.onstatus
+			= listener.onconnect, listener.ondisconnect, listener.onincoming,
+			  listener.ontimeout, listener.onreadtimeout, listener.onstatus;
 	end
-	
+
 	-- Stub handlers
 	function interface_mt:onconnect()
 	end
@@ -450,6 +451,12 @@
 	end
 	function interface_mt:ontimeout()
 	end
+	function interface_mt:onreadtimeout()
+		self.fatalerror = "timeout during receiving"
+		debug( "connection failed:", self.fatalerror )
+		self:_close()
+		self.eventread = nil
+	end
 	function interface_mt:ondrain()
 	end
 	function interface_mt:onstatus()
@@ -477,6 +484,7 @@
 			ondisconnect = listener.ondisconnect;  -- will be called when client disconnects
 			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
 			onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS)
 			eventread = false, eventwrite = false, eventclose = false,
 			eventhandshake = false, eventstarthandshake = false;  -- event handler
@@ -574,61 +582,56 @@
 				interface.eventread = nil
 				return -1
 			end
-			if EV_TIMEOUT == event then  -- took too long to get some data from client -> disconnect
-				interface.fatalerror = "timeout during receiving"
-				debug( "connection failed:", interface.fatalerror )
+			if EV_TIMEOUT == event and interface:onreadtimeout() ~= true then
+				return -1 -- took too long to get some data from client -> disconnect
+			end
+			if interface._usingssl then  -- handle luasec
+				if interface.eventwritetimeout then  -- ok, in the past writecallback was regged
+					local ret = interface.writecallback( )  -- call it
+					--vdebug( "tried to write in readcallback, result:", tostring(ret) )
+				end
+				if interface.eventreadtimeout then
+					interface.eventreadtimeout:close( )
+					interface.eventreadtimeout = nil
+				end
+			end
+			local buffer, err, part = interface.conn:receive( interface._pattern )  -- receive buffer with "pattern"
+			--vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
+			buffer = buffer or part
+			if buffer and #buffer > cfg.MAX_READ_LENGTH then  -- check buffer length
+				interface.fatalerror = "receive buffer exceeded"
+				debug( "fatal error:", interface.fatalerror )
 				interface:_close()
 				interface.eventread = nil
 				return -1
-			else -- can read
-				if interface._usingssl then  -- handle luasec
-					if interface.eventwritetimeout then  -- ok, in the past writecallback was regged
-						local ret = interface.writecallback( )  -- call it
-						--vdebug( "tried to write in readcallback, result:", tostring(ret) )
+			end
+			if err and ( err ~= "timeout" and err ~= "wantread" ) then
+				if "wantwrite" == err then -- need to read on write event
+					if not interface.eventwrite then  -- register new write event if needed
+						interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT )
 					end
-					if interface.eventreadtimeout then
-						interface.eventreadtimeout:close( )
-						interface.eventreadtimeout = nil
-					end
-				end
-				local buffer, err, part = interface.conn:receive( interface._pattern )  -- receive buffer with "pattern"
-				--vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
-				buffer = buffer or part
-				if buffer and #buffer > cfg.MAX_READ_LENGTH then  -- check buffer length
-					interface.fatalerror = "receive buffer exceeded"
-					debug( "fatal error:", interface.fatalerror )
+					interface.eventreadtimeout = addevent( base, nil, EV_TIMEOUT,
+						function( )
+							interface:_close()
+						end, cfg.READ_TIMEOUT
+					)
+					debug( "wantwrite during read attempt, reg it in writecallback but dont know what really happens next..." )
+					-- to be honest i dont know what happens next, if it is allowed to first read, the write etc...
+				else  -- connection was closed or fatal error
+					interface.fatalerror = err
+					debug( "connection failed in read event:", interface.fatalerror )
 					interface:_close()
 					interface.eventread = nil
 					return -1
 				end
-				if err and ( err ~= "timeout" and err ~= "wantread" ) then
-					if "wantwrite" == err then -- need to read on write event
-						if not interface.eventwrite then  -- register new write event if needed
-							interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT )
-						end
-						interface.eventreadtimeout = addevent( base, nil, EV_TIMEOUT,
-							function( )
-								interface:_close()
-							end, cfg.READ_TIMEOUT
-						)
-						debug( "wantwrite during read attempt, reg it in writecallback but dont know what really happens next..." )
-						-- to be honest i dont know what happens next, if it is allowed to first read, the write etc...
-					else  -- connection was closed or fatal error
-						interface.fatalerror = err
-						debug( "connection failed in read event:", interface.fatalerror )
-						interface:_close()
-						interface.eventread = nil
-						return -1
-					end
-				else
-					interface.onincoming( interface, buffer, err )  -- send new data to listener
-				end
-				if interface.noreading then
-					interface.eventread = nil;
-					return -1;
-				end
-				return EV_READ, cfg.READ_TIMEOUT
+			else
+				interface.onincoming( interface, buffer, err )  -- send new data to listener
 			end
+			if interface.noreading then
+				interface.eventread = nil;
+				return -1;
+			end
+			return EV_READ, cfg.READ_TIMEOUT
 		end
 
 		client:settimeout( 0 )  -- set non blocking