diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2005-12-15 07:41:49 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2005-12-15 07:41:49 +0000 |
commit | c3f5ea53917dea9c80751ee5809c7455589888be (patch) | |
tree | dc317bccff92e459c51102a655ec708d8ce0ac67 /system | |
parent | 37b6643df2df7d784a31ca73f7bb90dc109c2401 (diff) |
oops, mixed a few
svn path=/trunk/externals/pdp/; revision=4218
Diffstat (limited to 'system')
-rw-r--r-- | system/net/Makefile | 11 | ||||
-rw-r--r-- | system/net/pdp_net.c | 685 |
2 files changed, 0 insertions, 696 deletions
diff --git a/system/net/Makefile b/system/net/Makefile deleted file mode 100644 index 53d1d61..0000000 --- a/system/net/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -OBJECTS = pdp_net.o - - -include ../../Makefile.config - -all: $(OBJECTS) - -clean: - rm -f *~ - rm -f *.o diff --git a/system/net/pdp_net.c b/system/net/pdp_net.c deleted file mode 100644 index 04c97d6..0000000 --- a/system/net/pdp_net.c +++ /dev/null @@ -1,685 +0,0 @@ - -#include "pdp_net.h" -#include "pdp_debug.h" -#include "pdp_post.h" -#include "pdp_mem.h" - -#define D if (0) // DEBUG MSG -#define DD if (0) // DROP DEBUG MSG - -/* shared internals */ - -static int _is_udp_header(t_pdp_udp_header *header, unsigned int size) -{ - if (size < sizeof(t_pdp_udp_header)) return 0; - if (strcmp(header->signature, "PDP")) return 0; - if (PDP_UDP_VERSION != header->version) return 0; - return 1; -} - -static void _make_udp_header(t_pdp_udp_header *header) -{ - strcpy(header->signature, "PDP"); - header->version = PDP_UDP_VERSION; -} - - - - -/* R E C E I V E R */ - - -/* INTERNALS */ - -static void _send_packet(t_pdp_udp_receiver *x) -{ - _make_udp_header(&x->x_resend_header); - PDP_ASSERT(x->x_resend_udp_packet_size <= sizeof(t_pdp_udp_header) + sizeof(x->x_resend_chunks)); - - /* send the packet */ - if (-1 == sendto (x->x_socket, &x->x_resend_header, x->x_resend_udp_packet_size, 0, - (struct sockaddr *)&x->x_source_socket, x->x_sslen)){ - pdp_post("pdp_netreceive: send failed"); - } -} - -static void _send_ack_new(t_pdp_udp_receiver *x) -{ - /* setup resend header */ - x->x_resend_header.connection_id = x->x_connection_id; - x->x_resend_header.sequence_number = PDP_UDP_ACKNEW; - x->x_resend_udp_packet_size = sizeof(t_pdp_udp_header); - - _send_packet(x); - -} - - -static int _handle_PDP_UDP_NEW(t_pdp_udp_receiver *x) -{ - /* we've got a PDP_UDP_NEW packet, so prepare to receive the data */ - t_pdp_udp_newpacket *np = (t_pdp_udp_newpacket *)x->x_buf; - - - //pdp_post("conn_id = %x", x->x_header.connection_id); - //pdp_post("size = %d", np->data_size); - //pdp_post("nb_chunks = %d", np->nb_chunks); - //pdp_post("chunk_size = %d", np->chunk_size); - //pdp_post("type = %s", np->type); - - /* check if it is a resend of the PDP_UDP_NEW packet (if NEW_ACK didn't get through) - if not, prepare for reception */ - - if (x->x_connection_id != x->x_header.connection_id){ - - - /* prepare for reception : TODO add some more checks here */ - - // setup type info - if (x->x_data_type) pdp_dealloc (x->x_data_type); - x->x_data_type = pdp_alloc(1 + strlen(np->type)); - strcpy(x->x_data_type, np->type); - - // setup data buffer - x->x_data_size = np->data_size; - if (x->x_data) pdp_dealloc (x->x_data); - x->x_data = pdp_alloc(x->x_data_size); - memset(x->x_data, 0, x->x_data_size); // clear for debug - - // setup connection info - x->x_connection_id = x->x_header.connection_id; - x->x_nb_chunks = np->nb_chunks; - x->x_chunk_size = np->chunk_size; - - /* setup chunk list */ - if (x->x_chunk_list) pdp_dealloc(x->x_chunk_list); - x->x_chunk_list = pdp_alloc(sizeof(unsigned int)*x->x_nb_chunks); - memset(x->x_chunk_list, 0, sizeof(unsigned int)*x->x_nb_chunks); - - x->x_receive_finished = 0; // we're in a receiving state - x->x_packet_transferred = 0; // we didn't pass the packet yet - } - - /* send ACK */ - _send_ack_new(x); - - - - return 1; -} - -static void _handle_PDP_UDP_DONE(t_pdp_udp_receiver *x) -{ - unsigned int chunk; - unsigned int missing; - unsigned int i; - unsigned int resend_packet_size; - - - /* check the connection id */ - if (x->x_connection_id != x->x_header.connection_id) return; - - /* determine how many packets are missing */ - missing = 0; - for (i=0; i<x->x_nb_chunks; i++) - if (!x->x_chunk_list[i]) missing++; - - D pdp_post ("last packet %x had %d/%d dropped chunks", x->x_connection_id, missing, x->x_nb_chunks); - - - /* build the resend request (chunk list )*/ - if (missing > RESEND_MAX_CHUNKS) missing = RESEND_MAX_CHUNKS; - chunk = 0; - i = missing; - while(i--){ - while (x->x_chunk_list[chunk]) chunk++; // find next missing chunk - x->x_resend_chunks[i] = chunk++; // store it in list - } - - /* set the packet size to include the list */ - x->x_resend_udp_packet_size = sizeof(t_pdp_udp_header) - + missing * sizeof(unsigned int); - - /* setup resend header */ - strcpy((char *)&x->x_resend_header, "PDP"); - x->x_resend_header.version = PDP_UDP_VERSION; - x->x_resend_header.connection_id = x->x_connection_id; - x->x_resend_header.sequence_number = PDP_UDP_RESEND; - - D pdp_post("pdp_netreceive: sending RESEND response for %u chunks", missing); - - /* send out */ - _send_packet(x); - - /* indicate we're done if there's no chunks missing */ - if (!missing) x->x_receive_finished = 1; - -} - - -static int _handle_UDP_DATA(t_pdp_udp_receiver *x) -{ - unsigned int seq = x->x_header.sequence_number; - unsigned int offset = x->x_chunk_size * seq; - - /* ignore the packet if we're not expecting it */ - if ((!x->x_connection_id) || (x->x_connection_id != x->x_header.connection_id)){ - //pdp_post("pdp_netreceive: got invalid data packet: transmission id %x is not part of current transmisson %x", - // x->x_header.connection_id, x->x_connection_id); - return 0; - } - - /* check if it is valid */ - if (seq >= x->x_nb_chunks){ - pdp_post("pdp_netreceive: got invalid data packet: sequence number %u out of bound (nb_chunks=%u)", - seq, x->x_nb_chunks); - return 0; - } - - /* final check */ - PDP_ASSERT(offset + x->x_buf_size <= x->x_data_size); - - /* write & log it */ - memcpy(x->x_data + offset, x->x_buf, x->x_buf_size); - x->x_chunk_list[seq] = 1; - return 1; - -} - -/* INTERFACE */ - -/* setup */ -t_pdp_udp_receiver *pdp_udp_receiver_new(int port) -{ - t_pdp_udp_receiver *x = pdp_alloc(sizeof(*x)); - memset(x, 0, sizeof(*x)); - - /* init */ - x->x_data = 0; - x->x_data_type = 0; - x->x_data_size = 0; - x->x_chunk_list = 0; - x->x_receive_finished = 0; - x->x_packet_transferred = 0; - x->x_zero_terminator = 0; - - x->x_socket = socket(PF_INET, SOCK_DGRAM, 0); - x->x_connection_id = 0; /* zero for bootstrap (0 == an invalid id) */ - x->x_sslen = sizeof(struct sockaddr_in); - - /* bind socket */ - x->x_sa.sin_port = htons(port); - x->x_sa.sin_addr.s_addr = 0; - if (-1 != bind (x->x_socket, (struct sockaddr *)&x->x_sa, - sizeof(struct sockaddr_in))) return x; - - /* suicide if find failed */ - else { - pdp_dealloc(x); - return 0; - } -} -void pdp_udp_receiver_free(t_pdp_udp_receiver *x) -{ - if (!x) return; - if (x->x_socket != 1) close (x->x_socket); - if (x->x_data) pdp_dealloc(x->x_data); - if (x->x_data_type) pdp_dealloc (x->x_data_type); - if (x->x_chunk_list) pdp_dealloc (x->x_chunk_list); -} - -void pdp_udp_receiver_reset(t_pdp_udp_receiver *x) -{ - x->x_connection_id = 0; -} - - -/* receive loop, returns 1 on success, -1 on error, 0 on timeout */ -int pdp_udp_receiver_receive(t_pdp_udp_receiver *x, unsigned int timeout_ms) -{ - /* listen for packets */ - - unsigned int size; - struct timeval tv = {0,1000 * timeout_ms}; - fd_set inset; - FD_ZERO(&inset); - FD_SET(x->x_socket, &inset); - switch(select (x->x_socket+1, &inset, NULL, NULL, &tv)){ - case -1: - return -1; /* select error */ - case 0: - return 0; /* select time out */ - default: - break; /* data ready */ - } - - /* this won't block, since there's data available */ - if (-1 == (int)(size = recvfrom(x->x_socket, (void *)&x->x_header, - PDP_UDP_BUFSIZE+sizeof(x->x_header), 0, - (struct sockaddr *)&x->x_source_socket, &x->x_sslen))) return -1; - - /* store the data size of the packet */ - x->x_buf_size = size - sizeof(t_pdp_udp_header); - - /* parse the udp packet */ - if (_is_udp_header(&x->x_header, size)){ - - /* it is a control packet */ - if ((int)x->x_header.sequence_number < 0){ - - switch (x->x_header.sequence_number){ - case PDP_UDP_NEW: - _handle_PDP_UDP_NEW(x); - break; - - case PDP_UDP_DONE: - _handle_PDP_UDP_DONE(x); - - /* check if we got a complete packet - and signal arrival if we haven't done this already */ - if (x->x_receive_finished && !x->x_packet_transferred){ - x->x_packet_transferred = 1; - return 1; // data complete, please receive - } - break; - - default: - pdp_post("got unknown msg"); - break; - } - } - - /* it is a data packet */ - else { - _handle_UDP_DATA(x); - } - - - } - - else { - pdp_post("pdp_netreceive: got invalid UDP packet (size = %d)", size); - } - - return 0; //no major event, please poll again - -} - -/* get meta & data */ -char *pdp_udp_receiver_type(t_pdp_udp_receiver *x){return x->x_data_type;} -unsigned int pdp_udp_receiver_size(t_pdp_udp_receiver *x){return x->x_data_size;} -void *pdp_udp_receiver_data(t_pdp_udp_receiver *x){return x->x_data;} - - -/* S E N D E R */ - -/* INTERNALS */ - -static void _sleep(t_pdp_udp_sender *x) -{ - int sleep_period = x->x_sleep_period; - - if (sleep_period) { - if (!x->x_sleep_count++) usleep(x->x_sleepgrain_us); - x->x_sleep_count %= sleep_period; - } -} - -static void _send(t_pdp_udp_sender *x) -{ - //post("sending %u data bytes", x->x_buf_size); - - _make_udp_header(&x->x_header); - - PDP_ASSERT (x->x_buf_size <= PDP_UDP_BUFSIZE); - - if (-1 == sendto (x->x_socket, &x->x_header, x->x_buf_size + sizeof(t_pdp_udp_header), - 0, (struct sockaddr *)&x->x_sa, sizeof(struct sockaddr_in))) - pdp_post("pdp_netsend: send FAILED"); - - _sleep(x); - -} - - -static void _prepare_for_new_transmission(t_pdp_udp_sender *x, char *type, unsigned int size, void *data) -{ - unsigned int i; - - /* setup data for transmission */ - x->x_data_type = type; - x->x_data_size = size; - x->x_data = data; - x->x_chunk_size = x->x_udp_payload_size; - x->x_nb_chunks = (x->x_data_size - 1) / x->x_chunk_size + 1; - - /* generate a connection id (non-zero) */ - while (!(x->x_connection_id = rand())); - - /* setup chunk list to contain all chunks */ - if (x->x_chunk_list) free (x->x_chunk_list); - x->x_chunk_list_size = x->x_nb_chunks; - x->x_chunk_list = malloc(sizeof(unsigned int)*x->x_chunk_list_size); - for (i=0; i<x->x_chunk_list_size; i++) x->x_chunk_list[i] = i; - -} - -static void _send_header_packet(t_pdp_udp_sender *x) -{ - t_pdp_udp_newpacket *np = (t_pdp_udp_newpacket *)x->x_buf; /* buf contains the PDP_UDP_NEW body */ - - /* init packet */ - x->x_header.sequence_number = PDP_UDP_NEW; - x->x_header.connection_id = x->x_connection_id; - np->data_size = x->x_data_size; - np->nb_chunks = x->x_nb_chunks; - np->chunk_size = x->x_chunk_size; - strcpy(np->type, x->x_data_type); - x->x_buf_size = sizeof(*np) + strlen(np->type) + 1; - PDP_ASSERT(x->x_buf_size <= PDP_UDP_BUFSIZE); - - /* send the packet */ - _send(x); -} - -/* saend the chunks in the chunk list */ -static void _send_chunks(t_pdp_udp_sender *x){ - unsigned int i; - unsigned int count = 0; - - /* send chunks: this requires header is setup ok (sig,ver,connid)*/ - for (i=0; i<x->x_chunk_list_size; i++){ - unsigned int offset; - unsigned int current_chunk_size; - unsigned int seq = x->x_chunk_list[i]; - - PDP_ASSERT(seq < x->x_nb_chunks); - x->x_header.sequence_number = seq; // store chunk number - - /* get current chunk offset */ - offset = seq * x->x_chunk_size; - PDP_ASSERT(offset < x->x_data_size); - - - /* get current chunk size */ - current_chunk_size = (offset + x->x_chunk_size > x->x_data_size) ? - (x->x_data_size - offset) : x->x_chunk_size; - x->x_buf_size = current_chunk_size; - PDP_ASSERT(x->x_buf_size <= PDP_UDP_BUFSIZE); - - /* copy chunk to transmission buffer & send */ - PDP_ASSERT(offset + current_chunk_size <= x->x_data_size); - memcpy(x->x_buf, x->x_data + offset, current_chunk_size); - - - /* send the chunk */ - _send(x); - count++; - - } - D pdp_post("sent %d chunks, id=%x", count,x->x_connection_id); -} - -/* send a DONE packet */ -static void _send_done(t_pdp_udp_sender *x){ - x->x_header.sequence_number = PDP_UDP_DONE; - x->x_buf_size = 0; - _send(x); -} -static int _receive_packet(t_pdp_udp_sender *x, int desired_type) -/* 0 == timeout, -1 == error, 1 == got packet */ -{ - unsigned int size; - int type; - - struct timeval tv; - fd_set inset; - int sr; - - - while (1){ - int retval; - - /* wait for incoming */ - tv.tv_sec = 0; - tv.tv_usec = x->x_timeout_us; - FD_ZERO(&inset); - FD_SET(x->x_socket, &inset); - switch (select (x->x_socket+1, &inset, NULL, NULL, &tv)){ - case -1: - return -1; /* select error */ - case 0: - return 0; /* select time out */ - default: - break; /* data ready */ - } - - /* read packet */ - if (-1 == (int)(size = recv(x->x_socket, (void *)&x->x_resend_header, MAX_UDP_PACKET, 0))){ - pdp_post("pdp_netsend: error while reading from socket"); - return -1; - } - - /* check if it is a valid PDP_UDP packet */ - if (!_is_udp_header(&x->x_resend_header, size)){ - pdp_post("pdp_netsend: ignoring invalid UDP packet (size = %u)", size); - continue; - } - - - /* check connection id */ - if (x->x_connection_id != x->x_resend_header.connection_id){ - D pdp_post("pdp_netsend: ignoring ghost packet id=%x, current id=%x", - x->x_resend_header.connection_id, x->x_connection_id); - continue; - } - - /* check type */ - type = x->x_resend_header.sequence_number; - if (type != desired_type) continue; - - - /* setup data buffer for known packets */ - switch(type){ - case PDP_UDP_RESEND: - x->x_resend_items = (size - sizeof(t_pdp_udp_header)) / sizeof(unsigned int); - break; - default: - break; - } - - return 1; - } - -} - -/* get the resend list */ -static int _need_resend(t_pdp_udp_sender *x) { - - int retries = 3; - int retval; - while (retries--){ - - /* send a DONE msg */ - _send_done(x); - - /* wait for ACK */ - switch(_receive_packet(x, PDP_UDP_RESEND)){ - case 0: - /* timeout, retry */ - continue; - case -1: - /* error */ - goto move_on; - - default: - /* got PDP_UDP_RESEND packet: setup resend list */ - if (x->x_resend_items > x->x_nb_chunks){ - pdp_post("pdp_netsend: WARNING: chunk list size (%d) is too big, ignoring RESEND request", - x->x_resend_items); - x->x_resend_items = 0; - continue; - } - x->x_chunk_list_size = x->x_resend_items; - - memcpy(x->x_chunk_list, x->x_resend_chunks, sizeof(unsigned int) * x->x_resend_items); - D pdp_post("got RESEND request for %d chunks (id %x)", x->x_resend_items,x->x_connection_id); - - return x->x_chunk_list_size > 0; - } - - } - - /* timeout */ - move_on: - x->x_chunk_list_size = 0; - return 0; - - -} - - -/* INTERFACE */ - - -/* some flow control hacks */ - -void pdp_udp_sender_timeout_us(t_pdp_udp_sender *x, unsigned int timeout_us) -{ - x->x_timeout_us = timeout_us; -} - - -void pdp_udp_sender_sleepgrain_us(t_pdp_udp_sender *x, unsigned int sleepgrain_us) -{ - x->x_sleepgrain_us = sleepgrain_us; -} - -void pdp_udp_sender_sleepperiod(t_pdp_udp_sender *x, unsigned int sleepperiod) -{ - x->x_sleep_period = sleepperiod; -} - - -void pdp_udp_sender_udp_packet_size(t_pdp_udp_sender *x, unsigned int udp_packet_size) -{ - int i = (int)udp_packet_size - sizeof(t_pdp_udp_header); - if (i < 1024) i = 1024; - if (i > PDP_UDP_BUFSIZE) i = PDP_UDP_BUFSIZE; - x->x_udp_payload_size = i; -} - -void pdp_udp_sender_connect(t_pdp_udp_sender *x, char *host, unsigned int port) -{ - struct hostent *hp; - - hp = gethostbyname(host); - if (!hp){ - pdp_post("pdp_udp_sender: host %s not found", host); - } - else{ - /* host ok, setup address */ - x->x_sa.sin_family = AF_INET; - x->x_sa.sin_port = htons(port); - memcpy((char *)&x->x_sa.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* create the a socket if necessary */ - if (x->x_socket == -1){ - if (-1 == (x->x_socket = socket(PF_INET, SOCK_DGRAM, 0))){ - pdp_post("pdp_udp_sender: can't create socket"); - } - if (1){ - int on = 1; - if (setsockopt(x->x_socket,SOL_SOCKET,SO_BROADCAST,(char *)&on,sizeof(on))<0) - pdp_post("pdp_udp_sender: can't set broadcast flag"); - } - } - } -} - -/* setup */ -t_pdp_udp_sender *pdp_udp_sender_new(void) -{ - t_pdp_udp_sender *x = pdp_alloc(sizeof(*x)); - memset(x,0,sizeof(*x)); - - x->x_chunk_list = 0; - - /* no connection */ - x->x_socket = -1; - - - /* set flow control */ - pdp_udp_sender_timeout_us(x, 50000); - x->x_sleep_count = 0; - pdp_udp_sender_sleepgrain_us(x, 0); - pdp_udp_sender_sleepperiod(x, 50); - pdp_udp_sender_udp_packet_size(x, 1472); //optimal udp packet size (ip: 1500 = 28 + 1472) - - - return x; -} - -void pdp_udp_sender_free(t_pdp_udp_sender *x) -{ - int i; - void* retval; - if (x->x_socket != -1) close(x->x_socket); - if (x->x_chunk_list) free (x->x_chunk_list); -} - -/* send, returns 1 on success, 0 on error */ -int pdp_udp_sender_send(t_pdp_udp_sender *x, char* type, unsigned int size, void *data) -{ - - /* SEND A PACKET */ - - /* get the type and data from caller */ - /* send header packet and make sure it has arrived */ - /* send a chunk burst */ - /* send done packet and get the resend list */ - /* repeat until send list is empty */ - - - int hs_retry = 5; // retry count for initial handshake - int rs_retry = 5; // retry count for resends - - /* check if we have a target */ - if (-1 == x->x_socket) goto transerror; - - /* setup internal state */ - _prepare_for_new_transmission(x,type,size,data); - - /* handshake a new transmission */ - do { - if (!(hs_retry--)) break; - // pdp_post("handshake retry %d for packet %x", hscount, x->x_connection_id); - _send_header_packet(x); - } while (!_receive_packet(x, PDP_UDP_ACKNEW)); - - - /* exit if no handshake was possible */ - if (hs_retry < 0){ - DD pdp_post("pdp_netsend: DROP: receiver does not accept new transmission"); - goto transerror; - } - - /* transmission loop */ - do { - if (!(rs_retry--)) break; - _send_chunks(x); - } while (_need_resend(x)); - - /* exit if transmission was not successful */ - if (rs_retry < 0){ - DD pdp_post("pdp_netsend: DROP: receiver did not confirm reception"); - goto transerror; - } - - /* send successful */ - return 1; - - transerror: - /* transmission error */ - return 0; -} |