Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

150 lignes
4.5 KiB

  1. -----------------------------------------------------------------------------
  2. -- LuaSocket helper module
  3. -- Author: Diego Nehab
  4. -- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
  5. -----------------------------------------------------------------------------
  6. -----------------------------------------------------------------------------
  7. -- Declare module and import dependencies
  8. -----------------------------------------------------------------------------
  9. local base = _G
  10. local string = require("string")
  11. local math = require("math")
  12. local socket = require("socket.core")
  13. module("socket")
  14. -----------------------------------------------------------------------------
  15. -- Exported auxiliar functions
  16. -----------------------------------------------------------------------------
  17. function connect(address, port, laddress, lport)
  18. if address == "*" then address = "0.0.0.0" end
  19. local addrinfo, err = socket.dns.getaddrinfo(address);
  20. if not addrinfo then return nil, err end
  21. local sock, err;
  22. if addrinfo[1].family == "inet" then
  23. sock, err = socket.tcp()
  24. else
  25. sock, err = socket.tcp6()
  26. end
  27. if not sock then return nil, err end
  28. if laddress then
  29. local res, err = sock:bind(laddress, lport, -1)
  30. if not res then return nil, err end
  31. end
  32. local res, err = sock:connect(address, port)
  33. if not res then return nil, err end
  34. return sock
  35. end
  36. function bind(host, port, backlog)
  37. if host == "*" then host = "0.0.0.0" end
  38. local addrinfo, err = socket.dns.getaddrinfo(host);
  39. if not addrinfo then return nil, err end
  40. local sock, err;
  41. if addrinfo[1].family == "inet" then
  42. sock, err = socket.tcp()
  43. else
  44. sock, err = socket.tcp6()
  45. end
  46. if not sock then return nil, err end
  47. sock:setoption("reuseaddr", true)
  48. local res, err = sock:bind(host, port)
  49. if not res then return nil, err end
  50. res, err = sock:listen(backlog)
  51. if not res then return nil, err end
  52. return sock
  53. end
  54. try = newtry()
  55. function choose(table)
  56. return function(name, opt1, opt2)
  57. if base.type(name) ~= "string" then
  58. name, opt1, opt2 = "default", name, opt1
  59. end
  60. local f = table[name or "nil"]
  61. if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
  62. else return f(opt1, opt2) end
  63. end
  64. end
  65. -----------------------------------------------------------------------------
  66. -- Socket sources and sinks, conforming to LTN12
  67. -----------------------------------------------------------------------------
  68. -- create namespaces inside LuaSocket namespace
  69. sourcet = {}
  70. sinkt = {}
  71. BLOCKSIZE = 2048
  72. sinkt["close-when-done"] = function(sock)
  73. return base.setmetatable({
  74. getfd = function() return sock:getfd() end,
  75. dirty = function() return sock:dirty() end
  76. }, {
  77. __call = function(self, chunk, err)
  78. if not chunk then
  79. sock:close()
  80. return 1
  81. else return sock:send(chunk) end
  82. end
  83. })
  84. end
  85. sinkt["keep-open"] = function(sock)
  86. return base.setmetatable({
  87. getfd = function() return sock:getfd() end,
  88. dirty = function() return sock:dirty() end
  89. }, {
  90. __call = function(self, chunk, err)
  91. if chunk then return sock:send(chunk)
  92. else return 1 end
  93. end
  94. })
  95. end
  96. sinkt["default"] = sinkt["keep-open"]
  97. sink = choose(sinkt)
  98. sourcet["by-length"] = function(sock, length)
  99. return base.setmetatable({
  100. getfd = function() return sock:getfd() end,
  101. dirty = function() return sock:dirty() end
  102. }, {
  103. __call = function()
  104. if length <= 0 then return nil end
  105. local size = math.min(socket.BLOCKSIZE, length)
  106. local chunk, err = sock:receive(size)
  107. if err then return nil, err end
  108. length = length - string.len(chunk)
  109. return chunk
  110. end
  111. })
  112. end
  113. sourcet["until-closed"] = function(sock)
  114. local done
  115. return base.setmetatable({
  116. getfd = function() return sock:getfd() end,
  117. dirty = function() return sock:dirty() end
  118. }, {
  119. __call = function()
  120. if done then return nil end
  121. local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
  122. if not err then return chunk
  123. elseif err == "closed" then
  124. sock:close()
  125. done = 1
  126. return partial
  127. else return nil, err end
  128. end
  129. })
  130. end
  131. sourcet["default"] = sourcet["until-closed"]
  132. source = choose(sourcet)