NetworkManager r3570 - in trunk: . src



Author: dcbw
Date: Thu Apr 17 12:08:52 2008
New Revision: 3570
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3570&view=rev

Log:
2008-04-17  Dan Williams  <dcbw redhat com>

	* src/nm-serial-device.c
	  src/nm-serial-device.h
		- (wait_for_reply_got_data): break input into lines, and search each
			line for responses _and_ terminator strings; also make sure that
			the read loop doesn't continue after the timeout is supposed to fire
		- (nm_serial_device_wait_for_reply): take an array of terminators too

	* src/nm-gsm-device.c
	  src/nm-cdma-device.c
		- Send terminators to nm_serial_device_wait_for_reply()



Modified:
   trunk/ChangeLog
   trunk/src/nm-cdma-device.c
   trunk/src/nm-gsm-device.c
   trunk/src/nm-serial-device.c
   trunk/src/nm-serial-device.h

Modified: trunk/src/nm-cdma-device.c
==============================================================================
--- trunk/src/nm-cdma-device.c	(original)
+++ trunk/src/nm-cdma-device.c	Thu Apr 17 12:08:52 2008
@@ -135,7 +135,7 @@
 	g_free (command);
 
 	if (success) {
-		id = nm_serial_device_wait_for_reply (device, 60, responses, dial_done, NULL);
+		id = nm_serial_device_wait_for_reply (device, 60, responses, responses, dial_done, NULL);
 		if (id)
 			cdma_device_set_pending (NM_CDMA_DEVICE (device), id);
 		else
@@ -171,14 +171,14 @@
 init_modem (NMSerialDevice *device, gpointer user_data)
 {
 	guint id;
-	char *responses[] = { "OK", "ERR", NULL };
+	char *responses[] = { "OK", "ERROR", "ERR", NULL };
 
 	if (!nm_serial_device_send_command_string (device, "ATZ E0")) {
 		nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
 		return;
 	}
 
-	id = nm_serial_device_wait_for_reply (device, 10, responses, init_done, NULL);
+	id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
 
 	if (id)
 		cdma_device_set_pending (NM_CDMA_DEVICE (device), id);

Modified: trunk/src/nm-gsm-device.c
==============================================================================
--- trunk/src/nm-gsm-device.c	(original)
+++ trunk/src/nm-gsm-device.c	Thu Apr 17 12:08:52 2008
@@ -144,7 +144,7 @@
 	g_free (command);
 
 	if (success) {
-		id = nm_serial_device_wait_for_reply (device, 60, responses, dial_done, NULL);
+		id = nm_serial_device_wait_for_reply (device, 60, responses, responses, dial_done, NULL);
 		if (id)
 			gsm_device_set_pending (NM_GSM_DEVICE (device), id);
 		else
@@ -192,7 +192,7 @@
 	g_free (command);
 
 	if (success) {
-		id = nm_serial_device_wait_for_reply (device, 30, responses, manual_registration_done, NULL);
+		id = nm_serial_device_wait_for_reply (device, 30, responses, responses, manual_registration_done, NULL);
 		if (id)
 			gsm_device_set_pending (NM_GSM_DEVICE (device), id);
 		else
@@ -282,13 +282,14 @@
 {
 	guint id;
 	char *responses[] = { "+CREG: 0,1", "+CREG: 0,5", "+CREG: 0,2", "+CREG: 0,0", NULL };
+	char *terminators[] = { "OK", "ERROR", "ERR", NULL };
 
 	if (!nm_serial_device_send_command_string (device, "AT+CREG?")) {
 		nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
 		return;
 	}
 
-	id = nm_serial_device_wait_for_reply (device, 60, responses, automatic_registration_response, NULL);
+	id = nm_serial_device_wait_for_reply (device, 60, responses, terminators, automatic_registration_response, NULL);
 	if (id)
 		gsm_device_set_pending (NM_GSM_DEVICE (device), id);
 	else
@@ -391,7 +392,7 @@
 		g_free (command);
 
 		if (success) {
-			id = nm_serial_device_wait_for_reply (device, 3, responses, enter_pin_done, NULL);
+			id = nm_serial_device_wait_for_reply (device, 3, responses, responses, enter_pin_done, NULL);
 			if (id)
 				gsm_device_set_pending (NM_GSM_DEVICE (device), id);
 			else
@@ -441,13 +442,14 @@
 {
 	guint id;
 	char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
+	char *terminators[] = { "OK", "ERROR", "ERR", NULL };
 
 	if (!nm_serial_device_send_command_string (device, "AT+CPIN?")) {
 		nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
 		return;
 	}
 
-	id = nm_serial_device_wait_for_reply (device, 3, responses, check_pin_done, NULL);
+	id = nm_serial_device_wait_for_reply (device, 3, responses, terminators, check_pin_done, NULL);
 	if (id)
 		gsm_device_set_pending (NM_GSM_DEVICE (device), id);
 	else
@@ -480,14 +482,14 @@
 init_modem (NMSerialDevice *device, gpointer user_data)
 {
 	guint id;
-	char *responses[] = { "OK", "ERR", NULL };
+	char *responses[] = { "OK", "ERROR", "ERR", NULL };
 
 	if (!nm_serial_device_send_command_string (device, "ATZ E0")) {
 		nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
 		return;
 	}
 
-	id = nm_serial_device_wait_for_reply (device, 10, responses, init_done, NULL);
+	id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
 	if (id)
 		gsm_device_set_pending (NM_GSM_DEVICE (device), id);
 	else

Modified: trunk/src/nm-serial-device.c
==============================================================================
--- trunk/src/nm-serial-device.c	(original)
+++ trunk/src/nm-serial-device.c	Thu Apr 17 12:08:52 2008
@@ -524,9 +524,12 @@
 typedef struct {
 	NMSerialDevice *device;
 	char **str_needles;
+	char **terminators;
 	GString *result;
 	NMSerialWaitForReplyFn callback;
 	gpointer user_data;
+	guint timeout;
+	time_t start;
 	guint timeout_id;
 	guint got_data_id;
 } WaitForReplyInfo;
@@ -543,6 +546,7 @@
 		g_string_free (info->result, TRUE);
 
 	g_strfreev (info->str_needles);
+	g_strfreev (info->terminators);
 	g_free (info);
 }
 
@@ -557,6 +561,35 @@
 }
 
 static gboolean
+find_terminator (const char *line, char **terminators)
+{
+	int i;
+
+	for (i = 0; terminators[i]; i++) {
+		if (!strcasecmp (line, terminators[i]))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+find_response (const char *line, char **responses, gint *idx)
+{
+	int i;
+
+	/* Don't look for a result again if we got one previously */
+	for (i = 0; responses[i]; i++) {
+		if (strcasestr (line, responses[i])) {
+			*idx = i;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+#define RESPONSE_LINE_MAX 128
+
+static gboolean
 wait_for_reply_got_data (GIOChannel *source,
 					GIOCondition condition,
 					gpointer data)
@@ -565,9 +598,9 @@
 	gchar buf[SERIAL_BUF_SIZE + 1];
 	gsize bytes_read;
 	GIOStatus status;
+	gboolean got_response = FALSE;
 	gboolean done = FALSE;
 	int idx = -1;
-	int i;
 
 	if (!(condition & G_IO_IN))
 		goto done;
@@ -587,14 +620,42 @@
 			g_string_append (info->result, buf);
 
 			serial_debug ("Got:", info->result->str, info->result->len);
+		}
+
+		/* Look for needles and terminators */
+		if ((bytes_read > 0) && info->result->str) {
+			char *p = info->result->str;
+
+			/* Break the response up into lines and process each one */
+			while (   (p < info->result->str + strlen (info->result->str))
+			       && !(done && got_response)) {
+				char line[RESPONSE_LINE_MAX] = { '\0', };
+				char *tmp;
+				int i;
+				gboolean got_something = FALSE;
+
+				for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) {
+					/* Ignore front CR/LF */
+					if ((*p == '\n') || (*p == '\r')) {
+						if (got_something)
+							break;
+					} else {
+						line[i++] = *p;
+						got_something = TRUE;
+					}
+				}
+				line[i] = '\0';
 
-			for (i = 0; info->str_needles[i]; i++) {
-				if (   info->result->str
-				    && strcasestr (info->result->str, info->str_needles[i])) {
-					idx = i;
-					done = TRUE;
+				tmp = g_strstrip (line);
+				if (tmp && strlen (tmp)) {
+					done = find_terminator (tmp, info->terminators);
+					if (idx == -1)
+						got_response = find_response (tmp, info->str_needles, &idx);
 				}
 			}
+
+			if (done && got_response)
+				break;
 		}
 
 		/* Limit the size of the buffer */
@@ -602,7 +663,19 @@
 			g_warning ("%s (%s): response buffer filled before repsonse received",
 			           __func__, nm_device_get_iface (NM_DEVICE (info->device)));
 			done = TRUE;
+			break;
 		}
+
+		/* Make sure we don't go over the timeout, in addition to the timeout
+		 * handler that's been scheduled.  If for some reason this loop doesn't
+		 * terminate (terminator not found, whatever) then this should make
+		 * sure that NM doesn't spin the CPU forever.
+		 */
+		if (time (NULL) - info->start > info->timeout + 1) {
+			done = TRUE;
+			break;
+		} else
+			g_usleep (50);
 	} while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
 
 done:
@@ -624,29 +697,20 @@
 nm_serial_device_wait_for_reply (NMSerialDevice *device,
 						   guint timeout,
 						   char **responses,
+						   char **terminators,
 						   NMSerialWaitForReplyFn callback,
 						   gpointer user_data)
 {
 	WaitForReplyInfo *info;
-	char **str_array;
-	int i;
 
 	g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0);
 	g_return_val_if_fail (responses != NULL, 0);
 	g_return_val_if_fail (callback != NULL, 0);
 
-	/* Copy the array */
-	str_array = g_new (char*, g_strv_length (responses) + 1);
-	i = 0;
-	while (responses[i]) {
-		str_array[i] = g_strdup (responses[i]);
-		i++;
-	}
-	str_array[i] = NULL;
-
 	info = g_new0 (WaitForReplyInfo, 1);
 	info->device = device;
-	info->str_needles = str_array;
+	info->str_needles = g_strdupv (responses);
+	info->terminators = g_strdupv (terminators);
 	info->result = g_string_new (NULL);
 	info->callback = callback;
 	info->user_data = user_data;
@@ -656,6 +720,8 @@
 								 wait_for_reply_got_data,
 								 info);
 
+	info->timeout = timeout * 1000;
+	info->start = time (NULL);
 	info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
 								    timeout * 1000,
 								    wait_for_reply_timeout,

Modified: trunk/src/nm-serial-device.h
==============================================================================
--- trunk/src/nm-serial-device.h	(original)
+++ trunk/src/nm-serial-device.h	Thu Apr 17 12:08:52 2008
@@ -61,6 +61,7 @@
 guint    nm_serial_device_wait_for_reply      (NMSerialDevice *device,
 									  guint timeout,
 									  char **responses,
+									  char **terminators,
 									  NMSerialWaitForReplyFn callback,
 									  gpointer user_data);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]