You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tcp.lua 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. --[[[
  2. -- Just a test for TCP API
  3. --]]
  4. local rspamd_tcp = require "rspamd_tcp"
  5. local logger = require "rspamd_logger"
  6. local tcp_sync = require "lua_tcp_sync"
  7. -- [[ old fashioned callback api ]]
  8. local function http_simple_tcp_async_symbol(task)
  9. logger.errx(task, 'http_tcp_symbol: begin')
  10. local function http_get_cb(err, data, conn)
  11. logger.errx(task, 'http_get_cb: got reply: %s, error: %s, conn: %s', data, err, conn)
  12. task:insert_result('HTTP_ASYNC_RESPONSE_2', 1.0, data)
  13. end
  14. local function http_read_post_cb(err, conn)
  15. logger.errx(task, 'http_read_post_cb: write done: error: %s, conn: %s', err, conn)
  16. conn:add_read(http_get_cb)
  17. end
  18. local function http_read_cb(err, data, conn)
  19. logger.errx(task, 'http_read_cb: got reply: %s, error: %s, conn: %s', data, err, conn)
  20. conn:add_write(http_read_post_cb, "POST /request2 HTTP/1.1\r\n\r\n")
  21. task:insert_result('HTTP_ASYNC_RESPONSE', 1.0, data or err)
  22. end
  23. rspamd_tcp:request({
  24. task = task,
  25. callback = http_read_cb,
  26. host = '127.0.0.1',
  27. data = {'GET /request HTTP/1.1\r\nConnection: keep-alive\r\n\r\n'},
  28. read = true,
  29. port = 18080,
  30. })
  31. end
  32. local function http_simple_tcp_ssl_symbol(task)
  33. logger.errx(task, 'ssl_tcp_symbol: begin')
  34. local function ssl_get_cb(err, data, conn)
  35. logger.errx(task, 'ssl_get_cb: got reply: %s, error: %s, conn: %s', data, err, conn)
  36. task:insert_result('TCP_SSL_RESPONSE_2', 1.0, tostring(data):gsub('%s', ''))
  37. end
  38. local function ssl_read_post_cb(err, conn)
  39. logger.errx(task, 'ssl_read_post_cb: write done: error: %s, conn: %s', err, conn)
  40. conn:add_read(ssl_get_cb)
  41. end
  42. local function ssl_read_cb(err, data, conn)
  43. logger.errx(task, 'ssl_read_cb: got reply: %s, error: %s, conn: %s', data, err, conn)
  44. conn:add_write(ssl_read_post_cb, "test2\n")
  45. task:insert_result('TCP_SSL_RESPONSE', 1.0, tostring(data):gsub('%s', ''))
  46. end
  47. rspamd_tcp:request({
  48. task = task,
  49. callback = ssl_read_cb,
  50. host = '127.0.0.1',
  51. data = {'test\n'},
  52. read = true,
  53. ssl = true,
  54. ssl_noverify = true,
  55. port = 14433,
  56. })
  57. end
  58. local function http_large_tcp_ssl_symbol(task)
  59. local data = {}
  60. local function ssl_get_cb(err, rep, conn)
  61. logger.errx(task, 'ssl_get_cb: got reply: %s, error: %s, conn: %s', rep, err, conn)
  62. task:insert_result('TCP_SSL_LARGE_2', 1.0)
  63. end
  64. local function ssl_read_post_cb(err, conn)
  65. logger.errx(task, 'ssl_large_read_post_cb: write done: error: %s, conn: %s', err, conn)
  66. conn:add_read(ssl_get_cb)
  67. end
  68. local function ssl_read_cb(err, rep, conn)
  69. logger.errx(task, 'ssl_large_read_cb: got reply: %s, error: %s, conn: %s', rep, err, conn)
  70. conn:add_write(ssl_read_post_cb, 'foo\n')
  71. task:insert_result('TCP_SSL_LARGE', 1.0)
  72. end
  73. if task:get_queue_id() == 'SSL Large TCP request' then
  74. logger.errx(task, 'ssl_large_tcp_symbol: begin')
  75. for i = 1,2 do
  76. local st = {}
  77. for j=1,300000 do
  78. st[j] = 't'
  79. end
  80. data[i] = table.concat(st)
  81. end
  82. data[#data + 1] = '\n'
  83. rspamd_tcp:request({
  84. task = task,
  85. callback = ssl_read_cb,
  86. host = '127.0.0.1',
  87. data = data,
  88. read = true,
  89. ssl = true,
  90. stop_pattern = '\n',
  91. ssl_noverify = true,
  92. port = 14433,
  93. timeout = 20,
  94. })
  95. else
  96. logger.errx(task, 'ssl_large_tcp_symbol: skip')
  97. end
  98. end
  99. local function http_simple_tcp_symbol(task)
  100. logger.errx(task, 'connect_sync, before')
  101. local err
  102. local is_ok, connection = tcp_sync.connect {
  103. task = task,
  104. host = '127.0.0.1',
  105. timeout = 20,
  106. port = 18080,
  107. }
  108. if not is_ok then
  109. task:insert_result('HTTP_SYNC_WRITE_ERROR', 1.0, connection)
  110. logger.errx(task, 'write error: %1', connection)
  111. end
  112. logger.errx(task, 'connect_sync %1, %2', is_ok, tostring(connection))
  113. is_ok, err = connection:write('GET /request_sync HTTP/1.1\r\nConnection: keep-alive\r\n\r\n')
  114. logger.errx(task, 'write %1, %2', is_ok, err)
  115. if not is_ok then
  116. task:insert_result('HTTP_SYNC_WRITE_ERROR', 1.0, err)
  117. logger.errx(task, 'write error: %1', err)
  118. end
  119. local data
  120. local got_content = ''
  121. repeat
  122. is_ok, data = connection:read_once();
  123. logger.errx(task, 'read_once: is_ok: %1, data: %2', is_ok, data)
  124. if not is_ok then
  125. task:insert_result('HTTP_SYNC_ERROR', 1.0, data)
  126. return
  127. else
  128. got_content = got_content .. data
  129. end
  130. if got_content:find('hello') then
  131. -- dummy_http.py responds with either hello world or hello post
  132. break
  133. end
  134. until false
  135. task:insert_result('HTTP_SYNC_RESPONSE', 1.0, got_content)
  136. is_ok, err = connection:write("POST /request2 HTTP/1.1\r\n\r\n")
  137. logger.errx(task, 'write[2] %1, %2', is_ok, err)
  138. got_content = ''
  139. repeat
  140. is_ok, data = connection:read_once();
  141. logger.errx(task, 'read_once[2]: is_ok %1, data: %2', is_ok, data)
  142. if not is_ok then
  143. task:insert_result('HTTP_SYNC_ERROR_2', 1.0, data)
  144. return
  145. else
  146. got_content = got_content .. data
  147. end
  148. if got_content:find('hello') then
  149. -- dummy_http.py responds with either hello world or hello post
  150. break
  151. end
  152. until false
  153. task:insert_result('HTTP_SYNC_RESPONSE_2', 1.0, data)
  154. connection:close()
  155. end
  156. local function http_tcp_symbol(task)
  157. local url = tostring(task:get_request_header('url'))
  158. local method = tostring(task:get_request_header('method'))
  159. if url == 'nil' then
  160. return
  161. end
  162. local err
  163. local is_ok, connection = tcp_sync.connect {
  164. task = task,
  165. host = '127.0.0.1',
  166. timeout = 20,
  167. port = 18080,
  168. }
  169. logger.errx(task, 'connect_sync %1, %2', is_ok, tostring(connection))
  170. if not is_ok then
  171. logger.errx(task, 'connect error: %1', connection)
  172. return
  173. end
  174. is_ok, err = connection:write(string.format('%s %s HTTP/1.1\r\nConnection: close\r\n\r\n', method:upper(), url))
  175. logger.errx(task, 'write %1, %2', is_ok, err)
  176. if not is_ok then
  177. logger.errx(task, 'write error: %1', err)
  178. return
  179. end
  180. local content_length, content
  181. while true do
  182. local header_line
  183. is_ok, header_line = connection:read_until("\r\n")
  184. if not is_ok then
  185. logger.errx(task, 'failed to get header: %1', header_line)
  186. return
  187. end
  188. if header_line == "" then
  189. logger.errx(task, 'headers done')
  190. break
  191. end
  192. local value
  193. local header = header_line:gsub("([%w-]+): (.*)",
  194. function (h, v) value = v; return h:lower() end)
  195. logger.errx(task, 'parsed header: %1 -> "%2"', header, value)
  196. if header == "content-length" then
  197. content_length = tonumber(value)
  198. end
  199. end
  200. if content_length then
  201. is_ok, content = connection:read_bytes(content_length)
  202. if is_ok then
  203. task:insert_result('HTTP_SYNC_CONTENT_' .. method, 1.0, content)
  204. end
  205. else
  206. is_ok, content = connection:read_until_eof()
  207. if is_ok then
  208. task:insert_result('HTTP_SYNC_EOF_' .. method, 1.0, content)
  209. end
  210. end
  211. logger.errx(task, '(is_ok: %1) content [%2 bytes] %3', is_ok, content_length, content)
  212. end
  213. rspamd_config:register_symbol({
  214. name = 'SIMPLE_TCP_ASYNC_TEST',
  215. score = 1.0,
  216. callback = http_simple_tcp_async_symbol,
  217. no_squeeze = true
  218. })
  219. rspamd_config:register_symbol({
  220. name = 'SIMPLE_TCP_ASYNC_SSL_TEST',
  221. score = 1.0,
  222. callback = http_simple_tcp_ssl_symbol,
  223. no_squeeze = true
  224. })
  225. rspamd_config:register_symbol({
  226. name = 'LARGE_TCP_ASYNC_SSL_TEST',
  227. score = 1.0,
  228. callback = http_large_tcp_ssl_symbol,
  229. no_squeeze = true
  230. })
  231. rspamd_config:register_symbol({
  232. name = 'SIMPLE_TCP_TEST',
  233. score = 1.0,
  234. callback = http_simple_tcp_symbol,
  235. no_squeeze = true,
  236. flags = 'coro',
  237. })
  238. rspamd_config:register_symbol({
  239. name = 'HTTP_TCP_TEST',
  240. score = 1.0,
  241. callback = http_tcp_symbol,
  242. no_squeeze = true,
  243. flags = 'coro',
  244. })
  245. -- ]]