[asterisk-commits] branch north/chan_skinny-fixup r30193 - /team/north/chan_skinny-fixup/channels/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu May 25 01:33:18 MST 2006


Author: north
Date: Thu May 25 03:33:17 2006
New Revision: 30193

URL: http://svn.digium.com/view/asterisk?rev=30193&view=rev
Log:
Lots of rearranging.  Split a function with several hundred lines into multiple handle_* functions.
Added extremely basic support for redial (this might've already been there..I don't recall).

Less segfaulting... "Well, it works here."
I think I fixed the poll()ing too.  It was...bad.

Modified:
    team/north/chan_skinny-fixup/channels/chan_skinny.c

Modified: team/north/chan_skinny-fixup/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/channels/chan_skinny.c?rev=30193&r1=30192&r2=30193&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/channels/chan_skinny.c (original)
+++ team/north/chan_skinny-fixup/channels/chan_skinny.c Thu May 25 03:33:17 2006
@@ -4,6 +4,7 @@
  * Copyright (C) 1999 - 2005, Digium, Inc.
  *
  * chan_skinny was developed by Jeremy McNamara & Florian Overkamp
+ * chan_skinny was heavily modified/fixed by North Antara
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -20,7 +21,7 @@
  *
  * \brief Implementation of the Skinny protocol
  *
- * \author Jeremy McNamara & Florian Overkamp
+ * \author Jeremy McNamara & Florian Overkamp & North Antara
  * \ingroup channel_drivers
  */
 
@@ -921,7 +922,7 @@
 	char version_id[16];
 	int type;
 	int registered;
-	char model[10];
+//	char model[10];
 	struct sockaddr_in addr;
 	struct in_addr ourip;
 	struct skinny_line *lines;
@@ -1098,18 +1099,12 @@
 static skinny_req *req_alloc(size_t size, int response_message)
 {
 	skinny_req *req;
-	skinny_data *data;
-
-	if (!(req = ast_calloc(1, sizeof(skinny_req))))
-		return NULL;
-
-	if (!(data = ast_calloc(1, size)))
+
+	if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
 		return NULL;
 
 	req->len = htolel(size+4);
 	req->e = htolel(response_message);
-
-	req->data = *data;
 
 	return req;
 }
@@ -1313,14 +1308,14 @@
 		if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
 			return;
 	} else {
-		if (!(req = req_alloc(4, STOP_TONE_MESSAGE)))
+		if (!(req = req_alloc(0, STOP_TONE_MESSAGE)))
 			return;
 	}
 
 	if (tone > 0) {
 		req->data.starttone.tone = htolel(tone);
 	} else {
-		req->len = htolel(4);
+//		req->len = htolel(4);
 	}
 	transmit_response(s, req);
 }
