PERFORCE change 123330 for review

Alexey Tarasov taleks at FreeBSD.org
Wed Jul 11 15:03:40 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=123330

Change 123330 by taleks at taleks_th on 2007/07/11 15:02:42

	all: changed in some places PXE_DEBUG output to PXE_DEBUG_HELL to reduce output level.
	pxe_connection, pxe_tcp: LAST_ACK handling is more correct now
	pxe_dhcp: www server option is  processed
	pxe_http: started implementing of partial retrieving.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#7 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.h#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#20 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#16 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_dhcp.c#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_dhcp.h#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_http.c#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_http.h#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.c#11 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#6 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#14 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#12 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#9 edit

Differences ...

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

@@ -224,12 +224,13 @@
 	
 	if (connection->state == PXE_TCP_CLOSED) { /* already  closed */
 #ifdef PXE_DEBUG
-		printf("pxe_tcp_disconnect(): connection already is closing.\n");
+		printf("pxe_tcp_disconnect(): connection already is closed.\n");
 #endif
 		return (1);
 	}
 	
-	if (!pxe_tcp_syssend(connection, PXE_TCP_FIN | PXE_TCP_ACK)) {
+	if (!pxe_tcp_syssend(connection, PXE_TCP_FIN | PXE_TCP_ACK)) { 
+/*	if (!pxe_tcp_syssend(connection, PXE_TCP_FIN)) { */
 		printf("pxe_tcp_disconnect(): failed to send FIN.\n");
 		free_connection(connection);
 		return (0);
@@ -244,17 +245,17 @@
 		/* active closing by our host */
 		connection->state = PXE_TCP_FIN_WAIT1;
 #ifdef PXE_DEBUG
-	printf("pxe_tcp_disconnect(): new state - FIN_WAIT_1\n");
+		printf("pxe_tcp_disconnect(): new state - FIN_WAIT_1\n");
 #endif
 		wait_data.state = PXE_TCP_TIME_WAIT;
 	
 	} else { /* if connection breaked by remote host */
-		wait_data.state = PXE_TCP_LAST_ACK;
+		connection->state = PXE_TCP_LAST_ACK;
+		wait_data.state = PXE_TCP_CLOSED;
 	}
 
 	connection->state_out = PXE_TCP_FIN;
 
-
 	/* awaiting expected state to close connection
 	 * connection will fell in this state in pxe_tcp_callback()
 	 */
@@ -309,8 +310,11 @@
 		return (-1);
 	}
 	
-	if (connection->state != PXE_TCP_ESTABLISHED)
-		return (-1);	/* cannot write to not established connection */
+	if ( (connection->state != PXE_TCP_ESTABLISHED) &&
+	     (connection->state != PXE_TCP_CLOSE_WAIT) )
+	{
+		return (-1);	/* cannot write, incorrect state */
+	}
 	
 	/* trying current segment */
 	PXE_TCP_QUEUED_SEGMENT *segment = connection->segment;
@@ -432,23 +436,25 @@
 
 /* pxe_tcp_push() - flushes send buffer (actually current send segment)
  * in:
- *      sock		- TCP socket to flush
+ *      filter		- filter of socket, which buffers need to flush
  * out:
  *      0	- failed
  *      1	- success
  */
 int
