1. Ryan Stecker
  2. LuaSteamKit

Commits

Ryan Stecker  committed cdfeea2

Initial commit.

  • Participants
  • Branches default

Comments (0)

Files changed (4)

File .hgignore

  • Ignore whitespace
Empty file added.

File cosocket.lua

View file
  • Ignore whitespace
+
+
+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 tasklet.lua

View file
  • Ignore whitespace
+
+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

File test.lua

View file
  • Ignore whitespace
+
+require "cosocket"
+require "tasklet"
+
+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 )
+
+tasklet.run()