Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Jul 2007 14:15:22 GMT
From:      Alexey Tarasov <taleks@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 123897 for review
Message-ID:  <200707221415.l6MEFM5e089380@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123897

Change 123897 by taleks@taleks_th on 2007/07/22 14:15:16

	pxe_sock: added pxe_socket_state() funxtion, used to get current socket state.
	pxe_http: added support for keep-alive connections and reestablishing of closed connections.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/Makefile#11 edit
.. //depot/projects/soc2007/taleks-pxe_http/httpfs.c#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#10 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_http.c#8 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_http.h#6 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#16 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#14 edit

Differences ...

==== //depot/projects/soc2007/taleks-pxe_http/Makefile#11 (text+ko) ====

@@ -30,6 +30,7 @@
 #CFLAGS+=	-DPXE_ARP_DEBUG
 #CFLAGS+=	-DPXE_ARP_DEBUG_HELL
 # httpfs module
-#CFLAGS+=	-DPXE_HTTP_DEBUG
+CFLAGS+=	-DPXE_HTTP_DEBUG
+#CFLAGS+=	-DPXE_HTTP_DEBUG_HELL
 
 .include <bsd.lib.mk>

==== //depot/projects/soc2007/taleks-pxe_http/httpfs.c#4 (text+ko) ====

@@ -124,7 +124,10 @@
         }
 
         f->f_fsdata = (void *) httpfile;
-	
+
+#ifdef PXE_HTTP_DEBUG
+	printf("http_open(): success\n");
+#endif	
 	return (0);
 }
 
@@ -138,7 +141,7 @@
 		return (EINVAL);
 	}
 	
-#ifdef PXE_HTTP_DEBUG	
+#ifdef PXE_HTTP_DEBUG_HELL
 	printf("http_read(): %s:%llu+%lu\n",
 	    httpfile->filename, httpfile->offset, size);
 #endif
