Browse Source

mass deployment of the new "str" object - does this thing still work?

git.mgm/mediaproxy-ng/2.2
Richard Fuchs 13 years ago
parent
commit
60da1bc445
16 changed files with 296 additions and 110 deletions
  1. +1
    -1
      daemon/Makefile
  2. +25
    -0
      daemon/bencode.h
  3. +32
    -33
      daemon/call.c
  4. +7
    -6
      daemon/call.h
  5. +2
    -2
      daemon/control.c
  6. +33
    -34
      daemon/control_ng.c
  7. +16
    -15
      daemon/control_udp.c
  8. +10
    -9
      daemon/cookie_cache.c
  9. +4
    -3
      daemon/cookie_cache.h
  10. +4
    -4
      daemon/sdp.c
  11. +2
    -1
      daemon/sdp.h
  12. +28
    -0
      daemon/str.c
  13. +119
    -0
      daemon/str.h
  14. +5
    -0
      daemon/streambuf.h
  15. +6
    -1
      daemon/udp_listener.c
  16. +2
    -1
      daemon/udp_listener.h

+ 1
- 1
daemon/Makefile View File

@ -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)


+ 25
- 0
daemon/bencode.h View File

@ -5,12 +5,15 @@
#include <string.h>
#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

+ 32
- 33
daemon/call.c View File

@ -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";


+ 7
- 6
daemon/call.h View File

@ -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 *);


+ 2
- 2
daemon/control.c View File

@ -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);
}


+ 33
- 34
daemon/control_ng.c View File

@ -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);
}


+ 16
- 15
daemon/control_udp.c View File

@ -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);


+ 10
- 9
daemon/cookie_cache.c View File

@ -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);


+ 4
- 3
daemon/cookie_cache.h View File

@ -4,6 +4,7 @@
#include <time.h>
#include <glib.h>
#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

+ 4
- 4
daemon/sdp.c View File

@ -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;
}


+ 2
- 1
daemon/sdp.h View File

@ -2,8 +2,9 @@
#define _SDP_H_
#include <glib.h>
#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);


+ 28
- 0
daemon/str.c View File

@ -0,0 +1,28 @@
#include <assert.h>
#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;
}

+ 119
- 0
daemon/str.h View File

@ -1,6 +1,15 @@
#ifndef _STR_H_
#define _STR_H_
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
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

+ 5
- 0
daemon/streambuf.h View File

@ -8,6 +8,8 @@
#include <glib.h>
#include <stdarg.h>
#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

+ 6
- 1
daemon/udp_listener.c View File

@ -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);
}
}


+ 2
- 1
daemon/udp_listener.h View File

@ -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;


Loading…
Cancel
Save