| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #include <time.h>
- #include "squirrel.h"
- #include "sqstdblobimpl.h"
- SQ_OPT_STRING_STRLEN();
- /* Lua System: Internet Server Application: FastCGI */
- #define FCGI_VERSION 1
- #define FCGI_HEADER_LEN 8
- #define FCGI_END_REQUEST_LEN 8
- #define FCGI_RESPONDER 1
- #define FCGI_KEEP_CONN 1
- #define FCGI_BEGIN_REQUEST 1
- #define FCGI_ABORT_REQUEST 2
- #define FCGI_END_REQUEST 3
- #define FCGI_PARAMS 4
- #define FCGI_STDIN 5
- #define FCGI_STDOUT 6
- #define FCGI_STDERR 7
- #define FCGI_DATA 8
- #define FCGI_GET_VALUES 9
- #define FCGI_GET_VALUES_RESULT 10
- #define FCGI_UNKNOWN_TYPE 11
- #define FCGI_REQUEST_COMPLETE 0
- #define FCGI_CANT_MPX_CONN 1
- #define FCGI_OVERLOADED 2
- #define FCGI_UNKNOWN_ROLE 3
- #define FCGI_NULL_REQUEST_ID ~0U
- #define FCGI_MAX_CONTENT_LEN 0xFFFF
- static const char *
- fcgi_decode_begin_request (HSQUIRRELVM v, const unsigned char *cp,
- const size_t size)
- {
- int role, keep_conn;
- if (size != 8) return "bad content";
- role = (*cp++ << 8);
- role |= *cp++;
- keep_conn = *cp & FCGI_KEEP_CONN;
- if (role != FCGI_RESPONDER) return "bad role";
- sq_pushbool(v, keep_conn);
- sq_setfield(v, -2, "keep_conn");
- return NULL;
- }
- static const char *
- fcgi_decode_params (HSQUIRRELVM v, const unsigned char *cp, const size_t size)
- {
- const unsigned char *endp = cp + size;
- while (cp < endp)
- {
- unsigned int name_len, value_len;
- name_len = *cp++;
- if (name_len & 0x80)
- {
- if (cp + 3 >= endp) return "bad content";
- name_len ^= 0x80;
- name_len = (name_len << 8) | *cp++;
- name_len = (name_len << 8) | *cp++;
- name_len = (name_len << 8) | *cp++;
- }
- if (cp >= endp) return "bad content";
- value_len = *cp++;
- if (value_len & 0x80)
- {
- if (cp + 3 >= endp) return "bad content";
- value_len ^= 0x80;
- value_len = (value_len << 8) | *cp++;
- value_len = (value_len << 8) | *cp++;
- value_len = (value_len << 8) | *cp++;
- }
- if (cp + name_len + value_len > endp)
- return "bad content";
- sq_pushstring(v, (const char *) cp, name_len);
- cp += name_len;
- sq_pushstring(v, (const char *) cp, value_len);
- cp += value_len;
- sq_rawset(v, -3);
- }
- return NULL;
- }
- static const char *
- fcgi_decode_stdin (HSQUIRRELVM v, const unsigned char *cp, const size_t size)
- {
- int concat = 1;
- sq_getfield(v, -1, "stdin");
- if (sq_isnil(v, -1))
- {
- sq_pop(v, 1);
- concat = 0;
- }
- sq_pushstring(v, (const char *) cp, size);
- if (concat) sq_concat(v, 2);
- sq_setfield(L, -2, "stdin");
- return NULL;
- }
- /*
- * Arguments: ..., channel (table)
- */
- static int
- fcgi_decode_record (HSQUIRRELVM v, const unsigned char *cp, const size_t size,
- unsigned int *ready_request_id)
- {
- unsigned int version, type, request_id, content_len, padding_len, len;
- int is_ready = 0;
- const char *err = NULL;
- version = *cp++;
- type = *cp++;
- request_id = (*cp++ << 8);
- request_id |= *cp++;
- content_len = (*cp++ << 8);
- content_len |= *cp++;
- padding_len = *cp++;
- cp++; /* reserved */
- len = FCGI_HEADER_LEN + content_len + padding_len;
- if (len > size) return 0;
- sq_rawgeti(v, -1, request_id);
- if (!sq_istable(v, -1))
- {
- sq_pop(v, 1);
- sq_newtable(v);
- sq_pushvalue(v, -1);
- sq_rawseti(v, -3, request_id);
- sq_pushinteger(v, request_id);
- sq_setfield(v, -2, "id");
- sq_getfield(v, -2, "request_meta"); /* metatable from channel */
- sq_setmetatable(v, -2);
- sq_pushvalue(v, -2); /* channel */
- sq_setfield(v, -2, "channel");
- }
- if (version != FCGI_VERSION)
- err = "bad version";
- else
- {
- switch (type)
- {
- case FCGI_BEGIN_REQUEST:
- err = fcgi_decode_begin_request(v, cp, content_len);
- break;
- case FCGI_ABORT_REQUEST:
- break;
- case FCGI_PARAMS:
- if (content_len)
- err = fcgi_decode_params(v, cp, content_len);
- break;
- case FCGI_STDIN:
- if (content_len)
- err = fcgi_decode_stdin(v, cp, content_len);
- else
- is_ready = 1;
- break;
- default:
- err = "bad type";
- }
- }
- if (err)
- {
- sq_pushstring(v, err, -1);
- sq_setfield(v, -2, "error");
- /*
- lua_pushinteger(L, version);
- lua_setfield(L, -2, "version");
- lua_pushinteger(L, type);
- lua_setfield(L, -2, "type");
- lua_pushlstring(L, cp, content_len);
- lua_setfield(L, -2, "content");
- */
- is_ready = 1;
- }
- if (is_ready)
- {
- if (*ready_request_id != FCGI_NULL_REQUEST_ID)
- sq_pushinteger(v, *ready_request_id);
- else
- sq_pushnil(v);
- sq_setfield(v, -2, "next_ready");
- *ready_request_id = request_id;
- }
- sq_pop(v, 1);
- return len;
- }
- /*
- * Arguments: {string | membuf_udata}, channel (table)
- * Returns: [request_id (number)]
- */
- static SQRESULT sq_fastcgi_decode (HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- struct sys_buffer sb;
- const char *cp;
- unsigned int ready_request_id = FCGI_NULL_REQUEST_ID;
- if (!sys_buffer_read_init(v, 1, &sb))
- return 0;
- sq_checktype(v, 2, LUA_TTABLE);
- cp = sb.ptr.r;
- while (sb.size >= FCGI_HEADER_LEN)
- {
- const int len = fcgi_decode_record(v,
- (const unsigned char *) cp, sb.size, &ready_request_id);
- if (!len) break;
- cp += len;
- sb.size -= len;
- }
- sys_buffer_read_next(&sb, cp - sb.ptr.r);
- if (ready_request_id != FCGI_NULL_REQUEST_ID)
- {
- sq_pushinteger(v, ready_request_id);
- return 1;
- }
- return 0;
- }
- /*
- * Arguments: membuf_udata, request_id (number), prev_offset (number), string
- * Returns: offset (number)
- */
- static SQRESULT sq_fastcgi_encode (HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- SQBlob *blob = NULL;
- SQObjectType ptype = sq_gettype(v, 2);
- if(ptype == OT_INSTANCE){
- if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&blob,(SQUserPointer)SQBlob::SQBlob_TAG)))
- return sq_throwerror(v,_SC("invalid type tag"));
- if(!blob || !blob->IsValid())
- return sq_throwerror(v,_SC("the blob is invalid"));
- }
- SQ_GET_INTEGER(v, 3, request_id);
- SQ_GET_INTEGER(v, 4, prev_offset);
- SQ_GET_STRING(v, 5, s);
- unsigned char *cp;
- unsigned char *lenp;
- SQInteger prev_len = 0, prev_padding_len = 0;
- SQInteger data_len, padding_len;
- if (s_size > FCGI_MAX_CONTENT_LEN) {
- return sq_throwerror(v,_SC("too long"));
- }
- sys_buffer_write_init(v, 1, &sb, NULL, 0);
- if (prev_offset)
- {
- cp = (unsigned char *) sb.ptr.w - prev_offset;
- if (cp[-1] == (unsigned char) request_id
- && cp[-2] == (unsigned char) (request_id >> 8))
- {
- prev_len = (cp[0] << 8) | cp[1];
- prev_padding_len = cp[2];
- }
- else
- {
- prev_offset = 0;
- }
- }
- if (!len)
- {
- data_len = 2 * FCGI_HEADER_LEN + FCGI_END_REQUEST_LEN;
- prev_offset = 0;
- }
- else
- {
- data_len = len;
- if (!prev_offset || (prev_len + len) > FCGI_MAX_CONTENT_LEN)
- {
- data_len += FCGI_HEADER_LEN;
- prev_offset = 0;
- }
- else
- {
- data_len -= prev_padding_len;
- }
- }
- if (data_len <= 0)
- {
- padding_len = prev_padding_len - len; /* fits to previous padding */
- data_len = 0;
- }
- else
- {
- padding_len = 8 - data_len % 8;
- if (padding_len == 8) padding_len = 0;
- data_len += padding_len;
- if (!sys_buffer_write_next(v, &sb, NULL, data_len))
- return 0;
- }
- /* buffer may be re-allocated */
- cp = (unsigned char *) sb.ptr.w;
- if (prev_offset)
- {
- lenp = cp - prev_offset;
- cp -= prev_padding_len;
- memcpy(cp, s, len); /* concat to previous record */
- cp += len;
- len += prev_len;
- }
- else
- {
- *cp++ = FCGI_VERSION;
- *cp++ = FCGI_STDOUT;
- *cp++ = (unsigned char) (request_id >> 8);
- *cp++ = (unsigned char) request_id;
- lenp = cp++; /* content_len */
- cp++;
- cp++; /* padding_len */
- *cp++ = 0; /* reserved */
- if (len)
- {
- memcpy(cp, s, len);
- cp += len;
- }
- else
- {
- *cp++ = FCGI_VERSION;
- *cp++ = FCGI_END_REQUEST;
- *cp++ = (unsigned char) (request_id >> 8);
- *cp++ = (unsigned char) request_id;
- *cp++ = 0; /* content_len */
- *cp++ = FCGI_END_REQUEST_LEN;
- *cp++ = 0; /* padding_len */
- *cp++ = 0; /* reserved */
- memset(cp, 0, FCGI_END_REQUEST_LEN);
- }
- }
- lenp[0] = (unsigned char) (len >> 8);
- lenp[1] = (unsigned char) len;
- lenp[2] = (unsigned char) padding_len;
- if (padding_len)
- {
- memset(cp, 0, padding_len);
- cp += padding_len;
- }
- sys_buffer_write_done(v, &sb, NULL, data_len);
- sq_pushinteger(v, cp - lenp);
- return 1;
- }
- #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_fastcgi_##name,nparams,tycheck}
- static SQRegFunction sq_fastcgi_methods[] =
- {
- _DECL_FUNC(encode, -1, _SC("x")),
- _DECL_FUNC(decode, 1, _SC("x")),
- {0,0}
- };
- #undef _DECL_FUNC
- #ifdef __cplusplus
- extern "C" {
- #endif
- SQRESULT sqext_register_fastcgi(HSQUIRRELVM v)
- {
- //add a namespace sqfastcgi
- sq_pushstring(v, sq_fastcgi_TAG,-1);
- sq_newclass(v, SQFalse);
- sq_insert_reg_funcs(v, sq_fastcgi_methods);
- sq_newslot(v,-3,SQTrue); //add sqfastcgi table to the root table
- return SQ_OK;
- }
- #ifdef __cplusplus
- }
- #endif
|