/* TODO: typed object support */ static void amf0_encode_table_as_object(amf_buf *buf, lua_State *L, int idx, int ridx) { size_t key_len; const char *key; amf_buf_append_char(buf, AMF0_OBJECT); for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) { switch (lua_type(L, -2)) { case LUA_TNUMBER: lua_pushvalue(L, -2); key = lua_tolstring(L, -1, &key_len); amf_buf_append_u16(buf, (uint16_t)key_len); amf_buf_append(buf, key, key_len); lua_pop(L, 1); break; case LUA_TSTRING: key = lua_tolstring(L, -2, &key_len); amf_buf_append_u16(buf, (uint16_t)key_len); amf_buf_append(buf, key, key_len); break; default: continue; } amf0_encode(L, buf, 0, -1, ridx); } amf_buf_append_u16(buf, (uint16_t)0); amf_buf_append_char(buf, AMF0_END_OF_OBJECT); }
static void encode_hdr(lua_State *L, amf_buf *buf, int ver) { if(!lua_istable(L, -1)) { luaL_error(L, "invalid header structure, must be a dense table"); } /* name */ lua_rawgeti(L, -1, 1); size_t len; const char *name = lua_tolstring(L, -1, &len); amf_buf_append_u16(buf, (uint16_t)len); if (len > 0) amf_buf_append(buf, name, (uint16_t)len); lua_pop(L, 1); /* must understand */ lua_rawgeti(L, -1, 2); int mu = lua_toboolean(L, -1); amf_buf_append_char(buf, (char)mu); lua_pop(L, 1); /* content length */ amf_buf_append_u32(buf, (uint32_t)0); lua_rawgeti(L, -1, 3); lua_newtable(L); amf0_encode(L, buf, (ver == 3), -2, lua_gettop(L)); lua_pop(L, 2); /* pops the obj and ref table */ }
int lua_amf_encode(lua_State *L) { int ver, freebuf = 1; amf_buf *buf; if (lua_isnumber(L, 1)) { ver = luaL_checkint(L, 1); check_amf_ver(ver, 1); luaL_checkany(L, 2); buf = amf_buf_init(NULL); } else { buf = luaL_checkudata(L, 1, "amf_buffer"); ver = luaL_checkint(L, 2); check_amf_ver(ver, 2); luaL_checkany(L, 3); freebuf = 0; } if (buf == NULL) { lua_pushnil(L); return 1; } int base = lua_gettop(L); if (ver == AMF_VER0) { lua_newtable(L); amf0_encode(L, buf, 0, base, base+1); } else { lua_newtable(L); lua_newtable(L); lua_newtable(L); amf3_encode(L, buf, base, base+1, base+2, base+3); } if (freebuf) { lua_pushlstring(L, buf->b, buf->len); amf_buf_free(buf); return 1; } else { return 0; } }
static void amf0_encode_table_as_array(amf_buf *buf, lua_State *L, int idx, int ridx, int len) { amf_buf_append_char(buf, AMF0_STRICT_ARRAY); amf_buf_append_u32(buf, (uint32_t)len); // array count for (int i = 1; i <= len; i++) { lua_pushinteger(L, i); lua_gettable(L, idx); amf0_encode(L, buf, 0, -1, ridx); lua_pop(L, 1); } }
static void encode_body(lua_State *L, amf_buf *buf, int ver) { if(!lua_istable(L, -1)) { luaL_error(L, "invalid body structure, must be a dense table"); } size_t len; const char *uri; /* target uri */ lua_rawgeti(L, -1, 1); uri = lua_tolstring(L, -1, &len); amf_buf_append_u16(buf, (uint16_t)len); if (len > 0) { amf_buf_append(buf, uri, (uint16_t)len); printf("target: %s\n", uri); } lua_pop(L, 1); /* response uri */ lua_rawgeti(L, -1, 2); uri = lua_tolstring(L, -1, &len); amf_buf_append_u16(buf, (uint16_t)len); if (len > 0) { amf_buf_append(buf, uri, (uint16_t)len); printf("response: %s\n", uri); } lua_pop(L, 1); /* content length */ amf_buf_append_u32(buf, (uint32_t)0); lua_rawgeti(L, -1, 3); lua_newtable(L); amf0_encode(L, buf, (ver == 3), -2, lua_gettop(L)); lua_pop(L, 2); /* pops the obj and ref table */ }