static int class_fetches_ref;
static int class_converters_ref;
static int class_http_ref;
+static int class_http_msg_ref;
static int class_map_ref;
static int class_applet_tcp_ref;
static int class_applet_http_ref;
return 1;
}
+/* This function creates and returns an array containing the status-line
+ * elements. This function does not fails.
+ */
+__LJMP static int hlua_http_get_stline(lua_State *L, struct htx_sl *sl)
+{
+ /* Create the table. */
+ lua_newtable(L);
+
+ if (sl->flags & HTX_SL_F_IS_RESP) {
+ lua_pushstring(L, "version");
+ lua_pushlstring(L, HTX_SL_RES_VPTR(sl), HTX_SL_RES_VLEN(sl));
+ lua_settable(L, -3);
+ lua_pushstring(L, "code");
+ lua_pushlstring(L, HTX_SL_RES_CPTR(sl), HTX_SL_RES_CLEN(sl));
+ lua_settable(L, -3);
+ lua_pushstring(L, "reason");
+ lua_pushlstring(L, HTX_SL_RES_RPTR(sl), HTX_SL_RES_RLEN(sl));
+ lua_settable(L, -3);
+ }
+ else {
+ lua_pushstring(L, "method");
+ lua_pushlstring(L, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl));
+ lua_settable(L, -3);
+ lua_pushstring(L, "uri");
+ lua_pushlstring(L, HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl));
+ lua_settable(L, -3);
+ lua_pushstring(L, "version");
+ lua_pushlstring(L, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl));
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
/* This function creates ans returns an array of HTTP headers.
* This function does not fails. It is used as wrapper with the
* 2 following functions.
if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
WILL_LJMP(lua_error(L));
- return hlua_http_add_hdr(L, &htxn->s->txn->req);
+ return hlua_http_add_hdr(L, &htxn->s->txn->req);
+}
+
+__LJMP static int hlua_http_res_add_hdr(lua_State *L)
+{
+ struct hlua_txn *htxn;
+
+ MAY_LJMP(check_args(L, 3, "res_add_hdr"));
+ htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+ if (htxn->dir != SMP_OPT_DIR_RES || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ return hlua_http_add_hdr(L, &htxn->s->txn->rsp);
+}
+
+static int hlua_http_req_set_hdr(lua_State *L)
+{
+ struct hlua_txn *htxn;
+
+ MAY_LJMP(check_args(L, 3, "req_set_hdr"));
+ htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+ if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ hlua_http_del_hdr(L, &htxn->s->txn->req);
+ return hlua_http_add_hdr(L, &htxn->s->txn->req);
+}
+
+static int hlua_http_res_set_hdr(lua_State *L)
+{
+ struct hlua_txn *htxn;
+
+ MAY_LJMP(check_args(L, 3, "res_set_hdr"));
+ htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+ if (htxn->dir != SMP_OPT_DIR_RES || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ hlua_http_del_hdr(L, &htxn->s->txn->rsp);
+ return hlua_http_add_hdr(L, &htxn->s->txn->rsp);
+}
+
+/* This function set the method. */
+static int hlua_http_req_set_meth(lua_State *L)
+{
+ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ size_t name_len;
+ const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ lua_pushboolean(L, http_req_replace_stline(0, name, name_len, htxn->p, htxn->s) != -1);
+ return 1;
+}
+
+/* This function set the method. */
+static int hlua_http_req_set_path(lua_State *L)
+{
+ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ size_t name_len;
+ const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ lua_pushboolean(L, http_req_replace_stline(1, name, name_len, htxn->p, htxn->s) != -1);
+ return 1;
+}
+
+/* This function set the query-string. */
+static int hlua_http_req_set_query(lua_State *L)
+{
+ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ size_t name_len;
+ const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ /* Check length. */
+ if (name_len > trash.size - 1) {
+ lua_pushboolean(L, 0);
+ return 1;
+ }
+
+ /* Add the mark question as prefix. */
+ chunk_reset(&trash);
+ trash.area[trash.data++] = '?';
+ memcpy(trash.area + trash.data, name, name_len);
+ trash.data += name_len;
+
+ lua_pushboolean(L,
+ http_req_replace_stline(2, trash.area, trash.data, htxn->p, htxn->s) != -1);
+ return 1;
+}
+
+/* This function set the uri. */
+static int hlua_http_req_set_uri(lua_State *L)
+{
+ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ size_t name_len;
+ const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ lua_pushboolean(L, http_req_replace_stline(3, name, name_len, htxn->p, htxn->s) != -1);
+ return 1;
+}
+
+/* This function set the response code & optionally reason. */
+static int hlua_http_res_set_status(lua_State *L)
+{
+ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
+ const char *str = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
+ const struct ist reason = ist2(str, (str ? strlen(str) : 0));
+
+ if (htxn->dir != SMP_OPT_DIR_RES || !IS_HTX_STRM(htxn->s))
+ WILL_LJMP(lua_error(L));
+
+ http_res_set_status(code, reason, htxn->s);
+ return 0;
+}
+
+/*
+ *
+ *
+ * Class HTTPMessage
+ *
+ *
+ */
+
+/* Returns a struct http_msg if the stack entry "ud" is a class HTTPMessage,
+ * otherwise it throws an error.
+ */
+__LJMP static struct http_msg *hlua_checkhttpmsg(lua_State *L, int ud)
+{
+ return MAY_LJMP(hlua_checkudata(L, ud, class_http_msg_ref));
+}
+
+/* Creates and pushes on the stack a HTTP object according with a current TXN.
+ */
+static __maybe_unused int hlua_http_msg_new(lua_State *L, struct http_msg *msg)
+{
+ /* Check stack size. */
+ if (!lua_checkstack(L, 3))
+ return 0;
+
+ lua_newtable(L);
+ lua_pushlightuserdata(L, msg);
+ lua_rawseti(L, -2, 0);
+
+ /* Create the "channel" field that contains the request channel object. */
+ lua_pushstring(L, "channel");
+ if (!hlua_channel_new(L, msg->chn))
+ return 0;
+ lua_rawset(L, -3);
+
+ /* Pop a class stream metatable and affect it to the table. */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_msg_ref);
+ lua_setmetatable(L, -2);
+
+ return 1;
+}
+
+/* Helper function returning a filter attached to the HTTP message at the
+ * position <ud> in the stack, filling the current offset and length of the
+ * filter. If no filter is attached, NULL is returned and <offet> and <len> are
+ * filled with output and input length respectively.
+ */
+static struct filter *hlua_http_msg_filter(lua_State *L, int ud, struct http_msg *msg, size_t *offset, size_t *len)
+{
+ struct channel *chn = msg->chn;
+ struct htx *htx = htxbuf(&chn->buf);
+ struct filter *filter = NULL;
+
+ *offset = co_data(msg->chn);
+ *len = htx->data - co_data(msg->chn);
+
+ if (lua_getfield(L, ud, "__filter") == LUA_TLIGHTUSERDATA) {
+ filter = lua_touserdata (L, -1);
+ if (msg->msg_state >= HTTP_MSG_DATA) {
+ struct hlua_flt_ctx *flt_ctx = filter->ctx;
+
+ *offset = flt_ctx->cur_off[CHN_IDX(chn)];
+ *len = flt_ctx->cur_len[CHN_IDX(chn)];
+ }
+ }
+
+ lua_pop(L, 1);
+ return filter;
+}
+
+/* Returns true if the channel attached to the HTTP message is the response
+ * channel.
+ */
+__LJMP static int hlua_http_msg_is_resp(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 1, "is_resp"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ lua_pushboolean(L, !!(msg->chn->flags & CF_ISRESP));
+ return 1;
+}
+
+/* Returns an array containing the elements status-line of the HTTP message. It relies
+ * on hlua_http_get_stline().
+ */
+__LJMP static int hlua_http_msg_get_stline(lua_State *L)
+{
+ struct http_msg *msg;
+ struct htx *htx;
+ struct htx_sl *sl;
+
+ MAY_LJMP(check_args(L, 1, "get_stline"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ htx = htxbuf(&msg->chn->buf);
+ sl = http_get_stline(htx);
+ if (!sl)
+ return 0;
+ return hlua_http_get_stline(L, sl);
+}
+
+/* Returns an array containing all headers of the HTTP message. it relies on
+ * hlua_http_get_headers().
+ */
+__LJMP static int hlua_http_msg_get_headers(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 1, "get_headers"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ return hlua_http_get_headers(L, msg);
+}
+
+/* Deletes all occurrences of an header in the HTTP message matching on its
+ * name. It relies on hlua_http_del_hdr().
+ */
+__LJMP static int hlua_http_msg_del_hdr(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 2, "del_header"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ return hlua_http_del_hdr(L, msg);
+}
+
+/* Matches the full value line of all occurences of an header in the HTTP
+ * message given its name against a regex and replaces it if it matches. It
+ * relies on hlua_http_rep_hdr().
+ */
+__LJMP static int hlua_http_msg_rep_hdr(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 4, "rep_header"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ return hlua_http_rep_hdr(L, msg, 1);
+}
+
+/* Matches all comma-separated values of all occurences of an header in the HTTP
+ * message given its name against a regex and replaces it if it matches. It
+ * relies on hlua_http_rep_hdr().
+ */
+__LJMP static int hlua_http_msg_rep_val(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 4, "rep_value"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ return hlua_http_rep_hdr(L, msg, 0);
+}
+
+/* Add an header in the HTTP message. It relies on hlua_http_add_hdr() */
+__LJMP static int hlua_http_msg_add_hdr(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 3, "add_header"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ return hlua_http_add_hdr(L, msg);
+}
+
+/* Add an header in the HTTP message removing existing headers with the same
+ * name. It relies on hlua_http_del_hdr() and hlua_http_add_hdr().
+ */
+__LJMP static int hlua_http_msg_set_hdr(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 3, "set_header"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ hlua_http_del_hdr(L, msg);
+ return hlua_http_add_hdr(L, msg);
+}
+
+/* Rewrites the request method. It relies on http_req_replace_stline(). */
+__LJMP static int hlua_http_msg_set_meth(lua_State *L)
+{
+ struct stream *s;
+ struct http_msg *msg;
+ const char *name;
+ size_t name_len;
+
+ MAY_LJMP(check_args(L, 2, "set_method"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if ((msg->chn->flags & CF_ISRESP) || msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ s = chn_strm(msg->chn);
+ lua_pushboolean(L, http_req_replace_stline(0, name, name_len, s->be, s) != -1);
+ return 1;
+}
+
+/* Rewrites the request path. It relies on http_req_replace_stline(). */
+__LJMP static int hlua_http_msg_set_path(lua_State *L)
+{
+ struct stream *s;
+ struct http_msg *msg;
+ const char *name;
+ size_t name_len;
+
+ MAY_LJMP(check_args(L, 2, "set_path"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if ((msg->chn->flags & CF_ISRESP) || msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ s = chn_strm(msg->chn);
+ lua_pushboolean(L, http_req_replace_stline(1, name, name_len, s->be, s) != -1);
+ return 1;
+}
+
+/* Rewrites the request query-string. It relies on http_req_replace_stline(). */
+__LJMP static int hlua_http_msg_set_query(lua_State *L)
+{
+ struct stream *s;
+ struct http_msg *msg;
+ const char *name;
+ size_t name_len;
+
+ MAY_LJMP(check_args(L, 2, "set_query"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if ((msg->chn->flags & CF_ISRESP) || msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ /* Check length. */
+ if (name_len > trash.size - 1) {
+ lua_pushboolean(L, 0);
+ return 1;
+ }
+
+ /* Add the mark question as prefix. */
+ chunk_reset(&trash);
+ trash.area[trash.data++] = '?';
+ memcpy(trash.area + trash.data, name, name_len);
+ trash.data += name_len;
+
+ s = chn_strm(msg->chn);
+ lua_pushboolean(L, http_req_replace_stline(2, trash.area, trash.data, s->be, s) != -1);
+ return 1;
+}
+
+/* Rewrites the request URI. It relies on http_req_replace_stline(). */
+__LJMP static int hlua_http_msg_set_uri(lua_State *L)
+{
+ struct stream *s;
+ struct http_msg *msg;
+ const char *name;
+ size_t name_len;
+
+ MAY_LJMP(check_args(L, 2, "set_uri"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+
+ if ((msg->chn->flags & CF_ISRESP) || msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ s = chn_strm(msg->chn);
+ lua_pushboolean(L, http_req_replace_stline(3, name, name_len, s->be, s) != -1);
+ return 1;
+}
+
+/* Rewrites the response status code. It relies on http_res_set_status(). */
+__LJMP static int hlua_http_msg_set_status(lua_State *L)
+{
+ struct http_msg *msg;
+ unsigned int code;
+ const char *reason;
+ size_t reason_len;
+
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ code = MAY_LJMP(luaL_checkinteger(L, 2));
+ reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, &reason_len));
+
+ if (!(msg->chn->flags & CF_ISRESP) || msg->msg_state > HTTP_MSG_BODY)
+ WILL_LJMP(lua_error(L));
+
+ lua_pushboolean(L, http_res_set_status(code, ist2(reason, reason_len), chn_strm(msg->chn)) != -1);
+ return 1;
+}
+
+/* Returns true if the HTTP message is full. */
+__LJMP static int hlua_http_msg_is_full(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 1, "is_full"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ lua_pushboolean(L, channel_full(msg->chn, 0));
+ return 1;
+}
+
+/* Returns true if the HTTP message may still receive data. */
+__LJMP static int hlua_http_msg_may_recv(lua_State *L)
+{
+ struct http_msg *msg;
+ struct htx *htx;
+
+ MAY_LJMP(check_args(L, 1, "may_recv"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ htx = htxbuf(&msg->chn->buf);
+ lua_pushboolean(L, (htx_expect_more(htx) && !channel_input_closed(msg->chn) && channel_may_recv(msg->chn)));
+ return 1;
+}
+
+/* Returns true if the HTTP message EOM was received */
+__LJMP static int hlua_http_msg_is_eom(lua_State *L)
+{
+ struct http_msg *msg;
+ struct htx *htx;
+
+ MAY_LJMP(check_args(L, 1, "may_recv"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ htx = htxbuf(&msg->chn->buf);
+ lua_pushboolean(L, !htx_expect_more(htx));
+ return 1;
+}
+
+/* Returns the number of bytes available in the input side of the HTTP
+ * message. This function never fails.
+ */
+__LJMP static int hlua_http_msg_get_in_len(lua_State *L)
+{
+ struct http_msg *msg;
+ struct htx *htx;
+
+ MAY_LJMP(check_args(L, 1, "input"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ htx = htxbuf(&msg->chn->buf);
+ lua_pushinteger(L, htx->data - co_data(msg->chn));
+ return 1;
+}
+
+/* Returns the number of bytes available in the output side of the HTTP
+ * message. This function never fails.
+ */
+__LJMP static int hlua_http_msg_get_out_len(lua_State *L)
+{
+ struct http_msg *msg;
+
+ MAY_LJMP(check_args(L, 1, "output"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ lua_pushinteger(L, co_data(msg->chn));
+ return 1;
+}
+
+/* Copies at most <len> bytes of DATA blocks from the HTTP message <msg>
+ * starting at the offset <offset> and put it in a string LUA variables. It
+ * returns the length of the builded string. It stops on the first non-DATA HTX
+ * block. This function is called during the payload filtering, so the headers
+ * are already scheduled for output (from the filter point of view).
+ */
+static int _hlua_http_msg_dup(struct http_msg *msg, lua_State *L, size_t offset, size_t len)
+{
+ struct htx *htx = htxbuf(&msg->chn->buf);
+ struct htx_blk *blk;
+ struct htx_ret htxret;
+ luaL_Buffer b;
+ int ret = 0;
+
+ luaL_buffinit(L, &b);
+ htxret = htx_find_offset(htx, offset);
+ for (blk = htxret.blk, offset = htxret.ret; blk && len; blk = htx_get_next_blk(htx, blk)) {
+ enum htx_blk_type type = htx_get_blk_type(blk);
+ struct ist v;
+
+ switch (type) {
+ case HTX_BLK_UNUSED:
+ break;
+
+ case HTX_BLK_DATA:
+ v = htx_get_blk_value(htx, blk);
+ v.ptr += offset;
+ v.len -= offset;
+ if (v.len > len)
+ v.len = len;
+
+ luaL_addlstring(&b, v.ptr, v.len);
+ ret += v.len;
+ break;
+
+ default:
+ if (!ret) {
+ /* Remove the empty string and push nil on the stack */
+ lua_pop(L, 1);
+ lua_pushnil(L);
+ }
+ goto end;
+ }
+ offset = 0;
+ }
+
+ luaL_pushresult(&b);
+
+end:
+ return ret;
+}
+
+/* Copies the string <str> to the HTTP message <msg> at the offset
+ * <offset>. This function returns -1 if data cannot be copied. Otherwise, it
+ * returns the amount of data written. This function is responsibile to update
+ * the filter context.
+ */
+static int _hlua_http_msg_insert(struct http_msg *msg, struct filter *filter, struct ist str, size_t offset)
+{
+ struct htx *htx = htx_from_buf(&msg->chn->buf);
+ struct htx_ret htxret;
+ int /*max, */ret = 0;
+
+ /* Nothing to do, just return */
+ if (unlikely(istlen(str) == 0))
+ goto end;
+
+ if (istlen(str) > htx_free_data_space(htx)) {
+ ret = -1;
+ goto end;
+ }
+
+ htxret = htx_find_offset(htx, offset);
+ if (!htxret.blk || htx_get_blk_type(htxret.blk) != HTX_BLK_DATA) {
+ if (!htx_add_last_data(htx, str))
+ goto end;
+ }
+ else {
+ struct ist v = htx_get_blk_value(htx, htxret.blk);
+ v.ptr += htxret.ret;
+ v.len = 0;
+ if (!htx_replace_blk_value(htx, htxret.blk, v, str))
+ goto end;
+ }
+ ret = str.len;
+ if (ret) {
+ struct hlua_flt_ctx *flt_ctx = filter->ctx;
+ flt_update_offsets(filter, msg->chn, ret);
+ flt_ctx->cur_len[CHN_IDX(msg->chn)] += ret;
+ }
+
+ end:
+ htx_to_buf(htx, &msg->chn->buf);
+ return ret;
+}
+
+/* Helper function removing at most <len> bytes of DATA blocks at the absolute
+ * position <offset>. It stops on the first non-DATA HTX block. This function is
+ * called during the payload filtering, so the headers are already scheduled for
+ * output (from the filter point of view). This function is responsibile to
+ * update the filter context.
+ */
+static void _hlua_http_msg_delete(struct http_msg *msg, struct filter *filter, size_t offset, size_t len)
+{
+ struct hlua_flt_ctx *flt_ctx = filter->ctx;
+ struct htx *htx = htx_from_buf(&msg->chn->buf);
+ struct htx_blk *blk;
+ struct htx_ret htxret;
+ size_t ret = 0;
+
+ /* Be sure <len> is always the amount of DATA to remove */
+ if (htx->data == offset+len && htx_get_tail_type(htx) == HTX_BLK_DATA) {
+ htx_truncate(htx, offset);
+ ret = len;
+ goto end;
+ }
+
+ htxret = htx_find_offset(htx, offset);
+ blk = htxret.blk;
+ if (htxret.ret) {
+ struct ist v;
+
+ if (htx_get_blk_type(blk) != HTX_BLK_DATA)
+ goto end;
+ v = htx_get_blk_value(htx, blk);
+ v.ptr += htxret.ret;
+ if (v.len > len)
+ v.len = len;
+ blk = htx_replace_blk_value(htx, blk, v, ist2(NULL, 0));
+ len -= v.len;
+ ret += v.len;
+ }
+
+
+ while (blk && len) {
+ enum htx_blk_type type = htx_get_blk_type(blk);
+ uint32_t sz = htx_get_blksz(blk);
+
+ switch (type) {
+ case HTX_BLK_UNUSED:
+ break;
+
+ case HTX_BLK_DATA:
+ if (len < sz) {
+ htx_cut_data_blk(htx, blk, len);
+ ret += len;
+ goto end;
+ }
+ break;
+
+ default:
+ goto end;
+ }
+
+ /* Remove oll the data block */
+ len -= sz;
+ ret += sz;
+ blk = htx_remove_blk(htx, blk);
+ }
+
+end:
+ flt_update_offsets(filter, msg->chn, -ret);
+ flt_ctx->cur_len[CHN_IDX(msg->chn)] -= ret;
+ /* WARNING: we don't call htx_to_buf() on purpose, because we don't want
+ * to loose the EOM flag if the message is empty.
+ */
+}
+
+/* Copies input data found in an HTTP message. Unlike the channel function used
+ * to duplicate raw data, this one can only be called inside a filter, from
+ * http_payload callback. So it cannot yield. An exception is returned if it is
+ * called from another callback. If nothing was copied, a nil value is pushed on
+ * the stack.
+ */
+__LJMP static int hlua_http_msg_get_body(lua_State *L)
+{
+ struct http_msg *msg;
+ struct filter *filter;
+ size_t output, input;
+ int offset, len;
+
+ if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
+ WILL_LJMP(luaL_error(L, "'data' expects at most 2 arguments"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state < HTTP_MSG_DATA)
+ WILL_LJMP(lua_error(L));
+
+ filter = hlua_http_msg_filter(L, 1, msg, &output, &input);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ if (!ci_data(msg->chn) && channel_input_closed(msg->chn)) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ offset = output;
+ if (lua_gettop(L) > 1) {
+ offset = MAY_LJMP(luaL_checkinteger(L, 2));
+ if (offset < 0)
+ offset = MAX(0, input + offset);
+ offset += output;
+ if (offset < output || offset > input + output) {
+ lua_pushfstring(L, "offset out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
+ len = output + input - offset;
+ if (lua_gettop(L) == 3) {
+ len = MAY_LJMP(luaL_checkinteger(L, 3));
+ if (!len)
+ goto dup;
+ if (len == -1)
+ len = global.tune.bufsize;
+ if (len < 0) {
+ lua_pushfstring(L, "length out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
+
+ dup:
+ _hlua_http_msg_dup(msg, L, offset, len);
+ return 1;
+}
+
+/* Appends a string to the HTTP message, after all existing DATA blocks but
+ * before the trailers, if any. It returns the amount of data written or -1 if
+ * nothing was copied. Unlike the channel function used to append data, this one
+ * can only be called inside a filter, from http_payload callback. So it cannot
+ * yield. An exception is returned if it is called from another callback.
+ */
+__LJMP static int hlua_http_msg_append(lua_State *L)
+{
+ struct http_msg *msg;
+ struct filter *filter;
+ const char *str;
+ size_t offset, len, sz;
+ int ret;
+
+ MAY_LJMP(check_args(L, 2, "append"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state < HTTP_MSG_DATA)
+ WILL_LJMP(lua_error(L));
+
+ str = MAY_LJMP(luaL_checklstring(L, 2, &sz));
+ filter = hlua_http_msg_filter(L, 1, msg, &offset, &len);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset+len);
+ lua_pushinteger(L, ret);
+ return 1;
}
-__LJMP static int hlua_http_res_add_hdr(lua_State *L)
+/* Prepends a string to the HTTP message, before all existing DATA blocks. It
+ * returns the amount of data written or -1 if nothing was copied. Unlike the
+ * channel function used to prepend data, this one can only be called inside a
+ * filter, from http_payload callback. So it cannot yield. An exception is
+ * returned if it is called from another callback.
+ */
+__LJMP static int hlua_http_msg_prepend(lua_State *L)
{
- struct hlua_txn *htxn;
+ struct http_msg *msg;
+ struct filter *filter;
+ const char *str;
+ size_t offset, len, sz;
+ int ret;
- MAY_LJMP(check_args(L, 3, "res_add_hdr"));
- htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ MAY_LJMP(check_args(L, 2, "prepend"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
- if (htxn->dir != SMP_OPT_DIR_RES || !IS_HTX_STRM(htxn->s))
+ if (msg->msg_state < HTTP_MSG_DATA)
WILL_LJMP(lua_error(L));
- return hlua_http_add_hdr(L, &htxn->s->txn->rsp);
+ str = MAY_LJMP(luaL_checklstring(L, 2, &sz));
+ filter = hlua_http_msg_filter(L, 1, msg, &offset, &len);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset);
+ lua_pushinteger(L, ret);
+ return 1;
}
-static int hlua_http_req_set_hdr(lua_State *L)
+/* Inserts a string to the HTTP message at a given offset. By default the string
+ * is appended at the end of DATA blocks. It returns the amount of data written
+ * or -1 if nothing was copied. Unlike the channel function used to insert data,
+ * this one can only be called inside a filter, from http_payload callback. So
+ * it cannot yield. An exception is returned if it is called from another
+ * callback.
+ */
+__LJMP static int hlua_http_msg_insert_data(lua_State *L)
{
- struct hlua_txn *htxn;
+ struct http_msg *msg;
+ struct filter *filter;
+ const char *str;
+ size_t input, output, sz;
+ int offset;
+ int ret;
- MAY_LJMP(check_args(L, 3, "req_set_hdr"));
- htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ if (lua_gettop(L) < 2 || lua_gettop(L) > 3)
+ WILL_LJMP(luaL_error(L, "'insert' expects at least 1 argument and at most 2 arguments"));
+ MAY_LJMP(check_args(L, 2, "insert"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
- if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ if (msg->msg_state < HTTP_MSG_DATA)
WILL_LJMP(lua_error(L));
- hlua_http_del_hdr(L, &htxn->s->txn->req);
- return hlua_http_add_hdr(L, &htxn->s->txn->req);
+ str = MAY_LJMP(luaL_checklstring(L, 2, &sz));
+ filter = hlua_http_msg_filter(L, 1, msg, &input, &output);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ offset = input + output;
+ if (lua_gettop(L) > 2) {
+ offset = MAY_LJMP(luaL_checkinteger(L, 3));
+ if (offset < 0)
+ offset = MAX(0, input + offset);
+ offset += output;
+
+ if (offset < output || offset > output + input) {
+ lua_pushfstring(L, "offset out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
+
+ ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset);
+ lua_pushinteger(L, ret);
+ return 1;
}
-static int hlua_http_res_set_hdr(lua_State *L)
+/* Removes a given amount of data from the HTTP message at a given offset. By
+ * default all DATA blocks are removed. It returns the amount of data
+ * removed. Unlike the channel function used to remove data, this one can only
+ * be called inside a filter, from http_payload callback. So it cannot yield. An
+ * exception is returned if it is called from another callback.
+ */
+__LJMP static int hlua_http_msg_del_data(lua_State *L)
{
- struct hlua_txn *htxn;
+ struct http_msg *msg;
+ struct filter *filter;
+ size_t input, output;
+ int offset, len;
- MAY_LJMP(check_args(L, 3, "res_set_hdr"));
- htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+ if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
+ WILL_LJMP(luaL_error(L, "'insert' expects at most 2 arguments"));
+ MAY_LJMP(check_args(L, 2, "insert"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
- if (htxn->dir != SMP_OPT_DIR_RES || !IS_HTX_STRM(htxn->s))
+ if (msg->msg_state < HTTP_MSG_DATA)
WILL_LJMP(lua_error(L));
- hlua_http_del_hdr(L, &htxn->s->txn->rsp);
- return hlua_http_add_hdr(L, &htxn->s->txn->rsp);
-}
+ filter = hlua_http_msg_filter(L, 1, msg, &input, &output);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
-/* This function set the method. */
-static int hlua_http_req_set_meth(lua_State *L)
-{
- struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
- size_t name_len;
- const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+ offset = input + output;
+ if (lua_gettop(L) > 2) {
+ offset = MAY_LJMP(luaL_checkinteger(L, 3));
+ if (offset < 0)
+ offset = MAX(0, input + offset);
+ offset += output;
- if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
- WILL_LJMP(lua_error(L));
+ if (offset < output || offset > output + input) {
+ lua_pushfstring(L, "offset out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
- lua_pushboolean(L, http_req_replace_stline(0, name, name_len, htxn->p, htxn->s) != -1);
+ len = output + input - offset;
+ if (lua_gettop(L) == 4) {
+ len = MAY_LJMP(luaL_checkinteger(L, 4));
+ if (!len)
+ goto end;
+ if (len == -1)
+ len = output + input - offset;
+ if (len < 0 || offset + len > output + input) {
+ lua_pushfstring(L, "length out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
+
+ _hlua_http_msg_delete(msg, filter, offset, len);
+
+ end:
+ lua_pushinteger(L, len);
return 1;
}
-/* This function set the method. */
-static int hlua_http_req_set_path(lua_State *L)
+/* Replaces a given amount of data at the given offet by a string. By default,
+ * all remaining data are removed, accordingly to the filter context. It returns
+ * the amount of data written or -1 if nothing was copied. Unlike the channel
+ * function used to replace data, this one can only be called inside a filter,
+ * from http_payload callback. So it cannot yield. An exception is returned if
+ * it is called from another callback.
+ */
+__LJMP static int hlua_http_msg_set_data(lua_State *L)
{
- struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
- size_t name_len;
- const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+ struct http_msg *msg;
+ struct filter *filter;
+ struct htx *htx;
+ const char *str;
+ size_t input, output, sz;
+ int offset, len;
+ int ret;
- if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ if (lua_gettop(L) < 2 || lua_gettop(L) > 4)
+ WILL_LJMP(luaL_error(L, "'set' expects at least 1 argument and at most 3 arguments"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state < HTTP_MSG_DATA)
WILL_LJMP(lua_error(L));
- lua_pushboolean(L, http_req_replace_stline(1, name, name_len, htxn->p, htxn->s) != -1);
+ str = MAY_LJMP(luaL_checklstring(L, 2, &sz));
+ filter = hlua_http_msg_filter(L, 1, msg, &output, &input);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ offset = output;
+ if (lua_gettop(L) > 2) {
+ offset = MAY_LJMP(luaL_checkinteger(L, 3));
+ if (offset < 0)
+ offset = MAX(0, input + offset);
+ offset += output;
+ if (offset < output || offset > input + output) {
+ lua_pushfstring(L, "offset out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
+
+ len = output + input - offset;
+ if (lua_gettop(L) == 4) {
+ len = MAY_LJMP(luaL_checkinteger(L, 4));
+ if (!len)
+ goto set;
+ if (len == -1)
+ len = output + input - offset;
+ if (len < 0 || offset + len > output + input) {
+ lua_pushfstring(L, "length out of range.");
+ WILL_LJMP(lua_error(L));
+ }
+ }
+
+ set:
+ /* Be sure we can copied the string once input data will be removed. */
+ htx = htx_from_buf(&msg->chn->buf);
+ if (sz > htx_free_data_space(htx) + len)
+ lua_pushinteger(L, -1);
+ else {
+ _hlua_http_msg_delete(msg, filter, offset, len);
+ ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset);
+ lua_pushinteger(L, ret);
+ }
return 1;
}
-/* This function set the query-string. */
-static int hlua_http_req_set_query(lua_State *L)
+/* Prepends data into an HTTP message and forward it, from the filter point of
+ * view. It returns the amount of data written or -1 if nothing was sent. Unlike
+ * the channel function used to send data, this one can only be called inside a
+ * filter, from http_payload callback. So it cannot yield. An exception is
+ * returned if it is called from another callback.
+ */
+__LJMP static int hlua_http_msg_send(lua_State *L)
{
- struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
- size_t name_len;
- const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+ struct http_msg *msg;
+ struct filter *filter;
+ struct htx *htx;
+ const char *str;
+ size_t offset, len, sz;
+ int ret;
- if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ MAY_LJMP(check_args(L, 2, "send"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state < HTTP_MSG_DATA)
WILL_LJMP(lua_error(L));
- /* Check length. */
- if (name_len > trash.size - 1) {
- lua_pushboolean(L, 0);
+ str = MAY_LJMP(luaL_checklstring(L, 2, &sz));
+ filter = hlua_http_msg_filter(L, 1, msg, &offset, &len);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ /* Return an error if the channel's output is closed */
+ if (unlikely(channel_output_closed(msg->chn))) {
+ lua_pushinteger(L, -1);
return 1;
}
- /* Add the mark question as prefix. */
- chunk_reset(&trash);
- trash.area[trash.data++] = '?';
- memcpy(trash.area + trash.data, name, name_len);
- trash.data += name_len;
+ htx = htx_from_buf(&msg->chn->buf);
+ if (sz > htx_free_data_space(htx)) {
+ lua_pushinteger(L, -1);
+ return 1;
+ }
- lua_pushboolean(L,
- http_req_replace_stline(2, trash.area, trash.data, htxn->p, htxn->s) != -1);
+ ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset);
+ if (ret > 0) {
+ struct hlua_flt_ctx *flt_ctx = filter->ctx;
+
+ FLT_OFF(filter, msg->chn) += ret;
+ flt_ctx->cur_len[CHN_IDX(msg->chn)] -= ret;
+ flt_ctx->cur_off[CHN_IDX(msg->chn)] += ret;
+ }
+
+ lua_pushinteger(L, ret);
return 1;
}
-/* This function set the uri. */
-static int hlua_http_req_set_uri(lua_State *L)
+/* Forwards a given amount of bytes. It return -1 if the channel's output is
+ * closed. Otherwise, it returns the number of bytes forwarded. Unlike the
+ * channel function used to forward data, this one can only be called inside a
+ * filter, from http_payload callback. So it cannot yield. An exception is
+ * returned if it is called from another callback. All other functions deal with
+ * DATA block, this one not.
+*/
+__LJMP static int hlua_http_msg_forward(lua_State *L)
{
- struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
- size_t name_len;
- const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+ struct http_msg *msg;
+ struct filter *filter;
+ size_t offset, len;
+ int fwd, ret = 0;
- if (htxn->dir != SMP_OPT_DIR_REQ || !IS_HTX_STRM(htxn->s))
+ MAY_LJMP(check_args(L, 2, "forward"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+
+ if (msg->msg_state < HTTP_MSG_DATA)
WILL_LJMP(lua_error(L));
- lua_pushboolean(L, http_req_replace_stline(3, name, name_len, htxn->p, htxn->s) != -1);
+ fwd = MAY_LJMP(luaL_checkinteger(L, 2));
+ filter = hlua_http_msg_filter(L, 1, msg, &offset, &len);
+ if (!filter || !hlua_filter_from_payload(filter))
+ WILL_LJMP(lua_error(L));
+
+ /* Nothing to do, just return */
+ if (!fwd)
+ goto end;
+
+ /* Return an error if the channel's output is closed */
+ if (unlikely(channel_output_closed(msg->chn))) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = fwd;
+ if (ret > len)
+ ret = len;
+
+ if (ret) {
+ struct hlua_flt_ctx *flt_ctx = filter->ctx;
+
+ FLT_OFF(filter, msg->chn) += ret;
+ flt_ctx->cur_off[CHN_IDX(msg->chn)] += ret;
+ flt_ctx->cur_len[CHN_IDX(msg->chn)] -= ret;
+ }
+
+ end:
+ lua_pushinteger(L, ret);
return 1;
}
-/* This function set the response code & optionally reason. */
-static int hlua_http_res_set_status(lua_State *L)
+/* Set EOM flag on the HTX message.
+ *
+ * NOTE: Not sure it is a good idea to manipulate this flag but for now I don't
+ * really know how to do without this feature.
+ */
+__LJMP static int hlua_http_msg_set_eom(lua_State *L)
{
- struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
- unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
- const char *str = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
- const struct ist reason = ist2(str, (str ? strlen(str) : 0));
+ struct http_msg *msg;
+ struct htx *htx;
- if (htxn->dir != SMP_OPT_DIR_RES || !IS_HTX_STRM(htxn->s))
- WILL_LJMP(lua_error(L));
+ MAY_LJMP(check_args(L, 1, "set_eom"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ htx = htxbuf(&msg->chn->buf);
+ htx->flags |= HTX_FL_EOM;
+ return 0;
+}
- http_res_set_status(code, reason, htxn->s);
+/* Unset EOM flag on the HTX message.
+ *
+ * NOTE: Not sure it is a good idea to manipulate this flag but for now I don't
+ * really know how to do without this feature.
+ */
+__LJMP static int hlua_http_msg_unset_eom(lua_State *L)
+{
+ struct http_msg *msg;
+ struct htx *htx;
+
+ MAY_LJMP(check_args(L, 1, "set_eom"));
+ msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
+ htx = htxbuf(&msg->chn->buf);
+ htx->flags &= ~HTX_FL_EOM;
return 0;
}
/* Register previous table in the registry with reference and named entry. */
class_http_ref = hlua_register_metatable(L, CLASS_HTTP);
+ /*
+ *
+ * Register class HTTPMessage
+ *
+ */
+
+ /* Create and fill the metatable. */
+ lua_newtable(L);
+
+ /* Create and fille the __index entry. */
+ lua_pushstring(L, "__index");
+ lua_newtable(L);
+
+ /* Register Lua functions. */
+ hlua_class_function(L, "is_resp", hlua_http_msg_is_resp);
+ hlua_class_function(L, "get_stline", hlua_http_msg_get_stline);
+ hlua_class_function(L, "get_headers", hlua_http_msg_get_headers);
+ hlua_class_function(L, "del_header", hlua_http_msg_del_hdr);
+ hlua_class_function(L, "rep_header", hlua_http_msg_rep_hdr);
+ hlua_class_function(L, "rep_value", hlua_http_msg_rep_val);
+ hlua_class_function(L, "add_header", hlua_http_msg_add_hdr);
+ hlua_class_function(L, "set_header", hlua_http_msg_set_hdr);
+ hlua_class_function(L, "set_method", hlua_http_msg_set_meth);
+ hlua_class_function(L, "set_path", hlua_http_msg_set_path);
+ hlua_class_function(L, "set_query", hlua_http_msg_set_query);
+ hlua_class_function(L, "set_uri", hlua_http_msg_set_uri);
+ hlua_class_function(L, "set_status", hlua_http_msg_set_status);
+ hlua_class_function(L, "is_full", hlua_http_msg_is_full);
+ hlua_class_function(L, "may_recv", hlua_http_msg_may_recv);
+ hlua_class_function(L, "eom", hlua_http_msg_is_eom);
+ hlua_class_function(L, "input", hlua_http_msg_get_in_len);
+ hlua_class_function(L, "output", hlua_http_msg_get_out_len);
+
+ hlua_class_function(L, "body", hlua_http_msg_get_body);
+ hlua_class_function(L, "set", hlua_http_msg_set_data);
+ hlua_class_function(L, "remove", hlua_http_msg_del_data);
+ hlua_class_function(L, "append", hlua_http_msg_append);
+ hlua_class_function(L, "prepend", hlua_http_msg_prepend);
+ hlua_class_function(L, "insert", hlua_http_msg_insert_data);
+ hlua_class_function(L, "set_eom", hlua_http_msg_set_eom);
+ hlua_class_function(L, "unset_eom", hlua_http_msg_unset_eom);
+
+ hlua_class_function(L, "send", hlua_http_msg_send);
+ hlua_class_function(L, "forward", hlua_http_msg_forward);
+
+ lua_rawset(L, -3);
+
+ /* Register previous table in the registry with reference and named entry. */
+ class_http_msg_ref = hlua_register_metatable(L, CLASS_HTTP_MSG);
/*
*
* Register class AppletTCP