@@ -148,7 +151,7 @@
 	{
 	    if (resid)
 		*resid = size;
-#ifdef PXE_HTTP_DEBUG
+#ifdef PXE_HTTP_DEBUG_HELL
 	    printf("http_read(): EOF\n");
 #endif
 	    return (0);

==== //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#10 (text+ko) ====

@@ -536,6 +536,10 @@
 	if ( (connection->state != PXE_TCP_ESTABLISHED) &&
 	     (recv_buffer->bufleft == recv_buffer->bufsize) )
 	{
+#ifdef PXE_DEBUG
+		printf("pxe_tcp_read(): state %u, no data in buffer\n",
+		    connection->state);
+#endif
 		return (-1);	/* connection closed and no data in buffer */
 	}
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_http.c#8 (text+ko) ====

@@ -91,7 +91,7 @@
 	
 	if (found == NULL)
 		return (0);	/* failed to parse response code */
-		
+
 	found = strstr(data, "Content-Length:");
 
 	parse_data->size = PXE_HTTP_SIZE_UNKNOWN;
@@ -126,8 +126,12 @@
 	while (count < maxsize - 1) {
 		result = pxe_recv(socket, &data[count], maxsize - 1 - count);
 		
-		if (result == -1)	/* failed to recv */
+		if (result == -1) {	/* failed to recv */
+#ifdef PXE_HTTP_DEBUG_HELL
+			printf("http_get_header(): pxe_recv() failed\n");
+#endif
 			break;
+		}
 		
 		if (result == 0)	/* nothing received yet */
 			continue;
@@ -157,6 +161,65 @@
 	return (result);
 }
 
+/* http_get_header2() - gets from socket data related to http header
+ *			byte by byte.
+ * in:
+ *	socket		- socket descriptor
+ *	data		- pointer to working buffer
+ *	maxsize		- buffer size
+ * 	found_result	- if not NULL, there stored pointer to end of header
+ *	count_result	- if not NULL, received count stored
+ * out:
+ *	-1	- failed
+ *	>=0	- success
+ */
+int
+http_get_header2(int socket, char *data, size_t maxsize,
+		char **found_result, size_t *count_result)
+{
+	int		result = -1;
+	size_t		count = 0;
+	char		*found = NULL;
+	char		ch = '\0';
+	
+	while (count < maxsize - 1) {
+		result = pxe_recv(socket, &data[count], 1);
+		
+		if (result == -1) {	/* failed to recv */
+#ifdef PXE_HTTP_DEBUG_HELL
+			printf("http_get_header2(): pxe_recv() failed\n");
+#endif
+			break;
+		}
+		
+		if (result == 0)	/* nothing received yet */
+			continue;
+
+		/* make string ended with '\0' */
+		ch = data[count + result];
+		data[count + result] = '\0';
+		
+		/* searching end of reply */
+		found = strstr(&data[count], "\r\n\r\n");
+
+		/* restore char replaced by zero */
+		data[count + result] = ch;
+		
+		count += 1;
+		
+		if (found != NULL)
+			break;
+	}
+
+	if (found_result)
+		*found_result = found;
+	
+	if (count_result)
+		*count_result = count;
+	
+	return (result);
+}
+
 /* pxe_fetch() - testing function, if size = from = 0, retrieve full file,
  *		otherwise partial 
  * in:
@@ -300,23 +363,45 @@
 {
 	size_t size_to_get = (size > 0) ? size : hh->size;
 	
-#ifdef PXE_DEBUG
+#ifdef PXE_HTTP_DEBUG_HELL
 	printf("pxe_get(): %s:%s:%llu+%lu(%lu:%lu) to 0x%x\n",
 	    inet_ntoa(hh->ip), hh->filename, hh->offset,
 	    size_to_get, size, hh->size, hh->buf);
 #endif
 
 	if (hh->socket == -1) {
-		printf("pxe_get(): socket is not connected.\n");
+		printf("pxe_get(): invalid socket.\n");
 		return (-1);
 	}
+	
+	if (pxe_socket_state(hh->socket) != PXE_SOCKET_ESTABLISHED) {
+		/* means connection was closed, due e.g. for Apache
+		 * - MaxKeepAliveRequests exceeds for that connection
+		 * - Waited between read attempts more than KeepAliveTimeout
+		 *  or
+		 * some other problem
+		 * need to reestablish connection
+		 */
+		 
+		 /* close socket gracefully */
+		 pxe_close(hh->socket);
+		 hh->socket = -1;
+		 
+		 if (!pxe_exists(hh)) {
+#ifdef PXE_HTTP_DEBUG
+			printf("pxe_get(): connection breaked.\n");
+#endif
+			return (-1);
+		 }
+		 /* reestablished, continue normal work */
+	}
 
 	if ( (size_to_get < PXE_HTTP_SIZE_UNKNOWN) &&
 	     (size_to_get > 0))
 	{
 		snprintf(hh->buf, hh->bufsize, "GET %s HTTP/1.1\r\nHost: %s\r\n"
 		    "Range: bytes=%llu-%llu\r\nConnection: keep-alive\r\n"
-		    "User-Agent: pxe_http/0\r\n\r\n",
+		    "Keep-Alive: 300\r\nUser-Agent: pxe_http/0\r\n\r\n",
 		    hh->filename, hh->servername, hh->offset,
 		    hh->offset + size - 1);
 	} else {
@@ -345,7 +430,7 @@
 		    &found, &count);
 
 	if (found == NULL) {	/* haven't found end of header */
-		printf("pxe_get(): cannot find reply header\n");
+		printf("pxe_get(): cannot find reply header.\n");
 		return (-1);
 	}
 	
@@ -354,7 +439,7 @@
 	pxe_memset(&parse_data, 0, sizeof(PXE_HTTP_PARSE_DATA));
 	
 	if (!http_reply_parse(hh->buf, count, &parse_data)) {
-		printf("pxe_get(): cannot parse reply header\n");
+		printf("pxe_get(): cannot parse reply header.\n");
 		return (-1);
 	}
 
@@ -394,7 +479,7 @@
 		count += result;
 	}
 	
-#ifdef PXE_DEBUG
+#ifdef PXE_HTTP_DEBUG_HELL
 	printf("\npxe_get(): %lu of %lu byte(s) received.\n", count, size);
 #endif
 
@@ -470,7 +555,8 @@
 	char	*found = NULL;
 
 	/* retrieve header */	
