Advertisement
CapsAdmin

Untitled

Mar 16th, 2013
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.13 KB | None | 0 0
  1. --[[
  2.  
  3. Most of these functions can be called at any time. Send queues what you send until a connection is made.
  4. On* functions can be overriden
  5.  
  6. Only "tcp" and "udp" is supported. Default is tcp.
  7. There isn't really any difference when it comes to what events and functions to use in this wrapper.
  8.  
  9. by default the socket has a 3 second timeout
  10. the timeout count is started/restarted whenever the mesage is "timeout" and stopped otherwise
  11.  
  12.  
  13. luasocket.debug = true
  14.     will print debug messages about sending and receiving data
  15.     very useful for (duh) debugging!
  16.  
  17. -- client
  18.    
  19.     CLIENT = luasocket.Client("udp" or "tcp") -- this defaults to tcp
  20.  
  21.     CLIENT:GetTimeoutDuration()
  22.    
  23.     CLIENT:IsTimingOut()
  24.     CLIENT:IsSending()
  25.     CLIENT:IsConnected()
  26.  
  27.     CLIENT:SetTimeout(seconds or nil)
  28.     CLIENT:GetTimeout()
  29.  
  30.     CLIENT:OnReceive(str)
  31.  
  32.     -- return false to prevent the socket from being removed
  33.     -- if the timeout duration has exceeded the max timeout duration
  34.    
  35.     CLIENT:OnTimeout(count)
  36.    
  37.     CLIENT:OnSend(str, bytes)
  38.     CLIENT:OnError(msg)
  39.     CLIENT:OnClose()
  40.    
  41.     CLIENT:Connect(ip, port)
  42. --
  43.  
  44. -- server
  45.     SERVER = luasocket.Server("udp" or "tcp") -- this defaults to tcp
  46.    
  47.     SERVER:Host(ip, port)
  48.    
  49.     -- returning false here will close and remove the client
  50.     -- returning true will call SetKeepAlive true on the client
  51.     SERVER:OnClientConnected(client, ip, port)
  52.    
  53.    
  54.     SERVER:OnReceive(str, client)
  55.     SERVER:OnClientClosed(client)
  56.     SERVER:OnClientError(client, msg)
  57.  
  58.     SERVER:GetClients()
  59. --
  60.  
  61. -- shared
  62.     SHARED:Send(str, instant)
  63.     SHARED:GetIP()
  64.     SHARED:GetPort()
  65.  
  66.     SHARED:IsValid()
  67.     SHARED:Remove()
  68.  
  69.     -- These have Get ones as well but they only return something if Set was called. This uses setoption.
  70.     SHARED:SetReuseAddress(val)
  71.     SHARED:SetNoDelay(val)
  72.     SHARED:SetLinger(val)
  73.     SHARED:SetKeepAlive(val)
  74. --
  75. ]]
  76.  
  77. if luasocket then luasocket.Panic() end
  78.  
  79. luasocket = {}
  80. local check = check or function() end
  81.  
  82. luasocket.ltn12 = require("mime")
  83. luasocket.socket = require("socket")
  84. luasocket.mime = require("mime")
  85. luasocket.url = require("socket.url")
  86. luasocket.http = require("socket.http")
  87. luasocket.tp = require("socket.tp")
  88. luasocket.smtp = require("socket.smtp")
  89. luasocket.ftp = require("socket.ftp")
  90.  
  91. function luasocket.DebugPrint(...)
  92.     if luasocket.debug then
  93.         MsgN(string.format(...))
  94.     end
  95. end
  96.  
  97. function luasocket.HeaderToTable(header)
  98.     local tbl = {}
  99.  
  100.     for line in header:gmatch("(.-)\n") do
  101.         local key, value = line:match("(.+):%s+(.+)\13")
  102.        
  103.         if key and value then
  104.             tbl[key] = value
  105.         end
  106.     end
  107.  
  108.     return tbl
  109. end
  110.  
  111. function luasocket.TableToHeader(tbl)
  112.     local str = ""
  113.  
  114.     for key, value in pairs(tbl) do
  115.         str = str .. tostring(key) .. ": " .. tostring(value) .. "\n"
  116.     end
  117.  
  118.     return str
  119. end
  120.  
  121. function luasocket.Get(url, callback)
  122.     check(url, "string")
  123.     check(callback, "function", "nil", "false")
  124.  
  125.     url = url:gsub("http://", "")
  126.     callback = callback or PrintTable
  127.  
  128.     local host, get = url:match("(.-)/(.+)")
  129.  
  130.     if not get then
  131.         host = url:gsub("/", "")
  132.         get = ""
  133.     end
  134.  
  135.     local socket = luasocket.Client("tcp")
  136.     socket:Connect(host, 80)
  137.    
  138.     socket:Send(("GET /%s HTTP/1.1\r\n"):format(get))
  139.     socket:Send(("Host: %s\r\n"):format(host))
  140.     socket:Send("User-Agent: gmod\r\n")
  141.     socket:Send("\r\n")
  142.     socket:SetTimeoutLength(5)
  143.        
  144.     function socket:OnReceive(str)     
  145.         local header, content = str:match("(.-\10\13)(.+)")
  146.        
  147.         local ok, err = xpcall(callback, print, {content = content, header = luasocket.HeaderToTable(header), status = status})
  148.         if err then
  149.             print(err)
  150.         end
  151.        
  152.         self:Remove()
  153.     end
  154. end
  155.  
  156. function luasocket.SendUDPData(ip, port, str)
  157.  
  158.     if not str and type(port) == "string" then
  159.         str = port
  160.         port = tonumber(ip:match(".-:(.+)"))
  161.     end
  162.  
  163.     local sck = luasocket.socket.udp()
  164.     local ok, msg = sck:sendto(str, ip, port)
  165.     sck:close()
  166.    
  167.     if ok then
  168.         luasocket.DebugPrint("SendUDPData sent data to %s:%i (%s)", ip, port, str)
  169.     else
  170.         luasocket.DebugPrint("SendUDPData failed %q", msg)
  171.     end
  172.    
  173.     return ok, msg
  174. end
  175.  
  176. local receive_types = {all = "*a", lines = "*l"}
  177.  
  178. do -- tcp socket meta
  179.     local sockets = {}
  180.    
  181.     function luasocket.GetSockets()
  182.         return sockets
  183.     end
  184.  
  185.     function luasocket.Panic()
  186.         for key, sock in pairs(sockets) do
  187.             if sock:IsValid() then
  188.                 sock:DebugPrintf("removed from luasocket.Panic()")
  189.                 sock:Remove()
  190.             else
  191.                 table.remove(sockets, key)
  192.             end
  193.         end
  194.     end
  195.  
  196.     timer.Create("socket_think", 0, 0, function()
  197.         for key, sock in pairs(sockets) do
  198.        
  199.             if sock.remove_me then
  200.                 setmetatable(sock, getmetatable(NULL))
  201.             end
  202.        
  203.             if sock:IsValid() then
  204.                 local ok, err = pcall(sock.Think, sock)
  205.                 if not ok then
  206.                     ErrorNoHalt(err)
  207.                 end
  208.             else
  209.                 table.remove(sockets, key)
  210.             end
  211.         end
  212.     end)
  213.  
  214.     local function assert(res, err)
  215.         if not res then
  216.             error(res, 3)
  217.         end
  218.         return res
  219.     end
  220.  
  221.     local function new_socket(override, META, typ)
  222.         typ = typ or "tcp"
  223.         typ = typ:lower()
  224.  
  225.         if typ == "udp" or typ == "tcp" then
  226.             local self = {}
  227.  
  228.             self.socket = override or assert(luasocket.socket[typ]())
  229.             self.socket:settimeout(0)
  230.             self.socket_type = typ
  231.  
  232.             local obj = setmetatable(self, META)
  233.             obj:Initialize()
  234.             table.insert(sockets, obj)
  235.  
  236.             return obj
  237.         end
  238.     end
  239.  
  240.     local function remove_socket(self)
  241.         self.socket:close()    
  242.         self.remove_me = true
  243.     end
  244.    
  245.    
  246.     local options =
  247.     {
  248.         KeepAlive = "keepalive",
  249.         Linger = "linger",
  250.         ReuseAddress = "ReuseAddr",
  251.         NoDelay = "tcp-nodelay",
  252.     }
  253.        
  254.     local function add_options(tbl)
  255.         for func_name, key in pairs(options) do
  256.             tbl["Set" .. func_name] = function(self, val)
  257.                 self.socket:setoption(key, val)
  258.                 self:DebugPrintf("option[%q] = %s", key, tostring(val))
  259.                 self[func_name] = val
  260.             end
  261.            
  262.             tbl["Get" .. func_name] = function(self, val)
  263.                 return self[func_name]
  264.             end        
  265.         end
  266.     end
  267.  
  268.     do -- client
  269.         local CLIENT = {}
  270.         CLIENT.__index = CLIENT
  271.  
  272.         add_options(CLIENT)
  273.        
  274.         function CLIENT:Initialize()
  275.             self.Buffer = {}
  276.         end
  277.  
  278.         function CLIENT:__tostring()
  279.             return string.format("client_%s[%s][%s]", self.socket_type, self:GetIP() or "none", self:GetPort() or "0")
  280.         end
  281.  
  282.         function CLIENT:DebugPrintf(fmt, ...)
  283.             luasocket.DebugPrint("%s - " .. fmt, self, ...)
  284.         end
  285.  
  286.         function CLIENT:Connect(ip, port)
  287.             check(ip, "string")
  288.             check(port, "number")
  289.  
  290.             self.socket:settimeout(0) -- is this needed?
  291.            
  292.             if self.socket_type == "tcp" then
  293.                 self.socket:connect(ip, port)
  294.             else
  295.                 self.socket:setpeername(ip, port)
  296.             end
  297.  
  298.             self.connecting = true
  299.         end
  300.  
  301.         function CLIENT:Send(str, instant)
  302.             if self.socket_type == "tcp" then
  303.                 if instant then
  304.                     local bytes, b, c, d = self.socket:send(str)
  305.  
  306.                     if bytes then
  307.                         self:DebugPrintf("sucessfully sent %q", str)
  308.                        
  309.                         self:OnSend(str, bytes, b,c,d)
  310.                     end
  311.                 else
  312.                     table.insert(self.Buffer, str)
  313.                 end
  314.             else
  315.                 self.socket:send(str)
  316.                 self:DebugPrintf("sent %q", str)
  317.             end
  318.         end
  319.            
  320.         CLIENT.ReceiveMode = "all"
  321.            
  322.         function CLIENT:SetReceiveMode(type)
  323.             self.ReceiveMode = type
  324.         end
  325.        
  326.         function CLIENT:GetReceiveMode()
  327.             return self.ReceiveMode
  328.         end
  329.        
  330.         function CLIENT:Think()
  331.             local sock = self.socket
  332.             sock:settimeout(0)
  333.  
  334.             if self.connecting then
  335.                 local res, msg = sock:getpeername()
  336.                 if res then            
  337.                     self:DebugPrintf("connected to %s:%s", res, msg)
  338.                    
  339.                     -- ip, port = res, msg
  340.  
  341.                     self.connected = true
  342.                     self.connecting = nil
  343.                     self:OnConnect(res, msg)
  344.                    
  345.                     self:Timeout(false)
  346.                 elseif msg == "timeout" or msg == "getpeername failed" then
  347.                     self:Timeout(true)
  348.                 else
  349.                     self:DebugPrintf("errored: %s", msg)
  350.                
  351.                     self:OnError(msg)
  352.                     self.connecting = nil
  353.                 end
  354.             end
  355.  
  356.             if self.socket_type == "tcp" and self.connected then
  357.                 while true do
  358.                     local data = self.Buffer[1]
  359.                     if data then
  360.                         local bytes, b, c, d = sock:send(data)
  361.  
  362.                         if bytes then
  363.                             self:DebugPrintf("sucessfully sent %q", data)
  364.                            
  365.                             self:OnSend(data, bytes, b,c,d)
  366.                             table.remove(self.Buffer, 1)
  367.                         end
  368.                     else
  369.                         break
  370.                     end
  371.                 end
  372.             end
  373.        
  374.             local data, err, partial = sock:receive(receive_types[self.ReceiveMode] or self.ReceiveMode)
  375.            
  376.             if not data and partial ~= "" then
  377.                 data = partial
  378.             end
  379.  
  380.             --self:DebugPrintf("receive: %s, %s, %s, %i", data or "", err or "", partial or "", self.Timeouts)
  381.            
  382.             if data then
  383.                 self:DebugPrintf("received %q", data)
  384.                
  385.                 self:OnReceive(data)
  386.                 self:Timeout(false)
  387.                
  388.             elseif err == "timeout" then
  389.                 self:Timeout(true)
  390.             elseif err == "closed" then
  391.                 self:DebugPrintf("wants to close", client)
  392.                
  393.                 self:Remove()
  394.                
  395.             else
  396.                 self:DebugPrintf("errored: %s", err)
  397.                
  398.                 self:OnError(err)
  399.             end
  400.         end
  401.        
  402.         do -- timeout
  403.             CLIENT.TimeoutLength = 3
  404.        
  405.             function CLIENT:Timeout(bool)
  406.                 if not self.TimeoutLength then return end
  407.            
  408.                 if not bool then
  409.                     self.TimeoutStart = nil
  410.                     return
  411.                 end
  412.            
  413.                 local time = os.clock()
  414.                
  415.                 if not self.TimeoutStart then
  416.                     self.TimeoutStart = time + self.TimeoutLength
  417.                 end
  418.                
  419.                 local seconds = time - self.TimeoutStart
  420.                                
  421.                 if self:OnTimeout(seconds) ~= false then
  422.                     if seconds > self.TimeoutLength then
  423.                         self:DebugPrintf("timed out")
  424.                         self:Remove()
  425.                     end
  426.                 end
  427.             end
  428.  
  429.             function CLIENT:GetTimeoutDuration()
  430.                 if not self.TimeoutStart then return 0 end
  431.                
  432.                 local t = os.clock()
  433.                 return t - self.TimeoutStart
  434.             end
  435.            
  436.             function CLIENT:IsTimingOut()
  437.                 return
  438.             end
  439.            
  440.             function CLIENT:SetTimeout(seconds)
  441.                 self.TimeoutLength = seconds
  442.             end
  443.            
  444.             function CLIENT:GetTimeout()
  445.                 return self.TimeoutLength or math.huge
  446.             end
  447.         end
  448.        
  449.         function CLIENT:Remove()
  450.             self:OnClose()
  451.             remove_socket(self)
  452.         end
  453.  
  454.         function CLIENT:IsConnected()
  455.             return self.connected == true
  456.         end
  457.  
  458.         function CLIENT:IsSending()
  459.             return #self.Buffer > 0
  460.         end
  461.  
  462.         function CLIENT:GetIP()
  463.             local ip, port = self.socket:getpeername()
  464.             return ip
  465.         end
  466.  
  467.         function CLIENT:GetPort()
  468.             local ip, port = self.socket:getpeername()
  469.             return ip and port or nil
  470.         end
  471.  
  472.         function CLIENT:IsValid()
  473.             return true
  474.         end    
  475.    
  476.         function CLIENT:OnTimeout(count) end
  477.         function CLIENT:OnConnect(ip, port) end
  478.         function CLIENT:OnReceive(data) end
  479.         function CLIENT:OnError(msg) end
  480.         function CLIENT:OnSend(data, bytes, b,c,d) end
  481.        
  482.         function CLIENT:OnClose()
  483.             remove_socket(self)
  484.         end
  485.  
  486.         function luasocket.Client(typ)
  487.             return new_socket(nil, CLIENT, typ)
  488.         end
  489.  
  490.         luasocket.ClientMeta = CLIENT
  491.     end
  492.  
  493.     do -- server
  494.         local SERVER = {}
  495.         SERVER.__index = SERVER
  496.        
  497.         add_options(SERVER)
  498.        
  499.         function SERVER:Initialize()
  500.             self.Clients = {}
  501.         end
  502.  
  503.         function SERVER:__tostring()
  504.             return string.format("server_%s[%s][%s]", self.socket_type, self:GetIP() or "nil", self:GetPort() or "nil")
  505.         end
  506.  
  507.         function SERVER:DebugPrintf(fmt, ...)
  508.             luasocket.DebugPrint("%s - " .. fmt, self, ...)
  509.         end
  510.  
  511.         function SERVER:GetClients()
  512.             local copy = {}
  513.             for key, client in pairs(self.Clients) do
  514.                 if client.IsValid and client:IsValid() then
  515.                     table.insert(copy, client)
  516.                 else
  517.                     table.remove(self.Clients, key)
  518.                 end
  519.             end
  520.             return copy
  521.         end
  522.  
  523.         function SERVER:Host(ip, port)
  524.             ip = ip or "*"
  525.             port = port or 0
  526.  
  527.             self.socket:settimeout(0)
  528.             if self.socket_type == "tcp" then
  529.                 self.socket:setoption("reuseaddr", true)
  530.                 self.socket:bind(ip, port)
  531.                 self.socket:listen()
  532.                 self.ready = true
  533.             elseif self.socket_type == "udp" then
  534.                 self.socket:setsockname(ip, port)
  535.                 self.ready = true
  536.             end
  537.             self.socket:settimeout(0)
  538.         end
  539.        
  540.         SERVER.Bind = SERVER.Host
  541.  
  542.         function SERVER:Send(data, ip, port)
  543.             check(ip, "string")
  544.  
  545.             if self.socket_type == "tcp" then
  546.                 for key, client in pairs(self:GetClients()) do
  547.                     if client:GetIP() == ip and (not port or (port == client:GetPort())) then
  548.                         client:Send(data)
  549.                         break
  550.                     end
  551.                 end
  552.             elseif self.socket_type == "udp" then
  553.                 check(port, "number")
  554.                 self.socket:sendto(data, ip, port)
  555.             end
  556.         end
  557.        
  558.         local DUMMY = {}
  559.        
  560.         DUMMY.__tostring = function(s)
  561.             return string.format("client_%s[%s][%s]", "udp", s.ip or "nil", s.port or "nil")
  562.         end
  563.        
  564.         DUMMY.GetIp = function(s) return s.ip end
  565.         DUMMY.GetPort = function(s) return s.port end
  566.         DUMMY.IsValid = function() return true end
  567.         DUMMY.Close = function() return end
  568.         DUMMY.Remove = function() return end
  569.        
  570.         local function create_dummy_client(ip, port)
  571.             return setmetatable({ip = ip, port = port}, DUMMY)
  572.         end
  573.        
  574.         function SERVER:Think()
  575.             if not self.ready then return end
  576.  
  577.             if self.socket_type == "udp" then
  578.                 local data, ip, port = self.socket:receivefrom()
  579.                
  580.                 if ip == "timeout" then return end
  581.                
  582.                 if not data then
  583.                     self:DebugPrintf("errored: %s", tostring(ip))
  584.                 else
  585.                     self:OnReceive(data, create_dummy_client(ip, port))
  586.                     self:DebugPrintf("received %s from %s:%s", tostring(data), ip, port)
  587.                 end
  588.             elseif self.socket_type == "tcp" then
  589.                 local sock = self.socket
  590.                 sock:settimeout(0)
  591.  
  592.                 local ls_client, err = sock:accept()
  593.  
  594.                 if ls_client then
  595.                
  596.                     self:DebugPrintf("%s connected", client)
  597.                
  598.                     local client = new_socket(ls_client, luasocket.ClientMeta, "tcp")
  599.                     client.connected = true
  600.                     table.insert(self.Clients, client)
  601.  
  602.                     local b = self:OnClientConnected(client, client:GetIP(), client:GetPort())
  603.                    
  604.                     if b == true then
  605.                         client:SetKeepAlive(true)
  606.                     elseif b == false then
  607.                         client:Remove()
  608.                     end
  609.                 end
  610.  
  611.                 for _, client in pairs(self:GetClients()) do
  612.                     local data, err, partial = client.socket:receive(receive_types[self.ReceiveMode] or self.ReceiveMode)
  613.                    
  614.                 --  client:DebugPrintf("data = %s, error = %s, partial = %s", tostring(data), tostring(err), tostring(partial))
  615.                    
  616.                     if data then
  617.                        
  618.                         self:DebugPrintf("received %s from %s", data, client)
  619.                    
  620.                         self:OnReceive(data, client)
  621.                         client:OnSend(data)                    
  622.                        
  623.                     elseif err == "closed" then
  624.                    
  625.                         self:DebugPrintf("%s wants to close", client)
  626.                        
  627.                         if self:OnClientClosed(client) ~= false then                           
  628.                             client:Remove()
  629.                         end
  630.                     elseif err == "timeout" then
  631.                         --client:Timeout() -- hmm
  632.                     else
  633.                    
  634.                         self:DebugPrintf("%s errored: ", client, err)
  635.                        
  636.                         self:OnClientError(client, err)
  637.                         client:OnError(err)
  638.                     end
  639.                 end
  640.             end
  641.         end
  642.    
  643.         function SERVER:Remove()
  644.             remove_socket(self)
  645.         end
  646.  
  647.         function SERVER:IsValid()
  648.             return true
  649.         end
  650.  
  651.         function SERVER:GetIP()
  652.             local ip, port = self.socket:getsockname()
  653.             return ip
  654.         end
  655.  
  656.         function SERVER:GetPort()
  657.             local ip, port = self.socket:getsockname()
  658.             return ip and port or nil
  659.         end
  660.  
  661.         function SERVER:OnClientConnected(client, ip, port) end
  662.         function SERVER:OnClientClosed(client) end
  663.         function SERVER:OnReceive(data, client) end
  664.         function SERVER:OnClientError(client, err) end
  665.        
  666.         function luasocket.Server(typ)
  667.             return new_socket(nil, SERVER, typ)
  668.         end
  669.  
  670.         luasocket.ServerMeta = SERVER
  671.     end
  672. end
  673.  
  674. function luasocket.DumpDocs()
  675.     local function getargs(func)
  676.         local tbl = func:getparams()
  677.         table.remove(tbl, 1)
  678.         return tbl
  679.     end
  680.  
  681.     local tbl = {}
  682.    
  683.     for key, val in pairs(luasocket.ClientMeta) do
  684.         if type(val) == "function" then
  685.             table.insert(tbl, {key = key, str = "CLIENT:" .. key .. "(" .. table.concat(getargs(val), ", ") .. ")\n"})
  686.         end
  687.     end
  688.        
  689.     for key, val in pairs(luasocket.ServerMeta) do
  690.         if type(val) == "function" then
  691.             table.insert(tbl, {key = key, str = "SERVER:" .. key .. "(" .. table.concat(getargs(val), ", ") .. ")\n"})
  692.         end
  693.     end
  694.    
  695.     for k1,v1 in pairs(tbl) do
  696.     for k2,v2 in pairs(tbl) do
  697.         if v1.key == v2.key and k1 ~= k2 then
  698.             v1.str = v1.str:gsub("(.-):", "SHARED:")
  699.             print(v1.str)
  700.             tbl[k2] = nil
  701.             break
  702.         end
  703.     end
  704.     end
  705.    
  706.     table.sort(tbl, function(a, b) return a and b and a.str > b.str end)
  707.    
  708.     local str = ""
  709.    
  710.     for k,v in pairs(tbl) do
  711.         str = str .. v.str
  712.     end
  713.            
  714.     return str
  715. end
  716.  
  717. concommand.Add("luasocket_restart", function() include("luasocket.lua") end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement