Browse Source

add the ipv6 logic to the userspace daemon.

problems with this:
1) not pretty
2) most certainly doesn't work
3) only compiles with no-redis
4) not pretty and most certainly doesn't work
git.mgm/mediaproxy-ng/2.0
Richard Fuchs 14 years ago
parent
commit
d05f5831d4
7 changed files with 365 additions and 112 deletions
  1. +11
    -0
      daemon/aux.h
  2. +311
    -95
      daemon/call.c
  3. +10
    -3
      daemon/call.h
  4. +6
    -2
      daemon/control_udp.c
  5. +20
    -9
      daemon/kernel.c
  6. +5
    -1
      daemon/kernel.h
  7. +2
    -2
      daemon/main.c

+ 11
- 0
daemon/aux.h View File

@ -23,6 +23,17 @@
#define IPP(x) ((unsigned char *) (&(x)))[0], ((unsigned char *) (&(x)))[1], ((unsigned char *) (&(x)))[2], ((unsigned char *) (&(x)))[3] #define IPP(x) ((unsigned char *) (&(x)))[0], ((unsigned char *) (&(x)))[1], ((unsigned char *) (&(x)))[2], ((unsigned char *) (&(x)))[3]
#define DF IPF ":%u" #define DF IPF ":%u"
#define DP(x) IPP((x).sin_addr.s_addr), ntohs((x).sin_port) #define DP(x) IPP((x).sin_addr.s_addr), ntohs((x).sin_port)
#define IP6F "%x:%x:%x:%x:%x:%x:%x:%x"
#define IP6P(x) ntohs(((u_int16_t *) (x))[0]), \
ntohs(((u_int16_t *) (x))[1]), \
ntohs(((u_int16_t *) (x))[2]), \
ntohs(((u_int16_t *) (x))[3]), \
ntohs(((u_int16_t *) (x))[4]), \
ntohs(((u_int16_t *) (x))[5]), \
ntohs(((u_int16_t *) (x))[6]), \
ntohs(((u_int16_t *) (x))[7])
#define D6F IP6F ":%u"
#define D6P(x) IP6P((x).sin6_addr.s6_addr), ntohs((x).sin6_port)
#define NONBLOCK(x) fcntl(x, F_SETFL, O_NONBLOCK) #define NONBLOCK(x) fcntl(x, F_SETFL, O_NONBLOCK)
#define REUSEADDR(x) do { int ONE = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &ONE, sizeof(ONE)); } while (0) #define REUSEADDR(x) do { int ONE = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &ONE, sizeof(ONE)); } while (0)


+ 311
- 95
daemon/call.c View File

