Index: channels/chan_skinny.c
===================================================================
--- channels/chan_skinny.c	(revision 367677)
+++ channels/chan_skinny.c	(working copy)
@@ -2085,7 +2085,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);
@@ -2112,11 +2112,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;
 					ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
 					l->prefs = l->confprefs;
 					if (!l->prefs.order[0]) {
@@ -2135,7 +2130,6 @@
 						ast_extension_state_add(subline->context, subline->exten, skinny_extensionstate_cb, subline->container);
 					}
 					ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s", l->name);
-				}
 				--instance;
 			}
 			break;
@@ -2153,12 +2147,15 @@
 	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;
 		d->registered = 0;
+		d->hookstate = SKINNY_ONHOOK;
 
 		AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
 			if (sd->stateid > -1)
@@ -2166,7 +2163,24 @@
 		}
 		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;
+						ast_channel_tech_pvt_set(chan, 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;
 				ast_format_cap_remove_all(l->cap);
 				ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
 				l->instance = 0;
@@ -3179,7 +3193,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;
@@ -3858,7 +3872,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) {
@@ -3881,7 +3895,7 @@
 				"Label: %s\r\n",
 				idtext,
 				l->name,
-				(l->device?l->device->name:"None"),
+				l->device->name,
 				l->instance,
 				l->label);
 		}
@@ -4373,7 +4387,7 @@
 	struct ast_var_t *current;
 	int doautoanswer = 0;
 
-	if (!d->registered) {
+	if (!d->session) {
 		ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
 		return -1;
 	}
@@ -4613,7 +4627,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;
@@ -4843,7 +4857,7 @@
 	struct ast_variable *v = NULL;
 	struct ast_format tmpfmt;
 
-	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;
 	}
@@ -7462,6 +7476,7 @@
 							}
 							lineInstance++;
 							AST_LIST_INSERT_HEAD(&CDEV->lines, l, list);
+							l->device = CDEV;
 						}
  						break;
  					}
@@ -7703,7 +7718,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) {
