[svn-commits] rizzo: trunk r45463 - /trunk/main/http.c

svn-commits at lists.digium.com svn-commits at lists.digium.com
Tue Oct 17 21:05:57 MST 2006


Author: rizzo
Date: Tue Oct 17 23:05:56 2006
New Revision: 45463

URL: http://svn.digium.com/view/asterisk?rev=45463&view=rev
Log:
various code simplifications to reduce nesting depth,
minor optimizations to avoid extra calls of strlen(),
and some variable localization.

One feature worth backporting is the move of ast_variables_destroy()
to a different place in handle_uri() to avoid leaking memory
in case a uri is not found.


Modified:
    trunk/main/http.c

Modified: trunk/main/http.c
URL: http://svn.digium.com/view/asterisk/trunk/main/http.c?rev=45463&r1=45462&r2=45463&view=diff
==============================================================================
--- trunk/main/http.c (original)
+++ trunk/main/http.c Tue Oct 17 23:05:56 2006
@@ -285,23 +285,21 @@
 static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
 {
 	char *c;
-	char *params;
+	char *params = uri;
 	struct ast_http_uri *urih=NULL;
-	int prefix_len;
+	int l;
 	struct ast_variable *vars=NULL, *v, *prev = NULL;
 
+	strsep(&params, "?");
 	/* Extract arguments from the request and store them in variables. */
-	params = strchr(uri, '?');
 	if (params) {
 		char *var, *val;
 
-		*params++ = '\0';
-		while ((var = strsep(&params, "&"))) {
-			val = strchr(var, '=');
-			if (val) {
-				*val++ = '\0';
+		while ((val = strsep(&params, "&"))) {
+			var = strsep(&val, "=");
+			if (val)
 				ast_uri_decode(val);
-			} else 
+			else 
 				val = "";
 			ast_uri_decode(var);
 			if ((v = ast_variable_new(var, val))) {
@@ -316,7 +314,7 @@
 	/*
 	 * Append the cookies to the variables (the only reason to have them
 	 * at the end is to avoid another pass of the cookies list to find
-	 * the tail.
+	 * the tail).
 	 */
 	if (prev)
 		prev->next = *cookies;
@@ -326,38 +324,40 @@
 	ast_uri_decode(uri);
 
 	/* We want requests to start with the prefix and '/' */
-	prefix_len = strlen(prefix);
-	if (prefix_len && !strncasecmp(uri, prefix, prefix_len) && uri[prefix_len] == '/') {
-		uri += prefix_len + 1;
+	l = strlen(prefix);
+	if (l && !strncasecmp(uri, prefix, l) && uri[l] == '/') {
+		uri += l + 1;
 		/* scan registered uris to see if we match one. */
 		for (urih = uris; urih; urih = urih->next) {
-			int len = strlen(urih->uri);
-			if (!strncasecmp(urih->uri, uri, len)) {
-				if (!uri[len] || uri[len] == '/') {
-					char *turi = uri + len;	/* possible candidate */
-					if (*turi == '/')
-						turi++;
-					if (!*turi || urih->has_subtree) {
-						uri = turi;
-						break;
-					}
-				}
+			l = strlen(urih->uri);
+			c = uri + l;	/* candidate */
+			if (strncasecmp(urih->uri, uri, l) /* no match */
+			    || (*c && *c != '/')) /* substring */
+				continue;
+			if (*c == '/')
+				c++;
+			if (!*c || urih->has_subtree) {
+				uri = c;
+				break;
 			}
 		}
 	}
 	if (urih) {
 		c = urih->callback(sin, uri, vars, status, title, contentlength);
-		ast_variables_destroy(vars);
 	} else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
-		/* Special case: If no prefix, and no URI, send to /static/index.html */
-		c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for...");
+		/* Special case: no prefix, no URI, send to /static/index.html */
+		c = ast_http_error(302, "Moved Temporarily",
+			"Location: /static/index.html\r\n",
+			"This is not the page you are looking for...");
 		*status = 302;
 		*title = strdup("Moved Temporarily");
 	} else {
-		c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
+		c = ast_http_error(404, "Not Found", NULL,
+			"The requested URL was not found on this server.");
 		*status = 404;
 		*title = strdup("Not Found");
 	}
+	ast_variables_destroy(vars);
 	return c;
 }
 
@@ -365,121 +365,120 @@
 {
 	char buf[4096];
 	char cookie[4096];
-	char timebuf[256];
 	struct ast_http_server_instance *ser = data;
 	struct ast_variable *var, *prev=NULL, *vars=NULL;
 	char *uri, *c, *title=NULL;
-	char *vname, *vval;
 	int status = 200, contentlength = 0;
-	time_t t;
-
-	if (fgets(buf, sizeof(buf), ser->f)) {
-		uri = ast_skip_nonblanks(buf);	/* Skip method */
-		if (*uri)
-			*uri++ = '\0';
-
-		uri = ast_skip_blanks(uri);	/* Skip white space */
-
-		if (*uri) {			/* terminate at the first blank */
-			c = ast_skip_nonblanks(uri);
-			if (*c)
-				*c = '\0';
-		}
-
-		/* process "Cookie: " lines */
-		while (fgets(cookie, sizeof(cookie), ser->f)) {
-			/* Trim trailing characters */
-			ast_trim_blanks(cookie);
-			if (ast_strlen_zero(cookie))
-				break;
-			if (strncasecmp(cookie, "Cookie: ", 8))
+
+	if (!fgets(buf, sizeof(buf), ser->f))
+		goto done;
+
+	uri = ast_skip_nonblanks(buf);	/* Skip method */
+	if (*uri)
+		*uri++ = '\0';
+
+	uri = ast_skip_blanks(uri);	/* Skip white space */
+
+	if (*uri) {			/* terminate at the first blank */
+		c = ast_skip_nonblanks(uri);
+		if (*c)
+			*c = '\0';
+	}
+
+	/* process "Cookie: " lines */
+	while (fgets(cookie, sizeof(cookie), ser->f)) {
+		char *vname, *vval;
+		int l;
+
+		/* Trim trailing characters */
+		ast_trim_blanks(cookie);
+		if (ast_strlen_zero(cookie))
+			break;
+		if (strncasecmp(cookie, "Cookie: ", 8))
+			continue;
+
+		/* TODO - The cookie parsing code below seems to work   
+		   in IE6 and FireFox 1.5.  However, it is not entirely 
+		   correct, and therefore may not work in all           
+		   circumstances.		                        
+		      For more details see RFC 2109 and RFC 2965        */
+	
+		/* FireFox cookie strings look like:                    
+		     Cookie: mansession_id="********"                   
+		   InternetExplorer's look like:                        
+		     Cookie: $Version="1"; mansession_id="********"     */
+		
+		/* If we got a FireFox cookie string, the name's right  
+		    after "Cookie: "                                    */
+		vname = ast_skip_blanks(cookie + 8);
+			
+		/* If we got an IE cookie string, we need to skip to    
+		    past the version to get to the name                 */
+		if (*vname == '$') {
+			strsep(&vname, ";");
+			if (!vname)	/* no name ? */
 				continue;
-
-				/* XXX fix indentation */
-
-			/* TODO - The cookie parsing code below seems to work   
-			   in IE6 and FireFox 1.5.  However, it is not entirely 
-			   correct, and therefore may not work in all           
-			   circumstances.		                        
-			      For more details see RFC 2109 and RFC 2965        */
-		
-			/* FireFox cookie strings look like:                    
-			     Cookie: mansession_id="********"                   
-			   InternetExplorer's look like:                        
-			     Cookie: $Version="1"; mansession_id="********"     */
-			
-			/* If we got a FireFox cookie string, the name's right  
-			    after "Cookie: "                                    */
-			vname = cookie + 8;
-				
-			/* If we got an IE cookie string, we need to skip to    
-			    past the version to get to the name                 */
-			if (*vname == '$') {
-				vname = strchr(vname, ';');
-				if (vname) { 
-					vname++;
-					if (*vname == ' ')
-						vname++;
-				}
+			vname = ast_skip_blanks(vname);
+		}
+		vval = strchr(vname, '=');
+		if (!vval)
+			continue;
+		/* Ditch the = and the quotes */
+		*vval++ = '\0';
+		if (*vval)
+			vval++;
+		if ( (l = strlen(vval)) )
+			vval[l - 1] = '\0';	/* trim trailing quote */
+		var = ast_variable_new(vname, vval);
+		if (var) {
+			if (prev)
+				prev->next = var;
+			else
+				vars = var;
+			prev = var;
+		}
+	}
+
+	if (!*uri)
+		c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
+	else if (strcasecmp(buf, "get")) 
+		c = ast_http_error(501, "Not Implemented", NULL,
+			"Attempt to use unimplemented / unsupported method");
+	else	/* try to serve it */
+		c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
+
+	/* If they aren't mopped up already, clean up the cookies */
+	if (vars)
+		ast_variables_destroy(vars);
+
+	if (!c)
+		c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
+	if (c) {
+		time_t t = time(NULL);
+		char timebuf[256];
+
+		strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
+		ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
+		ast_cli(ser->fd, "Server: Asterisk\r\n");
+		ast_cli(ser->fd, "Date: %s\r\n", timebuf);
+		ast_cli(ser->fd, "Connection: close\r\n");
+		if (contentlength) {
+			char *tmp = strstr(c, "\r\n\r\n");
+
+			if (tmp) {
+				ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
+				/* first write the header, then the body */
+				write(ser->fd, c, (tmp + 4 - c));
+				write(ser->fd, tmp + 4, contentlength);
 			}
-				
-			if (vname) {
-				vval = strchr(vname, '=');
-				if (vval) {
-					/* Ditch the = and the quotes */
-					*vval++ = '\0';
-					if (*vval)
-						vval++;
-					if (strlen(vval))
-						vval[strlen(vval) - 1] = '\0';
-					var = ast_variable_new(vname, vval);
-					if (var) {
-						if (prev)
-							prev->next = var;
-						else
-							vars = var;
-						prev = var;
-					}
-				}
-			}
-		}
-
-		if (*uri) {
-			if (!strcasecmp(buf, "get")) 
-				c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
-			else 
-				c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
-		} else 
-			c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
-
-		/* If they aren't mopped up already, clean up the cookies */
-		if (vars)
-			ast_variables_destroy(vars);
-
-		if (!c)
-			c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
-		if (c) {
-			time(&t);
-			strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
-			ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
-			ast_cli(ser->fd, "Server: Asterisk\r\n");
-			ast_cli(ser->fd, "Date: %s\r\n", timebuf);
-			ast_cli(ser->fd, "Connection: close\r\n");
-			if (contentlength) {
-				char *tmp;
-				tmp = strstr(c, "\r\n\r\n");
-				if (tmp) {
-					ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
-					write(ser->fd, c, (tmp + 4 - c));
-					write(ser->fd, tmp + 4, contentlength);
-				}
-			} else
-				ast_cli(ser->fd, "%s", c);
-			free(c);
-		}
-		if (title)
-			free(title);
-	}
+		} else
+			ast_cli(ser->fd, "%s", c);
+		free(c);
+	}
+	if (title)
+		free(title);
+
+done:
 	fclose(ser->f);
 	free(ser);
 	return NULL;



More information about the svn-commits mailing list