PERFORCE change 122647 for review

Alexey Tarasov taleks at FreeBSD.org
Sun Jul 1 16:00:28 UTC 2007


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

Change 122647 by taleks at 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 <stdint.h>
 
@@ -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 <stand.h>
 
 #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 <stand.h>
 
 #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


More information about the p4-projects mailing list