2
* Copyright (c) 2004, Jeroen Asselman
4
*----------------------------------------------------------------------
5
* This file is part of gtk-gnutella.
7
* gtk-gnutella is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* gtk-gnutella is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with gtk-gnutella; if not, write to the Free Software
20
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*----------------------------------------------------------------------
28
* Needs short description here.
30
* @author Jeroen Asselman
34
#include "../common.h" /* For -DUSE_DMALLOC */
39
int sequencenumber = 0;
41
static int header_length = 8;
42
static int MTU = 1500;
43
int transmit_retransmit_interval = 10; /**< seconds */
44
int transmit_packet_timeout = 26; /**< seconds */
45
int receive_packet_expiry = 30; /**< seconds */
47
GSList *receiving_fragments_list;
48
GSList *received_fragments_list;
50
typedef struct fragment_s fragment_t;
56
time_t initial_transmitted;
57
time_t last_transmitted;
63
void udp_transceiver_timer(time_t now)
65
/* Fragments waiting for acknowledge > receive_packet_expiry?
66
* Remove acknowledge packets.
68
* Fragments waiting for acknowledge?
70
* Retransmit to be acknowledged packets
72
* Fragments to be send?
73
* Send a few fragments. No more then udp_bandwith_out / MTU
78
*** Building and sending
82
* Wether the udp transceiver might be able to handle this received fragment.
85
udp_transceiver_can_handle_received_fragment(char *buf, int length)
87
return length > header_length &&
88
buf[0] == 'G' && buf[1] == 'N' && buf[2] == 'D';
92
* Put fragment in the to send list.
95
udp_transceiver_put_send_fragment(fragment_t *fragment)
97
/* FIXME: glist_prepend fragment */
104
udp_transceiver_send_fragment(fragment_t *fragment,
106
gboolean acknowledge)
108
/* FIXME: Send fragment over socket. */
112
/* FIXME: Add fragment to waiting_for_acknowledge list */
117
* Free the fragment and all its associated memory.
120
udp_transceiver_free_fragment(fragment_t *fragment)
122
if (fragment->fragment != NULL)
123
free(fragment->fragment);
132
udp_transceiver_build_fragment(char *buffer, int length,
137
gboolean acknowledge)
139
fragment_t *fragment = (fragment_t *) malloc(sizeof(fragment_t));
140
fragment->fragment_length = length + header_length;
141
fragment->fragment = (char *) malloc(fragment->fragment_length);
143
/* Build identifier */
144
fragment->fragment[0] = 'G';
145
fragment->fragment[1] = 'N';
146
fragment->fragment[2] = 'D';
148
/* Endian doesn't matter */
149
fragment->fragment[4] = (sequencenumber & 0x00FF);
150
fragment->fragment[5] = (sequencenumber >> 8);
151
fragment->fragment[6] = partnumber;
152
fragment->fragment[7] = fragments;
154
memcpy(fragment->fragment + header_length, buffer, length);
160
* Send a fragment to the specified address.
163
udp_transceiver_send(char *buffer, int length, gboolean deflate,
164
gboolean acknowledge,
165
guint32 address, guint16 port)
167
/* Create fragments. */
168
int fragments = (int) ceil((double)length / (double) MTU);
174
for (i = 0; i < fragments; i++) {
175
fragment_t *fragment = udp_transceiver_build_fragment(
176
buffer + offset, length - offset > MTU ? MTU : length - offset,
177
sequencenumber, i, fragments, deflate, acknowledge);
179
fragment->ipaddress = address;
180
fragment->port = port;
182
udp_transceiver_send_fragment(fragment, deflate, acknowledge);
188
*** Receiving and parsing
192
* Get the sequence number from a fragment.
195
udp_transceiver_get_sequencenumber(fragment_t *fragment)
197
return (fragment->fragment[4] << 8) + fragment->fragment[5];
201
* Get the part number from a fragment.
204
udp_transceiver_get_partnumber(fragment_t *fragment)
206
return fragment->fragment[6];
210
* Get the number of fragments from a datagram fragment.
213
udp_transceiver_get_fragments(fragment_t *fragment)
215
return fragment->fragment[7];
219
* Gets previously received fragments from the given source with matching
223
udp_transceiver_lookup_fragments_by_sequencenumber_source(
224
fragment_t *fragment)
230
* Puts a received datagram fragment in a to handle list.
233
udp_transceiver_put_received_fragment(fragment_t *fragment)
235
int fragments = udp_transceiver_get_fragments(fragment);
236
int partnumber = udp_transceiver_get_partnumber(fragment);
237
int sequencenumber = udp_transceiver_get_sequencenumber(fragment);
239
GSList *fragment_list =
240
udp_transceiver_lookup_fragments_by_sequencenumber_source(
242
fragment_t *fragment_tmp;
244
if (fragment_list == NULL)
246
/* FIXME: Create new fragment list (array?) with size fragments */
249
/* fragment_tmp = gslist_at(fragment_list, partnumber) */
250
if (fragment_tmp == NULL)
253
* gslist_insert_at(fragment_list, partnumber, fragment_received) */
257
/* FIXME: udp_transceiver_free_fragment(fragment) */
260
/* FIXME: Check if all fragments are received */
262
/* All fragments received */
266
* Parses a datagram and if it is a fragment it will be handed over to
267
* udp_transceiver_put_received_fragment.
270
udp_transceiver_put_received_datagram(char *buf, int length,
271
guint32 ip, guint16 port)
273
fragment_t *fragment_received;
275
if (!udp_transceiver_can_handle_received_fragment(buf, length))
278
fragment_received = (fragment_t *) malloc(sizeof(fragment_t));
279
fragment_received->fragment = (char *) malloc(length);
280
memcpy(fragment_received->fragment, buf, length);
281
fragment_received->fragment_length = length;
282
fragment_received->ipaddress = ip;
283
fragment_received->port = port;
285
udp_transceiver_put_received_fragment(fragment_received);
289
* Handle receiving of data
292
udp_transceiver_receive(char **buffer, int *length)
294
/* FIXME: for bla in fragments_received */
295
/* *length += fragment->fragment_length - header_length */
300
/* vi: set ts=4 sw=4 cindent: */