-	result = http_get_header(socket, hh->buf, hh->bufsize - 1, &found, &count);
+	result = http_get_header(socket, hh->buf, hh->bufsize - 1,
+		    &found, &count);
 
 	if (found == NULL) {	/* haven't found end of header */
 		printf("pxe_get_close(): cannot find reply header\n");
@@ -583,8 +669,6 @@
 	/* retrieve header */	
 	result = http_get_header(socket, hh->buf, hh->bufsize, &found, &count);
 
-/*	pxe_close(socket); */
-	
 	if (found == NULL) {	/* haven't found end of header */
 		pxe_close(socket);
 		return (0);

==== //depot/projects/soc2007/taleks-pxe_http/pxe_http.h#6 (text+ko) ====

@@ -53,6 +53,9 @@
 	uint32_t	ip;		/* web server ip */
 	off_t		offset;		/* current offset in bytes from
 					 * beginning of file */
+					 
+	off_t		cache_start;	/* cached block, to reduce http requests */
+	uint16_t	cache_size;	/* size of cached block */
 
 	size_t		size;		/* file size if known */
 } PXE_HTTP_HANDLE;
@@ -60,8 +63,8 @@
 /* gets requested data from server */
 int pxe_get(PXE_HTTP_HANDLE *hh, size_t size, void *buffer);
 
-/* gets requested data from server */
-int pxe_get2(PXE_HTTP_HANDLE *hh, size_t size, void *buffer);
+/* gets requested data from server, closing connection after */
+int pxe_get_close(PXE_HTTP_HANDLE *hh, size_t size, void *buffer);
 
 /* checks if file exists and fills filesize if known */
 int pxe_exists(PXE_HTTP_HANDLE *hh);

==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#16 (text+ko) ====

@@ -170,10 +170,6 @@
 	/* flush data in buffers */
 	pxe_flush(socket);
 
-	/* socket buffers seems not be used more */
-/*	pxe_buffer_memfree(&sock->send_buffer);
-	pxe_buffer_memfree(&sock->recv_buffer);
-*/
 	if (filter == NULL) { /* sanity check */
 #ifdef PXE_DEBUG
 		printf("pxe_close(): filter is NULL.\n");
@@ -777,3 +773,42 @@
 
 	return (-1);
 }
+
+/* pxe_socket_state() - returns current state of socket
+ * in:
+ *	socket	- socket descriptor number
+ * out:
+ *	-1	- if failed
+ *	one of PXE_SOCKET_ state flags otherwise
+ */
+int
+pxe_socket_state(int socket)
+{
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
+		printf("pxe_socket_state(): invalid socket %d.\n", socket);
+		return (-1);
+	}
+	
+	PXE_SOCKET	*sock = &pxe_sockets[socket];
+	PXE_FILTER_ENTRY *filter = sock->filter;
+	
+	if (filter == NULL) {
+#ifdef PXE_DEBUG
+		printf("pxe_socket_state(): NULL filter\n");
+#endif
+		return (PXE_SOCKET_USED);
+	}
+	
+	if (filter->protocol == PXE_UDP_PROTOCOL) /* it's always 'established' */
+		return (PXE_SOCKET_ESTABLISHED);
+		
+	else if (filter->protocol == PXE_TCP_PROTOCOL) {
+		/* for TCP connections need to check state */
+		PXE_TCP_CONNECTION *connection = filter_to_connection(filter);
+		
+		if (connection && (connection->state == PXE_TCP_ESTABLISHED) )
+			return (PXE_SOCKET_ESTABLISHED);
+	}
+	
+	return (PXE_SOCKET_CONNECTED);
+}

==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#14 (text+ko) ====

@@ -88,10 +88,8 @@
 /* shows socket usage statistics */
 void	pxe_sock_stats();
 
-/* returns int socket by pointer to PXE_SOCKET
- * TODO: think about interfaces between pxe_filter and pxe_sock
- */
-int	pxe_sock_get(PXE_SOCKET *sock);
+/* returns current socket state */
+int	pxe_socket_state(int socket);
 
 /* pxe_listen() - creates "listening" socket 
  *    it's not the same as normal listen() system call.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707221415.l6MEFM5e089380>