123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include "tmate.h"
- #include "tmate-protocol.h"
- static void on_encoder_buffer_ready(__unused evutil_socket_t fd,
- __unused short what, void *arg)
- {
- struct tmate_encoder *encoder = arg;
- encoder->ev_active = false;
- if (encoder->ready_callback)
- encoder->ready_callback(encoder->userdata, encoder->buffer);
- }
- static int on_encoder_write(void *userdata, const char *buf, size_t len)
- {
- struct tmate_encoder *encoder = userdata;
- if (evbuffer_add(encoder->buffer, buf, len) < 0)
- tmate_fatal("Cannot buffer encoded data");
- if (!encoder->ev_active) {
- event_active(&encoder->ev_buffer, EV_READ, 0);
- encoder->ev_active = true;
- }
- return 0;
- }
- /* Really sad hack, but we can get away with it */
- #define tmate_encoder_from_pk(pk) ((struct tmate_encoder *)pk)
- void msgpack_pack_string(msgpack_packer *pk, const char *str)
- {
- size_t len = strlen(str);
- msgpack_pack_str(pk, len);
- msgpack_pack_str_body(pk, str, len);
- }
- void msgpack_pack_boolean(msgpack_packer *pk, bool value)
- {
- if (value)
- msgpack_pack_true(pk);
- else
- msgpack_pack_false(pk);
- }
- void tmate_encoder_init(struct tmate_encoder *encoder,
- tmate_encoder_write_cb *callback,
- void *userdata)
- {
- msgpack_packer_init(&encoder->pk, encoder, &on_encoder_write);
- encoder->buffer = evbuffer_new();
- encoder->ready_callback = callback;
- encoder->userdata = userdata;
- if (!encoder->buffer)
- tmate_fatal("Can't allocate buffer");
- event_set(&encoder->ev_buffer, -1,
- EV_READ | EV_PERSIST, on_encoder_buffer_ready, encoder);
- event_add(&encoder->ev_buffer, NULL);
- encoder->ev_active = false;
- }
- void tmate_encoder_destroy(struct tmate_encoder *encoder)
- {
- /* encoder->pk doesn't need any cleanup */
- evbuffer_free(encoder->buffer);
- event_del(&encoder->ev_buffer);
- memset(encoder, 0, sizeof(*encoder));
- }
- void tmate_encoder_set_ready_callback(struct tmate_encoder *encoder,
- tmate_encoder_write_cb *callback,
- void *userdata)
- {
- encoder->ready_callback = callback;
- encoder->userdata = userdata;
- if (encoder->ready_callback)
- encoder->ready_callback(encoder->userdata, encoder->buffer);
- }
- void tmate_decoder_error(void)
- {
- /* TODO Don't kill the session, disconnect */
- tmate_print_stack_trace();
- tmate_fatal("Received a bad message");
- }
- void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj)
- {
- if (obj.type != MSGPACK_OBJECT_ARRAY)
- tmate_decoder_error();
- uk->argv = obj.via.array.ptr;
- uk->argc = obj.via.array.size;
- }
- int64_t unpack_int(struct tmate_unpacker *uk)
- {
- int64_t val;
- if (uk->argc == 0)
- tmate_decoder_error();
- if (uk->argv[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER &&
- uk->argv[0].type != MSGPACK_OBJECT_NEGATIVE_INTEGER)
- tmate_decoder_error();
- val = uk->argv[0].via.i64;
- uk->argv++;
- uk->argc--;
- return val;
- }
- bool unpack_bool(struct tmate_unpacker *uk)
- {
- bool val;
- if (uk->argc == 0)
- tmate_decoder_error();
- if (uk->argv[0].type != MSGPACK_OBJECT_BOOLEAN)
- tmate_decoder_error();
- val = uk->argv[0].via.boolean;
- uk->argv++;
- uk->argc--;
- return val;
- }
- void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len)
- {
- if (uk->argc == 0)
- tmate_decoder_error();
- if (uk->argv[0].type != MSGPACK_OBJECT_STR &&
- uk->argv[0].type != MSGPACK_OBJECT_BIN)
- tmate_decoder_error();
- *len = uk->argv[0].via.str.size;
- *buf = uk->argv[0].via.str.ptr;
- uk->argv++;
- uk->argc--;
- }
- char *unpack_string(struct tmate_unpacker *uk)
- {
- const char *buf;
- char *alloc_buf;
- size_t len;
- unpack_buffer(uk, &buf, &len);
- alloc_buf = xmalloc(len + 1);
- memcpy(alloc_buf, buf, len);
- alloc_buf[len] = '\0';
- return alloc_buf;
- }
- void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested)
- {
- if (uk->argc == 0)
- tmate_decoder_error();
- init_unpacker(nested, uk->argv[0]);
- uk->argv++;
- uk->argc--;
- }
- #define UNPACKER_RESERVE_SIZE 1024
- void tmate_decoder_init(struct tmate_decoder *decoder, tmate_decoder_reader *reader,
- void *userdata)
- {
- if (!msgpack_unpacker_init(&decoder->unpacker, UNPACKER_RESERVE_SIZE))
- tmate_fatal("Cannot initialize the unpacker");
- decoder->reader = reader;
- decoder->userdata = userdata;
- }
- void tmate_decoder_destroy(struct tmate_decoder *decoder)
- {
- msgpack_unpacker_destroy(&decoder->unpacker);
- memset(decoder, 0, sizeof(*decoder));
- }
- void tmate_decoder_get_buffer(struct tmate_decoder *decoder,
- char **buf, size_t *len)
- {
- if (!msgpack_unpacker_reserve_buffer(&decoder->unpacker, UNPACKER_RESERVE_SIZE))
- tmate_fatal("cannot expand decoder buffer");
- *buf = msgpack_unpacker_buffer(&decoder->unpacker);
- *len = msgpack_unpacker_buffer_capacity(&decoder->unpacker);
- }
- void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len)
- {
- struct tmate_unpacker _uk, *uk = &_uk;
- msgpack_unpacked result;
- msgpack_unpacker_buffer_consumed(&decoder->unpacker, len);
- msgpack_unpacked_init(&result);
- while (msgpack_unpacker_next(&decoder->unpacker, &result)) {
- init_unpacker(uk, result.data);
- decoder->reader(decoder->userdata, uk);
- }
- msgpack_unpacked_destroy(&result);
- }
|