-pxe_tcp_push(PXE_SOCKET *sock)
+pxe_tcp_push(PXE_FILTER_ENTRY *filter)
 {
-	PXE_TCP_CONNECTION	*connection = filter_to_connection(sock->filter);
+	PXE_TCP_CONNECTION	*connection = filter_to_connection(filter);
 
 	if (connection == NULL) {
-		printf("pxe_tcp_push(): no connection for filter 0x%x (socket: 0x%x).\n", sock->filter, sock);
+		printf("pxe_tcp_push(): no connection for filter 0x%x.\n", filter);
 		return (0);
 	}
 
-	if (connection->state != PXE_TCP_ESTABLISHED) {
-		printf("pxe_tcp_push(): connection 0x%x is not in established state(%d).\n",
+	if ( (connection->state != PXE_TCP_ESTABLISHED) &&
+	     (connection->state != PXE_TCP_CLOSE_WAIT) )
+	{
+		printf("pxe_tcp_push(): connection 0x%x is in wrong state %d.\n",
 		    connection, connection->state
 		);
 		return (0);	/* connection not in established state, ignore available data */

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

@@ -87,7 +87,7 @@
 int pxe_tcp_read(PXE_SOCKET *sock, void *data, uint16_t size);
 
 /* pushes current segment data */
-int pxe_tcp_push(PXE_SOCKET *sock);
+int pxe_tcp_push(PXE_FILTER_ENTRY *entry);
 
 /* checks connection, by sending ACK */
 int pxe_tcp_check_connection(PXE_SOCKET *sock);

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

@@ -250,6 +250,7 @@
 	pxe_set_ip32(PXE_IP_GATEWAY, 0x0100a8c0);	/* gateway ip, default to 192.168.0.1 */
 	pxe_set_ip32(PXE_IP_NETMASK, 0x00ffffff);	/* gateway ip, default to 255.255.255.0 */
 	pxe_set_ip32(PXE_IP_BROADCAST, 0xffffffff);	/* broadcast address, default to 255.255.255.255 */
+	pxe_set_ip32(PXE_IP_WWW, 0x0100a8c0);		/* web server */
 	
 	/* initing modules */	
 	pxe_arp_init();
@@ -477,7 +478,7 @@
 	    undi_send->DestAddr.offset  = VTOPOFF(pack->dest_mac);
 	}
 
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("pxe_core_transmit(): %s %x:%x:%x:%x:%x:%x, proto = %d, %d bytes\n",
 	    (undi_send->XmitFlag == XMT_DESTADDR) ? "to" : "bcast",
 	    (*pack->dest_mac)[0], (*pack->dest_mac)[1], (*pack->dest_mac)[2],
@@ -652,9 +653,9 @@
 		return (processed_packets);
 	}
 	
-#ifdef PXE_DEBUG
-	printf("recv_packets(): size = %d, proto = %d, frame_length = %d bytes.\n",
-	    buffer_size, protocol, frame_size);
+#ifdef PXE_DEBUG_HELL
+	printf("pxe_core_recv_packets(): size = %d/%d, proto = %d.\n",
+	    frame_size, buffer_size, protocol);
 #endif		
 
 	/* we are interested in ARP & IP packets */

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

@@ -111,7 +111,8 @@
 #define PXE_IP_GATEWAY		4
 #define PXE_IP_BROADCAST	5
 #define PXE_IP_SERVER		6
-#define PXE_IP_MAX		7
+#define PXE_IP_WWW		7
+#define PXE_IP_MAX		8
 uint32_t pxe_get_ip32(uint8_t id);
 void	 pxe_set_ip32(uint8_t id, uint32_t ip);
 

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

@@ -115,10 +115,9 @@
 	                        break;
 
 			case PXE_DHCP_OPT_WWW_SERVER:
-#ifdef PXE_DEBUG
-	                        printf("server ip: %d.%d.%d.%d\n", *(p+1), *(p+2), *(p+3), *(p+4));
-#endif
-	                        break;				
+	                        printf("www server ip: %d.%d.%d.%d\n", *(p+1), *(p+2), *(p+3), *(p+4));
+				result->www = *((uint32_t *)(p+1));
+	                        break;
 	                default:
 				printf("DHCP option %d is unknown (%d bytes ignored)\n", code, len);
 	                        break;
@@ -262,7 +261,10 @@
 
 	if (opts_result.bcast_addr)
 		pxe_set_ip32(PXE_IP_BROADCAST, opts_result.bcast_addr);
-		
+	
+	if (opts_result.www)
+		pxe_set_ip32(PXE_IP_WWW, opts_result.www);
+	
 	return (1);
 }
 

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

@@ -94,6 +94,7 @@
 	uint32_t	bcast_addr;
 	uint32_t	ns;
 	uint32_t	gw;
+	uint32_t	www;
 	uint8_t		message_type;
 } PXE_DHCP_PARSE_RESULT;
 

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

@@ -6,10 +6,79 @@
 #include "pxe_ip.h"
 #include "pxe_tcp.h"
 
-char client_hdr[PXE_MAX_HTTP_HDRLEN];
+char http_data[PXE_MAX_HTTP_HDRLEN];
+
+/*
+ HTTP/1.1 200 OK
+ Date: 
+ Server: 
+ Last-Modified: 
+ Accept-Ranges: bytes
+ Content-Length: 123
+ Connection: close
+ Content-Type: text/html; charset=UTF-8
+*/
+
+char *
+parse_uint32(char *str, uint32_t *result)
+{
+	char *p = str;
+	
+	while ( (*p != '\0') && (!isdigit(*p)) ) {
+		++p;
+	}
+	
+	if (!isdigit(*p)) {	/* nothing to parse */
+		return (NULL);
+	}
+	
+	uint32_t accum = 0;
+	
+	while ( (*p) && (isdigit(*p))) {
+		accum *= 10;
+		accum += (*p - '0');
+		++p;
+	}
+	
+	*result = accum;
+	
+	return (p);
+}
+
+int
+http_reply_parse(char *data, int count, PXE_HTTP_PARSE_DATA *parse_data)
+{
+	if (strncmp(data, "HTTP/1.1", 8) != 0) { /* wrong header */
+		return (0);
+	}
+	
+	uint32_t result = 0;
+	
+	char *found = parse_uint32(data + 8, &result);
+	parse_data->code = (uint16_t) result;
+	
+	if (found == NULL) {
+		return (0);	/* failed to parse response code */
+	}
+		
+	found = strstr(data, "Content-Length:");
+
+	parse_data->size = PXE_HTTP_SIZE_UNKNOWN;
+	
+	if (found != NULL) { /* parsing message body size */
+		
+		found = parse_uint32(found + strlen("Content-Length:"), &parse_data->size);
+	}
+	
+	return (1);
+}
 
+/* if size = from = 0, retrieve full file, otherwise partial 
+ * where - NULL, if not needed or size = 0. Otherwise where
+ * must be big enough to store size bytes.
+ */
 int
-pxe_fetch(char *server_name, char *filename)
+pxe_fetch(char *server_name, char *filename, uint32_t from, uint32_t size, void *where)
 {
 	PXE_IPADDR	server;
 	
@@ -34,26 +103,36 @@
 		return (0);
 	}
 
-	sprintf(client_hdr, "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", filename, server_name);
+	if ( (from == 0) && (size == 0) ) {
+		sprintf(http_data, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Close\r\n\r\n",
+		    filename, server_name
+		);
+	} else {
+		sprintf(http_data, "GET /%s HTTP/1.1\r\nHost: %s\r\nRange: %d-%d\r\nConnection: Close\r\n\r\n",
+		    filename, server_name, from, from + size
+		);
+	}
 
-	int len = strlen(client_hdr);
+	int len = strlen(http_data);
 
-	if (len != pxe_send(socket, client_hdr, len)) {
+	if (len != pxe_send(socket, http_data, len)) {
 		printf("pxe_fetch(): failed to send request.\n");
 		pxe_close(socket);
 		return (0);
 	}
 
-	if (pxe_push(socket) == -1) {
+	if (pxe_flush(socket) == -1) {
 		printf("pxe_fetch(): failed to push request.\n");
 		pxe_close(socket);
 		return (0);
 	}
 
-	int count = 0;
-	
+	int	count = 0;
+	char	*found = NULL;
+
+	/* retrieve header */	
 	while (1) {
-		result = pxe_recv(socket, client_hdr, PXE_MAX_HTTP_HDRLEN-1);
+		result = pxe_recv(socket, &http_data[count], PXE_MAX_HTTP_HDRLEN - 1 - count);
 		
 		if (result == -1) {
 			break;
@@ -61,24 +140,74 @@
 		
 		if (result == 0)
 			continue;
+
+		http_data[count + result] = '\0';
+/*		printf("%s", http_data); */
 		
+		/* end of reply */
+		found = strstr(&http_data[count], "\r\n\r\n");
 		count += result;
-		client_hdr[result] = '\0';
+		
+		if (found != NULL)
+			break;
+	}
+
+	if (found == NULL) {	/* haven't found end of header */
+		pxe_close(socket);
+		return (0);
+	}
+	
+	/* parse header */
+	PXE_HTTP_PARSE_DATA	parse_data;
+	pxe_memset(&parse_data, 0, sizeof(PXE_HTTP_PARSE_DATA));
+	
+	if (!http_reply_parse(http_data, count, &parse_data)) {
+		pxe_close(socket);
+		return (0);
+	}
+
+	/* calculating body data offset*/
+/*	result = (found - http_data) + 4; */
+/*	result = count - result;	/* result = size of retirieved part of body */
+/*	count = (found - http_data) + 4; */
+/*	pxe_memcpy(&http_data[count], http_data, result); */
+	
+	printf("pxe_fetch(): response %d, length = %d\n", parse_data.code, parse_data.size);
+	delay(2000000);
+	
+	if ( (parse_data.code < 200) ||
+	     (parse_data.code >= 300) )
+	{
+		printf("pxe_fetch(): failed to fetch.\n");
+		pxe_close(socket);
+		return (0);
+	}
+
+	/* update counter, substruct header size */	
+	count -= (found - http_data) + 4;
 		
-		printf("%s", client_hdr);
+	/* process body data */
+	printf("%s", found + 4);
+	
+	while (1) {
+		result = pxe_recv(socket, http_data, PXE_MAX_HTTP_HDRLEN - 1);
 		
-		if (count == 0) {
-			if (!strncmp(client_hdr, "HTTP/1.1 200 OK", result)) {
-				
-			}
-			else {
-				pxe_close(socket);
-				return (0);
-			}
+		if (result == -1) {
+			break;
 		}
+		
+		if (result == 0)
+			continue;
+		
+		http_data[result] = '\0';
+		
+		printf("%s", http_data);
+		
+		count += result;
 	}
 	
-	printf("\npxe_fetch(): %d byte(s) received.\n", count);
+	pxe_close(socket);
+	printf("\npxe_fetch(): %d of %d byte(s) received.\n", count, parse_data.size);
 	
 	return (1);
 }

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

@@ -4,6 +4,14 @@
 #include <stdint.h>
 
 #define PXE_MAX_HTTP_HDRLEN	1024
-int pxe_fetch(char *server, char *filename);
+int pxe_fetch(char *server, char *filename, uint32_t from, uint32_t size, void* where);
+
+#define PXE_HTTP_SIZE_UNKNOWN	0xffffffff
+
+typedef struct pxe_http_parse_data {
+	uint16_t	code;	/* response code */
+	uint32_t	from;	/* for ranges: start of range */
+	uint32_t	size;	/* size of data if known */
+} PXE_HTTP_PARSE_DATA;
 
 #endif

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

@@ -329,7 +329,7 @@
 	for ( ; route_index < all_routes; ++route_index) {
     
 		if ( (dst_ip & route->mask) == route->net ) { /* found route */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("pxe_ip_route_find(): route 0x%x\n", (route->gw == 0) ? dst_ip : route->gw);
 #endif		    
 			/* gateway == 0 only for local network */

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

@@ -75,7 +75,7 @@
 PXE_TCP_QUEUED_SEGMENT *
 tcp_segment_alloc(PXE_TCP_CONNECTION *connection, int allocBig)
 {
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("tcp_segment_alloc(): connection 0x%x, big = %d.\n", connection, allocBig);
 #endif
 	int			block_index = 0;
@@ -142,7 +142,7 @@
 void
 tcp_segment_free(PXE_TCP_CONNECTION *connection, int block_index, PXE_TCP_QUEUED_SEGMENT *segment)
 {
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("tcp_segment_free(): connection: 0x%x, block: %d, chunk: 0x%x\n", connection, block_index, segment);
 #endif
 	uint8_t		*block = &connection->buf_blocks[block_index];
@@ -198,7 +198,7 @@
 				continue;	/* it was not ever sent yet */
 				
                         if (cur_time >= segment->resend_at) { /* time to resend */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 				printf("pxe_resend_check(): %d:%d resending (next try at: %d)\n",
 				    segment->resend_at, cur_time, segment->resend_at + PXE_RESEND_TIME * (segment->trys + 1)
 				);
@@ -225,7 +225,7 @@
                         if (segment->status == PXE_SEGMENT_SENT) {
 
                                 if (cur_time >= segment->resend_at) { /* time to resend */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 					printf("pxe_resend_check(): %d:%d resending (next try at: %d)\n",
 					    segment->resend_at, cur_time, segment->resend_at + PXE_RESEND_TIME * (segment->trys + 1)
 					);
@@ -325,7 +325,7 @@
 void
 pxe_resend_update(PXE_TCP_CONNECTION *connection)
 {
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("pxe_resend_update(): started.\n");
 #endif
         PXE_BUFFER              *buffer = connection->send;
@@ -366,7 +366,7 @@
                         if (segment->status == PXE_SEGMENT_SENT) {
 
                                 if (connection->una >= segment->seq) { /* segment was acked */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 				    printf("pxe_resend_update(): chunk %d@%d acked.\n", chunk_index, block_index);
 #endif
 	                                tcp_segment_free(connection, block_index, segment);

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

@@ -132,6 +132,8 @@
 	}
 
 	PXE_FILTER_ENTRY *filter = sock->filter;
+	/* flush data in buffers */
+	pxe_flush(socket);
 
 	/* socket buffers seems not be used more */
 	pxe_buffer_memfree(&sock->send_buffer);
@@ -472,7 +474,7 @@
 	if (result > 0)
 		sock->sent += result;
 
-	return (-1);
+	return (result);
 }
 
 /* pxe_recv() - receive data to socket
@@ -663,7 +665,7 @@
 	return (0);
 }
 
-/* pxe_push() - flushes send buffers
+/* pxe_flush() - flushes send buffers
  * in:
  *	socket	- socket descriptor number
  * out:
@@ -671,10 +673,10 @@
  *	0	- success
  */
 int
-pxe_push(int socket)
+pxe_flush(int socket)
 {
 	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
-		printf("pxe_push(): invalid socket %d.\n", socket);
+		printf("pxe_flush(): invalid socket %d.\n", socket);
 		return (-1);
 	}
 	
@@ -687,10 +689,10 @@
 		
 	} else if (filter->protocol == PXE_TCP_PROTOCOL) {
 	
-		return (pxe_tcp_push(sock) == 0) ? (-1) : 0;
+		return (pxe_tcp_push(sock->filter) == 0) ? (-1) : 0;
 	}	
 	
-	printf("pxe_push(): only TCP and UDP sockets are implemented.\n");
+	printf("pxe_flush(): only TCP and UDP sockets are implemented.\n");
 
 	return (-1);
 }

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

@@ -92,7 +92,7 @@
 int	pxe_bind(int socket, uint32_t ip, uint16_t port, uint8_t proto);
 
 /* flushes send buffers */
-int	pxe_push(int socket);
+int	pxe_flush(int socket);
 
 /* close socket */
 int	pxe_close(int socket);

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

@@ -484,10 +484,11 @@
 	
 	/* eighth, check FIN */
 	if (tcp_check_8(tcp_packet)) {	/* remote host requested connection break */
+
 		connection->state = PXE_TCP_CLOSE_WAIT;
 #ifdef PXE_DEBUG
 		printf("tcp_established(): new state - CLOSE_WAIT\n");
-#endif
+#endif	
 	}
 	
 	return (0);
@@ -749,12 +750,12 @@
 		return (0);
 	}
 */	
-	/* ignore data processing */
+	/* ignore data processing, input connection closed by remote host  */
 
 	return (0);
 }
 
-/* tcp_last_ack() - LAST_ACK state handler. TODO: implement
+/* tcp_last_ack() - LAST_ACK state handler.
  * in:
  *	tcp_packet - incoming packet data
  *	connection - current connection
@@ -800,7 +801,9 @@
 		return (0);
 	}
 */	
-	/* ignore data processing */
+	
+	/* if got here, means we have ACK */
+	connection->state = PXE_TCP_CLOSED;
 	return (0);
 }
 
@@ -841,6 +844,8 @@
 	    data_size, pack->data_size, 4 * (iphdr->ver_ihl & 0x0F), sizeof(PXE_IP_HDR),
 	    4 * (tcp_packet->tcphdr.data_off >> 4), sizeof(PXE_TCP_HDR)
 	);
+#endif
+#ifdef PXE_DEBUG
 	printf("pxe_tcp_callback(): tcp packet from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
 		from.octet[0], from.octet[1], from.octet[2], from.octet[3], src_port,
 		to.octet[0], to.octet[1], to.octet[2], to.octet[3], dst_port
@@ -938,7 +943,7 @@
 	if (connection->state < PXE_TCP_ALL_STATES) {
 	
 		while (1) {
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("pxe_tcp_callback(): connection state = 0x%x\n", connection->state);
 #endif		    
 			if (state_functions[connection->state] != NULL) {


More information about the p4-projects mailing list