Index: channels/chan_skinny.c
===================================================================
--- channels/chan_skinny.c	(revision 367677)
+++ channels/chan_skinny.c	(working copy)
@@ -1880,7 +1880,7 @@
 	AST_LIST_TRAVERSE(&devices, d, list){
 		struct ast_sockaddr addr;
 		ast_sockaddr_from_sin(&addr, &s->sin);
-		if (!strcasecmp(req->data.reg.name, d->id)
+		if (!d->session && !strcasecmp(req->data.reg.name, d->id)
 				&& ast_apply_ha(d->ha, &addr)) {
 			s->device = d;
 			d->type = letohl(req->data.reg.type);
@@ -1906,10 +1906,6 @@
 			}
 			AST_LIST_TRAVERSE(&d->lines, l, list) {
 				/* FIXME: All sorts of issues will occur if this line is already connected to a device */
-				if (l->device) {
-					manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Rejected\r\nCause: LINE_ALREADY_CONNECTED\r\n", l->name, l->device->name); 
-					ast_verb(1, "Line %s already connected to %s. Not connecting to %s.\n", l->name, l->device->name, d->name);
-				} else {
 					l->device = d;
 					l->capability = l->confcapability & d->capability;
 					l->prefs = l->confprefs;
@@ -1926,7 +1922,6 @@
 					/* initialize MWI on line and device */
 					mwi_event_cb(0, l);
 					ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
-				}
 				--instance;
 			}
 			break;
@@ -1944,11 +1939,14 @@
 	struct skinny_device *d;
 	struct skinny_line *l;
 	struct skinny_speeddial *sd;
+	struct skinny_subchannel *sub;
+	struct ast_channel *chan;
 
 	d = s->device;
 
 	if (d) {
 		d->session = NULL;
+		s->device = NULL;
 		d->registered = 0;
 
 		AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
@@ -1957,7 +1955,25 @@
 		}
 		AST_LIST_TRAVERSE(&d->lines, l, list) {
 			if (l->device == d) {
-				l->device = NULL;
+				AST_LIST_TRAVERSE(&l->sub, sub, list) {
+					AST_LIST_REMOVE(&l->sub, sub, list);
+					ast_mutex_lock(&sub->lock);
+					if (sub->owner) {
+						chan = sub->owner;
+						sub->owner = NULL;
+						chan->tech_pvt = NULL;
+						ast_softhangup(chan, AST_SOFTHANGUP_APPUNLOAD);
+					}
+					if (sub->rtp) {
+						ast_rtp_instance_destroy(sub->rtp);
+						sub->rtp = NULL;
+					}
+					ast_mutex_unlock(&sub->lock);
+					ast_free(sub);
+					ast_module_unref(ast_module_info->self);
+				}
+				l->activesub = NULL;
+				l->hookstate = SKINNY_ONHOOK;
 				l->capability = 0;
 				ast_parse_allow_disallow(&l->prefs, &l->capability, "all", 0);			
 				l->instance = 0;
@@ -2727,7 +2743,7 @@
 {
 	struct skinny_line *l = userdata;
 	struct skinny_device *d = l->device;
-	if (d) {
+	if (d && d->session) {
 		struct skinnysession *s = d->session;
 		struct skinny_line *l2;
 		int new_msgs = 0;
@@ -3413,7 +3429,7 @@
 		if (!s) {
 			ast_cli(fd, "%-20s %-20s %8d %-20s\n",
 				l->name,
-				(l->device ? l->device->name : "Not connected"),
+				l->device->name,
 				l->instance,
 				l->label);
 			if (verbose) {
@@ -3436,7 +3452,7 @@
 				"Label: %s\r\n",
 				idtext,
 				l->name,
-				(l->device?l->device->name:"None"),
+				l->device->name,
 				l->instance,
 				l->label);
 		}
@@ -3826,6 +3842,10 @@
 		res = 1;
 		}
 
+		if (sub != l->activesub) {
+			break;
+		}
+
 		timeout = 0;
 		len = strlen(d->exten);
 
@@ -3913,7 +3933,7 @@
 	struct skinny_line *l = sub->parent;
 	struct skinny_device *d = l->device;
 
-	if (!d->registered) {
+	if (!d->session) {
 		ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
 		return -1;
 	}
@@ -4224,7 +4244,7 @@
 
 	if (!l)
 		res = AST_DEVICE_INVALID;
-	else if (!l->device)
+	else if (!l->device || !l->device->session)
 		res = AST_DEVICE_UNAVAILABLE;
 	else if (l->dnd)
 		res = AST_DEVICE_BUSY;
@@ -4494,7 +4514,7 @@
 	struct ast_variable *v = NULL;
 	int fmt;
 
-	if (!l->device) {
+	if (!l->device || !l->device->session) {
 		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
 		return NULL;
 	}
@@ -7002,6 +7022,7 @@
 							}
 							lineInstance++;
 							AST_LIST_INSERT_HEAD(&CDEV->lines, l, list);
+							l->device = CDEV;
 						}
  						break;
  					}
@@ -7173,7 +7194,6 @@
 
 			AST_LIST_LOCK(&d->lines);
 			AST_LIST_TRAVERSE(&d->lines, l, list){
-				l->device = d;	
 
 				AST_LIST_LOCK(&temp->lines);
 				AST_LIST_TRAVERSE(&temp->lines, ltemp, list) {
