static void after_queue_work(uv_work_t* req, int status) { automem_t mem; webqueuework_t * qwork = container_of(req, webqueuework_t, work); rbnode_t * n = rb_first(&qwork->request->headers); automem_init(&mem, 256); if (qwork->conn->proto == WEB_PROTO_HTTP) { if (qwork->status == 101 && qwork->request->upgrade) { webheader_t k; rbnode_t * n; const char * ver = NULL, *key = NULL; k.key = "Sec-WebSocket-Version"; if (n = rb_find(&qwork->request->headers, &k.n)) ver = container_of(n, webheader_t, n)->val; k.key = "Sec-WebSocket-Key"; if (n = rb_find(&qwork->request->headers, &k.n)) key = container_of(n, webheader_t, n)->val; if (NULL != key && NULL != ver) { ws_do_handeshake(&mem, key, strlen(key)); qwork->conn->proto = WEB_PROTO_WEBSOCKET; if (uv_is_active((uv_handle_t *)&qwork->conn->conn)) { wsparser_init(&qwork->conn->ws_parser, 13, 20480); qwork->conn->request = webrequest_get(qwork->request);//引用起来,不丢掉. } goto contents_prepare_final; } } rbnode_t * n = rb_first(&qwork->headers); automem_init_headers(&mem, qwork->status, qwork->flags); while (n) { webheader_t * h = container_of(n, webheader_t, n); automem_append_voidp(&mem, h->key, strlen(h->key)); automem_append_voidp(&mem, ": ", 2); automem_append_voidp(&mem, h->val, strlen(h->val)); automem_append_voidp(&mem, "\r\n", 2); n = rb_next(n); } automem_append_contents(&mem, qwork->mem.pdata, qwork->mem.size); } else if(qwork->conn->proto==WEB_PROTO_WEBSOCKET) { wsframe_make(&mem, WS_TEXT_FRAME, 0, qwork->mem.pdata, qwork->mem.size); } contents_prepare_final: if (0 != webconn_sendmem(qwork->conn, &mem)) { automem_uninit(&mem); } webqueuework_free(qwork); }
int automem_append_field_int(automem_t* pmem, const char * field, unsigned int f_len, int val) { char intVal[20];int slen; automem_append_voidp(pmem, field, f_len); _itoa(val, intVal,10); slen = strlen(intVal); automem_ensure_newspace(pmem, slen + 4); pmem->pdata[pmem->size++]='='; pmem->pdata[pmem->size++]='"'; automem_append_voidp(pmem, intVal, slen); pmem->pdata[pmem->size++]='"'; pmem->pdata[pmem->size++]=' '; return pmem->size; }
int automem_append_field_fast(automem_t* pmem, const char * field, unsigned int f_len, const char * val,unsigned int v_len) { if(NULL == val) return pmem->size; if(0 == v_len) v_len = strlen(val); if(0 == v_len) return pmem->size; automem_append_voidp(pmem, field, f_len); automem_ensure_newspace(pmem, v_len + 5); pmem->pdata[pmem->size++]='='; pmem->pdata[pmem->size++]='"'; automem_append_voidp(pmem, val, v_len); pmem->pdata[pmem->size++]='"'; pmem->pdata[pmem->size++]=' '; return pmem->size; }
/* 构造一个或者一堆的Frame 。 //服务器端发往客户端的数据 不允许使用 mask */ void wsframe_make(automem_t * mem,enum wsFrameType opcode, int _mask, unsigned char * payload, size_t len) { struct wsFrameHeader * fh; uint8_t mask[4]; size_t i; srand((unsigned int)time(NULL)); automem_ensure_newspace(mem, len + 20); fh = (struct wsFrameHeader * )(&mem->pdata[mem->size]); fh->fin = 1; fh->opcode = opcode; fh->rsv13 = 0; fh->mask = 0; mem->size += 2; if (len < 126) { fh->plen = (uint8_t)len; } else if (len <= 0xFFFF) { uint16_t nlen = SWAP_U16(len); fh->plen = 126; automem_append_voidp(mem, &nlen, 2); } else { uint64_t nlen = SWAP_U64(len); fh->plen = 127; automem_append_voidp(mem, &nlen, sizeof(uint64_t)); } if (payload && len > 0){ if (_mask) { fh->mask = 1; mask[0] = rand() % 256; mask[1] = rand() % 256; mask[2] = rand() % 256; mask[3] = rand() % 256; automem_append_voidp(mem, mask, 4); for (i = 0; i < len; i++) { mem->pdata[mem->size++] = payload[0] ^ mask[i % 4]; } } else { automem_append_voidp(mem, payload, len); } } }
int ws_do_handeshake(automem_t * mem, char * key, int lkey) { char * sec; char sha_out[20], base64_out[40]; size_t base64_len = sizeof(base64_out); if (0 == lkey) return -1; sec = malloc(lkey + sizeof(secret)); strcpy(sec, key); strcpy(sec + lkey, secret); sha1(sec, lkey + sizeof(secret) - 1, sha_out); base64_encode(base64_out, &base64_len, sha_out, 20); automem_init(mem, 256); automem_append_voidp(mem, SWITCH_WEBSOCKET_PROTOCOL, sizeof(SWITCH_WEBSOCKET_PROTOCOL) - 1); automem_append_voidp(mem, base64_out, base64_len); automem_append_voidp(mem, "\r\n\r\n", 4); free(sec); return 0; }
static void webrequest_threadproc(uv_work_t * req) { int ref = LUA_NOREF,sess_ref = LUA_NOREF; automem_t mem; webqueuework_t * qwork = container_of(req, webqueuework_t, work); lua_State * L = luaL_newstate(); qwork->flags = qwork->conn->flags; luaL_openlibs(L); ref = lua_pushwebctx(L, qwork); sess_ref = luasession_init(L,qwork); automem_init(&mem,100); automem_append_voidp(&mem, "require(\"", sizeof("require(\"") - 1); automem_append_voidp(&mem, qwork->request->file, strlen(qwork->request->file)); switch (qwork->conn->proto) { case WEB_PROTO_HTTP: automem_append_voidp(&mem, "\"):main()", sizeof("\"):main()")); break; case WEB_PROTO_WEBSOCKET: automem_append_voidp(&mem, "\"):websocket()", sizeof("\"):websocket()")); break; } luaL_dostring(L, mem.pdata); if (LUA_TSTRING == lua_type(L, -1)) { size_t len; const char * err = lua_tolstring(L, -1, &len); qwork->status = 500; automem_append_voidp(&qwork->mem, err, len); } automem_uninit(&mem); luaL_unref(L,LUA_REGISTRYINDEX, ref); lua_close(L); }
// 向客户端输出内容. static int lua_webctx_write(lua_State * L) { int i,argc = lua_gettop(L),t; const char * s; webqueuework_t * qwork = (lua_rawgeti(L, LUA_REGISTRYINDEX, WEBCTX_REF), lua_touserdata(L, -1)); for (i = 1; i <= argc; i++) { size_t len; t = lua_type(L, i); switch (t) { case LUA_TNIL: case LUA_TNONE: break; default: s = lua_tolstring(L, i, &len); automem_append_voidp(&qwork->mem, s, (unsigned int)len); break; } } return 0; }
static void lua_tpl_expand_variables(lua_State * L, automem_t * mem, int bufsize) { if(lua_istable(L, 3)) { const char * key ; automem_init(mem, bufsize + 10240); lua_pushnil(L); automem_append_voidp(mem, "local _ARGS_= ...\n",sizeof("local _ARGS_= ...\n")-1); while(lua_next(L, 3)) { // -1 value -2 key if(lua_isstring(L, -2)) { size_t lkey; if(NULL != (key = lua_tolstring(L, -2, &lkey))) { automem_append_voidp(mem, "local ",sizeof("local ")-1); automem_append_voidp(mem, key, lkey); automem_append_voidp(mem, "=_ARGS_[\"",sizeof("=_ARGS_[\"")-1); automem_append_voidp(mem, key, lkey); automem_append_voidp(mem, "\"]\n", sizeof("\"]\n")-1); } } lua_pop(L, 1); } } else automem_init(mem, bufsize + 20); }
void wsparser_pushdata(wsparser_t * parser, unsigned char * data, uint32_t size, wsparser_onhandler handler, void * eParam) { unsigned char *p = data; uint32_t i; if (parser->buf.size > 0) { automem_append_voidp(&parser->buf, data, size); data = parser->buf.pdata; size = parser->buf.size; } while (parser->offset < size) { switch (parser->st) { case WS_STATE_OPCODE: if (size - parser->offset > 2) { struct wsFrameHeader * fh = (struct wsFrameHeader *)&data[parser->offset]; parser->fin = fh->fin; parser->mask = fh->mask; parser->opcode = fh->opcode==WS_CONTINUATION_FRAME? parser->opcode: fh->opcode; parser->offset += 2; parser->st = WS_STATE_PLEN; printf("OpCode = %d, Fin=%d\n", parser->opcode,parser->fin); switch (fh->plen) { case 126: parser->st = WS_STATE_PLEN; break; case 127: parser->st = WS_STATE_PLLEN; break; default: parser->len = fh->plen; parser->st = parser->mask ? WS_STATE_MASK : WS_STATE_PAYLOAD; break; } if (WS_PING_FRAME == parser->opcode) { handler(parser, NULL, eParam); } } break; case WS_STATE_PLEN: if (size - parser->offset < 2) goto wsparser_pushdata_final; parser->len = SWAP_U16(*(uint16_t *)&data[parser->offset]); parser->offset += 2; parser->st = parser->mask ? WS_STATE_MASK : WS_STATE_PAYLOAD; break; case WS_STATE_PLLEN: if (size - parser->offset < 8) goto wsparser_pushdata_final; parser->len = SWAP_U64(*(uint64_t *)&data[parser->offset]); #if defined(_DEBUG) printf("size = %lld", parser->len); #endif parser->offset += 8; parser->st = parser->mask ? WS_STATE_MASK : WS_STATE_PAYLOAD; break; case WS_STATE_MASK: if (size - parser->offset < 4) goto wsparser_pushdata_final; memcpy(parser->msk_bytes, &data[parser->offset], 4); parser->offset += 4; parser->st = WS_STATE_PAYLOAD; break; case WS_STATE_PAYLOAD: if (size - parser->offset < parser->len) goto wsparser_pushdata_final; //处理帧数据 if (parser->mask) { automem_t * m = &parser->payload; automem_ensure_newspace(m, parser->len); for (i = 0; i < parser->len; i++) { m->pdata[m->size++] = data[parser->offset+i] ^ parser->msk_bytes[i % 4]; } } if (parser->fin == 1) { wsFrame * f = malloc(sizeof(wsFrame)); f->len = parser->payload.size; f->opcode = parser->opcode; f->pdata = f->len > 0 ? parser->payload.pdata : NULL; handler(parser, f, eParam); if (f->len){ parser->payload.pdata = NULL; parser->payload.size = parser->payload.buffersize = 0; automem_init(&parser->payload, 2048); } } parser->offset += (uint32_t)parser->len; parser->st = WS_STATE_OPCODE; break; } } wsparser_pushdata_final: if (size > parser->offset) { if (data != parser->buf.pdata) { automem_append_voidp(&parser->buf, data + parser->offset, size - parser->offset);//将未用完的加入到 buf. parser->offset = 0; } } else if (size <= parser->offset) { if (data == parser->buf.pdata) { } if (parser->buf.buffersize > parser->maxsize) automem_clean(&parser->buf, parser->maxsize); else automem_reset(&parser->buf); parser->offset = 0; } return; }
int automem_append_field(automem_t* pmem, const char * field, unsigned int f_len, const char * val) { const char * p = val; char c; unsigned int t = 4, sz = 0; if(NULL == val)return pmem->size; while(c = *p++) { switch(c) { case '&': // 5 & t+=5;break; case '<': // 4 < t+=4;break; case '>': // 4 > t+=4;break; case '"': // 6 " t+=6;break; case '\'': // 6 ' t+=6;break; default: t++; } } automem_append_voidp(pmem, field, f_len); automem_ensure_newspace(pmem, t); sz = pmem->size; pmem->pdata[sz++]='='; pmem->pdata[sz++]='"'; p = val; while(c = *p++) { switch(c) { case '&': // 5 & *(int*)(pmem->pdata+sz) = *(int*)"&"; sz+=sizeof(int); pmem->pdata[sz++]=';'; break; case '<': // 4 < *(int*)(pmem->pdata+sz) = *(int*)"<"; sz+=sizeof(int); break; case '>': // 4 > *(int*)(pmem->pdata+sz) = *(int*)">"; sz+=sizeof(int); break; case '"': // 6 " *(int*)(pmem->pdata+sz) = *(int*)"&quo"; sz+=sizeof(int); *(short*)(pmem->pdata+sz) = *(short*)"t;"; sz+=sizeof(short); break; case '\'': // 6 ' *(int*)(pmem->pdata+sz) = *(int*)"&apo"; sz+=sizeof(int); *(short*)(pmem->pdata+sz) = *(short*)"s;"; sz+=sizeof(short); break; default: pmem->pdata[sz++]=c; } } *(short*)(pmem->pdata+sz) = *(short*)"\" "; sz+=sizeof(short); pmem->size = sz; return sz; }
void automem_append_byte(automem_t* pmem, unsigned char c) { automem_append_voidp(pmem, &c, sizeof(unsigned char)); }
void automem_append_char(automem_t* pmem, char c) { automem_append_voidp(pmem, &c, sizeof(char)); }
void automem_append_pchar(automem_t* pmem, char* n) { automem_append_voidp(pmem, &n, sizeof(char*)); }
void automem_append_int(automem_t* pmem, int n) { automem_append_voidp(pmem, &n, sizeof(int)); }
static void lua_tpl_compile_local(lua_State * L, automem_t * mem, const char * buf,int lbuf) { int state = tpl_state_normal, i = 0; register const char * sbuf; char c; size_t lcmd = sizeof("_") -1, lprefix = sizeof("([[")-1, lsuffix = sizeof("]])")-1; const char * cmd = "_(", * ecmd = ")", * prefix = "([[", * suffix = "]])"; if(lua_isstring(L, 4)) cmd =luaL_checklstring(L, 4, &lcmd); if(lua_isstring(L, 5)) prefix =luaL_checklstring(L, 5, &lprefix); if(lua_isstring(L, 6)) suffix =luaL_checklstring(L, 6, &lsuffix); sbuf = buf; while(i < lbuf) { c = buf[i]; switch (state) { case tpl_state_normal: switch(c) { case '{': state = tpl_state_scode_1; break; } break; case tpl_state_scode_1: switch(c) { case '#': state =tpl_state_code; append_end_stringfield(mem,sbuf, &buf[i] - sbuf-1); sbuf = &buf[i+1]; break; default: state = tpl_state_normal; break; } break; case tpl_state_code: switch(c) { case '#': state = tpl_state_ecode_1; break; } case tpl_state_ecode_1: switch(c) { case '}': automem_append_voidp(mem,sbuf, &buf[i] - sbuf-1); automem_append_byte(mem,'\n'); sbuf = &buf[i+1]; state = tpl_state_normal; break; default: state=tpl_state_code; } default: break; } i++; } if(tpl_state_normal == state) { append_end_stringfield(mem,sbuf, &buf[i] - sbuf); } }