Skip to content

Commit b5ffb11

Browse files
spacewanderagentzh
authored andcommitted
feature: implemented the receiveany() upstream cosocket method.
Signed-off-by: Yichun Zhang (agentzh) <agentzh@gmail.com>
1 parent 5a3c48d commit b5ffb11

9 files changed

+904
-177
lines changed

README.markdown

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3221,6 +3221,7 @@ Nginx API for Lua
32213221
* [tcpsock:sslhandshake](#tcpsocksslhandshake)
32223222
* [tcpsock:send](#tcpsocksend)
32233223
* [tcpsock:receive](#tcpsockreceive)
3224+
* [tcpsock:receiveany](#tcpsockreceiveany)
32243225
* [tcpsock:receiveuntil](#tcpsockreceiveuntil)
32253226
* [tcpsock:close](#tcpsockclose)
32263227
* [tcpsock:settimeout](#tcpsocksettimeout)
@@ -7002,6 +7003,7 @@ Creates and returns a TCP or stream-oriented unix domain socket object (also kno
70027003
* [settimeout](#tcpsocksettimeout)
70037004
* [settimeouts](#tcpsocksettimeouts)
70047005
* [setoption](#tcpsocksetoption)
7006+
* [receiveany](#tcpsockreceiveany)
70057007
* [receiveuntil](#tcpsockreceiveuntil)
70067008
* [setkeepalive](#tcpsocksetkeepalive)
70077009
* [getreusedtimes](#tcpsockgetreusedtimes)
@@ -7231,6 +7233,40 @@ This feature was first introduced in the `v0.5.0rc1` release.
72317233

72327234
[Back to TOC](#nginx-api-for-lua)
72337235

7236+
tcpsock:receiveany
7237+
------------------
7238+
**syntax:** *data, err = tcpsock:receiveany(max)*
7239+
7240+
**context:** *rewrite_by_lua&#42;, access_by_lua&#42;, content_by_lua&#42;, ngx.timer.&#42;, ssl_certificate_by_lua&#42;, ssl_session_fetch_by_lua&#42;*
7241+
7242+
Returns any data received by the connected socket, at most `max` bytes.
7243+
7244+
This method is a synchronous operation just like the [send](#tcpsocksend) method and is 100% nonblocking.
7245+
7246+
In case of success, it returns the data received; in case of error, it returns `nil` with a string describing the error.
7247+
7248+
If the received data is more than this size, this method will return with exactly this size of data.
7249+
The remaining data in the underlying receive buffer could be returned in the next reading operation.
7250+
7251+
Timeout for the reading operation is controlled by the [lua_socket_read_timeout](#lua_socket_read_timeout) config directive and the [settimeouts](#tcpsocksettimeouts) method. And the latter takes priority. For example:
7252+
7253+
```lua
7254+
7255+
sock:settimeouts(1000, 1000, 1000) -- one second timeout for connect/read/write
7256+
local data, err = sock:receiveany(10 * 1024 * 1024) -- read any data, at most 10K
7257+
if not data then
7258+
ngx.say("failed to read any data: ", err)
7259+
return
7260+
end
7261+
ngx.say("successfully read: ", data)
7262+
```
7263+
7264+
This method doesn't automatically close the current connection when the read timeout error occurs. For other connection errors, this method always automatically closes the connection.
7265+
7266+
This feature was first introduced in the `v0.10.14` release.
7267+
7268+
[Back to TOC](#nginx-api-for-lua)
7269+
72347270
tcpsock:receiveuntil
72357271
--------------------
72367272
**syntax:** *iterator = tcpsock:receiveuntil(pattern, options?)*

config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ HTTP_LUA_SRCS=" \
361361
$ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.c \
362362
$ngx_addon_dir/src/ngx_http_lua_ssl.c \
363363
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.c \
364+
$ngx_addon_dir/src/ngx_http_lua_input_filters.c \
364365
"
365366

366367
HTTP_LUA_DEPS=" \
@@ -422,6 +423,7 @@ HTTP_LUA_DEPS=" \
422423
$ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.h \
423424
$ngx_addon_dir/src/ngx_http_lua_ssl.h \
424425
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.h \
426+
$ngx_addon_dir/src/ngx_http_lua_input_filters.h \
425427
"
426428

427429
CFLAGS="$CFLAGS -DNDK_SET_VAR"

doc/HttpLuaModule.wiki

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5894,6 +5894,7 @@ Creates and returns a TCP or stream-oriented unix domain socket object (also kno
58945894
* [[#tcpsock:settimeout|settimeout]]
58955895
* [[#tcpsock:settimeouts|settimeouts]]
58965896
* [[#tcpsock:setoption|setoption]]
5897+
* [[#tcpsock:receiveany|receiveany]]
58975898
* [[#tcpsock:receiveuntil|receiveuntil]]
58985899
* [[#tcpsock:setkeepalive|setkeepalive]]
58995900
* [[#tcpsock:getreusedtimes|getreusedtimes]]
@@ -6103,6 +6104,36 @@ Since the <code>v0.8.8</code> release, this method no longer automatically close
61036104
61046105
This feature was first introduced in the <code>v0.5.0rc1</code> release.
61056106
6107+
== tcpsock:receiveany ==
6108+
'''syntax:''' ''data, err = tcpsock:receiveany(max)''
6109+
6110+
'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*''
6111+
6112+
Returns any data received by the connected socket, at most <code>max</code> bytes.
6113+
6114+
This method is a synchronous operation just like the [[#tcpsock:send|send]] method and is 100% nonblocking.
6115+
6116+
In case of success, it returns the data received; in case of error, it returns <code>nil</code> with a string describing the error.
6117+
6118+
If the received data is more than this size, this method will return with exactly this size of data.
6119+
The remaining data in the underlying receive buffer could be returned in the next reading operation.
6120+
6121+
Timeout for the reading operation is controlled by the [[#lua_socket_read_timeout|lua_socket_read_timeout]] config directive and the [[#tcpsock:settimeouts|settimeouts]] method. And the latter takes priority. For example:
6122+
6123+
<geshi lang="lua">
6124+
sock:settimeouts(1000, 1000, 1000) -- one second timeout for connect/read/write
6125+
local data, err = sock:receiveany(10 * 1024 * 1024) -- read any data, at most 10K
6126+
if not data then
6127+
ngx.say("failed to read any data: ", err)
6128+
return
6129+
end
6130+
ngx.say("successfully read: ", data)
6131+
</geshi>
6132+
6133+
This method doesn't automatically close the current connection when the read timeout error occurs. For other connection errors, this method always automatically closes the connection.
6134+
6135+
This feature was first introduced in the <code>v0.10.14</code> release.
6136+
61066137
== tcpsock:receiveuntil ==
61076138
'''syntax:''' ''iterator = tcpsock:receiveuntil(pattern, options?)''
61086139

src/ngx_http_lua_input_filters.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
/*
3+
* Copyright (C) by OpenResty Inc.
4+
*/
5+
6+
7+
#ifndef DDEBUG
8+
#define DDEBUG 0
9+
#endif
10+
#include "ddebug.h"
11+
12+
13+
#include "ngx_http_lua_common.h"
14+
15+
16+
ngx_int_t
17+
ngx_http_lua_read_bytes(ngx_buf_t *src, ngx_chain_t *buf_in, size_t *rest,
18+
ssize_t bytes, ngx_log_t *log)
19+
{
20+
if (bytes == 0) {
21+
return NGX_ERROR;
22+
}
23+
24+
if ((size_t) bytes >= *rest) {
25+
26+
buf_in->buf->last += *rest;
27+
src->pos += *rest;
28+
*rest = 0;
29+
30+
return NGX_OK;
31+
}
32+
33+
/* bytes < *rest */
34+
35+
buf_in->buf->last += bytes;
36+
src->pos += bytes;
37+
*rest -= bytes;
38+
39+
return NGX_AGAIN;
40+
}
41+
42+
43+
ngx_int_t
44+
ngx_http_lua_read_all(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes,
45+
ngx_log_t *log)
46+
{
47+
if (bytes == 0) {
48+
return NGX_OK;
49+
}
50+
51+
buf_in->buf->last += bytes;
52+
src->pos += bytes;
53+
54+
return NGX_AGAIN;
55+
}
56+
57+
58+
ngx_int_t
59+
ngx_http_lua_read_any(ngx_buf_t *src, ngx_chain_t *buf_in, size_t *max,
60+
ssize_t bytes, ngx_log_t *log)
61+
{
62+
if (bytes == 0) {
63+
return NGX_ERROR;
64+
}
65+
66+
if (bytes >= (ssize_t) *max) {
67+
bytes = (ssize_t) *max;
68+
}
69+
70+
buf_in->buf->last += bytes;
71+
src->pos += bytes;
72+
73+
return NGX_OK;
74+
}
75+
76+
77+
ngx_int_t
78+
ngx_http_lua_read_line(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes,
79+
ngx_log_t *log)
80+
{
81+
u_char *dst;
82+
u_char c;
83+
#if (NGX_DEBUG)
84+
u_char *begin;
85+
#endif
86+
87+
#if (NGX_DEBUG)
88+
begin = src->pos;
89+
#endif
90+
91+
if (bytes == 0) {
92+
return NGX_ERROR;
93+
}
94+
95+
dd("already read: %p: %.*s", buf_in,
96+
(int) (buf_in->buf->last - buf_in->buf->pos), buf_in->buf->pos);
97+
98+
dd("data read: %.*s", (int) bytes, src->pos);
99+
100+
dst = buf_in->buf->last;
101+
102+
while (bytes--) {
103+
104+
c = *src->pos++;
105+
106+
switch (c) {
107+
case '\n':
108+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0,
109+
"lua read the final line part: \"%*s\"",
110+
src->pos - 1 - begin, begin);
111+
112+
buf_in->buf->last = dst;
113+
114+
dd("read a line: %p: %.*s", buf_in,
115+
(int) (buf_in->buf->last - buf_in->buf->pos), buf_in->buf->pos);
116+
117+
return NGX_OK;
118+
119+
case '\r':
120+
/* ignore it */
121+
break;
122+
123+
default:
124+
*dst++ = c;
125+
break;
126+
}
127+
}
128+
129+
#if (NGX_DEBUG)
130+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0,
131+
"lua read partial line data: %*s", dst - begin, begin);
132+
#endif
133+
134+
buf_in->buf->last = dst;
135+
136+
return NGX_AGAIN;
137+
}

src/ngx_http_lua_input_filters.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
/*
3+
* Copyright (C) by OpenResty Inc.
4+
*/
5+
6+
7+
#ifndef _NGX_HTTP_LUA_INPUT_FILTERS_H_INCLUDED_
8+
#define _NGX_HTTP_LUA_INPUT_FILTERS_H_INCLUDED_
9+
10+
11+
#include "ngx_http_lua_common.h"
12+
13+
14+
ngx_int_t ngx_http_lua_read_bytes(ngx_buf_t *src, ngx_chain_t *buf_in,
15+
size_t *rest, ssize_t bytes, ngx_log_t *log);
16+
17+
ngx_int_t ngx_http_lua_read_all(ngx_buf_t *src, ngx_chain_t *buf_in,
18+
ssize_t bytes, ngx_log_t *log);
19+
20+
ngx_int_t ngx_http_lua_read_any(ngx_buf_t *src, ngx_chain_t *buf_in,
21+
size_t *max, ssize_t bytes, ngx_log_t *log);
22+
23+
ngx_int_t ngx_http_lua_read_line(ngx_buf_t *src, ngx_chain_t *buf_in,
24+
ssize_t bytes, ngx_log_t *log);
25+
26+
27+
#endif /* _NGX_HTTP_LUA_INPUT_FILTERS_H_INCLUDED_ */
28+
29+
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

0 commit comments

Comments
 (0)