21 static unsigned tpriority = 0;
22 static unsigned baseport = 5062;
23 static bool ipv6 =
false;
26 static media::proxy *list = NULL;
27 static fd_set connections;
28 static media::proxy *proxymap[
sizeof(connections) * 8];
29 static volatile bool running =
false;
30 static volatile int hiwater = 0;
33 static unsigned portcount = 0;
35 static int control[2];
36 static unsigned portcount = 38;
40 static media::thread *th = NULL;
42 static unsigned align(
unsigned value)
44 return ((value + 1) / 2) * 2;
62 if(::write(
control[1], &buf, 1) < 1)
63 shell::log(shell::ERR,
"media notify failure");
83 shell::log(
DEBUG1,
"starting media thread");
92 memcpy(&session, &connections,
sizeof(session));
94 select(max, &session, NULL, NULL, NULL);
99 for(so = 0; so < max; ++so) {
103 if(so ==
control[0] && FD_ISSET(so, &session)) {
104 if(::read(so, buf, 1) < 1)
105 shell::log(shell::ERR,
"media control failure");
110 if(!FD_ISSET(so, &session))
115 if(mp->
so == INVALID_SOCKET) {
129 shell::log(
DEBUG1,
"stopping media thread");
149 LinkedObject::release();
155 struct sockaddr_storage where;
156 struct sockaddr *wp = (
struct sockaddr *)&where;
157 ssize_t
count = Socket::recvfrom(so, buffer,
sizeof(buffer), 0, &where);
162 if(Socket::equal(wp, (
struct sockaddr *)&local)) {
163 Socket::sendto(so, buffer, count, 0, (
struct sockaddr *)&remote);
166 Socket::store(&remote, wp);
167 Socket::sendto(so, buffer, count, 0, (
struct sockaddr *)&local);
172 struct sockaddr *hp = (
struct sockaddr *)&local;
174 switch(host->sa_family) {
177 ((
struct sockaddr_in6*)(host))->sin6_port =
178 ((
struct sockaddr_in6 *)(hp))->sin6_port;
182 ((
struct sockaddr_in*)(host))->sin_port =
183 ((
struct sockaddr_in *)(hp))->sin_port;
185 Socket::store(&local, host);
190 struct sockaddr *iface = parser->
peering;
191 struct sockaddr *host = (
struct sockaddr *)&parser->local;
194 Socket::store(&local, host);
196 switch(iface->sa_family) {
199 so = Socket::create(AF_INET6, SOCK_DGRAM, 0);
200 ((
struct sockaddr_in6*)(host))->sin6_port = htons(++parser->
mediaport);
201 ((
struct sockaddr_in6*)(iface))->sin6_port = htons(port);
205 so = Socket::create(AF_INET, SOCK_DGRAM, 0);
206 ((
struct sockaddr_in*)(host))->sin_port = htons(++parser->
mediaport);
207 ((
struct sockaddr_in*)(iface))->sin_port = htons(port);
210 if(so == INVALID_SOCKET)
213 memset(&remote, 0,
sizeof(remote));
214 Socket::store(&peering, iface);
215 Socket::bindto(so, iface);
216 FD_SET(so, &connections);
217 if(so >= (socket_t)hiwater)
226 if(expire || so == INVALID_SOCKET)
229 FD_CLR(so, &connections);
237 outdata = result = NULL;
242 memset(&local, 0,
sizeof(local));
243 memset(&top, 0,
sizeof(local));
248 set(source, target, len);
253 linked_pointer<media::proxy> pp = *nat;
255 while(is(pp) && mediacount--) {
256 pp->reconnect((
struct sockaddr *)&local);
259 memcpy(&local, &top,
sizeof(local));
264 outdata = result = target;
275 if(!bufdata || *bufdata == 0) {
280 while(len > 1 && *bufdata != 0) {
281 if(*bufdata ==
'\r') {
285 else if(*bufdata ==
'\n') {
289 *(buffer++) = *(bufdata++);
293 check_connect(base, blen);
310 if(strnicmp(buffer,
"m=", 2))
313 cp = sp = strchr(buffer,
' ');
324 ep = strchr(cp,
'/');
326 tcount = atoi(ep + 1);
335 tcount = align(tcount);
337 ep = strchr(cp,
' ');
340 else while(isspace(*ep))
348 String::set(tmp,
sizeof(tmp), ep);
357 tport = (pp->
port / 2) * 2;
362 String::set(mtype,
sizeof(mtype), buffer);
364 snprintf(buffer, len,
"%s %u/%u %s",
365 mtype, tport, mediacount, tmp);
367 snprintf(buffer, len,
"%s %u %s",
370 mediacount = align(mediacount);
375 char *cp = buffer + 4;
378 const struct sockaddr *hp;
380 if(strnicmp(buffer,
"c=in", 4))
386 if(ipv6 && strnicmp(cp,
"ip6", 3))
388 else if(!ipv6 && strnicmp(cp,
"ip4", 3))
395 cp = strchr(ap,
'/');
397 String::set(ttl,
sizeof(ttl), cp);
403 if(!Socket::is_numeric(ap)) {
409 Socket::address addr(ap);
414 Socket::store(&local, hp);
416 Socket::store(&top, hp);
420 Socket::query((
struct sockaddr *)&peering, ap, len - 8);
421 String::add(buffer, len, ttl);
433 *(outdata++) = *(buffer++);
449 LinkedObject::release();
461 linked_pointer<service::keynode> mp = cfg->
getList(
"media");
466 value = mp->getPointer();
468 if(!stricmp(key,
"port"))
469 baseport = (atoi(value) / 2) * 2;
470 else if(!stricmp(key,
"priority"))
471 tpriority = atoi(value);
472 else if(!stricmp(key,
"count"))
473 portcount = align(atoi(value));
478 shell::log(
DEBUG2,
"media proxy configured for %d ports", portcount);
480 shell::log(
DEBUG1,
"media proxy disabled");
486 shell::log(
DEBUG1,
"starting media proxy");
490 memset(proxymap, 0,
sizeof(proxymap));
491 memset(&connections, 0,
sizeof(connections));
496 shell::log(shell::ERR,
"media proxy startup failed");
500 FD_SET(
control[0], &connections);
512 shell::log(
DEBUG1,
"stopping media proxy");
530 linked_pointer<media::proxy> pp = runlist;
532 if(pp->expires && pp->expires < now)
535 if(pp->so == INVALID_SOCKET && !pp->fw) {
536 if(pp->activate(parser))
538 pp->delist(&runlist);
540 pp->enlist(parser->
nat);
567 linked_pointer<proxy> pp = *nat;
572 member->enlist(&runlist);
579 bool media::isProxied(
const char *source,
const char *target,
struct sockaddr_storage *peering)
581 assert(source != NULL);
582 assert(target != NULL);
583 assert(peering != NULL);
592 if(String::equal(source, target))
596 if(String::equal(source,
"-") || String::equal(target,
"-"))
601 if(String::equal(source,
"*"))
605 if(String::equal(target,
"*") && ipv6)
609 if(String::equal(target,
"*")) {
622 if(!Socket::equal((
struct sockaddr *)(&src->
iface), (
struct sockaddr *)(&dst->
iface))) {
623 memcpy(peering, &dst->
iface,
sizeof(
struct sockaddr_storage));
636 assert(session != NULL);
637 assert(sdpin != NULL);
640 struct sockaddr_storage peering;
654 String::set(session->
sdp,
sizeof(session->
sdp), sdpin);
658 shell::log(
DEBUG3,
"reinvite proxied %s to %s", session->
network, target->network);
659 sdp parser(sdpin, session->
sdp,
sizeof(session->
sdp));
660 parser.
peering = (
struct sockaddr *)&peering;
668 assert(session != NULL);
669 assert(sdpin != NULL);
674 struct sockaddr_storage peering;
676 if(session == target || (cr->
target != NULL && cr->
target != session))
684 String::set(session->
sdp,
sizeof(session->
sdp), sdpin);
689 sdp parser(sdpin, session->
sdp,
sizeof(session->
sdp));
690 parser.
peering = (
struct sockaddr *)&peering;
698 assert(session != NULL);
699 assert(target != NULL);
703 struct sockaddr_storage peering;
706 String::set(sdpout, size, session->
sdp);
710 shell::log(
DEBUG3,
"invite proxied %s to %s", session->
network, target);
711 sdp parser(session->
sdp, sdpout, size);
712 parser.
peering = (
struct sockaddr *)&peering;
723 while(NULL != parser->
get(buffer,
sizeof(buffer))) {
724 if(!parser->
put(buffer))
char network[MAX_NETWORK_SIZE]
keynode * getList(const char *path)
Server control interfaces and functions.
struct sockaddr_storage iface
static void published(struct sockaddr_storage *peer)
static void release(stack::subnet *access)
static bool is_configured(void)
static stack::subnet * getSubnet(const char *id)
System configuration instance and service functions.
static unsigned short sip_port