Commits

Ryan Stecker  committed 3802873

Refactor out client and connection.

  • Participants
  • Parent commits cdfeea2

Comments (0)

Files changed (8)

File cosocket.lua

-
-
-require "socket"
-
-
-cosocket = {}
-
-
-local sock_mt = {}
-sock_mt.__index = sock_mt
-
-
-function sock_mt:receive( bytes )
-
-	-- perform a non-blocking receive
-	self.socket:settimeout( 0 )
-	
-	local data, err, part = self.socket:receive( bytes )
-	
-	-- if we've received all the data we've requested, return it
-	if ( data ) then
-		return data
-	end
-	
-	-- otherwise, we may have received only part of the buffer, so return that
-	if ( part and #part > 0 ) then
-		return part
-	end
-	
-	-- haven't received anything, or error
-	return nil, err
-	
-end
-
-function sock_mt:__tostring()
-	return "cosocket (" .. self.host .. ":" .. self.port .. ")"
-end
-
-
-function cosocket.connect( host, port )
-
-	local sock = 
-	{
-		host = host,
-		port = port,
-	}
-	
-	local err
-	sock.socket, err = socket.connect( host, port )
-	
-	if ( not sock.socket ) then
-		return nil, err -- unable to connect
-	end
-	
-	return setmetatable( sock, sock_mt )
-	
-end

File steam3/client.lua

+
+require "steam3.connection"
+
+
+client = {}
+client.__index = client
+
+
+function client:logon( user, pass )
+	-- todo
+end
+
+function client:login_anon()
+	-- todo
+end
+
+function client:handle_message( emsg, packet )
+	print( "handle message", emsg )
+end
+
+
+function client.new( host, port )
+
+	local cli =
+	{
+		conn = connection( host, port )
+	}
+	
+	cli.conn.client = cli
+	
+	return setmetatable( cli, client )
+	
+	
+end
+
+
+setmetatable( client, { __call = function( self, ... ) return client.new( ... ) end } )

File steam3/connection.lua

+
+require "util.cosocket"
+require "util.tasklet"
+
+require "struct"
+require "steam3.msgbase"
+
+
+connection = {}
+connection.__index = connection
+
+
+function connection:send( msg )
+	-- todo
+end
+
+function connection:receive_data()
+
+	-- buffer of the packet data read so far
+	local readBuffer = "" 
+
+	while ( true ) do
+	
+		local data, err = self.socket:receive( 1024 * 4 )
+		
+		if ( data ) then
+
+			-- add to the buffer
+			readBuffer = readBuffer .. data
+			
+			print( "Got data length: ", string.len( data ), "Buffer is length: ", string.len( readBuffer ) )
+			
+			while ( string.len( readBuffer ) >= 8 ) do
+			
+				local len, magic = struct.unpack( "I4c4", readBuffer )
+				
+				if ( magic ~= "VT01" ) then
+					tasklet.kill( "invalid packet magic" )
+				end
+				
+				if ( string.len( readBuffer ) < len + 8 ) then
+					break -- don't have the full packet in our buffer yet
+				end
+				
+				local packetData = string.sub( readBuffer, 8 + 1, len + 8 )
+				self:handle_packet( packetData )
+				
+				-- remove our read packet from the buffer
+				readBuffer = string.sub( readBuffer, len + 8 + 1 )
+			end
+			
+		end
+		
+		if ( err == "closed" ) then
+			tasklet.kill( "connection closed" )
+		end
+		
+		if ( err == "timeout" ) then
+			tasklet.yield() -- no data
+		end
+		
+	end
+end
+
+function connection:handle_packet( packet )
+
+	local emsg = struct.unpack( "I", packet )
+	-- todo: strip protobuf flag
+	
+	self.client:handle_message( emsg, packet )
+	
+end
+
+function connection.new( host, port )
+
+	local conn =
+	{
+		socket = cosocket.connect( host, port ),
+	}
+	
+	conn = setmetatable( conn, connection )
+	
+	tasklet.spawn( connection.receive_data, conn )
+	
+	return conn
+	
+end
+
+setmetatable( connection, { __call = function( _, ... ) return connection.new( ... ) end } )

File steam3/msgbase.lua

+
+
+MsgHdr = {}
+MsgHdr.__index = MsgHdr
+
+-- todo: work out the nightmare of 64bit ints in lua
+
+function MsgHdr:deserialize( data )
+	self.emsg, self.target_jobid, self.source_jobid = struct.unpack( "Ic8c8", data )
+end
+
+function MsgHdr:serialize()
+	return struct.pack( "Ic8c8", self.emsg, self.target_jobid, self.source_jobid )
+end
+
+function MsgHdr:__tostring()
+	return "MsgHdr " .. self.emsg
+end
+
+
+function MsgHdr.new( data )
+
+	local msg =
+	{
+		emsg = 0,
+		
+		target_jobid = -1,
+		source_jobid = -1,
+	}
+	
+	msg = setmetatable( msg, MsgHdr )
+	
+	if ( data ) then
+		msg:deserialize( data )
+	end
+	
+	return msg
+	
+end
+
+setmetatable( MsgHdr, { __call = function( self, ... ) return MsgHdr.new( ... ) end } )

File tasklet.lua

-
-tasklet =
-{
-	tasks = {}
-}
-
-function tasklet.spawn( func )
-	local task = coroutine.create( func )
-	table.insert( tasklet.tasks, task )
-end
-
-function tasklet.yield( res )
-	coroutine.yield( res )
-end
-
--- shorthand for yield to notify the tasklet scheduler that we wish to stop
-function tasklet.kill( reason )
-	tasklet.yield( { kill = true, reason = reason } )
-end
-
--- run any scheduled tasklets
-function tasklet.run()
-
-	while true do
-		for k, task in pairs( tasklet.tasks ) do
-		
-			local didResume, res = coroutine.resume( task )
-			
-			-- error when executing tasklet
-			if ( not didResume ) then
-				print( "unable to resume tasklet", res )
-				tasklet.tasks[ k ] = nil
-			end
-			
-			-- tasklet requesting termination
-			if ( res and type( res ) == "table" ) then
-				if ( res.kill ) then
-					print( "tasklet requested termination", res.reason )
-					tasklet.tasks[ k ] = nil
-				end
-			end
-			
-		end
-	end
-	
-end
 
-require "cosocket"
-require "tasklet"
+require "steam3.client"
 
-require "struct"
 
-
-local sock, err = cosocket.connect( "cm0.steampowered.com", 27017 )
-
-if ( not sock ) then
-	print( "unable to connect", err )
-	return
-end
-
-print( "connected!", sock )
-
-tasklet.spawn( function()
-
-	-- buffer of the packet data read so far
-	local readBuffer = ""
-	
-	while true do
-	
-		local data, err = sock:receive( 1024 * 4 )
-		
-		if ( data ) then
-
-			-- add to the buffer
-			readBuffer = readBuffer .. data
-			
-			print( "Got data length: ", string.len( data ), "Buffer is length: ", string.len( readBuffer ) )
-			
-			while ( string.len( readBuffer ) >= 8 ) do
-			
-				local len, magic = struct.unpack( "I4c4", readBuffer )
-				
-				if ( magic ~= "VT01" ) then
-					tasklet.kill( "invalid packet magic" )
-				end
-				
-				if ( string.len( readBuffer ) < len + 8 ) then
-					break -- don't have the full packet in our buffer yet
-				end
-				
-				local packet = string.sub( readBuffer, 8 + 1, len + 8 )
-				
-				-- todo: process packet
-				print( "got packet of len", string.len( packet ) )
-				
-				readBuffer = string.sub( readBuffer, len + 8 + 1 )
-			end
-			
-		end
-		
-		if ( err == "closed" ) then
-			tasklet.kill( "connection closed" )
-		end
-		
-		if ( err == "timeout" ) then
-			tasklet.yield() -- no data
-		end
-		
-	end
-end )
+local cli = client( "cm0.steampowered.com", 27017 )
 
 tasklet.run()

File util/cosocket.lua

+
+
+require "socket"
+
+
+cosocket = {}
+
+
+local sock_mt = {}
+sock_mt.__index = sock_mt
+
+
+function sock_mt:receive( bytes )
+
+	-- perform a non-blocking receive
+	self.socket:settimeout( 0 )
+	
+	local data, err, part = self.socket:receive( bytes )
+	
+	-- if we've received all the data we've requested, return it
+	if ( data ) then
+		return data
+	end
+	
+	-- otherwise, we may have received only part of the buffer, so return that
+	if ( part and #part > 0 ) then
+		return part
+	end
+	
+	-- haven't received anything, or error
+	return nil, err
+	
+end
+
+function sock_mt:__tostring()
+	return "cosocket (" .. self.host .. ":" .. self.port .. ")"
+end
+
+
+function cosocket.connect( host, port )
+
+	local sock = 
+	{
+		host = host,
+		port = port,
+	}
+	
+	local err
+	sock.socket, err = socket.connect( host, port )
+	
+	if ( not sock.socket ) then
+		return nil, err -- unable to connect
+	end
+	
+	return setmetatable( sock, sock_mt )
+	
+end

File util/tasklet.lua

+
+tasklet =
+{
+	tasks = {}
+}
+
+function tasklet.spawn( func, ... )
+
+	local task =
+	{
+		co = coroutine.create( func ),
+		args = { ... },
+	}
+
+	table.insert( tasklet.tasks, task )
+	
+end
+
+function tasklet.yield( res )
+	coroutine.yield( res )
+end
+
+-- shorthand for yield to notify the tasklet scheduler that we wish to stop
+function tasklet.kill( reason )
+	tasklet.yield( { kill = true, reason = reason } )
+end
+
+-- run any scheduled tasklets
+function tasklet.run()
+
+	while true do
+		for k, task in pairs( tasklet.tasks ) do
+		
+			local didResume, res = coroutine.resume( task.co, unpack( task.args ) )
+			
+			-- error when executing tasklet
+			if ( not didResume ) then
+				print( "unable to resume tasklet", res )
+				tasklet.tasks[ k ] = nil
+			end
+			
+			-- tasklet requesting termination
+			if ( res and type( res ) == "table" ) then
+				if ( res.kill ) then
+					print( "tasklet requested termination", res.reason )
+					tasklet.tasks[ k ] = nil
+				end
+			end
+			
+		end
+	end
+	
+end