size_t lua_calc_strlen_in_table ( lua_State *L, int index, int arg_i, unsigned strict ) { double key = 0; int max = 0; int i = 0; int type = 0; size_t size = 0; size_t len = 0; const char *msg = NULL; if ( index < 0 ) { index = lua_gettop ( L ) + index + 1; } max = 0; lua_pushnil ( L ); /* stack: table key */ while ( lua_next ( L, index ) != 0 ) { /* stack: table key value */ if ( lua_type ( L, -2 ) == LUA_TNUMBER ) { key = lua_tonumber ( L, -2 ); if ( floor ( key ) == key && key >= 1 ) { if ( key > max ) { max = key; } lua_pop ( L, 1 ); /* stack: table key */ continue; } } /* not an array (non positive integer key) */ lua_pop ( L, 2 ); /* stack: table */ //msg = lua_pushfstring(L, "non-array table found"); /// commented by oneoo //luaL_argerror(L, arg_i, msg); return 0; } size = 0; for ( i = 1; i <= max; i++ ) { lua_rawgeti ( L, index, i ); /* stack: table value */ type = lua_type ( L, -1 ); switch ( type ) { case LUA_TNUMBER: case LUA_TSTRING: lua_tolstring ( L, -1, &len ); size += len; break; case LUA_TNIL: if ( strict ) { goto bad_type; } size += sizeof ( "nil" ) - 1; break; case LUA_TBOOLEAN: if ( strict ) { goto bad_type; } if ( lua_toboolean ( L, -1 ) ) { size += sizeof ( "true" ) - 1; } else { size += sizeof ( "false" ) - 1; } break; case LUA_TTABLE: size += lua_calc_strlen_in_table ( L, -1, arg_i, strict ); break; case LUA_TLIGHTUSERDATA: if ( strict ) { goto bad_type; } if ( lua_touserdata ( L, -1 ) == NULL ) { size += sizeof ( "null" ) - 1; break; } continue; default: bad_type: msg = lua_pushfstring ( L, "bad data type %s found", lua_typename ( L, type ) ); return luaL_argerror ( L, arg_i, msg ); } lua_pop ( L, 1 ); /* stack: table */ } return size; }
static int _lua_echo(epdata_t *epd, lua_State *L, int nargs, int can_yield) { size_t len = 0; int have = 0; epd->next_out = NULL; if(lua_istable(L, 1)) { len = lua_calc_strlen_in_table(L, 1, 2, 0 /* strict */); if(len < 1) { return 0; } char *buf = temp_buf; if(len > 8192) { buf = malloc(len); if(!buf) { return 0; } lua_copy_str_in_table(L, 1, buf); have = network_send(epd, buf, len); if(have > 0 && can_yield) { epd->next_out = malloc(have); memcpy(epd->next_out, buf + (len - have), have); } free(buf); } else { lua_copy_str_in_table(L, 1, buf); have = network_send(epd, buf, len); if(have > 0 && can_yield) { epd->next_out = malloc(have); memcpy(epd->next_out, buf + (len - have), have); } } } else { const char *data = NULL; int i = 0; for(i = 1; i <= nargs; i++) { if(lua_isboolean(L, i)) { char *buf = NULL; if(lua_toboolean(L, i)) { buf = "true"; have = network_send(epd, buf, 4); } else { buf = "false"; have = network_send(epd, buf, 5); } if(have > 0 && can_yield) { epd->next_out = malloc(have); memcpy(epd->next_out, buf + (len - have), have); } } else { data = lua_tolstring(L, i, &len); have = network_send(epd, data, len); if(have > 0 && can_yield) { epd->next_out = malloc(have); memcpy(epd->next_out, data + (len - have), have); } } } } if(epd->next_out) { if(network_flush(epd) == 1) { epd->next_proc = send_then_send; epd->next_out_len = have; return have; } else { LOGF(ERR, "flush error"); free(epd->next_out); epd->next_out = NULL; return 0; } } return 0; }
static int lua_co_send(lua_State *L) { cosocket_t *c*k = NULL; { if(lua_gettop(L) < 2) { return 0; } int t = lua_type(L, 2); if(!lua_isuserdata(L, 1) || (t != LUA_TSTRING && t != LUA_TTABLE)) { lua_pushboolean(L, 0); lua_pushstring(L, "Error params!"); return 2; } c*k = (cosocket_t *) lua_touserdata(L, 1); if(c*k->status != 2 || c*k->fd == -1 || !c*k->ptr) { lua_pushboolean(L, 0); lua_pushstring(L, "Not connected!"); return 2; } if(c*k->inuse == 1) { lua_pushnil(L); lua_pushstring(L, "socket busy!"); return 2; } c*k->L = L; c*k->send_buf_ed = 0; if(t == LUA_TTABLE) { c*k->send_buf_len = lua_calc_strlen_in_table(L, 2, 2, 1 /* strict */); if(c*k->send_buf_len > 0) { if(c*k->send_buf_len < _SENDBUF_SIZE) { c*k->send_buf_need_free = NULL; lua_copy_str_in_table(L, 2, c*k->_send_buf); c*k->send_buf = c*k->_send_buf; } else { c*k->send_buf_need_free = large_malloc(c*k->send_buf_len); if(!c*k->send_buf_need_free) { LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__); exit(1); } lua_copy_str_in_table(L, 2, c*k->send_buf_need_free); c*k->send_buf = c*k->send_buf_need_free; } } } else { const char *p = lua_tolstring(L, 2, &c*k->send_buf_len); c*k->send_buf_need_free = NULL; if(c*k->send_buf_len < _SENDBUF_SIZE) { memcpy(c*k->_send_buf, p, c*k->send_buf_len); c*k->send_buf = c*k->_send_buf; } else { c*k->send_buf_need_free = large_malloc(c*k->send_buf_len); if(!c*k->send_buf_need_free) { LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__); exit(1); } memcpy(c*k->send_buf_need_free, p, c*k->send_buf_len); c*k->send_buf = c*k->send_buf_need_free; } } if(c*k->send_buf_len < 1) { lua_pushboolean(L, 0); lua_pushstring(L, "content empty!"); return 2; } c*k->inuse = 0; int ret = cosocket_be_write(c*k->ptr); if(ret > 0) { se_be_write(c*k->ptr, cosocket_be_write); c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle); c*k->inuse = 1; return lua_yield(L, 0); } else { return 0 - ret; } } }
int lua_echo ( lua_State *L ) { if ( !lua_isuserdata ( L, 1 ) ) { luaL_error ( L, "miss epd!" ); return 0; } int nargs = lua_gettop ( L ); if ( nargs < 2 ) { luaL_error ( L, "miss content!" ); return 0; } size_t len = 0; epdata_t *epd = lua_touserdata ( L, 1 ); if ( lua_istable ( L, 2 ) ) { len = lua_calc_strlen_in_table ( L, 2, 2, 0 /* strict */ ); if ( len < 1 ) { return 0; } char *buf = tbuf_4096; if ( len > 4096 ) { buf = large_malloc ( len ); if ( !buf ) { return 0; } lua_copy_str_in_table ( L, 2, buf ); network_send ( epd, buf, len ); free ( buf ); } else { lua_copy_str_in_table ( L, 2, buf ); network_send ( epd, buf, len ); } } else { const char *data = NULL; int i = 0; for ( i = 2; i <= nargs; i++ ) { if ( lua_isboolean ( L, i ) ) { if ( lua_toboolean ( L, i ) ) { network_send ( epd, "true", 4 ); } else { network_send ( epd, "false", 5 ); } } else { data = lua_tolstring ( L, i, &len ); network_send ( epd, data, len ); } } } return 0; }