@@ -1374,10 +1369,9 @@
 	skinny_req *req;
 
 	if (text == 0) {
-		if (!(req = req_alloc(4, CLEAR_DISPLAY_MESSAGE)))
+		if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
 			return;
 
-		req->len = htolel(4);
 		if (skinnydebug)
 			ast_verbose("Clearing Display\n");
 	} else {
@@ -1444,7 +1438,6 @@
 {
 	return ast_app_has_voicemail(l->mailbox, NULL);
 }
-
 
 static void do_housekeeping(struct skinnysession *s)
 {
@@ -1540,20 +1533,19 @@
 	ast_mutex_lock(&devicelock);
 	d = devices;
 
-	ast_cli(fd, "Name                 DeviceId         IP              TypeId R Model  NL\n");
-	ast_cli(fd, "-------------------- ---------------- --------------- ------ - ------ --\n");
+	ast_cli(fd, "Name                 DeviceId         IP              TypeId R NL\n");
+	ast_cli(fd, "-------------------- ---------------- --------------- ------ - --\n");
 	while(d) {
 		l = d->lines;
 		numlines = 0;
 		while(l) { numlines++; l = l->next; }
 
-		ast_cli(fd, "%-20s %-16s %-16s %6X %c %-6s %2d\n",
+		ast_cli(fd, "%-20s %-16s %-15s %6X %c %2d\n",
 				d->name,
 				d->id,
 				ast_inet_ntoa(iabuf, sizeof(iabuf), d->addr.sin_addr),
 				d->type,
 				d->registered?'Y':'N',
-				d->model,
 				numlines);
 
 		d = d->next;
@@ -1572,10 +1564,13 @@
 	}
 	ast_mutex_lock(&devicelock);
 	d = devices;
+
+	ast_cli(fd, "Device Name          Instance Name                 Label                O R\n");
+	ast_cli(fd, "-------------------- -------- -------------------- -------------------- - -\n");
 	while(d) {
 		l = d->lines;
 		while (l) {
-			ast_cli(fd, "%-20s %2d %-20s %-20s  %c  %c\n",
+			ast_cli(fd, "%-20s %8d %-20s %-20s %c %c\n",
 				l->parent->name,
 				l->instance,
 				l->name,
@@ -1657,8 +1652,8 @@
 				ast_copy_string(d->version_id, v->value, sizeof(d->version_id));
 			} else if (!strcasecmp(v->name, "nat")) {
 				nat = ast_true(v->value);
-			} else if (!strcasecmp(v->name, "model")) {
-				ast_copy_string(d->model, v->value, sizeof(d->model));
+//			} else if (!strcasecmp(v->name, "model")) {
+//				ast_copy_string(d->model, v->value, sizeof(d->model));
 			} else if (!strcasecmp(v->name, "callerid")) {
 				if (!strcasecmp(v->value, "asreceived")) {
 					cid_num[0] = '\0';
@@ -1899,6 +1894,7 @@
 					getforward = 0;
 				} else {
 					ast_copy_string(chan->exten, exten, sizeof(chan->exten));
+					ast_copy_string(l->lastnumberdialed, exten, sizeof(l->lastnumberdialed));
 					if (!ast_strlen_zero(l->cid_num)) {
 						if (!l->hidecallerid) {
 							chan->cid.cid_num = strdup(l->cid_num);
@@ -2424,9 +2420,13 @@
 	return tmp;
 }
 
-static int handle_alarm_message(skinny_req *req, struct skinnysession *s)
-{
-	/* no response necessary */
+static int handle_keep_alive_message(skinny_req *req, struct skinnysession *s)
+{
+	if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
+		return -1;
+
+	transmit_response(s, req);
+	do_housekeeping(s);
 	return 1;
 }
 
@@ -2463,36 +2463,59 @@
 	if (skinnydebug)
 		ast_verbose("Requesting capabilities\n");
 
-	if (!(req = req_alloc(4, CAPABILITIES_REQ_MESSAGE)))
+	if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
 		return -1;
 
-	req->len = htolel(4);
 	transmit_response(s, req);
 
 	return res;
 }
 
-static int handle_unregister_message(skinny_req *req, struct skinnysession *s)
-{
-	/* XXX Actually unregister the device */
+static int handle_ip_port_message(skinny_req *req, struct skinnysession *s)
+{
+	/* no response necessary */
 	return 1;
 }
 
-static int handle_headset_status_message(skinny_req *req, struct skinnysession *s)
-{
-	/* XXX umm...okay?  Why do I care? */
-	return 1;
-}
-
-static int handle_register_available_lines_message(skinny_req *req, struct skinnysession *s)
-{
-	/* XXX I have no clue what this is for, but my phone was sending it, so... */
-	return 1;
-}
-
-static int handle_ip_port_message(skinny_req *req, struct skinnysession *s)
-{
-	/* no response necessary */
+static int handle_keypad_button_message(skinny_req *req, struct skinnysession *s)
+{
+	struct skinny_line *l;
+	struct ast_frame f = { 0, };
+	char d;
+	int digit;
+
+	digit = letohl(req->data.keypad.button);
+	f.frametype = AST_FRAME_DTMF;
+	if (digit == 14) {
+		d = '*';
+	} else if (digit == 15) {
+		d = '#';
+	} else if (digit >=0 && digit <= 9) {
+		d = '0' + digit;
+	} else {
+		/* digit=10-13 (A,B,C,D ?), or
+		 * digit is bad value
+		 *
+		 * probably should not end up here, but set
+		 * value for backward compatibility, and log
+		 * a warning.
+		 */
+		d = '0' + digit;
+		ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
+	}
+	f.subclass = d;
+	f.src = "skinny";
+	l = s->device->lines;
+	if (l->owner) {
+		/* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
+		ast_queue_frame(l->owner, &f);
+		if (l->next && l->owner) {
+			ast_queue_frame(l->owner, &f);
+		}
+	} else {
+		if (skinnydebug)
+			ast_verbose("No owner: %s\n", l->name);
+	}
 	return 1;
 }
 
@@ -2528,14 +2551,14 @@
 		c = skinny_new(l, AST_STATE_DOWN);
 		if(c) {
 			if (ast_strlen_zero(l->lastnumberdialed)) {
-				ast_log(LOG_WARNING, "User attempted redial, but no previously dialed number found.\n");
+				ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
 				return 0;
 			}
 			if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
 				transmit_tone(s, SKINNY_SILENCE);
 			}
 			if (ast_exists_extension(c, c->context, l->lastnumberdialed, 1, l->cid_num)) {
-				if (!res || !ast_matchmore_extension(c, c->context, l->lastnumberdialed, 1, l->cid_num)) {
+				if (!ast_matchmore_extension(c, c->context, l->lastnumberdialed, 1, l->cid_num)) {
 					ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
 					if (!ast_strlen_zero(l->cid_num)) {
 						if (!l->hidecallerid) {
@@ -2551,14 +2574,9 @@
 					}
 					break;
 				}
-			} else if (res == 0) {
-				ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
-				transmit_tone(s, SKINNY_REORDER);
-				ast_hangup(c);
-				break;
 			}
 		} else {
-			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", s->device->lines->name, s->device->name);
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, s->device->name);
 		}
 		break;
 	case STIMULUS_SPEEDDIAL:
@@ -2583,8 +2601,9 @@
 				transmit_tone(s, SKINNY_SILENCE);
 			}
 			if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) {
-				if (!res || !ast_matchmore_extension(c, c->context, sd->exten, 1, l->cid_num)) {
+				if (!ast_matchmore_extension(c, c->context, sd->exten, 1, l->cid_num)) {
 					ast_copy_string(c->exten, sd->exten, sizeof(c->exten));
+					ast_copy_string(l->lastnumberdialed, sd->exten, sizeof(l->lastnumberdialed));
 					if (!ast_strlen_zero(l->cid_num)) {
 						if (!l->hidecallerid) {
 							c->cid.cid_num = strdup(l->cid_num);
@@ -2599,14 +2618,9 @@
 					}
 					break;
 				}
-			} else if (res == 0) {
-				ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
-				transmit_tone(s, SKINNY_REORDER);
-				ast_hangup(c);
-				break;
 			}
 		} else {
-			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", s->device->lines->name, s->device->name);
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, s->device->name);
 		}
 		break;
 	case STIMULUS_HOLD:
@@ -2644,16 +2658,17 @@
 
 		/* Do not disturb */
 		transmit_tone(s, SKINNY_DIALTONE);
-		if (s->device->lines->dnd != 0){
+		l = s->device->lines;
+		if (l->dnd != 0){
 			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n",s->device->lines->name,s->device->lines->name);
-			s->device->lines->dnd = 0;
+				ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n", l->name, l->name);
+			l->dnd = 0;
 			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
 			transmit_displaynotify(s, "DnD disabled",10);
 		} else {
 			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n",s->device->lines->name,s->device->lines->name);
-			s->device->lines->dnd = 1;
+				ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n", l->name, l->name);
+			l->dnd = 1;
 			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
 			transmit_displaynotify(s, "DnD enabled",10);
 		}
@@ -2729,25 +2744,181 @@
 	return 1;
 }
 
-static int handle_version_req_message(skinny_req *req, struct skinnysession *s)
-{
-	if (!(req = req_alloc(sizeof(version_res_message), VERSION_RES_MESSAGE)))
+static int handle_offhook_message(skinny_req *req, struct skinnysession *s)
+{
+	struct skinny_line *l;
+	struct ast_channel *c;
+	pthread_t t;
+
+	l = s->device->lines;
+
+	if (!l) {
+		ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
+		return 0;
+	}
+
+	transmit_ringer_mode(s,SKINNY_RING_OFF);
+	transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
+	l->hookstate = SKINNY_OFFHOOK;
+
+	if (l->outgoing) {
+		/* We're answering a ringing call */
+		ast_queue_control(l->owner, AST_CONTROL_ANSWER);
+		transmit_callstate(s, l->instance, SKINNY_OFFHOOK, l->callid);
+		transmit_tone(s, SKINNY_SILENCE);
+		transmit_callstate(s, l->instance, SKINNY_CONNECTED, l->callid);
+		transmit_selectsoftkeys(s, l->instance, l->callid, KEYDEF_CONNECTED);
+		start_rtp(l);
+		ast_setstate(l->owner, AST_STATE_UP);
+	} else {
+		if (!l->owner) {
+			transmit_callstate(s, l->instance, SKINNY_OFFHOOK, l->callid);
+			if (skinnydebug)
+				ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, s->device->name);
+			transmit_displaymessage(s, NULL); /* clear display */
+			transmit_tone(s, SKINNY_DIALTONE);
+			transmit_selectsoftkeys(s, l->instance, l->callid, KEYDEF_OFFHOOK);
+			c = skinny_new(l, AST_STATE_DOWN);
+			if(c) {
+				/* start the switch thread */
+				if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
+					ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
+					ast_hangup(c);
+				}
+			} else {
+				ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, s->device->name);
+			}
+		} else {
+			ast_log(LOG_DEBUG, "Current sub [%s] already has owner\n", l->owner->name);
+		}
+	}
+	return 1;
+}
+
+static int handle_onhook_message(skinny_req *req, struct skinnysession *s)
+{
+	struct skinny_line *l;
+
+	l = s->device->lines;
+
+	if (l->hookstate == SKINNY_ONHOOK) {
+		/* Something else already put us back on hook */
+		return 0;
+	}
+	l->cxmode = SKINNY_CX_RECVONLY;
+	l->hookstate = SKINNY_ONHOOK;
+	transmit_callstate(s, l->instance, l->hookstate, l->callid);
+	if (skinnydebug)
+		ast_verbose("Skinny %s@%s went on hook\n", l->name, s->device->name);
+	if (l->transfer && (l->owner && l->next && l->next->owner) && ((!l->outgoing) || (l->next && !l->next->outgoing))) {
+		/* We're allowed to transfer, we have two active calls and
+		   we made at least one of the calls.  Let's try and transfer */
+
+#if 0
+		if ((res = attempt_transfer(p)) < 0) {
+			if (l->next && l->next->owner) {
+				l->next->alreadygone = 1;
+				ast_queue_hangup(l->next->owner,1);
+			}
+		} else if (res) {
+			ast_log(LOG_WARNING, "Transfer attempt failed\n");
+			return 0;
+		}
+#endif
+	} else {
+		/* Hangup the current call */
+		/* If there is another active call, skinny_hangup will ring the phone with the other call */
+		if (l->owner) {
+			l->alreadygone = 1;
+			ast_queue_hangup(l->owner);
+		} else {
+			ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
+				l->name, s->device->name, l->callid);
+		}
+	}
+	if ((l->hookstate == SKINNY_ONHOOK) && (l->next && !l->next->rtp)) {
+		do_housekeeping(s);
+	}
+	return 1;
+}
+
+static int handle_capabilities_res_message(skinny_req *req, struct skinnysession *s)
+{
+	/* XXX process the capabilites */
+	return 1;
+}
+
+static int handle_speed_dial_stat_req_message(skinny_req *req, struct skinnysession *s)
+{
+	struct skinny_speeddial *sd;
+	int instance;
+
+	instance = letohl(req->data.speeddialreq.speedDialNumber);
+
+	if (!(req = req_alloc(sizeof(speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
 		return -1;
 
-	snprintf(req->data.version.version, sizeof(req->data.version.version), s->device->version_id);
+	sd = s->device->speeddials;
+
+	while (sd) {
+		if (sd->instance == instance) {
+			req->data.speeddialreq.speedDialNumber = htolel(instance);
+			snprintf(req->data.speeddial.speedDialDirNumber, sizeof(req->data.speeddial.speedDialDirNumber), sd->exten);
+			snprintf(req->data.speeddial.speedDialDisplayName, sizeof(req->data.speeddial.speedDialDisplayName), "test - use sd->label");
+			break;
+		}
+	}
+
 	transmit_response(s, req);
 	return 1;
 }
 
-static int handle_server_request_message(skinny_req *req, struct skinnysession *s)
-{
-	if (!(req = req_alloc(sizeof(server_res_message), SERVER_RES_MESSAGE)))
+static int handle_line_state_req_message(skinny_req *req, struct skinnysession *s)
+{
+	struct skinny_line *l;
+	int instance;
+
+	instance = letohl(req->data.line.lineNumber);
+
+	ast_mutex_lock(&devicelock);
+
+	l = find_line_by_instance(s->device, instance);
+
+	if (!l) {
+		return 0;
+	}
+
+	ast_mutex_unlock(&devicelock);
+
+	if (!(req = req_alloc(sizeof(line_stat_res_message), LINE_STAT_RES_MESSAGE)))
 		return -1;
 
-	memcpy(req->data.serverres.server[0].serverName, ourhost,
-			sizeof(req->data.serverres.server[0].serverName));
-	req->data.serverres.serverListenPort[0] = htolel(ourport);
-	req->data.serverres.serverIpAddr[0] = htolel(__ourip.s_addr);
+	req->data.linestat.lineNumber = letohl(instance);
+	memcpy(req->data.linestat.lineDirNumber, l->name,
+			sizeof(req->data.linestat.lineDirNumber));
+	memcpy(req->data.linestat.lineDisplayName, l->label,
+			sizeof(req->data.linestat.lineDisplayName));
+	transmit_response(s,req);
+	return 1;
+}
+
+static int handle_time_date_req_message(skinny_req *req, struct skinnysession *s)
+{
+	time_t timer;
+	struct tm *cmtime;
+
+	if (!(req = req_alloc(sizeof(definetimedate_message), DEFINETIMEDATE_MESSAGE)))
+		return -1;
+
+	timer = time(NULL);
+	cmtime = localtime(&timer);
+	req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
+	req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
+	req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
+	req->data.definetimedate.day = htolel(cmtime->tm_mday);
+	req->data.definetimedate.hour = htolel(cmtime->tm_hour);
+	req->data.definetimedate.minute = htolel(cmtime->tm_min);
+	req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
 	transmit_response(s, req);
 	return 1;
 }
@@ -2859,11 +3030,91 @@
 	req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
 
 	if (skinnydebug)
-		ast_verbose("Sending %d template to %s@%s (%s)\n",
+		ast_verbose("Sending %d template to %s\n",
 					s->device->type,
-					s->device->lines->name,
-					s->device->name,
-					s->device->model);
+					s->device->name);
+	transmit_response(s, req);
+	return 1;
+}
+
+static int handle_version_req_message(skinny_req *req, struct skinnysession *s)
+{
+	if (!(req = req_alloc(sizeof(version_res_message), VERSION_RES_MESSAGE)))
+		return -1;
+
+	snprintf(req->data.version.version, sizeof(req->data.version.version), s->device->version_id);
+	transmit_response(s, req);
+	return 1;
+}
+
+static int handle_server_request_message(skinny_req *req, struct skinnysession *s)
+{
+	if (!(req = req_alloc(sizeof(server_res_message), SERVER_RES_MESSAGE)))
+		return -1;
+
+	memcpy(req->data.serverres.server[0].serverName, ourhost,
+			sizeof(req->data.serverres.server[0].serverName));
+	req->data.serverres.serverListenPort[0] = htolel(ourport);
+	req->data.serverres.serverIpAddr[0] = htolel(__ourip.s_addr);
+	transmit_response(s, req);
+	return 1;
+}
+
+static int handle_alarm_message(skinny_req *req, struct skinnysession *s)
+{
+	/* no response necessary */
+	if (skinnydebug)
+		ast_verbose("Received Alarm Message: %s\n", req->data.alarm.displayMessage);
+
+	return 1;
+}
+
+static int handle_open_receive_channel_ack_message(skinny_req *req, struct skinnysession *s)
+{
+	struct skinny_line *l;
+	struct sockaddr_in sin;
+	struct sockaddr_in us;
+	char iabuf[INET_ADDRSTRLEN];
+	char addr[4];
+	int port;
+	int status;
+
+	l = s->device->lines;
+
+	status = letohl(req->data.openreceivechannelack.status);
+	if (status) {
+		ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
+		return 0;
+	}
+	/* ENDIAN */
+	memcpy(addr, req->data.openreceivechannelack.ipAddr, sizeof(addr));
+	port = htolel(req->data.openreceivechannelack.port);
+	sin.sin_family = AF_INET;
+	/* I smell endian problems */
+	memcpy(&sin.sin_addr, addr, sizeof(sin.sin_addr));
+	sin.sin_port = htons(port);
+	if (skinnydebug)
+		ast_verbose("ipaddr = %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
+	if (l->rtp) {
+		ast_rtp_set_peer(l->rtp, &sin);
+		ast_rtp_get_us(l->rtp, &us);
+	} else {
+		ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
+		return 0;
+	}
+	if (!(req = req_alloc(sizeof(start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
+		return -1;
+
+	req->data.startmedia.conferenceId = 0;
+	req->data.startmedia.passThruPartyId = 0;
+	memcpy(req->data.startmedia.remoteIp, &s->device->ourip, 4); /* Endian? */
+	req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
+	req->data.startmedia.packetSize = htolel(20);
+	req->data.startmedia.payloadType = htolel(convert_cap(l->capability));
+	req->data.startmedia.qualifier.precedence = htolel(127);
+	req->data.startmedia.qualifier.vad = 0;
+	req->data.startmedia.qualifier.packets = 0;
+	req->data.startmedia.qualifier.bitRate = 0;
 	transmit_response(s, req);
 	return 1;
 }
@@ -2907,6 +3158,7 @@
 	int event;
 	int instance;
 	int reference;
+	int res;
 
 	event = letohl(req->data.softkeyeventmessage.softKeyEvent);
 	instance = letohl(req->data.softkeyeventmessage.instance);
@@ -2926,11 +3178,45 @@
 			ast_verbose("Received Softkey Event: None(%d)\n", instance);
 		break;
 	case SOFTKEY_REDIAL:
-		/* If we can keep an array of dialed frames we can implement a quick
-		   and dirty redial, feeding the frames we last got into the queue
-		   function */
 		if (skinnydebug)
 			ast_verbose("Received Softkey Event: Redial(%d)\n", instance);
+
+		transmit_callstate(s, l->instance, SKINNY_OFFHOOK, l->callid);
+		if (skinnydebug)
+			ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, s->device->name);
+		transmit_displaymessage(s, NULL); /* clear display */
+		transmit_tone(s, SKINNY_DIALTONE);
+
+		c = skinny_new(l, AST_STATE_DOWN);
+		if(c) {
+			if (ast_strlen_zero(l->lastnumberdialed)) {
+				ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
+				return 0;
+			}
+			if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
+				transmit_tone(s, SKINNY_SILENCE);
+			}
+			if (ast_exists_extension(c, c->context, l->lastnumberdialed, 1, l->cid_num)) {
+				if (!ast_matchmore_extension(c, c->context, l->lastnumberdialed, 1, l->cid_num)) {
+					ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
+					if (!ast_strlen_zero(l->cid_num)) {
+						if (!l->hidecallerid) {
+							c->cid.cid_num = strdup(l->cid_num);
+							c->cid.cid_ani = strdup(l->cid_num);
+						}
+					}
+					ast_setstate(c, AST_STATE_RING);
+					res = ast_pbx_run(c);
+					if (res) {
+						ast_log(LOG_WARNING, "PBX exited non-zero\n");
+						transmit_tone(s, SKINNY_REORDER);
+					}
+					break;
+				}
+			}
+		} else {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, s->device->name);
+		}
 		break;
 	case SOFTKEY_NEWCALL:
 		/* XXX Untested */
@@ -2980,16 +3266,16 @@
 
 		/* Do not disturb */
 		transmit_tone(s, SKINNY_DIALTONE);
-		if (s->device->lines->dnd != 0){
+		if (l->dnd != 0){
 			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n",s->device->lines->name,s->device->lines->name);
-			s->device->lines->dnd = 0;
+				ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n", l->name, s->device->name);
+			l->dnd = 0;
 			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
 			transmit_displaynotify(s, "DnD disabled",10);
 		} else {
 			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n",s->device->lines->name,s->device->lines->name);
-			s->device->lines->dnd = 1;
+				ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n", l->name, s->device->name);
+			l->dnd = 1;
 			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
 			transmit_displaynotify(s, "DnD enabled",10);
 		}
@@ -3113,6 +3399,12 @@
 	return 1;
 }
 
+static int handle_unregister_message(skinny_req *req, struct skinnysession *s)
+{
+	/* XXX Actually unregister the device */
+	return 1;
+}
+
 static int handle_soft_key_template_req_message(skinny_req *req, struct skinnysession *s)
 {
 	if (!(req = req_alloc(sizeof(soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
@@ -3128,273 +3420,15 @@
 	return 1;
 }
 
-static int handle_time_date_req_message(skinny_req *req, struct skinnysession *s)
-{
-	time_t timer;
-	struct tm *cmtime;
-
-	if (!(req = req_alloc(sizeof(definetimedate_message), DEFINETIMEDATE_MESSAGE)))
-		return -1;
-
-	timer = time(NULL);
-	cmtime = localtime(&timer);
-	req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
-	req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
-	req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
-	req->data.definetimedate.day = htolel(cmtime->tm_mday);
-	req->data.definetimedate.hour = htolel(cmtime->tm_hour);
-	req->data.definetimedate.minute = htolel(cmtime->tm_min);
-	req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
-	transmit_response(s, req);
+static int handle_headset_status_message(skinny_req *req, struct skinnysession *s)
+{
+	/* XXX umm...okay?  Why do I care? */
 	return 1;
 }
 
-static int handle_speed_dial_stat_req_message(skinny_req *req, struct skinnysession *s)
-{
-	struct skinny_speeddial *sd;
-	int instance;
-
-	instance = letohl(req->data.speeddialreq.speedDialNumber);
-
-	if (!(req = req_alloc(sizeof(speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
-		return -1;
-
-	sd = s->device->speeddials;
-
-	while (sd) {
-		if (sd->instance == instance) {
-			req->data.speeddialreq.speedDialNumber = htolel(instance);
-			snprintf(req->data.speeddial.speedDialDirNumber, sizeof(req->data.speeddial.speedDialDirNumber), sd->exten);
-			snprintf(req->data.speeddial.speedDialDisplayName, sizeof(req->data.speeddial.speedDialDisplayName), "test - use sd->label");
-			break;
-		}
-	}
-
-	transmit_response(s, req);
-	return 1;
-}
-
-static int handle_line_state_req_message(skinny_req *req, struct skinnysession *s)
-{
-	struct skinny_line *l;
-	int instance;
-
-	instance = letohl(req->data.line.lineNumber);
-
-	ast_mutex_lock(&devicelock);
-
-	l = find_line_by_instance(s->device, instance);
-
-	if (!l) {
-		return 0;
-	}
-
-	ast_mutex_unlock(&devicelock);
-
-	if (!(req = req_alloc(sizeof(line_stat_res_message), LINE_STAT_RES_MESSAGE)))
-		return -1;
-
-	req->data.linestat.lineNumber = letohl(instance);
-	memcpy(req->data.linestat.lineDirNumber, l->name,
-			sizeof(req->data.linestat.lineDirNumber));
-	memcpy(req->data.linestat.lineDisplayName, l->label,
-			sizeof(req->data.linestat.lineDisplayName));
-	transmit_response(s,req);
-	return 1;
-}
-
-static int handle_capabilities_res_message(skinny_req *req, struct skinnysession *s)
-{
-	/* XXX process the capabilites */
-	return 1;
-}
-
-static int handle_keep_alive_message(skinny_req *req, struct skinnysession *s)
-{
-	if (!(req = req_alloc(4, KEEP_ALIVE_ACK_MESSAGE)))
-		return -1;
-
-	req->len = htolel(4);
-
-	transmit_response(s, req);
-	do_housekeeping(s);
-	return 1;
-}
-
-static int handle_offhook_message(skinny_req *req, struct skinnysession *s)
-{
-	struct ast_channel *c;
-	pthread_t t;
-
-	transmit_ringer_mode(s,SKINNY_RING_OFF);
-	transmit_lamp_indication(s, STIMULUS_LINE, s->device->lines->instance, SKINNY_LAMP_ON);
-	if (!s->device->lines) {
-		ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
-		return 0;
-	}
-	s->device->lines->hookstate = SKINNY_OFFHOOK;
-
-	if (s->device->lines->outgoing) {
-		/* We're answering a ringing call */
-		ast_queue_control(s->device->lines->owner, AST_CONTROL_ANSWER);
-		transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, s->device->lines->callid);
-		transmit_tone(s, SKINNY_SILENCE);
-		transmit_callstate(s, s->device->lines->instance, SKINNY_CONNECTED, s->device->lines->callid);
-		transmit_selectsoftkeys(s, s->device->lines->instance, s->device->lines->callid, KEYDEF_CONNECTED);
-		start_rtp(s->device->lines);
-		ast_setstate(s->device->lines->owner, AST_STATE_UP);
-	} else {
-		if (!s->device->lines->owner) {
-			transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, s->device->lines->callid);
-			if (skinnydebug)
-				ast_verbose("Attempting to Clear display on Skinny %s@%s\n",s->device->lines->name, s->device->name);
-			transmit_displaymessage(s, NULL); /* clear display */
-			transmit_tone(s, SKINNY_DIALTONE);
-			transmit_selectsoftkeys(s, s->device->lines->instance, s->device->lines->callid, KEYDEF_OFFHOOK);
-			c = skinny_new(s->device->lines, AST_STATE_DOWN);
-			if(c) {
-				/* start the switch thread */
-				if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
-					ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
-					ast_hangup(c);
-				}
-			} else {
-				ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", s->device->lines->name, s->device->name);
-			}
-		} else {
-			ast_log(LOG_DEBUG, "Current sub [%s] already has owner\n", s->device->lines->owner->name);
-		}
-	}
-	return 1;
-}
-
-static int handle_onhook_message(skinny_req *req, struct skinnysession *s)
-{
-	if (s->device->lines->hookstate == SKINNY_ONHOOK) {
-		/* Something else already put us back on hook */
-		return 0;
-	}
-	s->device->lines->cxmode = SKINNY_CX_RECVONLY;
-	s->device->lines->hookstate = SKINNY_ONHOOK;
-	transmit_callstate(s, s->device->lines->instance, s->device->lines->hookstate,s->device->lines->callid);
-	if (skinnydebug)
-		ast_verbose("Skinny %s@%s went on hook\n",s->device->lines->name, s->device->name);
-	if (s->device->lines->transfer && (s->device->lines->owner && s->device->lines->next && s->device->lines->next->owner) && ((!s->device->lines->outgoing) || (s->device->lines->next && !s->device->lines->next->outgoing))) {
-		/* We're allowed to transfer, we have two active calls and
-		   we made at least one of the calls.  Let's try and transfer */
-
-#if 0
-		if ((res = attempt_transfer(p)) < 0) {
-			if (s->device->lines->next && s->device->lines->next->owner) {
-				s->device->lines->next->alreadygone = 1;
-				ast_queue_hangup(s->device->lines->next->owner,1);
-			}
-		} else if (res) {
-			ast_log(LOG_WARNING, "Transfer attempt failed\n");
-			return 0;
-		}
-#endif
-	} else {
-		/* Hangup the current call */
-		/* If there is another active call, skinny_hangup will ring the phone with the other call */
-		if (s->device->lines->owner) {
-			s->device->lines->alreadygone = 1;
-			ast_queue_hangup(s->device->lines->owner);
-		} else {
-			ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
-				s->device->lines->name, s->device->name, s->device->lines->callid);
-		}
-	}
-	if ((s->device->lines->hookstate == SKINNY_ONHOOK) && (s->device->lines->next && !s->device->lines->next->rtp)) {
-		do_housekeeping(s);
-	}
-	return 1;
-}
-
-static int handle_keypad_button_message(skinny_req *req, struct skinnysession *s)
-{
-	struct ast_frame f = { 0, };
-	char d;
-	int digit;
-
-	digit = letohl(req->data.keypad.button);
-	f.frametype = AST_FRAME_DTMF;
-	if (digit == 14) {
-		d = '*';
-	} else if (digit == 15) {
-		d = '#';
-	} else if (digit >=0 && digit <= 9) {
-		d = '0' + digit;
-	} else {
-		/* digit=10-13 (A,B,C,D ?), or
-		 * digit is bad value
-		 *
-		 * probably should not end up here, but set
-		 * value for backward compatibility, and log
-		 * a warning.
-		 */
-		d = '0' + digit;
-		ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
-	}
-	f.subclass = d;
-	f.src = "skinny";
-	if (s->device->lines->owner) {
-		/* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
-		ast_queue_frame(s->device->lines->owner, &f);
-		if (s->device->lines->next && s->device->lines->next->owner) {
-			ast_queue_frame(s->device->lines->next->owner, &f);
-		}
-	} else {
-		if (skinnydebug)
-			ast_verbose("No owner: %s\n", s->device->lines->name);
-	}
-	return 1;
-}
-
-static int handle_open_receive_channel_ack_message(skinny_req *req, struct skinnysession *s)
-{
-	struct sockaddr_in sin;
-	struct sockaddr_in us;
-	char iabuf[INET_ADDRSTRLEN];
-	char addr[4];
-	int port;
-	int status;
-
-	status = letohl(req->data.openreceivechannelack.status);
-	if (status) {
-		ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
-		return 0;
-	}
-	/* ENDIAN */
-	memcpy(addr, req->data.openreceivechannelack.ipAddr, sizeof(addr));
-	port = htolel(req->data.openreceivechannelack.port);
-	sin.sin_family = AF_INET;
-	/* I smell endian problems */
-	memcpy(&sin.sin_addr, addr, sizeof(sin.sin_addr));
-	sin.sin_port = htons(port);
-	if (skinnydebug)
-		ast_verbose("ipaddr = %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
-	if (s->device->lines->rtp) {
-		ast_rtp_set_peer(s->device->lines->rtp, &sin);
-		ast_rtp_get_us(s->device->lines->rtp, &us);
-	} else {
-		ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
-		return 0;
-	}
-	if (!(req = req_alloc(sizeof(start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
-		return -1;
-
-	req->data.startmedia.conferenceId = 0;
-	req->data.startmedia.passThruPartyId = 0;
-	memcpy(req->data.startmedia.remoteIp, &s->device->ourip, 4); /* Endian? */
-	req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
-	req->data.startmedia.packetSize = htolel(20);
-	req->data.startmedia.payloadType = htolel(convert_cap(s->device->lines->capability));
-	req->data.startmedia.qualifier.precedence = htolel(127);
-	req->data.startmedia.qualifier.vad = 0;
-	req->data.startmedia.qualifier.packets = 0;
-	req->data.startmedia.qualifier.bitRate = 0;
-	transmit_response(s, req);
+static int handle_register_available_lines_message(skinny_req *req, struct skinnysession *s)
+{
+	/* XXX I have no clue what this is for, but my phone was sending it, so... */
 	return 1;
 }
 
@@ -3409,104 +3443,104 @@
 	}
 
 	switch(letohl(req->e))	{
+	case KEEP_ALIVE_MESSAGE:
+		res = handle_keep_alive_message(req, s);
+		break;
+	case REGISTER_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Device %s is attempting to register\n", req->data.reg.name);
+
+		res = handle_register_message(req, s);
+		break;
+	case IP_PORT_MESSAGE:
+		res = handle_ip_port_message(req, s);
+		break;
+	case KEYPAD_BUTTON_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Collected digit: [%d]\n", letohl(req->data.keypad.button));
+
+		res = handle_keypad_button_message(req, s);
+		break;
+	case STIMULUS_MESSAGE:
+		res = handle_stimulus_message(req, s);
+		break;
+	case OFFHOOK_MESSAGE:
+		res = handle_offhook_message(req, s);
+		break;
+	case ONHOOK_MESSAGE:
+		res = handle_onhook_message(req, s);
+		break;
+	case CAPABILITIES_RES_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received CapabilitiesRes\n");
+
+		res = handle_capabilities_res_message(req, s);
+		break;
+	case SPEED_DIAL_STAT_REQ_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received SpeedDialStatRequest\n");
+
+		res = handle_speed_dial_stat_req_message(req, s);
+		break;
+	case LINE_STATE_REQ_MESSAGE:
+		res = handle_line_state_req_message(req, s);
+		break;
+	case TIME_DATE_REQ_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received Time/Date Request\n");
+
+		res = handle_time_date_req_message(req, s);
+		break;
+	case BUTTON_TEMPLATE_REQ_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Buttontemplate requested\n");
+
+		res = handle_button_template_req_message(req, s);
+		break;
+	case VERSION_REQ_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Version Request\n");
+
+		res = handle_version_req_message(req, s);
+		break;
+	case SERVER_REQUEST_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received Server Request\n");
+
+		res = handle_server_request_message(req, s);
+		break;
 	case ALARM_MESSAGE:
 		res = handle_alarm_message(req, s);
 		break;
-	case REGISTER_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Device %s is attempting to register\n", req->data.reg.name);
-
-		res = handle_register_message(req, s);
+	case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received Open Receive Channel Ack\n");
+
+		res = handle_open_receive_channel_ack_message(req, s);
+		break;
+	case SOFT_KEY_SET_REQ_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received SoftKeySetReq\n");
+
+		res = handle_soft_key_set_req_message(req, s);
+		break;
+	case SOFT_KEY_EVENT_MESSAGE:
+		res = handle_soft_key_event_message(req, s);
 		break;
 	case UNREGISTER_MESSAGE:
 		res = handle_unregister_message(req, s);
 		break;
+	case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
+		if (skinnydebug)
+			ast_verbose("Received SoftKey Template Request\n");
+
+		res = handle_soft_key_template_req_message(req, s);
+		break;
 	case HEADSET_STATUS_MESSAGE:
 		res = handle_headset_status_message(req, s);
 		break;
 	case REGISTER_AVAILABLE_LINES_MESSAGE:
 		res = handle_register_available_lines_message(req, s);
-		break;
-	case IP_PORT_MESSAGE:
-		res = handle_ip_port_message(req, s);
-		break;
-	case STIMULUS_MESSAGE:
-		res = handle_stimulus_message(req, s);
-		break;
-	case VERSION_REQ_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Version Request\n");
-
-		res = handle_version_req_message(req, s);
-		break;
-	case SERVER_REQUEST_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received Server Request\n");
-
-		res = handle_server_request_message(req, s);
-		break;
-	case BUTTON_TEMPLATE_REQ_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Buttontemplate requested\n");
-
-		res = handle_button_template_req_message(req, s);
-		break;
-	case SOFT_KEY_SET_REQ_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received SoftKeySetReq\n");
-
-		res = handle_soft_key_set_req_message(req, s);
-		break;
-	case SOFT_KEY_EVENT_MESSAGE:
-		res = handle_soft_key_event_message(req, s);
-		break;
-	case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received SoftKey Template Request\n");
-
-		res = handle_soft_key_template_req_message(req, s);
-		break;
-	case TIME_DATE_REQ_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received Time/Date Request\n");
-
-		res = handle_time_date_req_message(req, s);
-		break;
-	case SPEED_DIAL_STAT_REQ_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received SpeedDialStatRequest\n");
-
-		res = handle_speed_dial_stat_req_message(req, s);
-		break;
-	case LINE_STATE_REQ_MESSAGE:
-		res = handle_line_state_req_message(req, s);
-		break;
-	case CAPABILITIES_RES_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received CapabilitiesRes\n");
-
-		res = handle_capabilities_res_message(req, s);
-		break;
-	case KEEP_ALIVE_MESSAGE:
-		res = handle_keep_alive_message(req, s);
-		break;
-	case OFFHOOK_MESSAGE:
-		res = handle_offhook_message(req, s);
-		break;
-	case ONHOOK_MESSAGE:
-		res = handle_onhook_message(req, s);
-		break;
-	case KEYPAD_BUTTON_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Collected digit: [%d]\n", letohl(req->data.keypad.button));
-
-		res = handle_keypad_button_message(req, s);
-		break;
-	case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
-		if (skinnydebug)
-			ast_verbose("Received Open Receive Channel Ack\n");
-
-		res = handle_open_receive_channel_ack_message(req, s);
 		break;
 	default:
 		if (skinnydebug)
@@ -3555,11 +3589,17 @@
 
  	fds[0].fd = s->fd;
 	fds[0].events = POLLIN;
+	fds[0].revents = 0;
 	res = poll(fds, 1, -1);
 
 	if (res < 0) {
-		ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
- 	} else if (res > 0) {
+		if (errno != EINTR)
+		{
+			ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
+			return res;
+		}
+ 	}
+	if (fds[0].revents) {
 		ast_mutex_lock(&s->lock);
 		memset(s->inbuf,0,sizeof(s->inbuf));
 		res = read(s->fd, s->inbuf, 4);
@@ -3585,8 +3625,9 @@
 			ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
 			return -1;
 		}
-	}
-	return res;
+		return res;
+	}
+	return 0;
 }
 
 static skinny_req *skinny_req_parse(struct skinnysession *s)
@@ -3598,18 +3639,18 @@
 	req = malloc(SKINNY_MAX_PACKET);
 	memset(req, 0, sizeof(skinny_req));
 #endif
-	/* XXX this might be wrong */
-	if (!(req = ast_calloc(1, sizeof(skinny_req))))
+
+	if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
 		return NULL;
 
-	if (!(data = ast_calloc(1, sizeof(skinny_data))))
-		return NULL;
-
 	ast_mutex_lock(&s->lock);
-	/* +8 to account for reserved and length fields */
+	/* +8 to account for reserved and length fields
 	memcpy(req, s->inbuf, skinny_header_size);
 	memcpy(data, s->inbuf+skinny_header_size, letohl(*(int*)(s->inbuf))-4);
-	req->data = *data;
+	*/
+	memcpy(req, s->inbuf, skinny_header_size);
+	memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*(int*)(s->inbuf))-4);
+
 	ast_mutex_unlock(&s->lock);
 
 	if (letohl(req->e) < 0) {
@@ -3617,6 +3658,7 @@
 		free(req);
 		return NULL;
 	}
+
 	return req;
 }
 
@@ -3636,15 +3678,18 @@
 			break;
 		}
 
-		if (!(req = skinny_req_parse(s))) {
-			destroy_session(s);
-			return NULL;
-		}
-
-		res = handle_message(req, s);
-		if (res < 0) {
-			destroy_session(s);
-			return NULL;
+		if (res > 0)
+		{

[... 14 lines stripped ...]


More information about the asterisk-commits mailing list