Browse Source

and while we're at it, add support for ipv6 on the udp control protocol as well

git.mgm/mediaproxy-ng/2.0
Richard Fuchs 14 years ago
parent
commit
e6e151bdd4
5 changed files with 50 additions and 20 deletions
  1. +3
    -1
      daemon/aux.h
  2. +2
    -4
      daemon/call.c
  3. +15
    -11
      daemon/control_udp.c
  4. +2
    -1
      daemon/control_udp.h
  5. +28
    -3
      daemon/main.c

+ 3
- 1
daemon/aux.h View File

@ -60,11 +60,13 @@ void g_queue_clear(GQueue *);
static inline void nonblock(int fd) { static inline void nonblock(int fd) {
fcntl(fd, F_SETFL, O_NONBLOCK); fcntl(fd, F_SETFL, O_NONBLOCK);
} }
static inline void reuseaddr(int fd) { static inline void reuseaddr(int fd) {
int one = 1; int one = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
} }
static inline void ipv6only(int fd, int yn) {
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yn, sizeof(yn));
}
static inline int bit_array_isset(int *name, unsigned int bit) { static inline int bit_array_isset(int *name, unsigned int bit) {
return name[(bit) / (sizeof(int) * 8)] & (1 << ((bit) % (sizeof(int) * 8))); return name[(bit) / (sizeof(int) * 8)] & (1 << ((bit) % (sizeof(int) * 8)));


+ 2
- 4
daemon/call.c View File

@ -582,7 +582,6 @@ fail:
static int get_port6(struct streamrelay *r, u_int16_t p) { static int get_port6(struct streamrelay *r, u_int16_t p) {
int fd; int fd;
struct sockaddr_in6 sin; struct sockaddr_in6 sin;
int i;
fd = socket(AF_INET6, SOCK_DGRAM, 0); fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd < 0) if (fd < 0)
@ -591,8 +590,7 @@ static int get_port6(struct streamrelay *r, u_int16_t p) {
nonblock(fd); nonblock(fd);
reuseaddr(fd); reuseaddr(fd);
setsockopt(fd, IPPROTO_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));
i = 0;
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i));
ipv6only(fd, 0);
ZERO(sin); ZERO(sin);
sin.sin6_family = AF_INET6; sin.sin6_family = AF_INET6;
@ -1128,7 +1126,7 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const
} }
else { else {
if (IN6_IS_ADDR_UNSPECIFIED(&t->peers[off].rtps[0].peer.ip46)) if (IN6_IS_ADDR_UNSPECIFIED(&t->peers[off].rtps[0].peer.ip46))
strcpy(ips, "::0");
strcpy(ips, "::");
else if (!IN6_IS_ADDR_UNSPECIFIED(&t->call->callmaster->adv_ipv6)) else if (!IN6_IS_ADDR_UNSPECIFIED(&t->call->callmaster->adv_ipv6))
inet_ntop(AF_INET6, &t->call->callmaster->adv_ipv6, ips, sizeof(ips)); inet_ntop(AF_INET6, &t->call->callmaster->adv_ipv6, ips, sizeof(ips));
else else


+ 15
- 11
daemon/control_udp.c View File

@ -6,6 +6,7 @@
#include <pcre.h> #include <pcre.h>
#include <glib.h> #include <glib.h>
#include <time.h> #include <time.h>
#include <netinet/in.h>
#include "control_udp.h" #include "control_udp.h"
#include "poller.h" #include "poller.h"
@ -29,13 +30,14 @@ static void control_udp_incoming(int fd, void *p) {
struct control_udp *u = p; struct control_udp *u = p;
int ret, len; int ret, len;
char buf[8192]; char buf[8192];
struct sockaddr_in sin;
struct sockaddr_in6 sin;
socklen_t sin_len; socklen_t sin_len;
int ovec[60]; int ovec[60];
const char **out; const char **out;
char *reply; char *reply;
struct msghdr mh; struct msghdr mh;
struct iovec iov[10]; struct iovec iov[10];
char addr[64];
sin_len = sizeof(sin); sin_len = sizeof(sin);
len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &sin, &sin_len); len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &sin, &sin_len);
@ -45,16 +47,17 @@ static void control_udp_incoming(int fd, void *p) {
} }
buf[len] = '\0'; buf[len] = '\0';
smart_ntop(addr, &sin.sin6_addr, sizeof(addr));
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, len, 0, 0, ovec, G_N_ELEMENTS(ovec));
if (ret <= 0) { 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, len, 0, 0, ovec, G_N_ELEMENTS(ovec));
if (ret <= 0) { if (ret <= 0) {
mylog(LOG_WARNING, "Unable to parse command line from udp:" DF ": %s", DP(sin), buf);
mylog(LOG_WARNING, "Unable to parse command line from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf);
return; return;
} }
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 %s:%u, using fallback RE", buf, addr, ntohs(sin.sin6_port));
pcre_get_substring_list(buf, ovec, ret, &out); pcre_get_substring_list(buf, ovec, ret, &out);
@ -87,7 +90,7 @@ static void control_udp_incoming(int fd, void *p) {
return; return;
} }
mylog(LOG_INFO, "Got valid command from udp:" DF ": %s", DP(sin), buf);
mylog(LOG_INFO, "Got valid command from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf);
pcre_get_substring_list(buf, ovec, ret, &out); pcre_get_substring_list(buf, ovec, ret, &out);
@ -104,7 +107,7 @@ static void control_udp_incoming(int fd, void *p) {
if (!reply) if (!reply)
reply = g_hash_table_lookup(u->stale_cookies, out[1]); reply = g_hash_table_lookup(u->stale_cookies, out[1]);
if (reply) { if (reply) {
mylog(LOG_INFO, "Detected command from udp:" DF " as a duplicate", DP(sin));
mylog(LOG_INFO, "Detected command from udp:%s:%u as a duplicate", addr, ntohs(sin.sin6_port));
sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len); sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len);
goto out; goto out;
} }
@ -158,28 +161,29 @@ out:
pcre_free(out); pcre_free(out);
} }
struct control_udp *control_udp_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m) {
struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int16_t port, struct callmaster *m) {
int fd; int fd;
struct control_udp *c; struct control_udp *c;
struct poller_item i; struct poller_item i;
struct sockaddr_in sin;
struct sockaddr_in6 sin;
const char *errptr; const char *errptr;
int erroff; int erroff;
if (!p || !m) if (!p || !m)
return NULL; return NULL;
fd = socket(AF_INET, SOCK_DGRAM, 0);
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd == -1) if (fd == -1)
return NULL; return NULL;
nonblock(fd); nonblock(fd);
reuseaddr(fd); reuseaddr(fd);
ipv6only(fd, 0);
ZERO(sin); ZERO(sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip;
sin.sin_port = htons(port);
sin.sin6_family = AF_INET6;
sin.sin6_addr = ip;
sin.sin6_port = htons(port);
if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))) if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)))
goto fail; goto fail;


