static void decode_hdr(lua_State *L, amf_cursor *c) { lua_createtable(L, 3, 0); const char *name; size_t len; amf_cursor_read_str(c, &name, &len); amf_cursor_checkerr(c); lua_pushlstring(L, name, len); lua_rawseti(L, -2, 1); uint8_t must_understand; amf_cursor_read_u8(c, &must_understand); amf_cursor_checkerr(c); lua_pushboolean(L, must_understand); lua_rawseti(L, -2, 2); /* content length*/ amf_cursor_skip(c, 4); lua_newtable(L); amf0_decode(L, c, lua_gettop(L)); amf_cursor_checkerr(c); lua_rawseti(L, -3, 3); /* ref table */ lua_pop(L, 1); }
static void decode_body(lua_State *L, amf_cursor *c) { lua_createtable(L, 3, 0); const char *uri; size_t len; /* target uri */ amf_cursor_read_str(c, &uri, &len); amf_cursor_checkerr(c); lua_pushlstring(L, uri, len); lua_rawseti(L, -2, 1); /* response uri */ amf_cursor_read_str(c, &uri, &len); amf_cursor_checkerr(c); lua_pushlstring(L, uri, len); lua_rawseti(L, -2, 2); /* content length*/ amf_cursor_skip(c, 4); lua_newtable(L); amf0_decode(L, c, lua_gettop(L)); amf_cursor_checkerr(c); lua_rawseti(L, -3, 3); /* ref table */ lua_pop(L, 1); }
void amf0_decode(lua_State *L, amf_cursor *c, int ridx) { amf_cursor_need(c, 1); switch (c->p[0]) { case AMF0_BOOLEAN: amf_cursor_need(c, 2); lua_pushboolean(L, c->p[1] == 0x01 ? 1 : 0); amf_cursor_consume(c, 2); break; case AMF0_NULL: case AMF0_UNDEFINED: lua_pushnil(L); amf_cursor_consume(c, 1); break; case AMF0_NUMBER: amf_cursor_need(c, 9); assert(sizeof(double) == 8); double d; memcpy(&d, c->p + 1, 8); reverse_if_little_endian(&d, 8); lua_pushnumber(L, d); amf_cursor_consume(c, 9); break; case AMF0_STRING: amf_cursor_consume(c, 1); amf0_decode_string(L, c, 16); break; case AMF0_L_STRING: amf_cursor_consume(c, 1); amf0_decode_string(L, c, 32); break; case AMF0_OBJECT: amf_cursor_consume(c, 1); amf0_decode_to_lua_table(L, c, ridx); break; case AMF0_ECMA_ARRAY: /* the property count, basicly 0 */ amf_cursor_skip(c, 5); amf0_decode_to_lua_table(L, c, ridx); break; case AMF0_STRICT_ARRAY: amf_cursor_need(c, 5); uint32_t count = c->p[1] << 24 | c->p[2] << 16 | c->p[3] << 8 | c->p[4]; amf_cursor_consume(c, 5); assert(count <= INT_MAX); if (count > INT_MAX) { c->err = AMF_CUR_ERR_BADFMT; c->err_msg = "strict array elements count overflow"; return; } lua_createtable(L, (int)count, 0); amf0_decode_remember_ref(L, -1, ridx); for (int i = 1; i <= (int)count; i++) { amf0_decode(L, c, ridx); amf_cursor_checkerr(c); lua_rawseti(L, -2, i); } break; case AMF0_TYPED_OBJECT: amf_cursor_consume(c, 1); amf0_decode_string(L, c, 16); amf0_decode_to_lua_table(L, c, ridx); /* push alias name */ lua_pushstring(L, "__amf_alias__"); lua_pushvalue(L, -3); lua_rawset(L, -3); /* remove alias from stack */ lua_remove(L, -2); break; case AMF0_REFERENCE: amf_cursor_need(c, 3); uint16_t ref = c->p[1] << 8 | c->p[2]; amf_cursor_consume(c, 3); lua_rawgeti(L, ridx, ref + 1); if (lua_isnil(L, -1)) { c->err = AMF_CUR_ERR_BADFMT; c->err_msg = "reference not found"; return; } break; case AMF0_AVMPLUS: { lua_newtable(L); lua_newtable(L); int sidx = lua_gettop(L); amf3_decode(L, c, sidx, ridx, sidx - 1); break; } default: c->err = AMF_CUR_ERR_BADFMT; } }