@ -119,17 +119,30 @@ static void kernelize(struct callstream *c) {
r = &p->rtps[j]; r = &p->rtps[j];
rp = &pp->rtps[j]; rp = &pp->rtps[j];
if (!r->peer.ip || !r->peer.port)
if (!r->peer.family || !r->peer.port)
continue; continue;
ZERO(r->kstats);
ks.local_port = r->localport; ks.local_port = r->localport;
ks.src.ip = c->call->callmaster->ip;
ks.tos = c->call->callmaster->tos;
ks.src.family = ks.dest.family = r->peer.family;
ks.src.port = rp->localport; ks.src.port = rp->localport;
ks.dest.ip = r->peer.ip;
ks.dest.port = r->peer.port; ks.dest.port = r->peer.port;
ks.tos = c->call->callmaster->tos;
switch (r->peer.family) {
case AF_INET:
ks.src.ipv4 = c->call->callmaster->ipv4;
ks.dest.ipv4 = r->peer.ipv4;
break;
case AF_INET6:
memcpy(ks.src.ipv6, c->call->callmaster->ipv6, 16);
memcpy(ks.dest.ipv6, r->peer.ipv6, 16);
break;
default:
/* XXX panic */
break;
}
ZERO(r->kstats);
kernel_add_stream(c->call->callmaster->kernelfd, &ks, 0); kernel_add_stream(c->call->callmaster->kernelfd, &ks, 0);
} }
@ -141,12 +154,13 @@ static void kernelize(struct callstream *c) {
static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_in *fsin) {
static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_storage *xsin) {
struct streamrelay *p, *p2; struct streamrelay *p, *p2;
struct peer *pe, *pe2; struct peer *pe, *pe2;
struct callstream *cs; struct callstream *cs;
int ret; int ret;
struct sockaddr_in sin; struct sockaddr_in sin;
struct sockaddr_in6 sin6;
struct msghdr mh; struct msghdr mh;
struct iovec iov; struct iovec iov;
unsigned char buf[256]; unsigned char buf[256];
@ -155,6 +169,11 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_
struct call *c; struct call *c;
struct callmaster *m; struct callmaster *m;
unsigned char cc; unsigned char cc;
struct sockaddr_in *fsin;
struct sockaddr_in6 *fsin6;
fsin = (void *) xsin;
fsin6 = (void *) xsin;
pe = r->up; pe = r->up;
cs = pe->up; cs = pe->up;
@ -164,7 +183,17 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_
m = c->callmaster; m = c->callmaster;
if (p->fd == -1) { if (p->fd == -1) {
mylog(LOG_WARNING, "[%s] RTP packet to port %u discarded from " DF, c->callid, r->localport, DP(*fsin));
switch (xsin->ss_family) {
case AF_INET:
mylog(LOG_WARNING, "[%s] RTP packet to port %u discarded from " DF, c->callid, r->localport, DP(*fsin));
break;
case AF_INET6:
mylog(LOG_WARNING, "[%s] RTP packet to port %u discarded from " D6F, c->callid, r->localport, D6P(*fsin6));
break;
default:
/* XXX panic */
;
}
r->stats.errors++; r->stats.errors++;
m->statsps.errors++; m->statsps.errors++;
return 0; return 0;
@ -184,17 +213,39 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_
pe->codec = "unknown"; pe->codec = "unknown";
} }
mylog(LOG_DEBUG, "[%s] Confirmed peer information for port %u - " DF, c->callid, r->localport, DP(*fsin));
switch (xsin->ss_family) {
case AF_INET:
mylog(LOG_DEBUG, "[%s] Confirmed peer information for port %u - " DF, c->callid, r->localport, DP(*fsin));
break;
case AF_INET6:
mylog(LOG_DEBUG, "[%s] Confirmed peer information for port %u - " D6F, c->callid, r->localport, D6P(*fsin6));
break;
default:
/* XXX panic */
;
}
pe->confirmed = 1; pe->confirmed = 1;
} }
p->peer.ip = fsin->sin_addr.s_addr;
p->peer.port = ntohs(fsin->sin_port);
p2 = &p->up->rtps[p->idx ^ 1]; p2 = &p->up->rtps[p->idx ^ 1];
p2->peer.ip = fsin->sin_addr.s_addr;
p2->peer.port = p->peer.port + ((int) (p2->idx * 2) - 1);
switch (xsin->ss_family) {
case AF_INET:
p->peer.ipv4 = fsin->sin_addr.s_addr;
p->peer.port = ntohs(fsin->sin_port);
p2->peer.ipv4 = fsin->sin_addr.s_addr;
p2->peer.port = p->peer.port + ((int) (p2->idx * 2) - 1);
break;
case AF_INET6:
memcpy(p->peer.ipv6, fsin6->sin6_addr.s6_addr, sizeof(p->peer.ipv6));
p->peer.port = ntohs(fsin6->sin6_port);
memcpy(p2->peer.ipv6, fsin6->sin6_addr.s6_addr, sizeof(p2->peer.ipv6));
p2->peer.port = p->peer.port + ((int) (p2->idx * 2) - 1);
break;
default:
/* XXX panic */
;
}
@ -207,37 +258,58 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_
} }
skip: skip:
if (!r->peer.ip || !r->peer.port)
if (!r->peer.family || !r->peer.port)
goto drop; goto drop;
ZERO(sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = r->peer.ip;
sin.sin_port = htons(r->peer.port);
ZERO(mh);
switch (r->peer.family) {
case AF_INET:
ZERO(sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = r->peer.ipv4;
sin.sin_port = htons(r->peer.port);
mh.msg_name = &sin;
mh.msg_namelen = sizeof(sin);
break;
case AF_INET6:
ZERO(sin6);
sin6.sin6_family = AF_INET6;
memcpy(sin6.sin6_addr.s6_addr, r->peer.ipv6, sizeof(sin6.sin6_addr.s6_addr));
sin6.sin6_port = htons(r->peer.port);
mh.msg_name = &sin6;
mh.msg_namelen = sizeof(sin6);
break;
default:
/* XXX panic */
;
}
ZERO(iov); ZERO(iov);
iov.iov_base = b; iov.iov_base = b;
iov.iov_len = l; iov.iov_len = l;
ZERO(mh);
mh.msg_name = &sin;
mh.msg_namelen = sizeof(sin);
mh.msg_iov = &iov; mh.msg_iov = &iov;
mh.msg_iovlen = 1; mh.msg_iovlen = 1;
mh.msg_control = buf;
mh.msg_controllen = sizeof(buf);
ch = CMSG_FIRSTHDR(&mh);
ZERO(*ch);
ch->cmsg_len = CMSG_LEN(sizeof(*pi));
ch->cmsg_level = IPPROTO_IP;
ch->cmsg_type = IP_PKTINFO;
if (r->peer.family == AF_INET) {
mh.msg_control = buf;
mh.msg_controllen = sizeof(buf);
pi = (void *) CMSG_DATA(ch);
ZERO(*pi);
pi->ipi_spec_dst.s_addr = m->ip;
ch = CMSG_FIRSTHDR(&mh);
ZERO(*ch);
ch->cmsg_len = CMSG_LEN(sizeof(*pi));
ch->cmsg_level = IPPROTO_IP;
ch->cmsg_type = IP_PKTINFO;
mh.msg_controllen = CMSG_SPACE(sizeof(*pi));
pi = (void *) CMSG_DATA(ch);
ZERO(*pi);
pi->ipi_spec_dst.s_addr = m->ipv4;
mh.msg_controllen = CMSG_SPACE(sizeof(*pi));
}
ret = sendmsg(p->fd, &mh, 0); ret = sendmsg(p->fd, &mh, 0);
@ -264,7 +336,7 @@ static void stream_readable(int fd, void *p) {
struct streamrelay *r = p; struct streamrelay *r = p;
char buf[1024]; char buf[1024];
int ret; int ret;
struct sockaddr_in sin;
struct sockaddr_storage sin;
unsigned int sinlen; unsigned int sinlen;
for (;;) { for (;;) {
@ -317,11 +389,12 @@ static int streams_parse_func(char **a, void **ret, void *p) {
st = g_slice_alloc0(sizeof(*st)); st = g_slice_alloc0(sizeof(*st));
st->ip = inet_addr(a[0]);
st->family = AF_INET;
st->ipv4 = inet_addr(a[0]);
st->port = atoi(a[1]); st->port = atoi(a[1]);
st->mediatype = strdup(a[2] ? : ""); st->mediatype = strdup(a[2] ? : "");
if (st->ip == -1)
if (st->ipv4 == -1)
goto fail; goto fail;
if (!st->port) if (!st->port)
goto fail; goto fail;
@ -388,7 +461,11 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
hlp->ports[p->rtps[1].localport] = &p->rtps[1]; hlp->ports[p->rtps[1].localport] = &p->rtps[1];
check = cm->timeout; check = cm->timeout;
if (!p->rtps[0].peer.ip || !p->rtps[0].peer.port)
if (!p->rtps[0].peer.port)
check = cm->silent_timeout;
else if (p->rtps[0].peer.family == AF_INET && !p->rtps[0].peer.ipv4)
check = cm->silent_timeout;
else if (p->rtps[0].peer.family == AF_INET6 && !memcmp(p->rtps[0].peer.ipv6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
check = cm->silent_timeout; check = cm->silent_timeout;
if (po->now - p->rtps[0].last < check) if (po->now - p->rtps[0].last < check)
@ -486,20 +563,17 @@ fail:
static int get_port(struct streamrelay *r, u_int16_t p) {
static int get_port4(struct streamrelay *r, u_int16_t p) {
int fd; int fd;
struct sockaddr_in sin; struct sockaddr_in sin;
if (BIT_ARRAY_ISSET(ports_used, p))
return -1;
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) if (fd < 0)
return -1; return -1;
NONBLOCK(fd); NONBLOCK(fd);
REUSEADDR(fd); REUSEADDR(fd);
setsockopt(fd, SOL_IP, IP_TOS, &r->up->up->call->callmaster->tos, sizeof(r->up->up->call->callmaster->tos));
setsockopt(fd, IPPROTO_IP, IP_TOS, &r->up->up->call->callmaster->tos, sizeof(r->up->up->call->callmaster->tos));
ZERO(sin); ZERO(sin);
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
@ -508,7 +582,6 @@ static int get_port(struct streamrelay *r, u_int16_t p) {
goto fail; goto fail;
r->fd = fd; r->fd = fd;
r->localport = p;
return 0; return 0;
@ -517,8 +590,66 @@ fail:
return -1; return -1;
} }
static int get_port6(struct streamrelay *r, u_int16_t p) {
int fd;
struct sockaddr_in6 sin;
int i;
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd < 0)
return -1;
NONBLOCK(fd);
REUSEADDR(fd);
setsockopt(fd, IPPROTO_IP, IP_TOS, &r->up->up->call->callmaster->tos, sizeof(r->up->up->call->callmaster->tos));
i = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i));
ZERO(sin);
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(p);
if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)))
goto fail;
r->fd = fd;
return 0;
fail:
close(fd);
return -1;
}
static int get_port(struct streamrelay *r, u_int16_t p, int family) {
int ret;
if (BIT_ARRAY_ISSET(ports_used, p))
return -1;
switch (family) {
case AF_INET:
ret = get_port4(r, p);
break;
case AF_INET6:
ret = get_port6(r, p);
break;
default:
/* panic XXX */
return -1;
}
if (ret)
return ret;
r->localport = p;
r->peer.family = family;
r->peer_advertised.family = family;
return 0;
}
static void get_port_pair(struct peer *p, int wanted_port) {
static void get_port_pair(struct peer *p, int wanted_port, int family) {
struct call *c; struct call *c;
struct callmaster *m; struct callmaster *m;
struct streamrelay *a, *b; struct streamrelay *a, *b;
@ -534,9 +665,9 @@ static void get_port_pair(struct peer *p, int wanted_port) {
if (wanted_port > 0) { if (wanted_port > 0) {
if ((wanted_port & 1)) if ((wanted_port & 1))
goto fail; goto fail;
if (get_port(a, wanted_port))
if (get_port(a, wanted_port, family))
goto fail; goto fail;
if (get_port(b, wanted_port + 1))
if (get_port(b, wanted_port + 1, family))
goto fail; goto fail;
goto reserve; goto reserve;
} }
@ -560,11 +691,11 @@ static void get_port_pair(struct peer *p, int wanted_port) {
if ((port & 1)) if ((port & 1))
goto next; goto next;
if (get_port(a, port))
if (get_port(a, port, family))
goto next; goto next;
port++; port++;
if (get_port(b, port))
if (get_port(b, port, family))
goto tryagain; goto tryagain;
break; break;
@ -603,14 +734,17 @@ static int setup_peer(struct peer *p, struct stream *s, const char *tag) {
a = &p->rtps[0]; a = &p->rtps[0];
b = &p->rtps[1]; b = &p->rtps[1];
if (a->peer_advertised.ip != s->ip || a->peer_advertised.port != s->port) {
if (a->peer_advertised.port != s->port
|| (s->family == AF_INET && a->peer_advertised.ipv4 != s->ipv4)
|| (s->family == AF_INET6 && memcmp(a->peer_advertised.ipv6, s->ipv6, 16))) {
cs->peers[0].confirmed = 0; cs->peers[0].confirmed = 0;
unkernelize(&cs->peers[0]); unkernelize(&cs->peers[0]);
cs->peers[1].confirmed = 0; cs->peers[1].confirmed = 0;
unkernelize(&cs->peers[1]); unkernelize(&cs->peers[1]);
} }
a->peer.ip = b->peer.ip = s->ip;
memcpy(a->peer.all, s->all, sizeof(a->peer.all));
memcpy(b->peer.all, s->all, sizeof(b->peer.all));
a->peer.port = b->peer.port = s->port; a->peer.port = b->peer.port = s->port;
if (b->peer.port) if (b->peer.port)
b->peer.port++; b->peer.port++;
@ -663,19 +797,23 @@ static void steal_peer(struct peer *dest, struct peer *src) {
sr->fd = srs->fd; sr->fd = srs->fd;
sr->peer.ip = srs->peer.ip;
sr->peer.family = srs->peer.family;
memcpy(sr->peer.all, srs->peer.all, sizeof(sr->peer.all));
sr->peer.port = srs->peer.port; sr->peer.port = srs->peer.port;
sr->peer_advertised.ip = srs->peer_advertised.ip;
sr->peer_advertised.family = srs->peer_advertised.family;
memcpy(sr->peer_advertised.all, srs->peer_advertised.all, sizeof(sr->peer_advertised.all));
sr->peer_advertised.port = srs->peer_advertised.port; sr->peer_advertised.port = srs->peer_advertised.port;
sr->localport = srs->localport; sr->localport = srs->localport;
srs->fd = -1; srs->fd = -1;
srs->peer.ip = 0;
srs->peer.family = 0;
ZERO(srs->peer.all);
srs->peer.port = 0; srs->peer.port = 0;
srs->localport = 0; srs->localport = 0;
srs->peer_advertised.ip = 0;
srs->peer_advertised.family = 0;
ZERO(srs->peer_advertised.all);
srs->peer_advertised.port = 0; srs->peer_advertised.port = 0;
pi.fd = sr->fd; pi.fd = sr->fd;
@ -688,7 +826,7 @@ static void steal_peer(struct peer *dest, struct peer *src) {
} }
static void callstream_init(struct callstream *s, struct call *ca, int port1, int port2) {
static void callstream_init(struct callstream *s, struct call *ca, int port1, int port2, int family) {
int i, j, tport; int i, j, tport;
struct peer *p; struct peer *p;
struct streamrelay *r; struct streamrelay *r;
@ -722,7 +860,7 @@ static void callstream_init(struct callstream *s, struct call *ca, int port1, in
tport = (i == 0) ? port1 : port2; tport = (i == 0) ? port1 : port2;
if (tport >= 0) { if (tport >= 0) {
get_port_pair(p, tport);
get_port_pair(p, tport, family);
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
r = &p->rtps[j]; r = &p->rtps[j];
@ -771,11 +909,24 @@ static int call_streams(struct call *c, GQueue *s, const char *tag, int opmode)
cs_o = l->data; cs_o = l->data;
for (x = 0; x < 2; x++) { for (x = 0; x < 2; x++) {
r = &cs_o->peers[x].rtps[0]; r = &cs_o->peers[x].rtps[0];
DBG("comparing new "IPF":%u/%s to old "IPF":%u/%s",
IPP(t->ip), t->port, tag,
IPP(r->peer_advertised.ip), r->peer_advertised.port, cs_o->peers[x].tag);
if (r->peer_advertised.ip != t->ip)
DBG("comparing new %i:"IPF6":%u/%s to old %i:"IPF6":%u/%s",
IPP(t->ipv6), t->port, tag,
IPP(r->peer_advertised.ipv6), r->peer_advertised.port, cs_o->peers[x].tag);
if (r->peer_advertised.family != t->family)
continue; continue;
switch (t->family) {
case AF_INET:
if (r->peer_advertised.ipv4 != t->ipv4)
continue;
break;
case AF_INET6:
if (memcmp(r->peer_advertised.ipv6, t->ipv6, 16))
continue;
break;
default:
/* XXX panic */
;
}
if (r->peer_advertised.port != t->port) if (r->peer_advertised.port != t->port)
continue; continue;
if (strcmp(cs_o->peers[x].tag, tag)) if (strcmp(cs_o->peers[x].tag, tag))
@ -799,13 +950,13 @@ found:
if (!r) { if (!r) {
/* nothing found to re-use, open new ports */ /* nothing found to re-use, open new ports */
callstream_init(cs, c, 0, 0);
callstream_init(cs, c, 0, 0, t->family);
p = &cs->peers[0]; p = &cs->peers[0];
setup_peer(p, t, tag); setup_peer(p, t, tag);
} }
else { else {
/* re-use, so don't open new ports */ /* re-use, so don't open new ports */
callstream_init(cs, c, -1, -1);
callstream_init(cs, c, -1, -1, t->family);
if (r->up->idx == 0) { if (r->up->idx == 0) {
/* request/lookup came in the same order as before */ /* request/lookup came in the same order as before */
steal_peer(&cs->peers[0], &cs_o->peers[0]); steal_peer(&cs->peers[0], &cs_o->peers[0]);
@ -870,7 +1021,7 @@ found:
DBG("case 4"); DBG("case 4");
cs_o = cs; cs_o = cs;
cs = g_slice_alloc(sizeof(*cs)); cs = g_slice_alloc(sizeof(*cs));
callstream_init(cs, c, 0, 0);
callstream_init(cs, c, 0, 0, t->family);
steal_peer(&cs->peers[0], &cs_o->peers[0]); steal_peer(&cs->peers[0], &cs_o->peers[0]);
p = &cs->peers[1]; p = &cs->peers[1];
setup_peer(p, t, tag); setup_peer(p, t, tag);
@ -987,7 +1138,7 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const
GList *l; GList *l;
struct callstream *t; struct callstream *t;
struct streamrelay *x; struct streamrelay *x;
u_int32_t ip;
char ips[64];
o = g_string_new(""); o = g_string_new("");
if (prefix) if (prefix)
@ -997,16 +1148,34 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const
goto out; goto out;
t = s->head->data; t = s->head->data;
ip = t->call->callmaster->ip;
if (t->call->callmaster->adv_ip)
ip = t->call->callmaster->adv_ip;
switch (t->peers[off].rtps[0].peer.family) {
case AF_INET:
if (!t->peers[off].rtps[0].peer.ipv4)
strcpy(ips, "0.0.0.0");
else if (t->call->callmaster->adv_ipv4)
sprintf(ips, IPF, IPP(t->call->callmaster->adv_ipv4));
else
sprintf(ips, IPF, IPP(t->peers[off].rtps[0].peer.ipv4));
break;
case AF_INET6:
if (!memcmp(t->peers[off].rtps[0].peer.ipv6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
strcpy(ips, "::");
else if (!memcmp(t->call->callmaster->adv_ipv6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
inet_ntop(AF_INET6, t->call->callmaster->adv_ipv6, ips, sizeof(ips));
else
inet_ntop(AF_INET6, t->peers[off].rtps[0].peer.ipv6, ips, sizeof(ips));
break;
default:
/* XXX panic */
;
}
t = s->head->data; t = s->head->data;
if (t->peers[off].rtps[0].peer.ip == 0)
ip = 0;
if (!swap) if (!swap)
g_string_append_printf(o, IPF, IPP(ip));
g_string_append(o, ips);
for (i = 0, l = s->head; i < num && l; i++, l = l->next) { for (i = 0, l = s->head; i < num && l; i++, l = l->next) {
t = l->data; t = l->data;
@ -1015,7 +1184,7 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const
} }
if (swap) if (swap)
g_string_append_printf(o, IPF, IPP(ip));
g_string_append(o, ips);
out: out:
g_string_append(o, "\n"); g_string_append(o, "\n");
@ -1043,6 +1212,32 @@ static struct call *call_get_or_create(const char *callid, struct callmaster *m)
return c; return c;
} }
static int addr_parse_udp(struct stream *st, const char **o) {
ZERO(st);
if (o[5] && *o[5]) {
st->family = AF_INET;
st->ipv4 = inet_addr(o[5]);
if (st->ipv4 == -1)
goto fail;
}
else if (o[6] && *o[6]) {
st->family = AF_INET6;
if (inet_pton(AF_INET6, o[6], st->ipv6) != 1)
goto fail;
}
else
goto fail;
st->port = atoi(o[7]);
st->mediatype = "unknown";
if (!st->port && strcmp(o[7], "0"))
goto fail;
return 0;
fail:
return -1;
}
char *call_update_udp(const char **o, struct callmaster *m) { char *call_update_udp(const char **o, struct callmaster *m) {
struct call *c; struct call *c;
GQueue q = G_QUEUE_INIT; GQueue q = G_QUEUE_INIT;
@ -1053,17 +1248,11 @@ char *call_update_udp(const char **o, struct callmaster *m) {
c = call_get_or_create(o[4], m); c = call_get_or_create(o[4], m);
strdupfree(&c->calling_agent, "UNKNOWN(udp)"); strdupfree(&c->calling_agent, "UNKNOWN(udp)");
ZERO(st);
st.ip = inet_addr(o[5]);
st.port = atoi(o[6]);
st.mediatype = "unknown";
if (st.ip == -1)
goto fail;
if (!st.port && strcmp(o[6], "0"))
if (addr_parse_udp(&st, o))
goto fail; goto fail;
g_queue_push_tail(&q, &st); g_queue_push_tail(&q, &st);
num = call_streams(c, &q, o[7], 0);
num = call_streams(c, &q, o[8], 0);
g_queue_clear(&q); g_queue_clear(&q);
@ -1076,7 +1265,7 @@ char *call_update_udp(const char **o, struct callmaster *m) {
return ret; return ret;
fail: fail:
mylog(LOG_WARNING, "Failed to parse a media stream: %s:%s", o[5], o[6]);
mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", o[5], o[6], o[7]);
asprintf(&ret, "%s E8\n", o[1]); asprintf(&ret, "%s E8\n", o[1]);
return ret; return ret;
} }
@ -1091,23 +1280,17 @@ char *call_lookup_udp(const char **o, struct callmaster *m) {
c = g_hash_table_lookup(m->callhash, o[4]); c = g_hash_table_lookup(m->callhash, o[4]);
if (!c) { if (!c) {
mylog(LOG_WARNING, "[%s] Got UDP LOOKUP for unknown call-id", o[4]); mylog(LOG_WARNING, "[%s] Got UDP LOOKUP for unknown call-id", o[4]);
asprintf(&ret, "%s 0 " IPF "\n", o[1], IPP(m->ip));
asprintf(&ret, "%s 0 " IPF "\n", o[1], IPP(m->ipv4));
return ret; return ret;
} }
strdupfree(&c->called_agent, "UNKNOWN(udp)"); strdupfree(&c->called_agent, "UNKNOWN(udp)");
ZERO(st);
st.ip = inet_addr(o[5]);
st.port = atoi(o[6]);
st.mediatype = "unknown";
if (st.ip == -1)
goto fail;
if (!st.port && strcmp(o[6], "0"))
if (addr_parse_udp(&st, o))
goto fail; goto fail;
g_queue_push_tail(&q, &st); g_queue_push_tail(&q, &st);
num = call_streams(c, &q, o[8], 1);
num = call_streams(c, &q, o[9], 1);
g_queue_clear(&q); g_queue_clear(&q);
@ -1120,7 +1303,7 @@ char *call_lookup_udp(const char **o, struct callmaster *m) {
return ret; return ret;
fail: fail:
mylog(LOG_WARNING, "Failed to parse a media stream: %s:%s", o[5], o[6]);
mylog(LOG_WARNING, "Failed to parse a media stream: %s/%s:%s", o[5], o[6], o[7]);
asprintf(&ret, "%s E8\n", o[1]); asprintf(&ret, "%s E8\n", o[1]);
return ret; return ret;
} }
@ -1239,17 +1422,50 @@ static void call_status_iterator(void *key, void *val, void *ptr) {
if (r1->fd == -1 || r2->fd == -1) if (r1->fd == -1 || r2->fd == -1)
continue; continue;
streambuf_printf(s->outbuf, "stream " IPF ":%u " IPF ":%u " IPF ":%u %llu/%llu/%llu %s %s %s %i\n",
IPP(r1->peer.ip), r1->peer.port,
IPP(r2->peer.ip), r2->peer.port,
IPP(m->ip), r1->localport,
streambuf_printf(s->outbuf, "stream ");
switch (r1->peer.family) {
case AF_INET:
streambuf_printf(s->outbuf, IPF, IPP(r1->peer.ipv4));
break;
case AF_INET6:
streambuf_printf(s->outbuf, IP6F, IP6P(r1->peer.ipv6));
break;
default:
/* XXX Panic */
;
}
streambuf_printf(s->outbuf, ":%u ", r1->peer.port);
switch (r2->peer.family) {
case AF_INET:
streambuf_printf(s->outbuf, IPF, IPP(r2->peer.ipv4));
break;
case AF_INET6:
streambuf_printf(s->outbuf, IP6F, IP6P(r2->peer.ipv6));
break;
default:
/* XXX Panic */
;
}
streambuf_printf(s->outbuf, ":%u ", r2->peer.port);
switch (r1->peer.family) {
case AF_INET:
streambuf_printf(s->outbuf, IPF, IPP(m->ipv4));
break;
case AF_INET6:
streambuf_printf(s->outbuf, IP6F, IP6P(m->ipv6));
break;
default:
/* XXX Panic */
;
}
streambuf_printf(s->outbuf, ":%u %llu/%llu/%llu %s %s %s %i\n",
r1->localport,
(long long unsigned int) r1->stats.bytes + rx1->stats.bytes, (long long unsigned int) r1->stats.bytes + rx1->stats.bytes,
(long long unsigned int) r2->stats.bytes + rx2->stats.bytes, (long long unsigned int) r2->stats.bytes + rx2->stats.bytes,
(long long unsigned int) r1->stats.bytes + rx1->stats.bytes + r2->stats.bytes + rx2->stats.bytes, (long long unsigned int) r1->stats.bytes + rx1->stats.bytes + r2->stats.bytes + rx2->stats.bytes,
"active", "active",
p->codec ? : "unknown", p->codec ? : "unknown",
p->mediatype, (int) (m->poller->now - r1->last)); p->mediatype, (int) (m->poller->now - r1->last));
} }
} }


+ 10
- 3
daemon/call.h View File

@ -31,7 +31,12 @@ struct redis;
struct stream { struct stream {
u_int32_t ip;
int family;
union {
unsigned char all[16];
u_int32_t ipv4;
unsigned char ipv6[16];
};
u_int16_t port; u_int16_t port;
char *mediatype; char *mediatype;
}; };
@ -90,8 +95,10 @@ struct callmaster {
#endif #endif
int kernelfd; int kernelfd;
unsigned int kernelid; unsigned int kernelid;
u_int32_t ip;
u_int32_t adv_ip;
u_int32_t ipv4;
u_int32_t adv_ipv4;
unsigned char ipv6[16];
unsigned char adv_ipv6[16];
int port_min; int port_min;
int port_max; int port_max;
unsigned int timeout; unsigned int timeout;


+ 6
- 2
daemon/control_udp.c View File

@ -56,6 +56,8 @@ static void control_udp_incoming(int fd, void *p) {
mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from "DF", using fallback RE", buf, DP(sin)); mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from "DF", using fallback RE", buf, DP(sin));
pcre_get_substring_list(buf, ovec, ret, &out);
ZERO(mh); ZERO(mh);
mh.msg_name = &sin; mh.msg_name = &sin;
mh.msg_namelen = sizeof(sin); mh.msg_namelen = sizeof(sin);
@ -73,6 +75,8 @@ static void control_udp_incoming(int fd, void *p) {
sendmsg(fd, &mh, 0); sendmsg(fd, &mh, 0);
pcre_free(out);
return; return;
} }
@ -185,8 +189,8 @@ struct control_udp *control_udp_new(struct poller *p, u_int32_t ip, u_int16_t po
c->stale_chunks = g_string_chunk_new(4 * 1024); c->stale_chunks = g_string_chunk_new(4 * 1024);
c->oven_time = p->now; c->oven_time = p->now;
c->parse_re = pcre_compile( c->parse_re = pcre_compile(
/* cookie cmd flags callid addr port from_tag to_tag cmd flags callid */
"^(\\S+)\\s+(?:([ul])(\\S*)\\s+(\\S+)\\s+([\\d.]+)\\s+(\\d+)\\s+(\\S+?)(?:;\\S+)?(?:\\s+(\\S+?)(?:;\\S+)?(?:\\s+.*)?)?\r?\n?$|(d)(\\S*)\\s+(\\S+)|(v)(\\S*)(?:\\s+(\\S+))?)",
/* cookie:1 cmd:2 flags:3 callid:4 addr4:5 addr6:6 port:7 from_tag:8 to_tag:9 cmd flags callid */
"^(\\S+)\\s+(?:([ul])(\\S*)\\s+(\\S+)\\s+(?:([\\d.]+)|([\\da-f:]+(?::[\\d.]+)?))\\s+(\\d+)\\s+(\\S+?)(?:;\\S+)?(?:\\s+(\\S+?)(?:;\\S+)?(?:\\s+.*)?)?\r?\n?$|(d)(\\S*)\\s+(\\S+)|(v)(\\S*)(?:\\s+(\\S+))?)",
PCRE_DOLLAR_ENDONLY | PCRE_DOTALL | PCRE_CASELESS, &errptr, &erroff, NULL); PCRE_DOLLAR_ENDONLY | PCRE_DOTALL | PCRE_CASELESS, &errptr, &erroff, NULL);
c->parse_ree = pcre_study(c->parse_re, 0, &errptr); c->parse_ree = pcre_study(c->parse_re, 0, &errptr);
/* cookie cmd flags callid addr port */ /* cookie cmd flags callid addr port */


+ 20
- 9
daemon/kernel.c View File

@ -71,21 +71,32 @@ fail:
} }
static void addr_copy(struct mp_address *mp, struct ip_port *ap) {
mp->family = ap->family;
mp->port = ap->port;
switch (mp->family) {
case AF_INET:
mp->ipv4 = ap->ipv4;
break;
case AF_INET6:
memcpy(mp->ipv6, ap->ipv6, 16);
break;
default:
/* XXX panic */
break;
}
}
int kernel_add_stream(int fd, struct kernel_stream *info, int update) { int kernel_add_stream(int fd, struct kernel_stream *info, int update) {
struct mediaproxy_message msg; struct mediaproxy_message msg;
ZERO(msg); ZERO(msg);
msg.cmd = update ? MMG_UPDATE : MMG_ADD; msg.cmd = update ? MMG_UPDATE : MMG_ADD;
msg.target.target_port = info->local_port; msg.target.target_port = info->local_port;
msg.target.src_addr.family = AF_INET;
msg.target.src_addr.ipv4 = info->src.ip;
msg.target.src_addr.port = info->src.port;
msg.target.dst_addr.family = AF_INET;
msg.target.dst_addr.ipv4 = info->dest.ip;
msg.target.dst_addr.port = info->dest.port;
msg.target.mirror_addr.family = AF_INET;
msg.target.mirror_addr.ipv4 = info->mirror.ip;
msg.target.mirror_addr.port = info->mirror.port;
addr_copy(&msg.target.src_addr, &info->src);
addr_copy(&msg.target.dst_addr, &info->dest);
addr_copy(&msg.target.mirror_addr, &info->mirror);
msg.target.tos = info->tos; msg.target.tos = info->tos;
return write(fd, &msg, sizeof(msg)) <= 0 ? -1 : 0; return write(fd, &msg, sizeof(msg)) <= 0 ? -1 : 0;


+ 5
- 1
daemon/kernel.h View File

@ -10,7 +10,11 @@
struct ip_port { struct ip_port {
u_int32_t ip;
int family;
union {
u_int32_t ipv4;
unsigned char ipv6[16];
};
u_int16_t port; u_int16_t port;
}; };


+ 2
- 2
daemon/main.c View File

@ -245,8 +245,8 @@ int main(int argc, char **argv) {
return -1; return -1;
m->kernelfd = kfd; m->kernelfd = kfd;
m->kernelid = table; m->kernelid = table;
m->ip = ip;
m->adv_ip = adv_ip;
m->ipv4 = ip;
m->adv_ipv4 = adv_ip;
m->port_min = port_min; m->port_min = port_min;
m->port_max = port_max; m->port_max = port_max;
m->timeout = timeout; m->timeout = timeout;


Loading…
Cancel
Save