ssize_t tnt_auth(struct tnt_stream *s, const char *user, int ulen, const char *pass, int plen) { struct tnt_iheader hdr; struct iovec v[6]; int v_sz = 5; char *data = NULL, *body_start = NULL; int guest = !user || (ulen == 5 && !strncmp(user, "guest", 5)); if (guest) { user = "******"; ulen = 5; } encode_header(&hdr, TNT_OP_AUTH, s->reqid++); v[1].iov_base = (void *)hdr.header; v[1].iov_len = hdr.end - hdr.header; char body[64]; data = body; body_start = data; data = mp_encode_map(data, 2); data = mp_encode_uint(data, TNT_USERNAME); data = mp_encode_strl(data, ulen); v[2].iov_base = body_start; v[2].iov_len = data - body_start; v[3].iov_base = (void *)user; v[3].iov_len = ulen; body_start = data; data = mp_encode_uint(data, TNT_TUPLE); if (!guest) { data = mp_encode_array(data, 2); data = mp_encode_str(data, "chap-sha1", strlen("chap-sha1")); data = mp_encode_strl(data, TNT_SCRAMBLE_SIZE); char salt[64], scramble[TNT_SCRAMBLE_SIZE]; base64_decode(TNT_SNET_CAST(s)->greeting + TNT_VERSION_SIZE, TNT_SALT_SIZE, salt, 64); tnt_scramble_prepare(scramble, salt, pass, plen); v[5].iov_base = scramble; v[5].iov_len = TNT_SCRAMBLE_SIZE; v_sz++; } else { data = mp_encode_array(data, 0); } v[4].iov_base = body_start; v[4].iov_len = data - body_start; size_t package_len = 0; for (int i = 1; i < v_sz; ++i) { package_len += v[i].iov_len; } char len_prefix[9]; char *len_end = mp_encode_luint32(len_prefix, package_len); v[0].iov_base = len_prefix; v[0].iov_len = len_end - len_prefix; return s->writev(s, v, v_sz); }
static void test_next_on_map(uint32_t count) { note("next/check on map(%u)", count); char *d1 = data; d1 = mp_encode_map(d1, count); for (uint32_t i = 0; i < 2 * count; i++) { d1 = mp_encode_uint(d1, i % 0x7f); /* one byte */ } uint32_t len = 2 * count + mp_sizeof_map(count); const char *d2 = data; const char *d3 = data; ok(!mp_check(&d2, data + BUF_MAXLEN), "mp_check(map %u))", count); is((d1 - data), (ptrdiff_t)len, "len(map %u) == %u", count, len); is((d2 - data), (ptrdiff_t)len, "len(mp_check(map %u)) == %u", count, len); mp_next(&d3); is((d3 - data), (ptrdiff_t)len, "len(mp_next(map %u)) == %u", count, len); }
ssize_t tnt_update(struct tnt_stream *s, uint32_t space, uint32_t index, struct tnt_stream *key, struct tnt_stream *ops) { if (tnt_object_verify(key, MP_ARRAY)) return -1; if (tnt_object_verify(ops, MP_ARRAY)) return -1; struct tnt_iheader hdr; struct iovec v[6]; int v_sz = 6; char *data = NULL, *body_start = NULL; encode_header(&hdr, TNT_OP_UPDATE, s->reqid++); v[1].iov_base = (void *)hdr.header; v[1].iov_len = hdr.end - hdr.header; char body[64]; body_start = body; data = body; data = mp_encode_map(data, 4); data = mp_encode_uint(data, TNT_SPACE); data = mp_encode_uint(data, space); data = mp_encode_uint(data, TNT_INDEX); data = mp_encode_uint(data, index); data = mp_encode_uint(data, TNT_KEY); v[2].iov_base = (void *)body_start; v[2].iov_len = data - body_start; body_start = data; v[3].iov_base = TNT_SBUF_DATA(key); v[3].iov_len = TNT_SBUF_SIZE(key); data = mp_encode_uint(data, TNT_TUPLE); v[4].iov_base = (void *)body_start; v[4].iov_len = data - body_start; body_start = data; v[5].iov_base = TNT_SBUF_DATA(ops); v[5].iov_len = TNT_SBUF_SIZE(ops); size_t package_len = 0; for (int i = 1; i < v_sz; ++i) package_len += v[i].iov_len; char len_prefix[9]; char *len_end = mp_encode_luint32(len_prefix, package_len); v[0].iov_base = len_prefix; v[0].iov_len = len_end - len_prefix; return s->writev(s, v, v_sz); }
static ssize_t tnt_rpc_base(struct tnt_stream *s, const char *proc, size_t proc_len, struct tnt_stream *args, enum tnt_request_t op) { if (!proc || proc_len == 0) return -1; if (tnt_object_verify(args, MP_ARRAY)) return -1; uint32_t fld = (is_call(op) ? TNT_FUNCTION : TNT_EXPRESSION); struct tnt_iheader hdr; struct iovec v[6]; int v_sz = 6; char *data = NULL, *body_start = NULL; encode_header(&hdr, op, s->reqid++); v[1].iov_base = (void *)hdr.header; v[1].iov_len = hdr.end - hdr.header; char body[64]; body_start = body; data = body; data = mp_encode_map(data, 2); data = mp_encode_uint(data, fld); data = mp_encode_strl(data, proc_len); v[2].iov_base = body_start; v[2].iov_len = data - body_start; v[3].iov_base = (void *)proc; v[3].iov_len = proc_len; body_start = data; data = mp_encode_uint(data, TNT_TUPLE); v[4].iov_base = body_start; v[4].iov_len = data - body_start; v[5].iov_base = TNT_SBUF_DATA(args); v[5].iov_len = TNT_SBUF_SIZE(args); size_t package_len = 0; for (int i = 1; i < v_sz; ++i) package_len += v[i].iov_len; char len_prefix[9]; char *len_end = mp_encode_luint32(len_prefix, package_len); v[0].iov_base = len_prefix; v[0].iov_len = len_end - len_prefix; return s->writev(s, v, v_sz); }
static int test_overflow() { plan(4); header(); const char *chk; char *d; d = data; chk = data; d = mp_encode_array(d, 1); d = mp_encode_array(d, UINT32_MAX); is(mp_check(&chk, d), 1, "mp_check array overflow") d = data; chk = data; d = mp_encode_array(d, 1); d = mp_encode_map(d, UINT32_MAX); is(mp_check(&chk, d), 1, "mp_check map overflow") d = data; chk = data; d = mp_encode_array(d, 2); d = mp_encode_str(d, "", 0); d = mp_encode_strl(d, UINT32_MAX); is(mp_check(&chk, d), 1, "mp_check str overflow") d = data; chk = data; d = mp_encode_array(d, 2); d = mp_encode_bin(d, "", 0); d = mp_encode_binl(d, UINT32_MAX); is(mp_check(&chk, d), 1, "mp_check bin overflow") footer(); return check_plan(); }
int test_mp_print() { plan(10); header(); char msgpack[128]; char *d = msgpack; d = mp_encode_array(d, 6); d = mp_encode_int(d, -5); d = mp_encode_uint(d, 42); d = mp_encode_str(d, "kill bill", 9); d = mp_encode_map(d, 6); d = mp_encode_str(d, "bool true", 9); d = mp_encode_bool(d, true); d = mp_encode_str(d, "bool false", 10); d = mp_encode_bool(d, false); d = mp_encode_str(d, "null", 4); d = mp_encode_nil(d); d = mp_encode_str(d, "float", 5); d = mp_encode_float(d, 3.14); d = mp_encode_str(d, "double", 6); d = mp_encode_double(d, 3.14); d = mp_encode_uint(d, 100); d = mp_encode_uint(d, 500); *d++ = 0xd4; /* let's pack smallest fixed ext */ *d++ = 0; *d++ = 0; char bin[] = "\x12test\x34\b\t\n\"bla\\-bla\"\f\r"; d = mp_encode_bin(d, bin, sizeof(bin)); assert(d <= msgpack + sizeof(msgpack)); const char *expected = "[-5, 42, \"kill bill\", " "{\"bool true\": true, \"bool false\": false, \"null\": null, " "\"float\": 3.14, \"double\": 3.14, 100: 500}, undefined, " "\"\\u0012test4\\b\\t\\n\\\"bla\\\\-bla\\\"\\f\\r\\u0000\"]"; int esize = strlen(expected); char result[256]; int fsize = mp_snprint(result, sizeof(result), msgpack); ok(fsize == esize, "mp_snprint return value"); ok(strcmp(result, expected) == 0, "mp_snprint result"); fsize = mp_snprint(NULL, 0, msgpack); ok(fsize == esize, "mp_snprint limit = 0"); fsize = mp_snprint(result, 1, msgpack); ok(fsize == esize && result[0] == '\0', "mp_snprint limit = 1"); fsize = mp_snprint(result, 2, msgpack); ok(fsize == esize && result[1] == '\0', "mp_snprint limit = 2"); fsize = mp_snprint(result, esize, msgpack); ok(fsize == esize && result[esize - 1] == '\0', "mp_snprint limit = expected"); fsize = mp_snprint(result, esize + 1, msgpack); ok(fsize == esize && result[esize] == '\0', "mp_snprint limit = expected + 1"); FILE *tmpf = tmpfile(); if (tmpf != NULL) { int fsize = mp_fprint(tmpf, msgpack); ok(fsize == esize, "mp_fprint return value"); (void) rewind(tmpf); int rsize = fread(result, 1, sizeof(result), tmpf); ok(rsize == esize && memcmp(result, expected, esize) == 0, "mp_fprint result"); fclose(tmpf); } /* stdin is read-only */ int rc = mp_fprint(stdin, msgpack); is(rc, -1, "mp_fprint I/O error"); footer(); return check_plan(); }
void _mpack_item(SV *res, SV *o) { size_t len, res_len, new_len; char *s, *res_s; res_s = SvPVbyte(res, res_len); unsigned i; if (!SvOK(o)) { new_len = res_len + mp_sizeof_nil(); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_nil(res_s + res_len); return; } if (SvROK(o)) { o = SvRV(o); if (SvOBJECT(o)) { SvGETMAGIC(o); HV *stash = SvSTASH(o); GV *mtd = gv_fetchmethod_autoload(stash, "msgpack", 0); if (!mtd) croak("Object has no method 'msgpack'"); dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs (sv_bless (sv_2mortal (newRV_inc(o)), stash)); PUTBACK; call_sv((SV *)GvCV(mtd), G_SCALAR); SPAGAIN; SV *pkt = POPs; if (!SvOK(pkt)) croak("O->msgpack returned undef"); s = SvPV(pkt, len); new_len = res_len + len; res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); memcpy(res_s + res_len, s, len); PUTBACK; FREETMPS; LEAVE; return; } switch(SvTYPE(o)) { case SVt_PVAV: { AV *a = (AV *)o; len = av_len(a) + 1; new_len = res_len + mp_sizeof_array(len); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_array(res_s + res_len, len); for (i = 0; i < len; i++) { SV **item = av_fetch(a, i, 0); if (!item) _mpack_item(res, 0); else _mpack_item(res, *item); } break; } case SVt_PVHV: { HV *h = (HV *)o; len = hv_iterinit(h); new_len = res_len + mp_sizeof_map(len); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_map(res_s + res_len, len); for (;;) { HE * iter = hv_iternext(h); if (!iter) break; SV *k = hv_iterkeysv(iter); SV *v = HeVAL(iter); _mpack_item(res, k); _mpack_item(res, v); } break; } default: croak("Can't serialize reference"); } return; } switch(SvTYPE(o)) { case SVt_PV: case SVt_PVIV: case SVt_PVNV: case SVt_PVMG: case SVt_REGEXP: if (!looks_like_number(o)) { s = SvPV(o, len); new_len = res_len + mp_sizeof_str(len); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_str(res_s + res_len, s, len); break; } case SVt_NV: { NV v = SvNV(o); IV iv = (IV)v; if (v != iv) { new_len = res_len + mp_sizeof_double(v); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_double(res_s + res_len, v); break; } } case SVt_IV: { IV v = SvIV(o); if (v >= 0) { new_len = res_len + mp_sizeof_uint(v); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_uint(res_s + res_len, v); } else { new_len = res_len + mp_sizeof_int(v); res_s = SvGROW(res, new_len); SvCUR_set(res, new_len); mp_encode_int(res_s + res_len, v); } break; } default: croak("Internal msgpack error %d", SvTYPE(o)); } }