From owner-p4-projects@FreeBSD.ORG Sun Jul 1 16:00:27 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B378016A46B; Sun, 1 Jul 2007 16:00:27 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 08F9C16A400 for ; Sun, 1 Jul 2007 16:00:27 +0000 (UTC) (envelope-from taleks@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id ECE8013C4B0 for ; Sun, 1 Jul 2007 16:00:26 +0000 (UTC) (envelope-from taleks@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l61G0QEn043101 for ; Sun, 1 Jul 2007 16:00:26 GMT (envelope-from taleks@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l61G0Qba043098 for perforce@freebsd.org; Sun, 1 Jul 2007 16:00:26 GMT (envelope-from taleks@FreeBSD.org) Date: Sun, 1 Jul 2007 16:00:26 GMT Message-Id: <200707011600.l61G0Qba043098@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to taleks@FreeBSD.org using -f From: Alexey Tarasov To: Perforce Change Reviews Cc: Subject: PERFORCE change 122647 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 Jul 2007 16:00:28 -0000 http://perforce.freebsd.org/chv.cgi?CH=122647 Change 122647 by taleks@taleks_th on 2007/07/01 16:00:25 Updated sockets pxe_recv()/pxe_send() code - now it distinguish TCP/UDP, moved previously located here code to udp module. Added tcp variants of read/write functions and pxe_push(). Sending data client->server works for small amount of data. Need testing for larger data blocks. There is issue when server breaks connection (client falls to incorrect state in pxe_tcp_disconnect()) Affected files ... .. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#3 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_connection.h#2 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#3 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_segment.h#3 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#10 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#9 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#5 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.h#6 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_udp.c#5 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_udp.h#3 edit Differences ... ==== //depot/projects/soc2007/taleks-pxe_http/pxe_connection.c#3 (text+ko) ==== @@ -154,7 +154,7 @@ pxe_resend_init(connection); - if (!pxe_tcp_send(connection, 0, PXE_TCP_SYN)) { + if (!pxe_tcp_syssend(connection, PXE_TCP_SYN)) { printf("pxe_tcp_connect(): failed to send SYN.\n"); free_connection(connection); return (0); @@ -217,7 +217,7 @@ return (1); } - if (!pxe_tcp_send(connection, 0, PXE_TCP_FIN | PXE_TCP_ACK)) { + if (!pxe_tcp_syssend(connection, PXE_TCP_FIN | PXE_TCP_ACK)) { printf("pxe_tcp_disconnect(): failed to send FIN.\n"); free_connection(connection); return (0); @@ -263,3 +263,165 @@ /* clear connections data */ pxe_memset(tcp_connections, 0, sizeof(tcp_connections)); } + +/* pxe_tcp_write() - transmit data via TCP protocol + * in: + * sock - TCP socket to write to + * data - pointer to data to send + * size_to_send - data size + * out: + * -1 - failed + * >=0 - actual bytes written + */ +int +pxe_tcp_write(PXE_SOCKET *sock, void *data, uint16_t size_to_send) +{ + PXE_TCP_CONNECTION *connection = filter_to_connection(sock->filter); + + if (connection == NULL) { + printf("pxe_tcp_write(): no connection for filter 0x%x (socket: 0x%x).\n", sock->filter, sock); + return (-1); + } + + if (connection->state != PXE_TCP_ESTABLISHED) + return (-1); /* cannot write to not established connection */ + + /* trying current segment */ + PXE_TCP_QUEUED_SEGMENT *segment = connection->segment; + + uint16_t sent_data = 0; + uint16_t bufleft = 0; + uint16_t send_now = 0; + void *segment_data = (void *)(segment + 1); + + while (sent_data < size_to_send) { + + /* have no allocated segment for writing data, try allocate it */ + if (segment == NULL) { + /* allocating new segment */ + segment = tcp_segment_alloc(connection, PXE_SEGMENT_BIG); + + if (segment == NULL) { + printf("pxe_tcp_write(): failed to allocate segment.\n"); + return (sent_data == 0) ? (-1) : sent_data; + } + + connection->segment = segment; + segment_data = (void *)(segment + 1); + + tcp_start_segment(connection, segment, PXE_SEGMENT_OPTS_NO); + } + + /* calculating free space in segment packet */ + bufleft = connection->chunk_size * PXE_TCP_CHUNK_COUNT; + bufleft -= sizeof(PXE_TCP_QUEUED_SEGMENT) - segment->size; + /* how much left to send */ + send_now = size_to_send - sent_data; + + if (send_now < bufleft) { + /* copy data to segment space, actually there is no send, till + * segment is fully filled or called pxe_tcp_push() + */ + pxe_memcpy(data + sent_data, segment_data + segment->size, send_now); + segment->size += send_now; + sent_data += send_now; + + return (sent_data); + } + + /* if we got here, then we need to finish current segment and alloc new segment */ + + pxe_memcpy(data + sent_data, segment_data + segment->size, bufleft); + segment->size += bufleft; + sent_data += bufleft; + + /* finish segment */ + tcp_finish_segment(connection, segment, PXE_TCP_ACK); + + segment->resend_at = pxe_get_secs() + PXE_RESEND_TIME; + + if (!pxe_tcp_send_segment(connection, segment)) { + printf("pxe_tcp_write(): failed to send segment.\n"); + /* this segment will be resent later, so continue normal processing */ + } + + segment = NULL; + connection->segment = NULL; + } + + return (sent_data); +} + +/* pxe_tcp_read() - wrapper to read data from TCP socket + * in: + * sock - TCP socket to read from + * data - buffer to read data + * size_to_read - buffer size + * out: + * -1 - failed + * >=0 - actual bytes read + */ +int +pxe_tcp_read(PXE_SOCKET *sock, void *data, uint16_t size_to_read) +{ + PXE_TCP_CONNECTION *connection = filter_to_connection(sock->filter); + + if (connection == NULL) { + printf("pxe_tcp_read(): no connection for filter 0x%x (socket: 0x%x).\n", sock->filter, sock); + return (-1); + } + + PXE_BUFFER *recv_buffer = connection->recv; + + if ( (connection->state != PXE_TCP_ESTABLISHED) && + (recv_buffer->bufleft == recv_buffer->bufsize) ) + { + return (-1); /* connection closed and no data in buffer */ + } + + + return (pxe_buffer_read(recv_buffer, data, size_to_read)); +} + +/* pxe_tcp_push() - flushes send buffer (actually current send segment) + * in: + * sock - TCP socket to flush + * out: + * 0 - failed + * 1 - success + */ +int +pxe_tcp_push(PXE_SOCKET *sock) +{ + PXE_TCP_CONNECTION *connection = filter_to_connection(sock->filter); + + if (connection == NULL) { + printf("pxe_tcp_push(): no connection for filter 0x%x (socket: 0x%x).\n", sock->filter, sock); + return (0); + } + + if ( connection->state != PXE_TCP_ESTABLISHED ){ + return (0); /* connection not in established state, ignore available data */ + } + + PXE_TCP_QUEUED_SEGMENT *segment = connection->segment; + + if (segment == NULL) { /* nothing to push */ + return (1); + } + + /* finish segment */ + tcp_finish_segment(connection, segment, PXE_TCP_ACK | PXE_TCP_PSH); + + segment->resend_at = pxe_get_secs() + PXE_RESEND_TIME; + + if (!pxe_tcp_send_segment(connection, segment)) { + printf("pxe_tcp_push(): failed to send segment.\n"); + /* this segment will be resent later, so continue normal processing */ + } + + segment = NULL; + connection->segment = NULL; + + return (1); +} ==== //depot/projects/soc2007/taleks-pxe_http/pxe_connection.h#2 (text+ko) ==== @@ -1,5 +1,5 @@ -#ifndef TCP_CONNECTION_INCLUDED -#define TCP_CONNECTION_INCLUDED +#ifndef PXE_CONNECTION_INCLUDED +#define PXE_CONNECTION_INCLUDED #include @@ -11,7 +11,7 @@ #define PXE_TCP_STATE_MASK 0x0f #define PXE_TCP_CLOSED 0x00 /* closed */ -#define PXE_TCP_RESETED 0x0f /* received RST */ +#define PXE_TCP_RESETED 0x0f /* TODO: check if this needed.(received RST) */ #define PXE_TCP_SYN_SENT 0x01 /* active */ #define PXE_TCP_SYN_RECEIVED 0x02 /* sent & received SYN */ @@ -31,7 +31,9 @@ typedef struct pxe_tcp_connecton { uint8_t state; /* current TCP conenction state */ - uint8_t state_out; /* */ + uint8_t state_out; /* show latest acked packet flags (e.g. we sent FIN and it was ACKed, + * here will be PXE_TCP_FIN. Currently used but ACKing not checked. + */ uint32_t next_recv; /* next sequence number to accept */ uint32_t next_send; /* next sequence number to send */ @@ -49,10 +51,16 @@ PXE_BUFFER *send; /* send buffer */ PXE_FILTER_ENTRY* filter; /* filter, associated with connection */ + + /* current segment to fill, NULL - if unknown */ + /* PXE_TCP_QUEUED_SEGMENT *segment; */ + void *segment; /* send buffer usage map */ uint8_t buf_blocks[PXE_TCP_BLOCK_COUNT]; uint16_t chunk_size; /* buffer chunk size */ + + /* TODO: check if two members below needed */ time_t last_sent; /* timestamp of last sending event */ time_t last_recv; /* timestamp of last received event */ } PXE_TCP_CONNECTION; @@ -63,10 +71,19 @@ /* returns associated connection by filter */ PXE_TCP_CONNECTION * filter_to_connection(PXE_FILTER_ENTRY *filter); +/* initates handshaking */ +int pxe_tcp_connect(PXE_SOCKET *sock); + /* initates connection break */ int pxe_tcp_disconnect(PXE_SOCKET* sock); +/* sends user data */ +int pxe_tcp_write(PXE_SOCKET *sock, void *data, uint16_t size); + +/* receives user data */ +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_SOCKET *sock); #endif ==== //depot/projects/soc2007/taleks-pxe_http/pxe_segment.c#3 (text+ko) ==== @@ -1,11 +1,11 @@ #include #include "pxe_buffer.h" +#include "pxe_segment.h" #include "pxe_connection.h" #include "pxe_conv.h" #include "pxe_core.h" #include "pxe_ip.h" -#include "pxe_segment.h" #include "pxe_tcp.h" @@ -87,7 +87,7 @@ data = buffer->data + PXE_TCP_CHUNK_COUNT * block_index * connection->chunk_size; segment = (PXE_TCP_QUEUED_SEGMENT *)data; - if (allocBig == 0) { /* alloc small packet (alloc chunk) */ + if (allocBig == PXE_SEGMENT_SMALL) { /* alloc small packet (alloc chunk) */ /* checking if block is not fully used */ if (buf_blocks[block_index] < PXE_TCP_BLOCK_USED) { @@ -298,7 +298,7 @@ tcp_packet->tcphdr.sequence = le2be32(connection->next_send); tcp_packet->tcphdr.data_off = sizeof(PXE_TCP_HDR); - if (add_options == 1) { + if (add_options == PXE_SEGMENT_OPTS_DEFAULT) { /* reserving 8 bytes for options */ length += 8; tcp_packet->tcphdr.data_off += 8; @@ -434,7 +434,7 @@ PXE_TCP_PACKET *tcp_packet = (PXE_TCP_PACKET *)(segment + 1); if (!pxe_ip_send(tcp_packet, connection->dst_ip, PXE_TCP_PROTOCOL, segment->size, 1)) { - printf("pxe_tcp_send_send(): failed to send tcp packet to 0x%x\n", connection->dst_ip); + printf("pxe_tcp_send_segment(): failed to send tcp packet to 0x%x\n", connection->dst_ip); return (0); } @@ -524,7 +524,7 @@ printf("pxe_resend_stats(): block %d awaiting %d ack.\n", block_index, segment->seq - connection->iss ); - } - } - } -}+ } /* check exclusive end*/ + } /* check free end */ + } /* cycle end */ +} ==== //depot/projects/soc2007/taleks-pxe_http/pxe_segment.h#3 (text+ko) ==== @@ -48,6 +48,8 @@ uint8_t status; /* segment status */ } PXE_TCP_QUEUED_SEGMENT; + + /* checks if need to resend some segments of connection */ void pxe_resend_check(PXE_TCP_CONNECTION *connection); @@ -63,12 +65,16 @@ /* sends chhosed segment to adrressee */ int pxe_tcp_send_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment); +#define PXE_SEGMENT_BIG 1 +#define PXE_SEGMENT_SMALL 0 /* allocates in buffer space segment */ PXE_TCP_QUEUED_SEGMENT * tcp_segment_alloc(PXE_TCP_CONNECTION *connection, int allocBig); /* releases memory used by segment */ void tcp_segment_free(PXE_TCP_CONNECTION *connection, int block_index, PXE_TCP_QUEUED_SEGMENT *segment); +#define PXE_SEGMENT_OPTS_DEFAULT 1 +#define PXE_SEGMENT_OPTS_NO 0 /* fills most of fields of tcp header of segment */ void tcp_start_segment(PXE_TCP_CONNECTION *connection, PXE_TCP_QUEUED_SEGMENT *segment, int add_options); ==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#10 (text+ko) ==== @@ -323,7 +323,6 @@ PXE_SOCKET *sock = &pxe_sockets[socket]; - if ( sock->state == PXE_SOCKET_BINDED) { /* if socket binded filter must not be NULL, cause pxe_bind() installs filter */ if (sock->filter == NULL) { @@ -331,14 +330,6 @@ return (-1); } - /* NOTE: is really difference? */ - /* if (filter->protocol == PXE_UDP_PROTOCOL) { - - } else { - - } - */ - } else { /* not binded, connect */ /* NOTE: if it's already connected, return error */ @@ -457,38 +448,29 @@ * nonnegative - actual count of bytes sent */ int -pxe_send(int socket, void *buf, size_t buflen) +pxe_send(int socket, void *buf, uint16_t buflen) { - if (buflen + sizeof(PXE_UDP_PACKET) > PXE_DEFAULT_SEND_BUFSIZE) { - printf("pxe_send(): send buffer too small for %d bytes.\n", buflen); + if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) { + printf("pxe_recv(): invalid socket %d.\n", socket); return (-1); } - PXE_SOCKET *sock = &pxe_sockets[socket]; - - /* for UDP socket, send buffer used only for one dgram */ - PXE_UDP_PACKET *udp_pack = (PXE_UDP_PACKET *)sock->send_buffer.data; - PXE_FILTER_ENTRY *filter = sock->filter; + PXE_SOCKET *sock = &pxe_sockets[socket]; + PXE_FILTER_ENTRY *filter = sock->filter; + + if (filter->protocol == PXE_UDP_PROTOCOL) { - if (filter == NULL) { /* not connected socket */ - printf("pxe_send(): socket is not connected.\n"); - return (-1); - } + return pxe_udp_write(sock, buf, buflen); + + } else if (filter->protocol == PXE_TCP_PROTOCOL) { - /* copy user data */ - pxe_memcpy(buf, udp_pack + 1, buflen); + return pxe_tcp_write(sock, buf, buflen); + } -#ifdef PXE_DEBUG - printf("pxe_send(): %8x:%d -> %8x:%d, size = %d bytes.\n", pxe_get_ip32(PXE_IP_MY), filter->dst_port, filter->src_ip, filter->src_port, buflen); -#endif + printf("pxe_send(): only TCP and UDP sockets are implemented.\n"); - if (!pxe_udp_send(udp_pack, filter->src_ip, filter->src_port, filter->dst_port, buflen + sizeof(PXE_UDP_PACKET), 1)) { - printf("pxe_send(): failed to send data.\n"); - return (-1); - } - - return (buflen); + return (-1); } /* pxe_recv() - receive data to socket @@ -501,55 +483,28 @@ * nonnegative - actual count of bytes received */ int -pxe_recv(int socket, void *tobuf, size_t buflen) +pxe_recv(int socket, void *tobuf, uint16_t buflen) { - /* common part */ if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) { printf("pxe_recv(): invalid socket %d.\n", socket); return (-1); } - PXE_BUFFER *buffer = &pxe_sockets[socket].recv_buffer; - - size_t usage = buffer->bufsize - buffer->bufleft; + PXE_SOCKET *sock = &pxe_sockets[socket]; + PXE_FILTER_ENTRY *filter = sock->filter; - if ( usage == 0 ) { /* nothing received */ -#ifdef PXE_DEBUG - printf("pxe_recv(): nothing to recv for socket %d.\n", socket); -#endif - return (0); - } - -#ifdef PXE_DEBUG - printf("pxe_recv(): usage = %d, buflen = %d.\n", usage, buflen); -#endif - - /* udp related part, need to move it to separate function */ - PXE_UDP_DGRAM udp_dgram; + if (filter->protocol == PXE_UDP_PROTOCOL) { - if (sizeof(PXE_UDP_DGRAM) != pxe_buffer_read(buffer, &udp_dgram, sizeof(PXE_UDP_DGRAM))) { -#ifdef PXE_DEBUG - printf("pxe_udp_sock_recv(): failed to read datagram data.\n"); -#endif - return (0); - } + return pxe_udp_read(sock, tobuf, buflen); + + } else if (filter->protocol == PXE_TCP_PROTOCOL) { - if (udp_dgram.magic != PXE_MAGIC_DGRAM) { /* sanity check failed */ -#ifdef PXE_DEBUG - printf("pxe_udp_sock_recv(): dgram magic failed.\n"); -#endif - return (0); - } + return pxe_tcp_read(sock, tobuf, buflen); + } - uint16_t tocopy = ((uint16_t)buflen < udp_dgram.size) ? (uint16_t)buflen : udp_dgram.size; + printf("pxe_recv(): only TCP and UDP sockets are implemented.\n"); - uint16_t result = pxe_buffer_read(buffer, tobuf, tocopy); - - if (result < udp_dgram.size) { /* free truncated dgram part */ - pxe_buffer_read(buffer, NULL, udp_dgram.size - result); - } - - return ((int)result); + return (-1); } /* pxe_recvfrom() - receive data to socket with information about sender @@ -669,3 +624,35 @@ return (0); } + +/* pxe_push() - flushes send buffers + * in: + * socket - socket descriptor number + * out: + * -1 - failed + * 0 - success + */ +int +pxe_push(int socket) +{ + if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) { + printf("pxe_push(): invalid socket %d.\n", socket); + return (-1); + } + + PXE_SOCKET *sock = &pxe_sockets[socket]; + PXE_FILTER_ENTRY *filter = sock->filter; + + if (filter->protocol == PXE_UDP_PROTOCOL) { + /* it's always flushed */ + return (0); + + } else if (filter->protocol == PXE_TCP_PROTOCOL) { + + return (pxe_tcp_push(sock) == 0) ? (-1) : 0; + } + + printf("pxe_push(): only TCP and UDP sockets are implemented.\n"); + + return (-1); +} ==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#9 (text+ko) ==== @@ -76,10 +76,10 @@ /* int pxe_listen_from(int socket, uint8_t proto, uint16_t port, uint32_t src_ip, uint16_t port, int block); */ /* send data to socket, blocking */ -int pxe_send(int socket, void *buf, size_t buflen); +int pxe_send(int socket, void *buf, uint16_t buflen); /* receive data from socket, blocking */ -int pxe_recv(int socket, void *buf, size_t buflen); +int pxe_recv(int socket, void *buf, uint16_t buflen); /* create new socket */ int pxe_socket(); @@ -87,6 +87,9 @@ /* binding */ int pxe_bind(int socket, uint32_t ip, uint16_t port, uint8_t proto); +/* flushes send buffers */ +int pxe_push(int socket); + /* close socket */ int pxe_close(int socket); ==== //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.c#5 (text+ko) ==== @@ -1,6 +1,7 @@ #include #include "pxe_await.h" +#include "pxe_buffer.h" #include "pxe_connection.h" #include "pxe_conv.h" #include "pxe_core.h" @@ -33,6 +34,9 @@ tcp_time_wait, /* PXE_TCP_TIME_WAIT */ }; +static PXE_BUFFER sysbuf; /* used by pxe_tcp_syssend, when connection have no buffers */ +static uint8_t bufdata[PXE_TCP_SYSBUF_SIZE]; /* buffer space for sysbuf */ + /* check_time_to_die() - moves to CLOSED state connections from state * TIME_WAIT if last received packet (ACK for FIN in most cases) * was more than 2*MSL time ago. @@ -82,7 +86,10 @@ connection.next_recv = seq + seglen; /* acking */ connection.next_send = ack; /* next send */ - return pxe_tcp_send(&connection, 0, flags); + connection.chunk_size = PXE_TCP_SYSBUF_SIZE; + connection.buf_blocks[0] = PXE_TCP_BLOCK_FREE; + + return pxe_tcp_syssend(&connection, flags); } /* tcp_is_acceptable() - first check for SYN_RECEIVED, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, @@ -150,7 +157,7 @@ return (1); } - pxe_tcp_send(connection, 0, PXE_TCP_ACK); + pxe_tcp_syssend(connection, PXE_TCP_ACK); #ifdef PXE_DEBUG_HELL printf("tcp_check_1(): failed\n"); @@ -241,7 +248,7 @@ #ifdef PXE_DEBUG_HELL printf("tcp_check_5(): acked %d, but nxt_snd = %d. Check failed\n", ack, connection->next_send); #endif - pxe_tcp_send(connection, 0, PXE_TCP_ACK); + pxe_tcp_syssend(connection, PXE_TCP_ACK); return (0); } @@ -304,12 +311,12 @@ #endif */ if (seglen > 0) { - /* write data to buffer */ + /* write data to buffer, always enough space, if packet is acceptable */ void *data = ((void *)tcp_packet) + sizeof(PXE_IP_HDR) + 4 * (tcp_packet->tcphdr.data_off >> 4); pxe_buffer_write(connection->recv, data, seglen); } - pxe_tcp_send(connection, 0, PXE_TCP_ACK); + pxe_tcp_syssend(connection, PXE_TCP_ACK); connection->last_recv = pxe_get_secs(); } @@ -402,7 +409,7 @@ if ((connection->una > connection->iss) || (acceptable == 1) ) { /* acking */ - if (pxe_tcp_send(connection, 0, PXE_TCP_ACK)) { + if (pxe_tcp_syssend(connection, PXE_TCP_ACK)) { #ifdef PXE_DEBUG printf("tcp_syn_sent(): new state - ESTABLISHED\n"); #endif @@ -504,7 +511,7 @@ if (!tcp_check_5(connection, tcp_packet)) { return (0); } else { - /* TODO: move updating of next_send to pxe_tcp_send() */ + /* TODO: move updating of next_send to pxe_tcp_syssend() */ connection->next_send = tcp_packet->tcphdr.ack_next; } @@ -953,45 +960,51 @@ printf("pxe_tcp_init(): started\n"); #endif pxe_connection_init(); + /* registering protocol */ pxe_core_register(PXE_TCP_PROTOCOL, pxe_tcp_callback); + + /* sysbuf init */ + sysbuf.data = &bufdata; + /* not really need, cause not using buffer realted functions */ + sysbuf.bufleft = PXE_TCP_SYSBUF_SIZE; + sysbuf.bufsize = PXE_TCP_SYSBUF_SIZE; + sysbuf.fstart = 0; + sysbuf.fend = PXE_TCP_SYSBUF_SIZE - 1; } -/* pxe_tcp_send() - send system packets via TCP protocol +/* pxe_tcp_syssend() - send system packets via TCP protocol * in: * connection - connection to send to - * size - data size * tcp_flags - one or more PXE_TCP_.. flags * out: * 0 - failed * 1 - success */ int -pxe_tcp_send(PXE_TCP_CONNECTION *connection, uint16_t size, uint8_t tcp_flags) +pxe_tcp_syssend(PXE_TCP_CONNECTION *connection, uint8_t tcp_flags) { - /* allocating smmall segment */ - PXE_TCP_QUEUED_SEGMENT *segment = tcp_segment_alloc(connection, 0); + /* allocating "small" segment */ + PXE_TCP_QUEUED_SEGMENT *segment = tcp_segment_alloc(connection, PXE_SEGMENT_SMALL); if (segment == NULL) { - printf("pxe_tcp_send(): failed to allocate segment.\n"); + printf("pxe_tcp_syssend(): failed to allocate segment.\n"); return (0); } -/* segment->seq = connection->next_send; */ - /* here is simpliest ever in the world way to calculate resend time - * for more reliable resend time calculation need to implement RTT calculating. - */ - - /* add to every system segment default options */ - tcp_start_segment(connection, segment, 1); + tcp_start_segment(connection, segment, PXE_SEGMENT_OPTS_DEFAULT); /* finish segment */ tcp_finish_segment(connection, segment, tcp_flags); + + /* Here is simpliest ever in the world way to calculate resend time. + * For more reliable resend time calculation need to implement RTT calculating. + */ segment->resend_at = pxe_get_secs() + PXE_RESEND_TIME; if (!pxe_tcp_send_segment(connection, segment)) { - printf("pxe_tcp_send(): failed to send segment.\n"); + printf("pxe_tcp_syssend(): failed to send segment.\n"); return (0); } ==== //depot/projects/soc2007/taleks-pxe_http/pxe_tcp.h#6 (text+ko) ==== @@ -19,6 +19,8 @@ #define PXE_TCP_PROTOCOL 6 /* maximum segment life time in ms */ #define PXE_TCP_MSL 60000 +/* buffer size used for system messages for packets without real connection */ +#define PXE_TCP_SYSBUF_SIZE 64 /* tcp packet flags */ #define PXE_TCP_FIN 0x01 @@ -71,16 +73,7 @@ /* init tcp */ void pxe_tcp_init(); -/* sends data */ -int pxe_tcp_send(PXE_TCP_CONNECTION *connection, uint16_t size, uint8_t tcp_flags); - -/* initates handshaking */ -int pxe_tcp_connect(PXE_SOCKET* sock); - -/* initates connection break */ -int pxe_tcp_disconnect(PXE_SOCKET* sock); - -/* pushes current segment data */ -int pxe_tcp_push(PXE_SOCKET* sock); +/* sends "system" (no user data) segment */ +int pxe_tcp_syssend(PXE_TCP_CONNECTION *connection, uint8_t tcp_flags); #endif // PXE_TCP_H_INCLUDED ==== //depot/projects/soc2007/taleks-pxe_http/pxe_udp.c#5 (text+ko) ==== @@ -52,12 +52,12 @@ if (function == PXE_CORE_FRAG) /* informm, we are interested in whole packet*/ return (1); - uint16_t buf_free = sock->recv_buffer.bufleft; +/* uint16_t buf_free = sock->recv_buffer.bufleft; */ uint16_t data_size = pack->data_size - sizeof(PXE_UDP_PACKET); - if (buf_free < data_size) +/* if (buf_free < data_size) return (0); - +*/ PXE_BUFFER* recv_buffer = &sock->recv_buffer; PXE_UDP_DGRAM udp_dgram; @@ -174,3 +174,88 @@ return (1); } +/* pxe_udp_read() - performs reading from UDP socket + * in: + * sock - UDP socket to read from + * tobuf - buffer, where to read + * buflen - buffer size + * out: + * -1 - failed + * >= 0 - actual bytes were read + */ +int +pxe_udp_read(PXE_SOCKET *sock, void *tobuf, uint16_t buflen) +{ + PXE_UDP_DGRAM udp_dgram; + PXE_BUFFER *buffer = &sock->recv_buffer; + uint16_t usage = buffer->bufsize - buffer->bufleft; + + if (sizeof(PXE_UDP_DGRAM) != pxe_buffer_read(buffer, &udp_dgram, sizeof(PXE_UDP_DGRAM))) { +#ifdef PXE_DEBUG + printf("pxe_udp_read(): failed to read datagram data.\n"); +#endif + return (0); + } + + if (udp_dgram.magic != PXE_MAGIC_DGRAM) { /* sanity check failed */ +#ifdef PXE_DEBUG + printf("pxe_udp_sock_recv(): dgram magic failed.\n"); +#endif + return (0); + } + + uint16_t tocopy = ((uint16_t)buflen < udp_dgram.size) ? (uint16_t)buflen : udp_dgram.size; + uint16_t result = pxe_buffer_read(buffer, tobuf, tocopy); + + if (result < udp_dgram.size) { /* free truncated dgram part */ + pxe_buffer_read(buffer, NULL, udp_dgram.size - result); + } + + return ((int)result); +} + +/* pxe_udp_write() - performs writing to UDP socket + * in: + * sock - UDP socket to write to + * tobuf - buffer with data to write + * buflen - buffer size + * out: + * -1 - failed + * >= 0 - actual bytes were written + */ +int +pxe_udp_write(PXE_SOCKET *sock, void *buf, uint16_t buflen) +{ + + if (buflen + sizeof(PXE_UDP_PACKET) > PXE_DEFAULT_SEND_BUFSIZE) { + printf("pxe_udp_write(): send buffer too small for %d bytes.\n", buflen); + return (-1); + } + + /* for UDP socket, send buffer used only for one dgram */ + PXE_UDP_PACKET *udp_pack = (PXE_UDP_PACKET *)sock->send_buffer.data; + PXE_FILTER_ENTRY *filter = sock->filter; + + if (filter == NULL) { /* not connected socket */ + printf("pxe_udp_write(): socket is not connected.\n"); + return (-1); + } + + /* copy user data */ + pxe_memcpy(buf, udp_pack + 1, buflen); + +#ifdef PXE_DEBUG + printf("pxe_udp_write(): %8x:%d -> %8x:%d, size = %d bytes.\n", + pxe_get_ip32(PXE_IP_MY), filter->dst_port, filter->src_ip, filter->src_port, buflen + ); +#endif + + if (!pxe_udp_send(udp_pack, filter->src_ip, filter->src_port, + filter->dst_port, buflen + sizeof(PXE_UDP_PACKET), 1)) + { + printf("pxe_udp_write(): failed to send data.\n"); + return (-1); + } + + return (buflen); +} ==== //depot/projects/soc2007/taleks-pxe_http/pxe_udp.h#3 (text+ko) ==== @@ -22,23 +22,14 @@ uint16_t checksum; /* header, pseudo header and data checksum */ } __packed PXE_UDP_HDR; -/* pseudo header, used in checksum calculation */ -typedef struct pxe_ip4_pseudo_hdr { +typedef struct pxe_udp_packet { - uint32_t src_ip; /* source ip */ - uint32_t dst_ip; /* destination ip */ - uint8_t zero; /* filled by zero */ - uint8_t proto; /* protocol */ - uint16_t length; /* UDP length (header + data) */ -} __packed PXE_IP4_PSEUDO_HDR; - - -typedef struct pxe_udp_packet { PXE_IP_HDR iphdr; PXE_UDP_HDR udphdr; } __packed PXE_UDP_PACKET; #define PXE_MAGIC_DGRAM 0x26101982 + /* structure is used to store datagrams in receive buffer of socket */ typedef struct pxe_udp_dgram { @@ -52,7 +43,9 @@ /* UDP module init */ void pxe_udp_init(); -/* sends ip packet */ +/* sends udp packet */ int pxe_udp_send(void *data, uint32_t dst_ip, uint16_t dst_port, uint16_t src_port, uint16_t size, int flags); +/* */ + #endif // PXE_IP_H_INCLUDED