X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Frnetclient.git;a=blobdiff_plain;f=rnet_message.c;h=95d8b41fc225de6e302f3f963d9851bac85a0372;hp=b9ee6d33052bc3e52cbed707887c82fcee3a7ef5;hb=147fc799f60a5799bd569e6da5542c4b7df132b7;hpb=70129a0fd2b6af1b0bdac75e3ab2b8d12c724b9c diff --git a/rnet_message.c b/rnet_message.c index b9ee6d3..95d8b41 100644 --- a/rnet_message.c +++ b/rnet_message.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Thadeu Lima de Souza Cascardo + * Copyright (C) 2014 Alexandre Oliva * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +28,7 @@ #define MAX(a,b) (a >= b) ? a : b #endif -static int rnet_message_expand(struct rnet_message **message, size_t len) +int rnet_message_expand(struct rnet_message **message, size_t len) { struct rnet_message *msg = *message; struct rnet_message *nmsg; @@ -58,13 +59,25 @@ void rnet_message_del(struct rnet_message *message) free(message); } -static int add_field(struct rnet_message *msg, char *key, int klen, char *val, int vlen) +int rnet_message_strip(struct rnet_message *message, size_t len) +{ + if (len > message->len) + return -1; + message->len -= len; + memmove(message->buffer, message->buffer + len, message->len); + return 0; +} + +static int add_field(struct rnet_message **message, char *key, int klen, + char *val, int vlen) { int n = 0; char *buffer; - if ((msg->alen - msg->len) < (klen + vlen + 3)) { - if (rnet_message_expand(&msg, MAX(msg->len, klen + vlen + 3))) + struct rnet_message *msg = *message; + if ((msg->alen - msg->len) < (size_t) (klen + vlen + 3)) { + if (rnet_message_expand(message, MAX(msg->len, (size_t) (klen + vlen + 3)))) return -ENOMEM; + msg = *message; } buffer = msg->buffer + msg->len; if (klen > 0x7f || klen < 0) @@ -95,24 +108,69 @@ static int add_field(struct rnet_message *msg, char *key, int klen, char *val, i return n; } -int rnet_message_add_u32(struct rnet_message *msg, char *key, uint32_t val) +int rnet_message_add_u32(struct rnet_message **msg, char *key, uint32_t val) { uint32_t nval = htonl(val); return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val)); } -int rnet_message_add_ascii(struct rnet_message *msg, char *key, char *val) +int rnet_message_add_ascii(struct rnet_message **msg, char *key, char *val) { return add_field(msg, key, strlen(key), val, strlen(val)); } -int rnet_message_add_u8(struct rnet_message *msg, char *key, uint8_t val) +int rnet_message_add_u8(struct rnet_message **msg, char *key, uint8_t val) { return add_field(msg, key, strlen(key), (char *) &val, sizeof(val)); } -int rnet_message_add_u16(struct rnet_message *msg, char *key, uint16_t val) +int rnet_message_add_u16(struct rnet_message **msg, char *key, uint16_t val) { uint16_t nval = htons(val); return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val)); } + +int rnet_message_add_u64(struct rnet_message **msg, char *key, uint64_t val) +{ + uint64_t nval = htobe64(val); + return add_field(msg, key, strlen(key), (char *) &nval, sizeof(val)); +} + +int rnet_message_add_buffer(struct rnet_message **msg, char *key, + char *buffer, size_t len) +{ + return add_field(msg, key, strlen(key), buffer, len); +} + +int rnet_message_parse(struct rnet_message *msg, char *skey, + char** value, int *vlen) +{ + char * buffer = msg->buffer; + size_t len = msg->len; + unsigned int i = 0; + unsigned int j; + int b; + char *key; + unsigned int klen; + /* skip first byte */ + i++; + while (i < len) { + j = (unsigned char)buffer[i]; + b = j & 0x80; + j = j & 0x7f; + i++; + key = buffer + i; + klen = j; + i += j; + j = (unsigned char)buffer[i]; + i++; + if (b) + j = j << 8 | (unsigned char)buffer[i++]; + *value = buffer + i; + *vlen = j; + i += j; + if (strlen(skey) == klen && !strncasecmp(key, skey, klen)) + return 0; + } + return 1; +}