|
|
@ -871,6 +871,8 @@ static int get_port(struct streamrelay *r, u_int16_t p) { |
|
|
int ret; |
|
|
int ret; |
|
|
struct callmaster *m = r->up->up->call->callmaster; |
|
|
struct callmaster *m = r->up->up->call->callmaster; |
|
|
|
|
|
|
|
|
|
|
|
assert(r->fd == -1); |
|
|
|
|
|
|
|
|
mutex_lock(&m->portlock); |
|
|
mutex_lock(&m->portlock); |
|
|
if (bit_array_isset(m->ports_used, p)) { |
|
|
if (bit_array_isset(m->ports_used, p)) { |
|
|
mutex_unlock(&m->portlock); |
|
|
mutex_unlock(&m->portlock); |
|
|
@ -909,79 +911,68 @@ static void release_port(struct streamrelay *r) { |
|
|
r->localport = 0; |
|
|
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; |
|
|
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); |
|
|
mutex_lock(&m->portlock); |
|
|
m->lastport = port; |
|
|
m->lastport = port; |
|
|
mutex_unlock(&m->portlock); |
|
|
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; |
|
|
return; |
|
|
|
|
|
|
|
|
fail: |
|
|
fail: |
|
|
mylog(LOG_ERR, LOG_PREFIX_CI "Failed to get RTP port pair", LOG_PARAMS_CI(c)); |
|
|
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 */ |
|
|
/* caller is responsible for appropriate locking */ |
|
|
|