|
|
|
|
@ -871,6 +871,8 @@ static int get_port(struct streamrelay *r, u_int16_t p) {
|
|
|
|
|
int ret;
|
|
|
|
|
struct callmaster *m = r->up->up->call->callmaster;
|
|
|
|
|
|
|
|
|
|
assert(r->fd == -1);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&m->portlock);
|
|
|
|
|
if (bit_array_isset(m->ports_used, p)) {
|
|
|
|
|
mutex_unlock(&m->portlock);
|
|
|
|
|
@ -909,79 +911,68 @@ static void release_port(struct streamrelay *r) {
|
|
|
|
|
r->localport = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void get_port_pair(struct peer *p, int wanted_port) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
struct callmaster *m;
|
|
|
|
|
struct streamrelay *a, *b;
|
|
|
|
|
u_int16_t port, min, max;
|
|
|
|
|
|
|
|
|
|
c = p->up->call;
|
|
|
|
|
m = c->callmaster;
|
|
|
|
|
a = &p->rtps[0];
|
|
|
|
|
b = &p->rtps[1];
|
|
|
|
|
|
|
|
|
|
assert(a->fd == -1 && b->fd == -1);
|
|
|
|
|
static void get_consecutive_ports(struct streamrelay *array, int array_len, int wanted_start_port, struct call *c) {
|
|
|
|
|
int i, j, cycle = 0;
|
|
|
|
|
struct streamrelay *it;
|
|
|
|
|
u_int16_t port;
|
|
|
|
|
struct callmaster *m = c->callmaster;
|
|
|
|
|
|
|
|
|
|
if (wanted_port > 0) {
|
|
|
|
|
if ((wanted_port & 1))
|
|
|
|
|
goto fail;
|
|
|
|
|
if (get_port(a, wanted_port))
|
|
|
|
|
goto fail;
|
|
|
|
|
if (get_port(b, wanted_port + 1))
|
|
|
|
|
goto fail;
|
|
|
|
|
goto done;
|
|
|
|
|
if (wanted_start_port > 0)
|
|
|
|
|
port = wanted_start_port;
|
|
|
|
|
else {
|
|
|
|
|
mutex_lock(&m->portlock);
|
|
|
|
|
port = m->lastport;
|
|
|
|
|
mutex_unlock(&m->portlock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
min = (m->conf.port_min > 0 && m->conf.port_min < 0xfff0) ? m->conf.port_min : 1024;
|
|
|
|
|
max = (m->conf.port_max > 0 && m->conf.port_max > min && m->conf.port_max < 0xfff0) ? m->conf.port_max : 0;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&m->portlock);
|
|
|
|
|
if (!m->lastport)
|
|
|
|
|
m->lastport = max;
|
|
|
|
|
port = m->lastport + 1;
|
|
|
|
|
mutex_unlock(&m->portlock);
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
if (port < min)
|
|
|
|
|
port = min;
|
|
|
|
|
else if (max && port > max)
|
|
|
|
|
port = min;
|
|
|
|
|
|
|
|
|
|
if (port == m->lastport)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
if ((port & 1))
|
|
|
|
|
goto next;
|
|
|
|
|
while (1) {
|
|
|
|
|
if (!wanted_start_port) {
|
|
|
|
|
if (port < m->conf.port_min)
|
|
|
|
|
port = m->conf.port_min;
|
|
|
|
|
if ((port & 1))
|
|
|
|
|
port++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (get_port(a, port))
|
|
|
|
|
goto next;
|
|
|
|
|
for (i = 0; i < array_len; i++) {
|
|
|
|
|
it = &array[i];
|
|
|
|
|
|
|
|
|
|
port++;
|
|
|
|
|
if (get_port(b, port))
|
|
|
|
|
goto tryagain;
|
|
|
|
|
if (!wanted_start_port && port > m->conf.port_max) {
|
|
|
|
|
port = 0;
|
|
|
|
|
cycle++;
|
|
|
|
|
goto release_restart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (get_port(it, port++))
|
|
|
|
|
goto release_restart;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
tryagain:
|
|
|
|
|
release_port(a);
|
|
|
|
|
next:
|
|
|
|
|
port++;
|
|
|
|
|
release_restart:
|
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
|
release_port(&array[j]);
|
|
|
|
|
|
|
|
|
|
if (cycle >= 2 || wanted_start_port > 0)
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* success */
|
|
|
|
|
mutex_lock(&m->portlock);
|
|
|
|
|
m->lastport = port;
|
|
|
|
|
mutex_unlock(&m->portlock);
|
|
|
|
|
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_CI "Opened ports %u/%u for RTP",
|
|
|
|
|
LOG_PARAMS_CI(c), a->localport, b->localport);
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
mylog(LOG_DEBUG, LOG_PREFIX_CI "Opened ports %u..%u for RTP",
|
|
|
|
|
LOG_PARAMS_CI(c), array[0].localport, array[array_len - 1].localport);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
mylog(LOG_ERR, LOG_PREFIX_CI "Failed to get RTP port pair", LOG_PARAMS_CI(c));
|
|
|
|
|
release_port(a);
|
|
|
|
|
release_port(b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void get_port_pair(struct peer *p, int wanted_port) {
|
|
|
|
|
struct call *c;
|
|
|
|
|
|
|
|
|
|
c = p->up->call;
|
|
|
|
|
get_consecutive_ports(p->rtps, 2, wanted_port, c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* caller is responsible for appropriate locking */
|
|
|
|
|
|