summaryrefslogtreecommitdiff
path: root/channels/chan_skinny.c
diff options
context:
space:
mode:
authorDamien Wedhorn <voip@facts.com.au>2013-12-19 00:32:00 +0000
committerDamien Wedhorn <voip@facts.com.au>2013-12-19 00:32:00 +0000
commitaf723c6572e988753c24cbb911d6b521600f4a3f (patch)
tree19d39d2a84da7c32a144dc7941a538ced8286053 /channels/chan_skinny.c
parent04dfe2d77f01c940db571582c6b7169c581a67f9 (diff)
Fixup skinny registration following network issues.
On session registration, if device is already reporting that it is connected to a device, an innocuous packet (update time) is sent to the already connected device. If the tcp connection is down, the device will be unregistered and the new connection allowed. Without this patch, network issues can see a situation where a device can not reregister until after 3*timeout. ........ Merged revisions 404292 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404293 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_skinny.c')
-rw-r--r--channels/chan_skinny.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 49f2c84f6..9d04f2336 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -1651,6 +1651,8 @@ static void activatesub(struct skinny_subchannel *sub, int state);
static void dialandactivatesub(struct skinny_subchannel *sub, char exten[AST_MAX_EXTENSION]);
static int skinny_nokeepalive_cb(const void *data);
+static void transmit_definetimedate(struct skinny_device *d);
+
static struct ast_channel_tech skinny_tech = {
.type = "Skinny",
.description = tdesc,
@@ -2252,6 +2254,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
struct sockaddr_in sin;
socklen_t slen;
int instance;
+ int res = -1;
if (s->auth_timeout_sched && ast_sched_del(sched, s->auth_timeout_sched)) {
return 0;
@@ -2262,10 +2265,16 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
AST_LIST_TRAVERSE(&devices, d, list){
struct ast_sockaddr addr;
ast_sockaddr_from_sin(&addr, &s->sin);
- if (!d->session && !strcasecmp(req->data.reg.name, d->id)
+ if (!strcasecmp(req->data.reg.name, d->id)
&& ast_apply_ha(d->ha, &addr)) {
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+ if (d->session) {
+ ast_log(LOG_WARNING, "Device already registered.\n");
+ transmit_definetimedate(d);
+ res = 0;
+ break;
+ }
s->device = d;
d->type = letohl(req->data.reg.type);
d->protocolversion = letohl(req->data.reg.protocolVersion);
@@ -2311,14 +2320,12 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
ast_endpoint_set_state(d->endpoint, AST_ENDPOINT_ONLINE);
blob = ast_json_pack("{s: s}", "peer_status", "Registered");
ast_endpoint_blob_publish(d->endpoint, ast_endpoint_state_type(), blob);
+ res = 1;
break;
}
}
AST_LIST_UNLOCK(&devices);
- if (!d) {
- return 0;
- }
- return 1;
+ return res;
}
static void end_session(struct skinnysession *s)
@@ -7276,15 +7283,21 @@ static int handle_message(struct skinny_req *req, struct skinnysession *s)
case REGISTER_MESSAGE:
SKINNY_DEBUG(DEBUG_PACKET, 3, "Received REGISTER_MESSAGE from %s, name %s, type %d, protovers %d\n",
d->name, req->data.reg.name, letohl(req->data.reg.type), letohl(req->data.reg.protocolVersion));
- if (skinny_register(req, s)) {
- ast_atomic_fetchadd_int(&unauth_sessions, -1);
- ast_verb(3, "Device '%s' successfully registered (protoVers %d)\n", s->device->name, s->device->protocolversion);
- transmit_registerack(s->device);
- transmit_capabilitiesreq(s->device);
- } else {
+ res = skinny_register(req, s);
+ if (!res) {
+ sleep(2);
+ res = skinny_register(req, s);
+ }
+ if (res != 1) {
transmit_registerrej(s);
return -1;
}
+ ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ ast_verb(3, "Device '%s' successfully registered (protoVers %d)\n", s->device->name, s->device->protocolversion);
+ transmit_registerack(s->device);
+ transmit_capabilitiesreq(s->device);
+ res = 0;
+ break;
case IP_PORT_MESSAGE:
SKINNY_DEBUG(DEBUG_PACKET, 3, "Received IP_PORT_MESSAGE from %s\n", d->name);
res = handle_ip_port_message(req, s);
@@ -7564,7 +7577,7 @@ static void *skinny_session(void *data)
if (res >= dlen) {
break;
}
- ast_log(LOG_WARNING, "Partial data received, waiting\n");
+ ast_log(LOG_WARNING, "Partial data received, waiting (%d bytes read of %d)\n", res, dlen);
if (sched_yield() < 0) {
ast_log(LOG_WARNING, "Data yield() returned error: %s\n", strerror(errno));
break;