buffer.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*=========================================================================*\
  2. * Input/Output interface for Lua programs
  3. * LuaSocket toolkit
  4. \*=========================================================================*/
  5. #include "lua.h"
  6. #include "lauxlib.h"
  7. #include "compat.h"
  8. #include "buffer.h"
  9. /*=========================================================================*\
  10. * Internal function prototypes
  11. \*=========================================================================*/
  12. static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b);
  13. static int recvline(p_buffer buf, luaL_Buffer *b);
  14. static int recvall(p_buffer buf, luaL_Buffer *b);
  15. static int buffer_get(p_buffer buf, const char **data, size_t *count);
  16. static void buffer_skip(p_buffer buf, size_t count);
  17. static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent);
  18. /* min and max macros */
  19. #ifndef MIN
  20. #define MIN(x, y) ((x) < (y) ? x : y)
  21. #endif
  22. #ifndef MAX
  23. #define MAX(x, y) ((x) > (y) ? x : y)
  24. #endif
  25. /*=========================================================================*\
  26. * Exported functions
  27. \*=========================================================================*/
  28. /*-------------------------------------------------------------------------*\
  29. * Initializes module
  30. \*-------------------------------------------------------------------------*/
  31. int buffer_open(lua_State *L) {
  32. (void) L;
  33. return 0;
  34. }
  35. /*-------------------------------------------------------------------------*\
  36. * Initializes C structure
  37. \*-------------------------------------------------------------------------*/
  38. void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
  39. buf->first = buf->last = 0;
  40. buf->io = io;
  41. buf->tm = tm;
  42. buf->received = buf->sent = 0;
  43. buf->birthday = timeout_gettime();
  44. }
  45. /*-------------------------------------------------------------------------*\
  46. * object:getstats() interface
  47. \*-------------------------------------------------------------------------*/
  48. int buffer_meth_getstats(lua_State *L, p_buffer buf) {
  49. lua_pushnumber(L, (lua_Number) buf->received);
  50. lua_pushnumber(L, (lua_Number) buf->sent);
  51. lua_pushnumber(L, timeout_gettime() - buf->birthday);
  52. return 3;
  53. }
  54. /*-------------------------------------------------------------------------*\
  55. * object:setstats() interface
  56. \*-------------------------------------------------------------------------*/
  57. int buffer_meth_setstats(lua_State *L, p_buffer buf) {
  58. buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
  59. buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
  60. if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
  61. lua_pushnumber(L, 1);
  62. return 1;
  63. }
  64. /*-------------------------------------------------------------------------*\
  65. * object:send() interface
  66. \*-------------------------------------------------------------------------*/
  67. int buffer_meth_send(lua_State *L, p_buffer buf) {
  68. int top = lua_gettop(L);
  69. int err = IO_DONE;
  70. size_t size = 0, sent = 0;
  71. const char *data = luaL_checklstring(L, 2, &size);
  72. long start = (long) luaL_optnumber(L, 3, 1);
  73. long end = (long) luaL_optnumber(L, 4, -1);
  74. timeout_markstart(buf->tm);
  75. if (start < 0) start = (long) (size+start+1);
  76. if (end < 0) end = (long) (size+end+1);
  77. if (start < 1) start = (long) 1;
  78. if (end > (long) size) end = (long) size;
  79. if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent);
  80. /* check if there was an error */
  81. if (err != IO_DONE) {
  82. lua_pushnil(L);
  83. lua_pushstring(L, buf->io->error(buf->io->ctx, err));
  84. lua_pushnumber(L, (lua_Number) (sent+start-1));
  85. } else {
  86. lua_pushnumber(L, (lua_Number) (sent+start-1));
  87. lua_pushnil(L);
  88. lua_pushnil(L);
  89. }
  90. #ifdef LUASOCKET_DEBUG
  91. /* push time elapsed during operation as the last return value */
  92. lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
  93. #endif
  94. return lua_gettop(L) - top;
  95. }
  96. /*-------------------------------------------------------------------------*\
  97. * object:receive() interface
  98. \*-------------------------------------------------------------------------*/
  99. int buffer_meth_receive(lua_State *L, p_buffer buf) {
  100. int err = IO_DONE, top = lua_gettop(L);
  101. luaL_Buffer b;
  102. size_t size;
  103. const char *part = luaL_optlstring(L, 3, "", &size);
  104. timeout_markstart(buf->tm);
  105. /* initialize buffer with optional extra prefix
  106. * (useful for concatenating previous partial results) */
  107. luaL_buffinit(L, &b);
  108. luaL_addlstring(&b, part, size);
  109. /* receive new patterns */
  110. if (!lua_isnumber(L, 2)) {
  111. const char *p= luaL_optstring(L, 2, "*l");
  112. if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
  113. else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
  114. else luaL_argcheck(L, 0, 2, "invalid receive pattern");
  115. /* get a fixed number of bytes (minus what was already partially
  116. * received) */
  117. } else {
  118. double n = lua_tonumber(L, 2);
  119. size_t wanted = (size_t) n;
  120. luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
  121. if (size == 0 || wanted > size)
  122. err = recvraw(buf, wanted-size, &b);
  123. }
  124. /* check if there was an error */
  125. if (err != IO_DONE) {
  126. /* we can't push anyting in the stack before pushing the
  127. * contents of the buffer. this is the reason for the complication */
  128. luaL_pushresult(&b);
  129. lua_pushstring(L, buf->io->error(buf->io->ctx, err));
  130. lua_pushvalue(L, -2);
  131. lua_pushnil(L);
  132. lua_replace(L, -4);
  133. } else {
  134. luaL_pushresult(&b);
  135. lua_pushnil(L);
  136. lua_pushnil(L);
  137. }
  138. #ifdef LUASOCKET_DEBUG
  139. /* push time elapsed during operation as the last return value */
  140. lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
  141. #endif
  142. return lua_gettop(L) - top;
  143. }
  144. /*-------------------------------------------------------------------------*\
  145. * Determines if there is any data in the read buffer
  146. \*-------------------------------------------------------------------------*/
  147. int buffer_isempty(p_buffer buf) {
  148. return buf->first >= buf->last;
  149. }
  150. /*=========================================================================*\
  151. * Internal functions
  152. \*=========================================================================*/
  153. /*-------------------------------------------------------------------------*\
  154. * Sends a block of data (unbuffered)
  155. \*-------------------------------------------------------------------------*/
  156. #define STEPSIZE 8192
  157. static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) {
  158. p_io io = buf->io;
  159. p_timeout tm = buf->tm;
  160. size_t total = 0;
  161. int err = IO_DONE;
  162. while (total < count && err == IO_DONE) {
  163. size_t done = 0;
  164. size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE;
  165. err = io->send(io->ctx, data+total, step, &done, tm);
  166. total += done;
  167. }
  168. *sent = total;
  169. buf->sent += total;
  170. return err;
  171. }
  172. /*-------------------------------------------------------------------------*\
  173. * Reads a fixed number of bytes (buffered)
  174. \*-------------------------------------------------------------------------*/
  175. static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) {
  176. int err = IO_DONE;
  177. size_t total = 0;
  178. while (err == IO_DONE) {
  179. size_t count; const char *data;
  180. err = buffer_get(buf, &data, &count);
  181. count = MIN(count, wanted - total);
  182. luaL_addlstring(b, data, count);
  183. buffer_skip(buf, count);
  184. total += count;
  185. if (total >= wanted) break;
  186. }
  187. return err;
  188. }
  189. /*-------------------------------------------------------------------------*\
  190. * Reads everything until the connection is closed (buffered)
  191. \*-------------------------------------------------------------------------*/
  192. static int recvall(p_buffer buf, luaL_Buffer *b) {
  193. int err = IO_DONE;
  194. size_t total = 0;
  195. while (err == IO_DONE) {
  196. const char *data; size_t count;
  197. err = buffer_get(buf, &data, &count);
  198. total += count;
  199. luaL_addlstring(b, data, count);
  200. buffer_skip(buf, count);
  201. }
  202. if (err == IO_CLOSED) {
  203. if (total > 0) return IO_DONE;
  204. else return IO_CLOSED;
  205. } else return err;
  206. }
  207. /*-------------------------------------------------------------------------*\
  208. * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
  209. * are not returned by the function and are discarded from the buffer
  210. \*-------------------------------------------------------------------------*/
  211. static int recvline(p_buffer buf, luaL_Buffer *b) {
  212. int err = IO_DONE;
  213. while (err == IO_DONE) {
  214. size_t count, pos; const char *data;
  215. err = buffer_get(buf, &data, &count);
  216. pos = 0;
  217. while (pos < count && data[pos] != '\n') {
  218. /* we ignore all \r's */
  219. if (data[pos] != '\r') luaL_addchar(b, data[pos]);
  220. pos++;
  221. }
  222. if (pos < count) { /* found '\n' */
  223. buffer_skip(buf, pos+1); /* skip '\n' too */
  224. break; /* we are done */
  225. } else /* reached the end of the buffer */
  226. buffer_skip(buf, pos);
  227. }
  228. return err;
  229. }
  230. /*-------------------------------------------------------------------------*\
  231. * Skips a given number of bytes from read buffer. No data is read from the
  232. * transport layer
  233. \*-------------------------------------------------------------------------*/
  234. static void buffer_skip(p_buffer buf, size_t count) {
  235. buf->received += count;
  236. buf->first += count;
  237. if (buffer_isempty(buf))
  238. buf->first = buf->last = 0;
  239. }
  240. /*-------------------------------------------------------------------------*\
  241. * Return any data available in buffer, or get more data from transport layer
  242. * if buffer is empty
  243. \*-------------------------------------------------------------------------*/
  244. static int buffer_get(p_buffer buf, const char **data, size_t *count) {
  245. int err = IO_DONE;
  246. p_io io = buf->io;
  247. p_timeout tm = buf->tm;
  248. if (buffer_isempty(buf)) {
  249. size_t got;
  250. err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm);
  251. buf->first = 0;
  252. buf->last = got;
  253. }
  254. *count = buf->last - buf->first;
  255. *data = buf->data + buf->first;
  256. return err;
  257. }