Browse Source

split generic udp receiving code into udp_listener

git.mgm/mediaproxy-ng/2.2
Richard Fuchs 13 years ago
parent
commit
4700a6dea0
4 changed files with 67 additions and 43 deletions
  1. +1
    -1
      daemon/control_ng.c
  2. +17
    -36
      daemon/control_udp.c
  3. +46
    -5
      daemon/udp_listener.c
  4. +3
    -1
      daemon/udp_listener.h

+ 1
- 1
daemon/control_ng.c View File

@ -4,7 +4,7 @@
#include "bencode.h"
static void control_ng_incoming(int fd, void *p, uintptr_t x) {
static void control_ng_incoming(struct obj *obj, char *buf, int len, struct sockaddr_in6 *sin, char *addr) {
}
struct control_ng *control_ng_new(struct poller *p, struct in6_addr ip, u_int16_t port, struct callmaster *m) {


+ 17
- 36
daemon/control_udp.c View File

@ -17,48 +17,30 @@
#include "udp_listener.h"
static void control_udp_incoming(int fd, void *p, uintptr_t x) {
struct control_udp *u = p;
int ret, len;
char buf[8192];
struct sockaddr_in6 sin;
socklen_t sin_len;
static void control_udp_incoming(struct obj *obj, char *buf, int len, 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];
char addr[64];
next:
sin_len = sizeof(sin);
len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &sin, &sin_len);
if (len < 0) {
if (errno == EINTR)
goto next;
if (errno != EWOULDBLOCK && errno != EAGAIN)
mylog(LOG_WARNING, "Error reading from UDP socket");
return;
}
buf[len] = '\0';
smart_ntop_p(addr, &sin.sin6_addr, sizeof(addr));
ret = pcre_exec(u->parse_re, u->parse_ree, 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));
if (ret <= 0) {
mylog(LOG_WARNING, "Unable to parse command line from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf);
goto next;
mylog(LOG_WARNING, "Unable to parse command line from udp:%s:%u: %s", addr, ntohs(sin->sin6_port), buf);
return;
}
mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from %s:%u, using fallback RE", buf, addr, ntohs(sin.sin6_port));
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);
ZERO(mh);
mh.msg_name = &sin;
mh.msg_namelen = sizeof(sin);
mh.msg_name = sin;
mh.msg_namelen = sizeof(*sin);
mh.msg_iov = iov;
iov[0].iov_base = (void *) out[RE_UDP_COOKIE];
@ -78,21 +60,21 @@ next:
mh.msg_iovlen = 2;
}
sendmsg(fd, &mh, 0);
sendmsg(u->udp_listener.fd, &mh, 0);
pcre_free(out);
goto next;
return;
}
mylog(LOG_INFO, "Got valid command from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), 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);
reply = cookie_cache_lookup(&u->cookie_cache, out[RE_UDP_COOKIE]);
if (reply) {
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);
mylog(LOG_INFO, "Detected command from udp:%s:%u as a duplicate", addr, ntohs(sin->sin6_port));
sendto(u->udp_listener.fd, reply, strlen(reply), 0, (struct sockaddr *) sin, sizeof(*sin));
goto out;
}
@ -106,8 +88,8 @@ next:
reply = call_query_udp(out, u->callmaster);
else if (chrtoupper(out[RE_UDP_V_CMD][0]) == 'V') {
ZERO(mh);
mh.msg_name = &sin;
mh.msg_namelen = sizeof(sin);
mh.msg_name = sin;
mh.msg_namelen = sizeof(*sin);
mh.msg_iov = iov;
mh.msg_iovlen = 2;
@ -133,12 +115,12 @@ next:
iov[2].iov_len = 9;
mh.msg_iovlen++;
}
sendmsg(fd, &mh, 0);
sendmsg(u->udp_listener.fd, &mh, 0);
}
if (reply) {
len = strlen(reply);
sendto(fd, reply, len, 0, (struct sockaddr *) &sin, sin_len);
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);
free(reply);
}
@ -147,7 +129,6 @@ next:
out:
pcre_free(out);
goto next;
}
struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int16_t port, struct callmaster *m) {


+ 46
- 5
daemon/udp_listener.c View File

@ -3,22 +3,60 @@
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "udp_listener.h"
#include "poller.h"
#include "aux.h"
struct udp_listener_callback {
struct obj obj;
udp_listener_callback_t func;
struct obj *p;
};
static void udp_listener_closed(int fd, void *p, uintptr_t x) {
abort();
}
int udp_listener_init(struct udp_listener *u, struct poller *p, struct in6_addr ip, u_int16_t port, poller_func_t func, struct obj *obj) {
static void udp_listener_incoming(int fd, void *p, uintptr_t x) {
struct udp_listener_callback *cb = p;
struct sockaddr_in6 sin;
socklen_t sin_len;
int len;
char buf[8192];
char addr[64];
for (;;) {
sin_len = sizeof(sin);
len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &sin, &sin_len);
if (len < 0) {
if (errno == EINTR)
continue;
if (errno != EWOULDBLOCK && errno != EAGAIN)
mylog(LOG_WARNING, "Error reading from UDP socket");
return;
}
buf[len] = '\0';
smart_ntop_p(addr, &sin.sin6_addr, sizeof(addr));
cb->func(cb->p, buf, len, &sin, addr);
}
}
int udp_listener_init(struct udp_listener *u, struct poller *p, struct in6_addr ip, u_int16_t port, udp_listener_callback_t func, struct obj *obj) {
struct sockaddr_in6 sin;
struct poller_item i;
struct udp_listener_callback *cb;
cb = obj_alloc("udp_listener_callback", sizeof(*cb), NULL);
cb->func = func;
cb->p = obj_get(obj);
u->fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (u->fd == -1)
return -1;
goto fail;
nonblock(u->fd);
reuseaddr(u->fd);
@ -34,14 +72,17 @@ int udp_listener_init(struct udp_listener *u, struct poller *p, struct in6_addr
ZERO(i);
i.fd = u->fd;
i.closed = udp_listener_closed;
i.readable = func;
i.obj = obj;
i.readable = udp_listener_incoming;
i.obj = &cb->obj;
if (poller_add_item(p, &i))
goto fail;
return 0;
fail:
close(u->fd);
if (u->fd != -1)
close(u->fd);
obj_put(obj);
obj_put(&cb->obj);
return -1;
}

+ 3
- 1
daemon/udp_listener.h View File

@ -7,11 +7,13 @@
struct poller;
struct obj;
typedef void (*udp_listener_callback_t)(struct obj *p, char *buf, int len, struct sockaddr_in6 *sin, char *addr);
struct udp_listener {
int fd;
struct poller *poller;
};
int udp_listener_init(struct udp_listener *, struct poller *p, struct in6_addr ip, u_int16_t port, poller_func_t, struct obj *);
int udp_listener_init(struct udp_listener *, struct poller *p, struct in6_addr ip, u_int16_t port, udp_listener_callback_t, struct obj *);
#endif

Loading…
Cancel
Save