+ 2
- 1
daemon/control_udp.h View File

@ -8,6 +8,7 @@
#include <pcre.h> #include <pcre.h>
#include <glib.h> #include <glib.h>
#include <time.h> #include <time.h>
#include <netinet/in.h>
@ -36,7 +37,7 @@ struct control_udp {
struct control_udp *control_udp_new(struct poller *, u_int32_t, u_int16_t, struct callmaster *);
struct control_udp *control_udp_new(struct poller *, struct in6_addr, u_int16_t, struct callmaster *);


+ 28
- 3
daemon/main.c View File

@ -36,7 +36,7 @@ static struct in6_addr ipv6;
static struct in6_addr adv_ipv6; static struct in6_addr adv_ipv6;
static u_int32_t listenp; static u_int32_t listenp;
static u_int16_t listenport; static u_int16_t listenport;
static u_int32_t udp_listenp;
static struct in6_addr udp_listenp;
static u_int16_t udp_listenport; static u_int16_t udp_listenport;
static int tos; static int tos;
static int table; static int table;
@ -108,6 +108,31 @@ out:
return ret; return ret;
} }
static int parse_ip6_port(struct in6_addr *ip6, u_int16_t *port, char *s) {
u_int32_t ip;
char *p;
if (!parse_ip_port(&ip, port, s)) {
if (ip)
in4_to_6(ip6, ip);
else
*ip6 = in6addr_any;
return 0;
}
if (*s != '[')
return -1;
if (inet_pton(AF_INET6, s+1, ip6) != 1)
return -1;
p = strstr(s, "]:");
if (!p)
return -1;
*port = atoi(p+2);
if (!*port)
return -1;
return 0;
}
static void options(int *argc, char ***argv) { static void options(int *argc, char ***argv) {
@ -130,7 +155,7 @@ static void options(int *argc, char ***argv) {
{ "ip6", 'I', 0, G_OPTION_ARG_STRING, &ipv6s, "Local IPv6 address for RTP", "IP6" }, { "ip6", 'I', 0, G_OPTION_ARG_STRING, &ipv6s, "Local IPv6 address for RTP", "IP6" },
{ "advertised-ip6",'A',0,G_OPTION_ARG_STRING, &adv_ipv6s, "IPv6 address to advertise", "IP6" }, { "advertised-ip6",'A',0,G_OPTION_ARG_STRING, &adv_ipv6s, "IPv6 address to advertise", "IP6" },
{ "listen", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" }, { "listen", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" },
{ "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP:]PORT" },
{ "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP46:]PORT" },
{ "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "TOS value to set on streams", "INT" }, { "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "TOS value to set on streams", "INT" },
{ "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" }, { "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" },
{ "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" },
@ -185,7 +210,7 @@ static void options(int *argc, char ***argv) {
die("Invalid IP or port (--listen)\n"); die("Invalid IP or port (--listen)\n");
} }
if (listenudps) { if (listenudps) {
if (parse_ip_port(&udp_listenp, &udp_listenport, listenudps))
if (parse_ip6_port(&udp_listenp, &udp_listenport, listenudps))
die("Invalid IP or port (--listen-udp)\n"); die("Invalid IP or port (--listen-udp)\n");
} }


Loading…
Cancel
Save