From 82376ce1eb1b2fc07ae6ca5a3036b5bb6583fab4 Mon Sep 17 00:00:00 2001 From: eutarass Date: Wed, 23 Apr 2008 20:11:12 +0000 Subject: 1. Bug 223520: [tcf] Registers service changes. 2. Fixed discovery periodic UDP broadcast. 3. Fixed json_read_binary_data() - it didn't work for buffers smaller then 3 bytes --- base64.c | 29 ++++---- channel_tcp.c | 14 ++-- discovery_udp.c | 40 ++++++----- json.c | 211 ++++++++++++++++++++++++++++++++------------------------ json.h | 4 +- registers.c | 164 ++++++++++++++++++++++++++++++++++++------- streams.h | 2 + 7 files changed, 311 insertions(+), 153 deletions(-) diff --git a/base64.c b/base64.c index c043ecf2..b1de14f9 100644 --- a/base64.c +++ b/base64.c @@ -58,23 +58,23 @@ int write_base64(OutputStream * out, const char * buf0, int len) { while (pos < len) { int byte0 = buf[pos++]; - out->write(out, int2char[byte0 >> 2]); + write_stream(out, int2char[byte0 >> 2]); if (pos == len) { - out->write(out, int2char[(byte0 << 4) & 0x3f]); - out->write(out, '='); - out->write(out, '='); + write_stream(out, int2char[(byte0 << 4) & 0x3f]); + write_stream(out, '='); + write_stream(out, '='); } else { int byte1 = buf[pos++]; - out->write(out, int2char[(byte0 << 4) & 0x3f | (byte1 >> 4)]); + write_stream(out, int2char[(byte0 << 4) & 0x3f | (byte1 >> 4)]); if (pos == len) { - out->write(out, int2char[(byte1 << 2) & 0x3f]); - out->write(out, '='); + write_stream(out, int2char[(byte1 << 2) & 0x3f]); + write_stream(out, '='); } else { int byte2 = buf[pos++]; - out->write(out, int2char[(byte1 << 2) & 0x3f | (byte2 >> 6)]); - out->write(out, int2char[byte2 & 0x3f]); + write_stream(out, int2char[(byte1 << 2) & 0x3f | (byte2 >> 6)]); + write_stream(out, int2char[byte2 & 0x3f]); } } } @@ -86,16 +86,17 @@ int read_base64(InputStream * inp, char * buf, int buf_size) { int pos = 0; int ch_max = sizeof(char2int) / sizeof(int); + assert(buf_size >= 3); while (pos + 3 <= buf_size) { int n0, n1, n2, n3; int ch0, ch1, ch2, ch3; - ch0 = inp->peek(inp); + ch0 = peek_stream(inp); if (ch0 < 0 || ch0 >= ch_max || (n0 = char2int[ch0]) < 0) break; - inp->read(inp); - ch1 = inp->read(inp); - ch2 = inp->read(inp); - ch3 = inp->read(inp); + read_stream(inp); + ch1 = read_stream(inp); + ch2 = read_stream(inp); + ch3 = read_stream(inp); if (ch1 < 0 || ch1 >= ch_max || (n1 = char2int[ch1]) < 0) exception(ERR_BASE64); buf[pos++] = (char)((n0 << 2) | (n1 >> 4)); if (ch2 == '=') break; diff --git a/channel_tcp.c b/channel_tcp.c index 6f2013ed..d1d04fae 100644 --- a/channel_tcp.c +++ b/channel_tcp.c @@ -125,7 +125,7 @@ static int tcp_is_closed(Channel * c) { return channel->socket < 0; } -static void flush_stream(OutputStream * out) { +static void tcp_flush_stream(OutputStream * out) { int cnt = 0; ChannelTCP * channel = channel2tcp(out2channel(out)); assert(is_dispatch_thread()); @@ -147,7 +147,7 @@ static void flush_stream(OutputStream * out) { channel->obuf_inp = 0; } -static void write_stream(OutputStream * out, int byte) { +static void tcp_write_stream(OutputStream * out, int byte) { ChannelTCP * channel = channel2tcp(out2channel(out)); int b0 = byte; assert(is_dispatch_thread()); @@ -156,7 +156,7 @@ static void write_stream(OutputStream * out, int byte) { if (channel->out_errno) return; if (b0 < 0) byte = ESC; channel->obuf[channel->obuf_inp++] = byte; - if (channel->obuf_inp == BUF_SIZE) flush_stream(out); + if (channel->obuf_inp == BUF_SIZE) tcp_flush_stream(out); if (b0 < 0 || b0 == ESC) { if (b0 == ESC) byte = 0; else if (b0 == MARKER_EOM) byte = 1; @@ -165,7 +165,7 @@ static void write_stream(OutputStream * out, int byte) { if (channel->socket < 0) return; if (channel->out_errno) return; channel->obuf[channel->obuf_inp++] = byte; - if (channel->obuf_inp == BUF_SIZE) flush_stream(out); + if (channel->obuf_inp == BUF_SIZE) tcp_flush_stream(out); } } @@ -214,7 +214,7 @@ static void send_eof_and_close(Channel * channel, int err) { if (c->socket < 0) return; ibuf_flush(&c->ibuf, &c->chan.inp); ibuf_read_done(&c->ibuf, 0); /* EOF */ - write_stream(&c->chan.out, MARKER_EOS); + tcp_write_stream(&c->chan.out, MARKER_EOS); write_errno(&c->chan.out, err); c->chan.out.write(&c->chan.out, MARKER_EOM); c->chan.out.flush(&c->chan.out); @@ -354,8 +354,8 @@ static ChannelTCP * create_channel(int sock) { c->magic = CHANNEL_MAGIC; c->chan.inp.read = tcp_read_stream; c->chan.inp.peek = tcp_peek_stream; - c->chan.out.write = write_stream; - c->chan.out.flush = flush_stream; + c->chan.out.write = tcp_write_stream; + c->chan.out.flush = tcp_flush_stream; c->chan.start_comm = start_channel; c->chan.check_pending = channel_check_pending; c->chan.message_count = channel_get_message_count; diff --git a/discovery_udp.c b/discovery_udp.c index 9e8f967a..c0b1d194 100644 --- a/discovery_udp.c +++ b/discovery_udp.c @@ -135,7 +135,8 @@ static int udp_send_peer_sever(PeerServer * ps, void * arg) { else { dst_addr = addr; } - trace(LOG_DISCOVERY, "udp_send_peer_sever: sending UDP_ACK_INFO, ID=%s:%s:%s, dst=%s", transport, host, port, inet_ntoa(dst_addr->sin_addr)); + trace(LOG_DISCOVERY, "sending UDP_ACK_INFO to %s:%d", + inet_ntoa(dst_addr->sin_addr), ntohs(dst_addr->sin_port)); buf[pos++] = 'T'; buf[pos++] = 'C'; @@ -188,13 +189,9 @@ static void udp_send_ack(struct sockaddr_in * addr) { static void udp_send_req(void) { int i = 0; char buf[PKT_SIZE]; - struct sockaddr_in dst_addr; + ip_ifc_info * ifc; - trace(LOG_DISCOVERY, "udp_send_req: sending UDP_REQ_INFO"); - memset(&dst_addr, 0, sizeof dst_addr); - dst_addr.sin_family = AF_INET; - dst_addr.sin_port = htons((short)discovery_port); - dst_addr.sin_addr.s_addr = INADDR_BROADCAST; + trace(LOG_DISCOVERY, "sending UDP_REQ_INFO"); buf[i++] = 'T'; buf[i++] = 'C'; @@ -204,9 +201,17 @@ static void udp_send_req(void) { buf[i++] = 0; buf[i++] = 0; buf[i++] = 0; - if (sendto(udp_server_socket, buf, i, 0, (struct sockaddr *)&dst_addr, sizeof dst_addr) < 0) { - trace(LOG_ALWAYS, "Can't send UDP discovery request packet to %s: %s", - inet_ntoa(dst_addr.sin_addr), errno_to_str(errno)); + + for (ifc = ifclist; ifc < &ifclist[ifcind]; ifc++) { + struct sockaddr_in dst_addr; + memset(&dst_addr, 0, sizeof dst_addr); + dst_addr.sin_family = AF_INET; + dst_addr.sin_port = htons((short)discovery_port); + dst_addr.sin_addr.s_addr = ifc->addr | ~ifc->mask; + if (sendto(udp_server_socket, buf, i, 0, (struct sockaddr *)&dst_addr, sizeof dst_addr) < 0) { + trace(LOG_ALWAYS, "Can't send UDP discovery request packet to %s: %s", + inet_ntoa(dst_addr.sin_addr), errno_to_str(errno)); + } } } @@ -216,13 +221,14 @@ static void udp_refresh_info(void * arg) { int delta; assert(is_dispatch_thread()); - trace(LOG_DISCOVERY, "udp_refresh_info, implcit %d, active %d, timenow %ld, last_refresh_time %ld", implcit_refresh, refresh_timer_active, timenow, last_refresh_time); + trace(LOG_DISCOVERY, "udp_refresh_info, implcit %d, active %d, timenow %ld, last_refresh_time %ld", + implcit_refresh, refresh_timer_active, timenow, last_refresh_time); if (implcit_refresh) { assert(refresh_timer_active); if ((delta = timenow - last_refresh_time) < REFRESH_TIME) { /* Recent explicit refresh - wait a little longer */ assert(delta > 0); - post_event_with_delay(udp_refresh_info, (void *)1, (REFRESH_TIME - delta)*1000*1000); + post_event_with_delay(udp_refresh_info, (void *)1, (REFRESH_TIME - delta) * 1000000); return; } refresh_timer_active = 0; @@ -240,13 +246,14 @@ static void udp_refresh_info(void * arg) { last_refresh_time = timenow; if (!refresh_timer_active) { refresh_timer_active = 1; - post_event_with_delay(udp_refresh_info, (void *)1, REFRESH_TIME*1000*1000); + post_event_with_delay(udp_refresh_info, (void *)1, REFRESH_TIME * 1000000); } } static void udp_receive_req(void * arg) { receive_message * m = arg; + trace(LOG_DISCOVERY, "received UDP_REQ_INFO from %s", inet_ntoa(m->addr.sin_addr)); udp_send_ack(&m->addr); trigger_recv(); } @@ -288,7 +295,7 @@ static void udp_receive_ack(void * arg) { p++; } if (p != NULL && ps->id != NULL) { - trace(LOG_DISCOVERY, "udp_receive_ack: received UDP_ACK_INFO, ID=%s", ps->id); + trace(LOG_DISCOVERY, "received UDP_ACK_INFO, ID=%s", ps->id); ps->flags |= PS_FLAG_DISCOVERABLE; peer_server_add(ps, STALE_TIME_DELTA); } @@ -316,10 +323,10 @@ static void udp_server_recv(void * x) { return; } if (m->buf[4] == UDP_REQ_INFO && is_remote_host(m->addr.sin_addr)) { - post_event(udp_receive_req, m); + udp_receive_req(m); } else if (m->buf[4] == UDP_ACK_INFO) { - post_event(udp_receive_ack, m); + udp_receive_ack(m); } else { trigger_recv(); @@ -398,5 +405,6 @@ int discovery_udp_server(const char * port) { trigger_recv(); peer_server_add_listener(local_server_change, NULL); + udp_refresh_info(NULL); return 0; } diff --git a/json.c b/json.c index 677b1f69..57dafc03 100644 --- a/json.c +++ b/json.c @@ -45,12 +45,12 @@ void json_write_ulong(OutputStream * out, unsigned long n) { json_write_ulong(out, n / 10); n = n % 10; } - out->write(out, n + '0'); + write_stream(out, n + '0'); } void json_write_long(OutputStream * out, long n) { if (n < 0) { - out->write(out, '-'); + write_stream(out, '-'); n = -n; } json_write_ulong(out, (unsigned long)n); @@ -58,7 +58,7 @@ void json_write_long(OutputStream * out, long n) { void json_write_int64(OutputStream * out, int64 n) { if (n < 0) { - out->write(out, '-'); + write_stream(out, '-'); n = -n; if (n < 0) exception(EINVAL); } @@ -66,7 +66,7 @@ void json_write_int64(OutputStream * out, int64 n) { json_write_int64(out, n / 10); n = n % 10; } - out->write(out, (int)n + '0'); + write_stream(out, (int)n + '0'); } void json_write_boolean(OutputStream * out, int b) { @@ -83,16 +83,16 @@ static char hex_digit(unsigned n) { void json_write_char(OutputStream * out, char ch) { unsigned n = ch & 0xff; if (n < ' ') { - out->write(out, '\\'); - out->write(out, 'u'); - out->write(out, '0'); - out->write(out, '0'); - out->write(out, hex_digit(n >> 4)); - out->write(out, hex_digit(n)); + write_stream(out, '\\'); + write_stream(out, 'u'); + write_stream(out, '0'); + write_stream(out, '0'); + write_stream(out, hex_digit(n >> 4)); + write_stream(out, hex_digit(n)); } else { - if (n == '"' || n == '\\') out->write(out, '\\'); - out->write(out, n); + if (n == '"' || n == '\\') write_stream(out, '\\'); + write_stream(out, n); } } @@ -101,9 +101,9 @@ void json_write_string(OutputStream * out, const char * str) { write_string(out, "null"); } else { - out->write(out, '"'); + write_stream(out, '"'); while (*str) json_write_char(out, *str++); - out->write(out, '"'); + write_stream(out, '"'); } } @@ -112,17 +112,17 @@ void json_write_string_len(OutputStream * out, const char * str, size_t len) { write_string(out, "null"); } else { - out->write(out, '"'); + write_stream(out, '"'); while (len > 0) { json_write_char(out, *str++); len--; } - out->write(out, '"'); + write_stream(out, '"'); } } static int readHex(InputStream * inp) { - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch >= '0' && ch <= '9') return ch - '0'; if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; @@ -139,7 +139,7 @@ static int readHexChar(InputStream * inp) { } static int read_esc_char(InputStream * inp) { - int ch = inp->read(inp); + int ch = read_stream(inp); switch (ch) { case '"': break; case '\\': break; @@ -157,17 +157,17 @@ static int read_esc_char(InputStream * inp) { int json_read_string(InputStream * inp, char * str, size_t size) { unsigned i = 0; - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == 'n') { - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); str[0] = 0; return -1; } if (ch != '"') exception(ERR_JSON_SYNTAX); for (;;) { - ch = inp->read(inp); + ch = read_stream(inp); if (ch == '"') break; if (ch == '\\') ch = read_esc_char(inp); if (i < size - 1) str[i] = (char)ch; @@ -181,16 +181,16 @@ int json_read_string(InputStream * inp, char * str, size_t size) { char * json_read_alloc_string(InputStream * inp) { char * str = NULL; unsigned buf_pos = 0; - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == 'n') { - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); return NULL; } if (ch != '"') exception(ERR_JSON_SYNTAX); for (;;) { - ch = inp->read(inp); + ch = read_stream(inp); if (ch == '"') break; if (ch == '\\') ch = read_esc_char(inp); if (buf_pos >= buf_size) realloc_buf(buf_pos); @@ -204,18 +204,18 @@ char * json_read_alloc_string(InputStream * inp) { } int json_read_boolean(InputStream * inp) { - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == 'f') { - if (inp->read(inp) != 'a') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 's') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'e') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'a') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 's') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'e') exception(ERR_JSON_SYNTAX); return 0; } if (ch == 't') { - if (inp->read(inp) != 'r') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'e') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'r') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'e') exception(ERR_JSON_SYNTAX); return 1; } exception(ERR_JSON_SYNTAX); @@ -225,17 +225,17 @@ int json_read_boolean(InputStream * inp) { long json_read_long(InputStream * inp) { long res = 0; int neg = 0; - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == '-') { neg = 1; - ch = inp->read(inp); + ch = read_stream(inp); } if (ch < '0' || ch > '9') exception(ERR_JSON_SYNTAX); res = ch - '0'; while (1) { ch = inp->peek(inp); if (ch < '0' || ch > '9') break; - inp->read(inp); + read_stream(inp); res = res * 10 + (ch - '0'); } if (neg) return -res; @@ -245,17 +245,17 @@ long json_read_long(InputStream * inp) { unsigned long json_read_ulong(InputStream * inp) { unsigned long res = 0; int neg = 0; - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == '-') { neg = 1; - ch = inp->read(inp); + ch = read_stream(inp); } if (ch < '0' || ch > '9') exception(ERR_JSON_SYNTAX); res = ch - '0'; while (1) { ch = inp->peek(inp); if (ch < '0' || ch > '9') break; - inp->read(inp); + read_stream(inp); res = res * 10 + (ch - '0'); } if (neg) return ~res + 1; @@ -265,17 +265,17 @@ unsigned long json_read_ulong(InputStream * inp) { int64 json_read_int64(InputStream * inp) { int64 res = 0; int neg = 0; - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == '-') { neg = 1; - ch = inp->read(inp); + ch = read_stream(inp); } if (ch < '0' || ch > '9') exception(ERR_JSON_SYNTAX); res = ch - '0'; while (1) { ch = inp->peek(inp); if (ch < '0' || ch > '9') break; - inp->read(inp); + read_stream(inp); res = res * 10 + (ch - '0'); } if (neg) return -res; @@ -283,25 +283,25 @@ int64 json_read_int64(InputStream * inp) { } int json_read_struct(InputStream * inp, struct_call_back call_back, void * arg) { - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == 'n') { - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); return 0; } if (ch == '{') { - ch = inp->read(inp); + ch = read_stream(inp); if (ch != '}') { for (;;) { int nm_len = 0; char nm[256]; if (ch != '"') exception(ERR_JSON_SYNTAX); for (;;) { - ch = inp->read(inp); + ch = read_stream(inp); if (ch == '"') break; if (ch == '\\') { - ch = inp->read(inp); + ch = read_stream(inp); switch (ch) { case '"': break; case '\\': break; @@ -321,13 +321,13 @@ int json_read_struct(InputStream * inp, struct_call_back call_back, void * arg) } } nm[nm_len] = 0; - ch = inp->read(inp); + ch = read_stream(inp); if (ch != ':') exception(ERR_JSON_SYNTAX); call_back(inp, nm, arg); - ch = inp->read(inp); + ch = read_stream(inp); if (ch == '}') break; if (ch != ',') exception(ERR_JSON_SYNTAX); - ch = inp->read(inp); + ch = read_stream(inp); } } return 1; @@ -337,12 +337,12 @@ int json_read_struct(InputStream * inp, struct_call_back call_back, void * arg) } char ** json_read_alloc_string_array(InputStream * inp, int * pos) { - int ch = inp->read(inp); + int ch = read_stream(inp); *pos = 0; if (ch == 'n') { - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); return NULL; } else if (ch != '[') { @@ -361,25 +361,25 @@ char ** json_read_alloc_string_array(InputStream * inp, int * pos) { char ** arr = NULL; if (inp->peek(inp) == ']') { - inp->read(inp); + read_stream(inp); } else { while (1) { - int ch = inp->read(inp); + int ch = read_stream(inp); int len = 0; if (len_pos >= len_buf_size) { len_buf_size = len_buf_size == 0 ? 0x100 : len_buf_size * 2; len_buf = (unsigned *)loc_realloc(len_buf, len_buf_size * sizeof(unsigned)); } if (ch == 'n') { - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); } else { if (ch != '"') exception(ERR_JSON_SYNTAX); for (;;) { - ch = inp->read(inp); + ch = read_stream(inp); if (ch == '"') break; if (ch == '\\') ch = read_esc_char(inp); if (buf_pos >= buf_size) realloc_buf(buf_pos); @@ -390,7 +390,7 @@ char ** json_read_alloc_string_array(InputStream * inp, int * pos) { if (buf_pos >= buf_size) realloc_buf(buf_pos); buf[buf_pos++] = 0; len_buf[len_pos++] = len; - ch = inp->read(inp); + ch = read_stream(inp); if (ch == ',') continue; if (ch == ']') break; exception(ERR_JSON_SYNTAX); @@ -414,21 +414,50 @@ char ** json_read_alloc_string_array(InputStream * inp, int * pos) { void json_read_binary_start(JsonReadBinaryState * state, InputStream * inp) { state->inp = inp; - if (inp->read(inp) != '"') exception(ERR_JSON_SYNTAX); + state->rem = 0; + if (read_stream(inp) != '"') exception(ERR_JSON_SYNTAX); } size_t json_read_binary_data(JsonReadBinaryState * state, char * buf, size_t len) { - return read_base64(state->inp, buf, len); + int res = 0; + while (len > 0) { + if (state->rem > 0) { + unsigned i = 0; + while (i < state->rem && i < len) *buf++ = state->buf[i++]; + len -= i; + res += i; + if (i < state->rem) { + int j = 0; + while (i < state->rem) state->buf[j++] = state->buf[i++]; + state->rem = j; + return res; + } + state->rem = 0; + } + if (len >= 3) { + int i = read_base64(state->inp, buf, len); + if (i == 0) break; + buf += i; + len -= i; + res += i; + } + else { + state->rem = read_base64(state->inp, state->buf, 3); + if (state->rem == 0) break; + } + } + return res; } void json_read_binary_end(JsonReadBinaryState * state) { - if (state->inp->read(state->inp) != '"') exception(ERR_JSON_SYNTAX); + if (state->rem != 0) exception(ERR_JSON_SYNTAX); + if (read_stream(state->inp) != '"') exception(ERR_JSON_SYNTAX); } void json_write_binary_start(JsonWriteBinaryState * state, OutputStream * out) { state->out = out; state->rem = 0; - state->out->write(state->out, '"'); + write_stream(state->out, '"'); } void json_write_binary_data(JsonWriteBinaryState * state, const char * str, size_t len) { @@ -463,23 +492,23 @@ void json_write_binary_end(JsonWriteBinaryState * state) { if ((rem = state->rem) > 0) { write_base64(state->out, state->buf, rem); } - state->out->write(state->out, '"'); + write_stream(state->out, '"'); } void json_skip_object(InputStream * inp) { - int ch = inp->read(inp); + int ch = read_stream(inp); if (ch == 'n') { - if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); - if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != 'l') exception(ERR_JSON_SYNTAX); return; } if (ch == '"') { for (;;) { - ch = inp->read(inp); + ch = read_stream(inp); if (ch == '"') break; if (ch == '\\') { - if (inp->read(inp) == 'u') readHexChar(inp); + if (read_stream(inp) == 'u') readHexChar(inp); } } return; @@ -488,19 +517,19 @@ void json_skip_object(InputStream * inp) { while (1) { ch = inp->peek(inp); if (ch < '0' || ch > '9') break; - inp->read(inp); + read_stream(inp); } return; } if (ch == '[') { if (inp->peek(inp) == ']') { - inp->read(inp); + read_stream(inp); } else { while (1) { int ch; json_skip_object(inp); - ch = inp->read(inp); + ch = read_stream(inp); if (ch == ',') continue; if (ch == ']') break; exception(ERR_JSON_SYNTAX); @@ -510,15 +539,15 @@ void json_skip_object(InputStream * inp) { } if (ch == '{') { if (inp->peek(inp) == '}') { - inp->read(inp); + read_stream(inp); } else { while (1) { int ch; json_skip_object(inp); - if (inp->read(inp) != ':') exception(ERR_JSON_SYNTAX); + if (read_stream(inp) != ':') exception(ERR_JSON_SYNTAX); json_skip_object(inp); - ch = inp->read(inp); + ch = read_stream(inp); if (ch == ',') continue; if (ch == '}') break; exception(ERR_JSON_SYNTAX); @@ -531,29 +560,29 @@ void json_skip_object(InputStream * inp) { void write_errno(OutputStream * out, int err) { char * msg = NULL; json_write_long(out, err); - out->write(out, 0); + write_stream(out, 0); if (err != 0) msg = errno_to_str(err); json_write_string(out, msg); - out->write(out, 0); + write_stream(out, 0); } void write_err_msg(OutputStream * out, int err, char * msg) { json_write_long(out, err); - out->write(out, 0); + write_stream(out, 0); if (err == 0) { write_string(out, "null"); } else { char * str = errno_to_str(err); - out->write(out, '"'); + write_stream(out, '"'); while (*str) json_write_char(out, *str++); if (msg != NULL) { - out->write(out, ':'); - out->write(out, ' '); + write_stream(out, ':'); + write_stream(out, ' '); while (*msg) json_write_char(out, *msg++); } - out->write(out, '"'); + write_stream(out, '"'); } - out->write(out, 0); + write_stream(out, 0); } diff --git a/json.h b/json.h index cdd41d4c..c9b5866c 100644 --- a/json.h +++ b/json.h @@ -60,6 +60,8 @@ extern void write_err_msg(OutputStream * out, int err, char * msg); typedef struct JsonReadBinaryState { /* Private members */ InputStream * inp; + unsigned rem; + char buf[3]; } JsonReadBinaryState; extern void json_read_binary_start(JsonReadBinaryState * state, InputStream * inp); @@ -69,7 +71,7 @@ extern void json_read_binary_end(JsonReadBinaryState * state); typedef struct JsonWriteBinaryState { /* Private members */ OutputStream * out; - int rem; + unsigned rem; char buf[3]; } JsonWriteBinaryState; diff --git a/registers.c b/registers.c index 730e2345..dc56b667 100644 --- a/registers.c +++ b/registers.c @@ -22,6 +22,7 @@ #include #include #include +#include "myalloc.h" #include "protocol.h" #include "context.h" #include "json.h" @@ -173,6 +174,10 @@ static int id2register(char * id, Context ** ctx, REG_INDEX ** idx) { } *ctx = id2ctx(id); *idx = regs_index + i; + if ((*ctx)->exited) { + errno = ERR_ALREADY_EXITED; + return -1; + } return 0; } @@ -186,10 +191,7 @@ static void command_get_context(char * token, Channel * c) { if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - id2register(id, &ctx, &idx); - - if (ctx == NULL) err = ERR_INV_CONTEXT; - else if (ctx->exited) err = ERR_ALREADY_EXITED; + if (id2register(id, &ctx, &idx) < 0) err = errno; write_stringz(&c->out, "R"); write_stringz(&c->out, token); @@ -240,6 +242,17 @@ static void command_get_children(char * token, Channel * c) { c->out.write(&c->out, MARKER_EOM); } +static void send_event_register_changed(Channel * c, char * id) { + write_stringz(&c->out, "E"); + write_stringz(&c->out, REGISTERS); + write_stringz(&c->out, "registerChanged"); + + json_write_string(&c->out, id); + c->out.write(&c->out, 0); + + c->out.write(&c->out, MARKER_EOM); +} + static void command_get(char * token, Channel * c) { int err = 0; char id[256]; @@ -250,10 +263,7 @@ static void command_get(char * token, Channel * c) { if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - id2register(id, &ctx, &idx); - - if (ctx == NULL || idx == NULL) err = ERR_INV_CONTEXT; - else if (ctx->exited) err = ERR_ALREADY_EXITED; + if (id2register(id, &ctx, &idx) < 0) err = errno; else if (!ctx->intercepted) err = ERR_IS_RUNNING; write_stringz(&c->out, "R"); @@ -275,24 +285,12 @@ static void command_get(char * token, Channel * c) { c->out.write(&c->out, MARKER_EOM); } -static void send_event_register_changed(Channel * c, char * id) { - write_stringz(&c->out, "E"); - write_stringz(&c->out, REGISTERS); - write_stringz(&c->out, "registerChanged"); - - json_write_string(&c->out, id); - c->out.write(&c->out, 0); - - c->out.write(&c->out, MARKER_EOM); -} - static void command_set(char * token, Channel * c) { int err = 0; char id[256]; char val[256]; int val_len = 0; JsonReadBinaryState state; - char * ptr = NULL; Context * ctx = NULL; REG_INDEX * idx = NULL; @@ -308,10 +306,7 @@ static void command_set(char * token, Channel * c) { if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); - id2register(id, &ctx, &idx); - - if (ctx == NULL || idx == NULL) err = ERR_INV_CONTEXT; - else if (ctx->exited) err = ERR_ALREADY_EXITED; + if (id2register(id, &ctx, &idx) < 0) err = errno; else if (!ctx->intercepted) err = ERR_IS_RUNNING; if (err == 0) { @@ -333,11 +328,132 @@ static void command_set(char * token, Channel * c) { c->out.write(&c->out, MARKER_EOM); } +struct Location { + char id[256]; + Context * ctx; + REG_INDEX * idx; + unsigned offs; + unsigned size; +}; +typedef struct Location Location; + +static Location * buf = NULL; +static int buf_pos = 0; +static int buf_len = 0; + +static int read_location_list(InputStream * inp) { + int err = 0; + int ch = inp->read(inp); + + buf_pos = 0; + if (ch == 'n') { + if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + } + else if (ch != '[') { + exception(ERR_PROTOCOL); + } + else { + if (inp->peek(inp) == ']') { + inp->read(inp); + } + else { + while (1) { + int ch = inp->read(inp); + if (ch == 'n') { + if (inp->read(inp) != 'u') exception(ERR_JSON_SYNTAX); + if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + if (inp->read(inp) != 'l') exception(ERR_JSON_SYNTAX); + } + else { + Location * loc = NULL; + if (ch != '[') exception(ERR_JSON_SYNTAX); + if (buf_pos >= buf_len) { + buf_len = buf_len == 0 ? 0x10 : buf_len * 2; + buf = (Location *)loc_realloc(buf, buf_len * sizeof(Location)); + } + loc = buf + buf_pos++; + json_read_string(inp, loc->id, sizeof(loc->id)); + if (inp->read(inp) != ',') exception(ERR_JSON_SYNTAX); + loc->offs = (unsigned)json_read_ulong(inp); + if (inp->read(inp) != ',') exception(ERR_JSON_SYNTAX); + loc->size = (unsigned)json_read_ulong(inp); + if (inp->read(inp) != ']') exception(ERR_JSON_SYNTAX); + if (id2register(loc->id, &loc->ctx, &loc->idx) < 0) err = errno; + else if (!loc->ctx->intercepted) err = ERR_IS_RUNNING; + } + ch = inp->read(inp); + if (ch == ',') continue; + if (ch == ']') break; + exception(ERR_JSON_SYNTAX); + } + } + } + return err; +} + +static void command_getm(char * token, Channel * c) { + int err = read_location_list(&c->inp); + if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + + write_stringz(&c->out, "R"); + write_stringz(&c->out, token); + write_errno(&c->out, err); + if (err == 0) { + int i = 0; + JsonWriteBinaryState state; + json_write_binary_start(&state, &c->out); + for (i = 0; i < buf_pos; i++) { + Location * l = buf + i; + char * data = (char *)&l->ctx->regs + l->idx->regOff + l->offs; + json_write_binary_data(&state, data, l->size); + } + json_write_binary_end(&state); + c->out.write(&c->out, 0); + } + else { + write_stringz(&c->out, "null"); + } + c->out.write(&c->out, MARKER_EOM); +} + +static void command_setm(char * token, Channel * c) { + int i = 0; + char tmp[256]; + JsonReadBinaryState state; + int err = read_location_list(&c->inp); + if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + json_read_binary_start(&state, &c->inp); + for (i = 0; i < buf_pos; i++) { + unsigned rd_done = 0; + Location * l = buf + i; + char * data = (char *)&l->ctx->regs + l->idx->regOff + l->offs; + while (rd_done < l->size) { + int rd = json_read_binary_data(&state, err ? tmp : (data + rd_done), l->size - rd_done); + if (rd == 0) break; + rd_done += rd; + } + if (!err) send_event_register_changed(c, l->id); + } + json_read_binary_end(&state); + if (c->inp.read(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + if (c->inp.read(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); + + write_stringz(&c->out, "R"); + write_stringz(&c->out, token); + write_errno(&c->out, err); + c->out.write(&c->out, MARKER_EOM); +} + void ini_registers_service(Protocol * proto) { add_command_handler(proto, REGISTERS, "getContext", command_get_context); add_command_handler(proto, REGISTERS, "getChildren", command_get_children); add_command_handler(proto, REGISTERS, "get", command_get); add_command_handler(proto, REGISTERS, "set", command_set); + add_command_handler(proto, REGISTERS, "getm", command_getm); + add_command_handler(proto, REGISTERS, "setm", command_setm); } #endif diff --git a/streams.h b/streams.h index 3c36f343..7b511436 100644 --- a/streams.h +++ b/streams.h @@ -43,6 +43,8 @@ struct InputStream { #define read_stream(inp) (((inp)->cur < (inp)->end) ? *(inp)->cur++ : (inp)->read((inp))) #define peek_stream(inp) (((inp)->cur < (inp)->end) ? *(inp)->cur : (inp)->peek((inp))) +#define write_stream(out, b) (out)->write((out), (b)) + extern int (read_stream)(InputStream * inp); extern int (peek_stream)(InputStream * inp); extern void write_string(OutputStream * out, const char * str); -- cgit v1.2.3