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