From 60da1bc445ec33c83d9c39f7ce2fb73abc8f2443 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 24 Jan 2013 09:30:15 -0500 Subject: [PATCH] mass deployment of the new "str" object - does this thing still work? --- daemon/Makefile | 2 +- daemon/bencode.h | 25 +++++++++ daemon/call.c | 65 ++++++++++++----------- daemon/call.h | 13 ++--- daemon/control.c | 4 +- daemon/control_ng.c | 67 ++++++++++++------------ daemon/control_udp.c | 31 +++++------ daemon/cookie_cache.c | 19 +++---- daemon/cookie_cache.h | 7 +-- daemon/sdp.c | 8 +-- daemon/sdp.h | 3 +- daemon/str.c | 28 ++++++++++ daemon/str.h | 119 ++++++++++++++++++++++++++++++++++++++++++ daemon/streambuf.h | 5 ++ daemon/udp_listener.c | 7 ++- daemon/udp_listener.h | 3 +- 16 files changed, 296 insertions(+), 110 deletions(-) create mode 100644 daemon/str.c diff --git a/daemon/Makefile b/daemon/Makefile index 7d1c13088..e2bed1b3f 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -26,7 +26,7 @@ CPPFLAGS+= `dpkg-buildflags --get CPPFLAGS` LDFLAGS+= `dpkg-buildflags --get LDFLAGS` SRCS= main.c kernel.c poller.c aux.c control.c streambuf.c call.c control_udp.c redis.c \ - bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c + bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c OBJS= $(SRCS:.c=.o) diff --git a/daemon/bencode.h b/daemon/bencode.h index b49780b8f..c430e7ceb 100644 --- a/daemon/bencode.h +++ b/daemon/bencode.h @@ -5,12 +5,15 @@ #include #if defined(PKG_MALLOC) || defined(pkg_malloc) +/* kamailio */ # include "../../mem/mem.h" # ifndef BENCODE_MALLOC # define BENCODE_MALLOC pkg_malloc # define BENCODE_FREE pkg_free # endif #else +/* mediaproxy-ng */ +# include "str.h" # ifndef BENCODE_MALLOC # define BENCODE_MALLOC malloc # define BENCODE_FREE free @@ -135,6 +138,9 @@ struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, u * bencode_buffer_t object is destroyed. */ char *bencode_collapse(bencode_item_t *root, int *len); +/* Identical to bencode_collapse() but fills in a "str" object. Returns "out". */ +static str *bencode_collapse_str(bencode_item_t *root, str *out); + /* Identical to bencode_collapse(), but the memory for the returned string is not allocated from * a bencode_buffer_t object, but instead using the function defined as BENCODE_MALLOC (normally * malloc() or pkg_malloc()), similar to strdup(). Using this function, the bencode_buffer_t @@ -185,6 +191,9 @@ bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len); * "expect". */ static inline bencode_item_t *bencode_decode_expect(bencode_buffer_t *buf, const char *s, int len, bencode_type_t expect); +/* Identical to bencode_decode_expect() but takes a "str" argument. */ +static inline bencode_item_t *bencode_decode_expect_str(bencode_buffer_t *buf, const str *s, bencode_type_t expect); + /* Searches the given dictionary object for the given key and returns the respective value. Returns * NULL if the given object isn't a dictionary or if the key doesn't exist. The key must be a * null-terminated string. */ @@ -199,6 +208,9 @@ bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key * valid pointer. The returned string will be valid until dict's bencode_buffer_t object is destroyed. */ static inline char *bencode_dictionary_get_string(bencode_item_t *dict, const char *key, int *len); +/* Identical to bencode_dictionary_get_string() but fills in a "str" struct. Returns str->s. */ +static inline char *bencode_dictionary_get_str(bencode_item_t *dict, const char *key, str *str); + /* Identical to bencode_dictionary_get() but returns the string in a newly allocated buffer (using the * BENCODE_MALLOC function), which remains valid even after bencode_buffer_t is destroyed. */ static inline char *bencode_dictionary_get_string_dup(bencode_item_t *dict, const char *key, int *len); @@ -252,6 +264,11 @@ static inline char *bencode_dictionary_get_string(bencode_item_t *dict, const ch return val->iov[1].iov_base; } +static inline char *bencode_dictionary_get_str(bencode_item_t *dict, const char *key, str *str) { + str->s = bencode_dictionary_get_string(dict, key, &str->len); + return str->s; +} + static inline char *bencode_dictionary_get_string_dup(bencode_item_t *dict, const char *key, int *len) { const char *s; char *ret; @@ -281,6 +298,10 @@ static inline bencode_item_t *bencode_decode_expect(bencode_buffer_t *buf, const return ret; } +static inline bencode_item_t *bencode_decode_expect_str(bencode_buffer_t *buf, const str *s, bencode_type_t expect) { + return bencode_decode_expect(buf, s->s, s->len, expect); +} + static inline bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict, const char *key, bencode_type_t expect) { bencode_item_t *ret; ret = bencode_dictionary_get(dict, key); @@ -288,5 +309,9 @@ static inline bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict return NULL; return ret; } +static inline str *bencode_collapse_str(bencode_item_t *root, str *out) { + out->s = bencode_collapse(root, &out->len); + return out; +} #endif diff --git a/daemon/call.c b/daemon/call.c index d72a56575..13c59728f 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -24,6 +24,7 @@ #include "xt_MEDIAPROXY.h" #include "bencode.h" #include "sdp.h" +#include "str.h" @@ -38,8 +39,6 @@ #define LOG_PARAMS_C(c) (c)->callid #define LOG_PARAMS_CI(c) (c)->callid, log_info -#define xasprintf(a...) if (asprintf(a) == -1) abort() - static __thread const char *log_info; @@ -1451,7 +1450,7 @@ static void call_destroy(struct call *c) { -static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const char *prefix, int format) { +static str *streams_print(GQueue *s, unsigned int num, unsigned int off, const char *prefix, int format) { GString *o; int i; GList *l; @@ -1462,7 +1461,7 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const int other_off; char af; - o = g_string_new(""); + o = g_string_new_str(); if (prefix) g_string_append_printf(o, "%s ", prefix); @@ -1512,7 +1511,7 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const out: g_string_append(o, "\n"); - return g_string_free(o, FALSE); + return g_string_free_str(o); } static gboolean g_str_equal0(gconstpointer a, gconstpointer b) { @@ -1642,12 +1641,12 @@ fail: return -1; } -char *call_update_udp(const char **out, struct callmaster *m) { +str *call_update_udp(const char **out, struct callmaster *m) { struct call *c; GQueue q = G_QUEUE_INIT; struct stream st; int num; - char *ret; + str *ret; c = call_get_or_create(out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH], m); log_info = out[RE_UDP_UL_VIABRANCH]; @@ -1666,7 +1665,7 @@ char *call_update_udp(const char **out, struct callmaster *m) { if (redis_update) redis_update(c, m->conf.redis); - mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); + mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %.*s", LOG_PARAMS_CI(c), STR_FMT(ret)); log_info = NULL; obj_put(c); return ret; @@ -1674,18 +1673,18 @@ char *call_update_udp(const char **out, struct callmaster *m) { fail: mutex_unlock(&c->lock); mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); - xasprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); + ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); log_info = NULL; obj_put(c); return ret; } -char *call_lookup_udp(const char **out, struct callmaster *m) { +str *call_lookup_udp(const char **out, struct callmaster *m) { struct call *c; GQueue q = G_QUEUE_INIT; struct stream st; int num; - char *ret; + str *ret; const char *branch; rwlock_lock_r(&m->hashlock); @@ -1696,7 +1695,7 @@ char *call_lookup_udp(const char **out, struct callmaster *m) { rwlock_unlock_r(&m->hashlock); mylog(LOG_WARNING, LOG_PREFIX_CI "Got UDP LOOKUP for unknown call-id or unknown via-branch", out[RE_UDP_UL_CALLID], out[RE_UDP_UL_VIABRANCH]); - xasprintf(&ret, "%s 0 " IPF "\n", out[RE_UDP_COOKIE], IPP(m->conf.ipv4)); + ret = str_sprintf("%s 0 " IPF "\n", out[RE_UDP_COOKIE], IPP(m->conf.ipv4)); return ret; } @@ -1724,7 +1723,7 @@ char *call_lookup_udp(const char **out, struct callmaster *m) { if (redis_update) redis_update(c, m->conf.redis); - mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); + mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %.*s", LOG_PARAMS_CI(c), STR_FMT(ret)); log_info = NULL; obj_put(c); return ret; @@ -1732,17 +1731,17 @@ char *call_lookup_udp(const char **out, struct callmaster *m) { fail: mutex_unlock(&c->lock); mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", out[RE_UDP_UL_ADDR4], out[RE_UDP_UL_ADDR6], out[RE_UDP_UL_PORT]); - xasprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); + ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); log_info = NULL; obj_put(c); return ret; } -char *call_request(const char **out, struct callmaster *m) { +str *call_request(const char **out, struct callmaster *m) { struct call *c; GQueue s = G_QUEUE_INIT; int num; - char *ret; + str *ret; c = call_get_or_create(out[RE_TCP_RL_CALLID], NULL, m); @@ -1758,16 +1757,16 @@ char *call_request(const char **out, struct callmaster *m) { if (redis_update) redis_update(c, m->conf.redis); - mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); + mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %.*s", LOG_PARAMS_CI(c), STR_FMT(ret)); obj_put(c); return ret; } -char *call_lookup(const char **out, struct callmaster *m) { +str *call_lookup(const char **out, struct callmaster *m) { struct call *c; GQueue s = G_QUEUE_INIT; int num; - char *ret; + str *ret; rwlock_lock_r(&m->hashlock); c = g_hash_table_lookup(m->callhash, out[RE_TCP_RL_CALLID]); @@ -1792,14 +1791,14 @@ char *call_lookup(const char **out, struct callmaster *m) { if (redis_update) redis_update(c, m->conf.redis); - mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %s", LOG_PARAMS_CI(c), ret); + mylog(LOG_INFO, LOG_PREFIX_CI "Returning to SIP proxy: %.*s", LOG_PARAMS_CI(c), STR_FMT(ret)); obj_put(c); return ret; } -char *call_delete_udp(const char **out, struct callmaster *m) { +str *call_delete_udp(const char **out, struct callmaster *m) { struct call *c; - char *ret; + str *ret; struct callstream *cs; GList *l; int i; @@ -1875,13 +1874,13 @@ tag_match: success_unlock: mutex_unlock(&c->lock); success: - xasprintf(&ret, "%s 0\n", out[RE_UDP_COOKIE]); + ret = str_sprintf("%s 0\n", out[RE_UDP_COOKIE]); goto out; err: if (c) mutex_unlock(&c->lock); - xasprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); + ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); goto out; out: @@ -1891,9 +1890,9 @@ out: return ret; } -char *call_query_udp(const char **out, struct callmaster *m) { +str *call_query_udp(const char **out, struct callmaster *m) { struct call *c; - char *ret; + str *ret; struct callstream *cs; long long unsigned int pcs[4] = {0,0,0,0}; time_t newest = 0; @@ -1954,7 +1953,7 @@ tag_match: mutex_unlock(&c->lock); - xasprintf(&ret, "%s %lld %llu %llu %llu %llu\n", out[RE_UDP_COOKIE], + ret = str_sprintf("%s %lld %llu %llu %llu %llu\n", out[RE_UDP_COOKIE], (long long int) m->conf.silent_timeout - (poller_now - newest), pcs[0], pcs[1], pcs[2], pcs[3]); goto out; @@ -1962,7 +1961,7 @@ tag_match: err: if (c) mutex_unlock(&c->lock); - xasprintf(&ret, "%s E8\n", out[RE_UDP_COOKIE]); + ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); goto out; out: @@ -2114,16 +2113,16 @@ struct callstream *callstream_new(struct call *ca, int num) { const char *call_offer(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) { - char *sdp, *errstr; - int sdp_len; + str sdp; + char *errstr; GQueue parsed = G_QUEUE_INIT; GQueue streams = G_QUEUE_INIT; - sdp = bencode_dictionary_get_string(input, "sdp", &sdp_len); - if (!sdp) + bencode_dictionary_get_str(input, "sdp", &sdp); + if (!sdp.s) return "No SDP body in message"; - if (sdp_parse(sdp, sdp_len, &parsed)) + if (sdp_parse(&sdp, &parsed)) return "Failed to parse SDP"; errstr = "Incomplete SDP specification"; diff --git a/daemon/call.h b/daemon/call.h index 1dce0de3c..6a7a1eb86 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -14,6 +14,7 @@ #include "obj.h" #include "aux.h" #include "bencode.h" +#include "str.h" struct poller; struct control_stream; @@ -123,13 +124,13 @@ struct callmaster *callmaster_new(struct poller *); void callmaster_config(struct callmaster *m, struct callmaster_config *c); -char *call_request(const char **, struct callmaster *); -char *call_update_udp(const char **, struct callmaster *); -char *call_lookup(const char **, struct callmaster *); -char *call_lookup_udp(const char **, struct callmaster *); +str *call_request(const char **, struct callmaster *); +str *call_update_udp(const char **, struct callmaster *); +str *call_lookup(const char **, struct callmaster *); +str *call_lookup_udp(const char **, struct callmaster *); void call_delete(const char **, struct callmaster *); -char *call_delete_udp(const char **, struct callmaster *); -char *call_query_udp(const char **, struct callmaster *); +str *call_delete_udp(const char **, struct callmaster *); +str *call_query_udp(const char **, struct callmaster *); void calls_status(struct callmaster *, struct control_stream *); diff --git a/daemon/control.c b/daemon/control.c index e18108094..4a728dfa9 100644 --- a/daemon/control.c +++ b/daemon/control.c @@ -100,7 +100,7 @@ static int control_stream_parse(struct control_stream *s, char *line) { int ret; const char **out; struct control *c = s->control; - char *output = NULL; + str *output = NULL; ret = pcre_exec(c->parse_re, c->parse_ree, line, strlen(line), 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { @@ -130,7 +130,7 @@ static int control_stream_parse(struct control_stream *s, char *line) { if (output) { mutex_lock(&s->lock); - streambuf_write(s->outbuf, output, strlen(output)); + streambuf_write_str(s->outbuf, output); mutex_unlock(&s->lock); free(output); } diff --git a/daemon/control_ng.c b/daemon/control_ng.c index 26dffdd8f..82c1d5dc2 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -7,62 +7,59 @@ #include "call.h" -static void control_ng_incoming(struct obj *obj, char *buf, int buf_len, struct sockaddr_in6 *sin, char *addr) { +static void control_ng_incoming(struct obj *obj, str *buf, struct sockaddr_in6 *sin, char *addr) { struct control_ng *c = (void *) obj; - char *data; bencode_buffer_t bencbuf; bencode_item_t *dict, *resp; - char *reply; - const char *cmd, *errstr, *cookie; - int cmd_len, cookie_len, data_len, reply_len; + str cmd, cookie, data, reply, *to_send; + const char *errstr; struct msghdr mh; struct iovec iov[3]; - data = memchr(buf, ' ', buf_len); - if (!data || data == buf) { - mylog(LOG_WARNING, "Received invalid data on NG port (no cookie) from %s: %.*s", addr, buf_len, buf); + str_chr_str(&data, buf, ' '); + if (!data.s || data.s == buf->s) { + mylog(LOG_WARNING, "Received invalid data on NG port (no cookie) from %s: %.*s", addr, STR_FMT(buf)); return; } bencode_buffer_init(&bencbuf); resp = bencode_dictionary(&bencbuf); - cookie = buf; - cookie_len = data - buf; - *data++ = '\0'; - data_len = buf_len - cookie_len - 1; + cookie = *buf; + cookie.len = data.s - buf->s; + *data.s++ = '\0'; + data.len--; errstr = "Invalid data (no payload)"; - if (data_len <= 0) + if (data.len <= 0) goto err_send; - reply = cookie_cache_lookup(&c->cookie_cache, cookie); - if (reply) { + to_send = cookie_cache_lookup(&c->cookie_cache, &cookie); + if (to_send) { mylog(LOG_INFO, "Detected command from %s as a duplicate", addr); - reply_len = strlen(reply); /* XXX fails for embedded nulls */ resp = NULL; goto send_only; } - dict = bencode_decode_expect(&bencbuf, data, data_len, BENCODE_DICTIONARY); + dict = bencode_decode_expect_str(&bencbuf, &data, BENCODE_DICTIONARY); errstr = "Could not decode dictionary"; if (!dict) goto err_send; - cmd = bencode_dictionary_get_string(dict, "command", &cmd_len); + bencode_dictionary_get_str(dict, "command", &cmd); errstr = "Dictionary contains no key \"command\""; - if (!cmd) + if (!cmd.s) goto err_send; - mylog(LOG_INFO, "Got valid command from %s: %.*s [%.*s]", addr, cmd_len, cmd, data_len, data); + mylog(LOG_INFO, "Got valid command from %s: %.*s [%.*s]", addr, STR_FMT(&cmd), STR_FMT(&data)); errstr = NULL; - if (!strmemcmp(cmd, cmd_len, "ping")) + if (!str_cmp(&cmd, "ping")) bencode_dictionary_add_string(resp, "result", "pong"); - else if (!strmemcmp(cmd, cmd_len, "offer")) { + else if (!str_cmp(&cmd, "offer")) { errstr = call_offer(dict, c->callmaster, resp); } - else if (!strmemcmp(cmd, cmd_len, "answer")) { + else if (!str_cmp(&cmd, "answer")) { errstr = call_answer(dict, c->callmaster, resp); } else @@ -71,16 +68,17 @@ static void control_ng_incoming(struct obj *obj, char *buf, int buf_len, struct if (errstr) goto err_send; - goto send_out; + goto send_resp; err_send: - mylog(LOG_WARNING, "Protocol error in packet from %s: %s [%.*s]", addr, errstr, data_len, data); + mylog(LOG_WARNING, "Protocol error in packet from %s: %s [%.*s]", addr, errstr, STR_FMT(&data)); bencode_dictionary_add_string(resp, "result", "error"); bencode_dictionary_add_string(resp, "error-reason", errstr); - goto send_out; + goto send_resp; -send_out: - reply = bencode_collapse(resp, &reply_len); +send_resp: + bencode_collapse_str(resp, &reply); + to_send = &reply; send_only: ZERO(mh); @@ -89,21 +87,22 @@ send_only: mh.msg_iov = iov; mh.msg_iovlen = 3; - iov[0].iov_base = (void *) cookie; - iov[0].iov_len = cookie_len; + iov[0].iov_base = cookie.s; + iov[0].iov_len = cookie.len; iov[1].iov_base = " "; iov[1].iov_len = 1; - iov[2].iov_base = reply; - iov[2].iov_len = reply_len; + iov[2].iov_base = to_send->s; + iov[2].iov_len = to_send->len; sendmsg(c->udp_listener.fd, &mh, 0); if (resp) - cookie_cache_insert(&c->cookie_cache, cookie, reply, reply_len); + cookie_cache_insert(&c->cookie_cache, &cookie, &reply); + else + free(to_send); goto out; - cookie_cache_remove(&c->cookie_cache, cookie); out: bencode_buffer_free(&bencbuf); } diff --git a/daemon/control_udp.c b/daemon/control_udp.c index 2107a5b36..9a3026f14 100644 --- a/daemon/control_udp.c +++ b/daemon/control_udp.c @@ -17,26 +17,26 @@ #include "udp_listener.h" -static void control_udp_incoming(struct obj *obj, char *buf, int len, struct sockaddr_in6 *sin, char *addr) { +static void control_udp_incoming(struct obj *obj, str *buf, struct sockaddr_in6 *sin, char *addr) { struct control_udp *u = (void *) obj; int ret; int ovec[100]; const char **out; - char *reply; struct msghdr mh; struct iovec iov[10]; + str cookie, *reply; - ret = pcre_exec(u->parse_re, u->parse_ree, buf, len, 0, 0, ovec, G_N_ELEMENTS(ovec)); + ret = pcre_exec(u->parse_re, u->parse_ree, buf->s, buf->len, 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { - ret = pcre_exec(u->fallback_re, NULL, buf, len, 0, 0, ovec, G_N_ELEMENTS(ovec)); + ret = pcre_exec(u->fallback_re, NULL, buf->s, buf->len, 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { - mylog(LOG_WARNING, "Unable to parse command line from udp:%s: %s", addr, buf); + mylog(LOG_WARNING, "Unable to parse command line from udp:%s: %.*s", addr, STR_FMT(buf)); return; } - mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from %s, using fallback RE", buf, addr); + mylog(LOG_WARNING, "Failed to properly parse UDP command line '%.*s' from %s, using fallback RE", STR_FMT(buf), addr); - pcre_get_substring_list(buf, ovec, ret, &out); + pcre_get_substring_list(buf->s, ovec, ret, &out); ZERO(mh); mh.msg_name = sin; @@ -67,14 +67,16 @@ static void control_udp_incoming(struct obj *obj, char *buf, int len, struct soc return; } - mylog(LOG_INFO, "Got valid command from udp:%s: %s", addr, buf); + mylog(LOG_INFO, "Got valid command from udp:%s: %.*s", addr, STR_FMT(buf)); - pcre_get_substring_list(buf, ovec, ret, &out); + pcre_get_substring_list(buf->s, ovec, ret, &out); - reply = cookie_cache_lookup(&u->cookie_cache, out[RE_UDP_COOKIE]); + str_init(&cookie, (void *) out[RE_UDP_COOKIE]); + reply = cookie_cache_lookup(&u->cookie_cache, &cookie); if (reply) { mylog(LOG_INFO, "Detected command from udp:%s as a duplicate", addr); - sendto(u->udp_listener.fd, reply, strlen(reply), 0, (struct sockaddr *) sin, sizeof(*sin)); + sendto(u->udp_listener.fd, reply->s, reply->len, 0, (struct sockaddr *) sin, sizeof(*sin)); + free(reply); goto out; } @@ -119,13 +121,12 @@ static void control_udp_incoming(struct obj *obj, char *buf, int len, struct soc } if (reply) { - len = strlen(reply); - sendto(u->udp_listener.fd, reply, len, 0, (struct sockaddr *) sin, sizeof(*sin)); - cookie_cache_insert(&u->cookie_cache, out[RE_UDP_COOKIE], reply, len); + sendto(u->udp_listener.fd, reply->s, reply->len, 0, (struct sockaddr *) sin, sizeof(*sin)); + cookie_cache_insert(&u->cookie_cache, &cookie, reply); free(reply); } else - cookie_cache_remove(&u->cookie_cache, out[RE_UDP_COOKIE]); + cookie_cache_remove(&u->cookie_cache, &cookie); out: pcre_free(out); diff --git a/daemon/cookie_cache.c b/daemon/cookie_cache.c index 3d5f3da40..49f13b909 100644 --- a/daemon/cookie_cache.c +++ b/daemon/cookie_cache.c @@ -3,11 +3,12 @@ #include "cookie_cache.h" #include "aux.h" #include "poller.h" +#include "str.h" static const char *cookie_in_use = "MAGIC"; static inline void cookie_cache_state_init(struct cookie_cache_state *s) { - s->cookies = g_hash_table_new(g_str_hash, g_str_equal); + s->cookies = g_hash_table_new(str_hash, str_equal); s->chunks = g_string_chunk_new(4 * 1024); } @@ -36,24 +37,24 @@ static void __cookie_cache_check_swap(struct cookie_cache *c) { } } -char *cookie_cache_lookup(struct cookie_cache *c, const char *s) { - char *ret; +str *cookie_cache_lookup(struct cookie_cache *c, const str *s) { + str *ret; mutex_lock(&c->lock); __cookie_cache_check_swap(c); restart: - /* XXX better hashing */ ret = g_hash_table_lookup(c->current.cookies, s); if (!ret) ret = g_hash_table_lookup(c->old.cookies, s); if (ret) { - if (ret == cookie_in_use) { + if (ret == (void *) cookie_in_use) { /* another thread is working on this right now */ cond_wait(&c->cond, &c->lock); goto restart; } + ret = str_dup(ret); mutex_unlock(&c->lock); return ret; } @@ -62,16 +63,16 @@ restart: return NULL; } -void cookie_cache_insert(struct cookie_cache *c, const char *s, const char *r, int len) { +void cookie_cache_insert(struct cookie_cache *c, const str *s, const str *r) { mutex_lock(&c->lock); - g_hash_table_replace(c->current.cookies, g_string_chunk_insert(c->current.chunks, s), - g_string_chunk_insert_len(c->current.chunks, r, (len >= 0) ? len : strlen(r))); + g_hash_table_replace(c->current.cookies, str_chunk_insert(c->current.chunks, s), + str_chunk_insert(c->current.chunks, r)); g_hash_table_remove(c->old.cookies, s); cond_broadcast(&c->cond); mutex_unlock(&c->lock); } -void cookie_cache_remove(struct cookie_cache *c, const char *s) { +void cookie_cache_remove(struct cookie_cache *c, const str *s) { mutex_lock(&c->lock); g_hash_table_remove(c->current.cookies, s); g_hash_table_remove(c->old.cookies, s); diff --git a/daemon/cookie_cache.h b/daemon/cookie_cache.h index aa1b8d902..05e2c22ab 100644 --- a/daemon/cookie_cache.h +++ b/daemon/cookie_cache.h @@ -4,6 +4,7 @@ #include #include #include "aux.h" +#include "str.h" struct cookie_cache_state { GHashTable *cookies; @@ -18,8 +19,8 @@ struct cookie_cache { }; void cookie_cache_init(struct cookie_cache *); -char *cookie_cache_lookup(struct cookie_cache *, const char *); -void cookie_cache_insert(struct cookie_cache *, const char *, const char *, int); -void cookie_cache_remove(struct cookie_cache *, const char *); +str *cookie_cache_lookup(struct cookie_cache *, const str *); +void cookie_cache_insert(struct cookie_cache *, const str *, const str *); +void cookie_cache_remove(struct cookie_cache *, const str *); #endif diff --git a/daemon/sdp.c b/daemon/sdp.c index c945a17f4..fb6f55c40 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -165,15 +165,15 @@ static int parse_media(char *start, char *end, struct sdp_media *output) { return 0; } -int sdp_parse(char *body, int len, GQueue *sessions) { +int sdp_parse(str *body, GQueue *sessions) { char *b, *end, *value, *line_end, *next_line; struct sdp_session *session = NULL; struct sdp_media *media = NULL; const char *errstr; str *attribute; - b = body; - end = body + len; + b = body->s; + end = str_end(body); while (b && b < end - 1) { errstr = "Missing '=' sign"; @@ -269,7 +269,7 @@ int sdp_parse(char *body, int len, GQueue *sessions) { return 0; error: - mylog(LOG_WARNING, "Error parsing SDP at offset %li: %s", (b - body), errstr); + mylog(LOG_WARNING, "Error parsing SDP at offset %li: %s", b - body->s, errstr); sdp_free(sessions); return -1; } diff --git a/daemon/sdp.h b/daemon/sdp.h index 180bd10e0..d8370a264 100644 --- a/daemon/sdp.h +++ b/daemon/sdp.h @@ -2,8 +2,9 @@ #define _SDP_H_ #include +#include "str.h" -int sdp_parse(char *body, int len, GQueue *sessions); +int sdp_parse(str *body, GQueue *sessions); int sdp_streams(const GQueue *sessions, GQueue *streams); void sdp_free(GQueue *sessions); diff --git a/daemon/str.c b/daemon/str.c new file mode 100644 index 000000000..018881770 --- /dev/null +++ b/daemon/str.c @@ -0,0 +1,28 @@ +#include +#include "str.h" + +guint str_hash(gconstpointer ss) { + const str *s = ss; + guint ret = 0; + str it = *s; + + while (it.len >= sizeof(guint)) { + guint *x = (void *) it.s; + ret ^= *x; + it.s += sizeof(guint); + it.len -= sizeof(guint); + } + while (it.len >= sizeof(gushort)) { + gushort *x = (void *) it.s; + ret ^= *x; + it.s += sizeof(gushort); + it.len -= sizeof(gushort); + } + while (it.len > 0) { + ret ^= *it.s; + it.s++; + it.len--; + } + + return ret; +} diff --git a/daemon/str.h b/daemon/str.h index c82eb4520..11077659c 100644 --- a/daemon/str.h +++ b/daemon/str.h @@ -1,6 +1,15 @@ #ifndef _STR_H_ #define _STR_H_ +#include +#include +#include +#include +#include +#include + + + struct _str { char *s; int len; @@ -8,4 +17,114 @@ struct _str { typedef struct _str str; +#define STR_FORMAT "%.*s" +#define STR_FMT(str) (str)->len, (str)->s + + + +static inline int str_cmp_str(const str *a, const str *b) { + if (a->len < b->len) + return -1; + if (a->len > b->len) + return 1; + return memcmp(a->s, b->s, a->len); +} +/* for GHashTables */ +guint str_hash(gconstpointer s); +static inline gboolean str_equal(gconstpointer a, gconstpointer b) { + return str_cmp_str((str *) a, (str *) b) == 0; +} + + + +static inline str *str_chunk_insert(GStringChunk *c, const str *s) { + str *i; + i = (void *) g_string_chunk_insert_len(c, (void *) s, sizeof(*s)); + i->s = g_string_chunk_insert_len(c, s->s, s->len); + return i; +} +static inline char *str_end(const str *s) { + return s->s + s->len; +} +static inline char *str_chr(const str *s, int c) { + return memchr(s->s, c, s->len); +} +static inline char *str_chr_str(str *out, const str *s, int c) { + out->s = str_chr(s, c); + out->len = out->s ? out->s - s->s : 0; + return out->s; +} +static inline int str_cmp(const str *a, const char *b) { + int l = strlen(b); + if (a->len < l) + return -1; + if (a->len > l) + return 1; + return memcmp(a->s, b, l); +} +static inline void str_init(str *out, char *s) { + out->s = s; + out->len = strlen(s); +} +static inline str *str_dup(const str *s) { + str *r; + r = malloc(sizeof(*r) + s->len + 1); + r->s = ((char *) r) + sizeof(*r); + r->len = s->len; + memcpy(r->s, s->s, s->len); + r->s[s->len] = '\0'; + return r; +} + +#define STR_MALLOC_PADDING "xxxxxxxxxxxxxxxx" +static inline str *__str_vsprintf(const char *fmt, va_list ap) { + char *r; + int l, pl; + str *ret; + + l = vasprintf(&r, fmt, ap); + if (l < 0) + abort(); + pl = strlen(STR_MALLOC_PADDING); + assert(pl >= sizeof(*ret)); + ret = (void *) r; + ret->s = r + pl; + ret->len = l - pl; + return ret; +} +static inline str *__str_sprintf(const char *fmt, ...) __attribute__((format(printf,1,2))); +static inline str *__str_sprintf(const char *fmt, ...) { + str *ret; + va_list ap; + va_start(ap, fmt); + ret = __str_vsprintf(fmt, ap); + va_end(ap); + return ret; +} +#define str_sprintf(fmt, a...) __str_sprintf(STR_MALLOC_PADDING fmt, a) +#define str_vsprintf(fmt, a) __str_vsprintf(STR_MALLOC_PADDING fmt, a) + +static inline GString *g_string_new_str(void) { + int pl; + GString *ret; + + ret = g_string_new(""); + pl = strlen(STR_MALLOC_PADDING); + assert(pl >= sizeof(str)); + g_string_append_len(ret, STR_MALLOC_PADDING, pl); + return ret; +} +static inline str *g_string_free_str(GString *gs) { + str *ret; + int pl; + + pl = strlen(STR_MALLOC_PADDING); + assert(gs->len >= pl); + ret = (void *) gs->str; + ret->s = gs->str + pl; + ret->len = gs->len - pl; + g_string_free(gs, FALSE); + return ret; +} + #endif diff --git a/daemon/streambuf.h b/daemon/streambuf.h index 622dafb07..da3eb4391 100644 --- a/daemon/streambuf.h +++ b/daemon/streambuf.h @@ -8,6 +8,8 @@ #include #include +#include "str.h" + struct poller; @@ -32,6 +34,9 @@ unsigned int streambuf_bufsize(struct streambuf *); void streambuf_printf(struct streambuf *, const char *, ...) __attribute__ ((format (printf, 2, 3))); void streambuf_vprintf(struct streambuf *, const char *, va_list); void streambuf_write(struct streambuf *, const char *, unsigned int); +static inline void streambuf_write_str(struct streambuf *b, str *s) { + streambuf_write(b, s->s, s->len); +} #endif diff --git a/daemon/udp_listener.c b/daemon/udp_listener.c index b5cfc6146..cb107b1b4 100644 --- a/daemon/udp_listener.c +++ b/daemon/udp_listener.c @@ -8,6 +8,7 @@ #include "udp_listener.h" #include "poller.h" #include "aux.h" +#include "str.h" struct udp_listener_callback { struct obj obj; @@ -26,6 +27,9 @@ static void udp_listener_incoming(int fd, void *p, uintptr_t x) { int len; char buf[8192]; char addr[64]; + str str; + + str.s = buf; for (;;) { sin_len = sizeof(sin); @@ -41,7 +45,8 @@ static void udp_listener_incoming(int fd, void *p, uintptr_t x) { buf[len] = '\0'; smart_ntop_port(addr, &sin, sizeof(addr)); - cb->func(cb->p, buf, len, &sin, addr); + str.len = len; + cb->func(cb->p, &str, &sin, addr); } } diff --git a/daemon/udp_listener.h b/daemon/udp_listener.h index e601869ad..792daac07 100644 --- a/daemon/udp_listener.h +++ b/daemon/udp_listener.h @@ -2,12 +2,13 @@ #define _UDP_LISTENER_H_ #include "poller.h" +#include "str.h" struct poller; struct obj; -typedef void (*udp_listener_callback_t)(struct obj *p, char *buf, int len, struct sockaddr_in6 *sin, char *addr); +typedef void (*udp_listener_callback_t)(struct obj *p, str *buf, struct sockaddr_in6 *sin, char *addr); struct udp_listener { int fd;