Date: Wed, 11 Jul 2007 15:03:38 GMT From: Alexey Tarasov <taleks@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123330 for review Message-ID: <200707111503.l6BF3cBE032097@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123330 Change 123330 by taleks@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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707111503.l6BF3cBE032097>