Changeset

4962:1d8fb12a9b2d

net.server_select, net.server_event: Change semantics of conn:close() - always call ondisconnect (with err == nil), and never close with data in send buffer (i.e. 'now' parameter removed)
author Matthew Wild <mwild1@gmail.com>
date Sun, 22 Jul 2012 16:54:33 +0100
parents 4961:29b24a4028ed
children 4963:54e2c83af127
files net/server_event.lua net/server_select.lua
diffstat 2 files changed, 32 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/net/server_event.lua	Sun Jul 22 16:50:14 2012 +0100
+++ b/net/server_event.lua	Sun Jul 22 16:54:33 2012 +0100
@@ -249,7 +249,7 @@
 			return true
 	end
 	function interface_mt:_destroy()  -- close this interface + events and call last listener
-			debug( "closing client with id:", self.id )
+			debug( "closing client with id:", self.id, self.fatalerror )
 			self:_lock( true, true, true )  -- first of all, lock the interface to avoid further actions
 			local _
 			_ = self.eventread and self.eventread:close( )  -- close events; this must be called outside of the event callbacks!
@@ -328,22 +328,22 @@
 		end
 		return true
 	end
-	function interface_mt:close(now)
+	function interface_mt:close()
 		if self.nointerface then return nil, "locked"; end
 		debug( "try to close client connection with id:", self.id )
 		if self.type == "client" then
 			self.fatalerror = "client to close"
-			if ( not self.eventwrite ) or now then  -- try to close immediately
+			if self.eventwrite then -- wait for incomplete write request
+				self:_lock( true, true, false )
+				debug "closing delayed until writebuffer is empty"
+				return nil, "writebuffer not empty, waiting"
+			else -- close now
 				self:_lock( true, true, true )
 				self:_close()
 				return true
-			else  -- wait for incomplete write request
-				self:_lock( true, true, false )
-				debug "closing delayed until writebuffer is empty"
-				return nil, "writebuffer not empty, waiting"
 			end
 		else
-			debug( "try to close server with id:", tostring(self.id), "args:", tostring(now) )
+			debug( "try to close server with id:", tostring(self.id))
 			self.fatalerror = "server to close"
 			self:_lock( true )
 			self:_close( 0 )  -- add new event to remove the server interface
--- a/net/server_select.lua	Sun Jul 22 16:50:14 2012 +0100
+++ b/net/server_select.lua	Sun Jul 22 16:54:33 2012 +0100
@@ -314,22 +314,28 @@
 		end
 		return false, "setoption not implemented";
 	end
-	handler.close = function( self, forced )
+	handler.force_close = function ( self )
+		if bufferqueuelen ~= 0 then
+			out_put("discarding unwritten data for ", tostring(ip), ":", tostring(clientport))
+			for i = bufferqueuelen, 1, -1 do
+				bufferqueue[i] = nil;
+			end
+			bufferqueuelen = 0;
+		end
+		return self:close();
+	end
+	handler.close = function( self )
 		if not handler then return true; end
 		_readlistlen = removesocket( _readlist, socket, _readlistlen )
 		_readtimes[ handler ] = nil
 		if bufferqueuelen ~= 0 then
-			if not ( forced or fatalerror ) then
-				handler.sendbuffer( )
-				if bufferqueuelen ~= 0 then -- try again...
-					if handler then
-						handler.write = nil -- ... but no further writing allowed
-					end
-					toclose = true
-					return false
+			handler.sendbuffer() -- Try now to send any outstanding data
+			if bufferqueuelen ~= 0 then -- Still not empty, so we'll try again later
+				if handler then
+					handler.write = nil -- ... but no further writing allowed
 				end
-			else
-				send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen )	-- forced send
+				toclose = true
+				return false
 			end
 		end
 		if socket then
@@ -347,7 +353,7 @@
 			local _handler = handler;
 			handler = nil
 			if disconnect then
-				disconnect(_handler, "closed");
+				disconnect(_handler, false);
 			end
 		end
 		if server then
@@ -480,7 +486,7 @@
 			_ = _cleanqueue and clean( bufferqueue )
 			--out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) )
 		else
-			succ, err, count = false, "closed", 0;
+			succ, err, count = false, "unexpected close", 0;
 		end
 		if succ then	-- sending succesful
 			bufferqueuelen = 0
@@ -491,7 +497,7 @@
 				drain(handler)
 			end
 			_ = needtls and handler:starttls(nil)
-			_ = toclose and handler:close( )
+			_ = toclose and handler:force_close( )
 			return true
 		elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write
 			buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer
@@ -504,7 +510,7 @@
 			out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) )
 			fatalerror = true
 			disconnect( handler, err )
-			_ = handler and handler:close( )
+			_ = handler and handler:force_close( )
 			return false
 		end
 	end
@@ -547,7 +553,7 @@
 				end
 				out_put( "server.lua: ssl handshake error: ", tostring(err or "handshake too long") )
 				disconnect( handler, "ssl handshake failed" )
-				_ = handler and handler:close( true )	 -- forced disconnect
+				_ = handler and handler:force_close()
                                return false, err -- handshake failed
 			end
 		)
@@ -810,7 +816,7 @@
 		end
 		for handler, err in pairs( _closelist ) do
 			handler.disconnect( )( handler, err )
-			handler:close( true )	 -- forced disconnect
+			handler:force_close()	 -- forced disconnect
 		end
 		clean( _closelist )
 		_currenttime = luasocket_gettime( )
@@ -896,7 +902,7 @@
 				if os_difftime( _currenttime - timestamp ) > _sendtimeout then
 					--_writetimes[ handler ] = nil
 					handler.disconnect( )( handler, "send timeout" )
-					handler:close( true )	 -- forced disconnect
+					handler:force_close()	 -- forced disconnect
 				end
 			end
 			for handler, timestamp in pairs( _readtimes ) do