aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-03-17 18:13:55 +0100
committerChristian Grothoff <christian@grothoff.org>2017-03-17 18:13:55 +0100
commit17d34d5e094c2f8a90717b07e3a711d6e2c15903 (patch)
tree777b5323145a5f4d1f044da29a682799008a11d4 /src/util
parent3391977e3f92a2ebcafc14ea6374aecd580df873 (diff)
downloadgnunet-17d34d5e094c2f8a90717b07e3a711d6e2c15903.tar.gz
gnunet-17d34d5e094c2f8a90717b07e3a711d6e2c15903.zip
more renamings relating to 'new' service now just being the 'normal' service
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am6
-rw-r--r--src/util/bandwidth.c20
-rw-r--r--src/util/client.c13
-rw-r--r--src/util/helper.c2
-rw-r--r--src/util/mst.c4
-rw-r--r--src/util/resolver_api.c2
-rw-r--r--src/util/server_mst.c313
-rw-r--r--src/util/server_nc.c472
-rw-r--r--src/util/server_tc.c242
-rw-r--r--src/util/service.c10
-rw-r--r--src/util/test_client.c2
-rw-r--r--src/util/test_service.c2
12 files changed, 35 insertions, 1053 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 2ca977065..9be572bb6 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -30,9 +30,9 @@ W32CONSOLEHELPER = gnunet-helper-w32-console
30endif 30endif
31 31
32if !MINGW 32if !MINGW
33 TEST_CLIENT_UNIC_NC = test_client_unix.nc 33 TEST_CLIENT_UNIX_NC = test_client_unix.nc
34else 34else
35 TEST_CLIENT_UNIC_NC = 35 TEST_CLIENT_UNIX_NC =
36endif 36endif
37 37
38if USE_COVERAGE 38if USE_COVERAGE
@@ -106,7 +106,7 @@ libgnunetutil_la_SOURCES = \
106 program.c \ 106 program.c \
107 resolver_api.c resolver.h \ 107 resolver_api.c resolver.h \
108 scheduler.c \ 108 scheduler.c \
109 service_new.c \ 109 service.c \
110 signal.c \ 110 signal.c \
111 strings.c \ 111 strings.c \
112 time.c \ 112 time.c \
diff --git a/src/util/bandwidth.c b/src/util/bandwidth.c
index a059fc738..bc0c3b9b4 100644
--- a/src/util/bandwidth.c
+++ b/src/util/bandwidth.c
@@ -184,8 +184,8 @@ update_excess (struct GNUNET_BANDWIDTH_Tracker *av)
184 } 184 }
185 /* negative current_consumption means that we have savings */ 185 /* negative current_consumption means that we have savings */
186 max_carry = ((uint64_t) av->available_bytes_per_s__) * av->max_carry_s__; 186 max_carry = ((uint64_t) av->available_bytes_per_s__) * av->max_carry_s__;
187 if (max_carry < GNUNET_SERVER_MAX_MESSAGE_SIZE) 187 if (max_carry < GNUNET_MAX_MESSAGE_SIZE)
188 max_carry = GNUNET_SERVER_MAX_MESSAGE_SIZE; 188 max_carry = GNUNET_MAX_MESSAGE_SIZE;
189 if (max_carry > INT64_MAX) 189 if (max_carry > INT64_MAX)
190 max_carry = INT64_MAX; 190 max_carry = INT64_MAX;
191 left_bytes = current_consumption + max_carry; 191 left_bytes = current_consumption + max_carry;
@@ -224,10 +224,10 @@ update_excess (struct GNUNET_BANDWIDTH_Tracker *av)
224/** 224/**
225 * Initialize bandwidth tracker. Note that in addition to the 225 * Initialize bandwidth tracker. Note that in addition to the
226 * 'max_carry_s' limit, we also always allow at least 226 * 'max_carry_s' limit, we also always allow at least
227 * #GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the 227 * #GNUNET_MAX_MESSAGE_SIZE to accumulate. So if the
228 * bytes-per-second limit is so small that within 'max_carry_s' not 228 * bytes-per-second limit is so small that within 'max_carry_s' not
229 * even #GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is 229 * even #GNUNET_MAX_MESSAGE_SIZE is allowed to accumulate, it is
230 * ignored and replaced by #GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in 230 * ignored and replaced by #GNUNET_MAX_MESSAGE_SIZE (which is in
231 * bytes). 231 * bytes).
232 * 232 *
233 * To stop notifications about updates and excess callbacks use 233 * To stop notifications about updates and excess callbacks use
@@ -271,10 +271,10 @@ GNUNET_BANDWIDTH_tracker_init2 (struct GNUNET_BANDWIDTH_Tracker *av,
271/** 271/**
272 * Initialize bandwidth tracker. Note that in addition to the 272 * Initialize bandwidth tracker. Note that in addition to the
273 * 'max_carry_s' limit, we also always allow at least 273 * 'max_carry_s' limit, we also always allow at least
274 * #GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the 274 * #GNUNET_MAX_MESSAGE_SIZE to accumulate. So if the
275 * bytes-per-second limit is so small that within 'max_carry_s' not 275 * bytes-per-second limit is so small that within 'max_carry_s' not
276 * even #GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is 276 * even #GNUNET_MAX_MESSAGE_SIZE is allowed to accumulate, it is
277 * ignored and replaced by #GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in 277 * ignored and replaced by #GNUNET_MAX_MESSAGE_SIZE (which is in
278 * bytes). 278 * bytes).
279 * 279 *
280 * @param av tracker to initialize 280 * @param av tracker to initialize
@@ -345,8 +345,8 @@ update_tracker (struct GNUNET_BANDWIDTH_Tracker *av)
345 left_bytes = - av->consumption_since_last_update__; 345 left_bytes = - av->consumption_since_last_update__;
346 max_carry = ((unsigned long long) av->available_bytes_per_s__) * 346 max_carry = ((unsigned long long) av->available_bytes_per_s__) *
347 av->max_carry_s__; 347 av->max_carry_s__;
348 if (max_carry < GNUNET_SERVER_MAX_MESSAGE_SIZE) 348 if (max_carry < GNUNET_MAX_MESSAGE_SIZE)
349 max_carry = GNUNET_SERVER_MAX_MESSAGE_SIZE; 349 max_carry = GNUNET_MAX_MESSAGE_SIZE;
350 if (max_carry > INT64_MAX) 350 if (max_carry > INT64_MAX)
351 max_carry = INT64_MAX; 351 max_carry = INT64_MAX;
352 if (max_carry > left_bytes) 352 if (max_carry > left_bytes)
diff --git a/src/util/client.c b/src/util/client.c
index 163ae6eb9..3d74bff33 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -35,6 +35,15 @@
35 35
36#define LOG(kind,...) GNUNET_log_from (kind, "util-client",__VA_ARGS__) 36#define LOG(kind,...) GNUNET_log_from (kind, "util-client",__VA_ARGS__)
37 37
38/**
39 * Timeout we use on TCP connect before trying another
40 * result from the DNS resolver. Actual value used
41 * is this value divided by the number of address families.
42 * Default is 5s.
43 */
44#define CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
45
46
38 47
39/** 48/**
40 * Internal state for a client connected to a GNUnet service. 49 * Internal state for a client connected to a GNUnet service.
@@ -656,7 +665,7 @@ try_connect_using_address (void *cls,
656 GNUNET_CONTAINER_DLL_insert (cstate->ap_head, 665 GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
657 cstate->ap_tail, 666 cstate->ap_tail,
658 ap); 667 ap);
659 ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, 668 ap->task = GNUNET_SCHEDULER_add_write_net (CONNECT_RETRY_TIMEOUT,
660 ap->sock, 669 ap->sock,
661 &connect_probe_continuation, 670 &connect_probe_continuation,
662 ap); 671 ap);
@@ -760,7 +769,7 @@ start_connect (void *cls)
760 cstate->dns_active 769 cstate->dns_active
761 = GNUNET_RESOLVER_ip_get (cstate->hostname, 770 = GNUNET_RESOLVER_ip_get (cstate->hostname,
762 AF_UNSPEC, 771 AF_UNSPEC,
763 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, 772 CONNECT_RETRY_TIMEOUT,
764 &try_connect_using_address, 773 &try_connect_using_address,
765 cstate); 774 cstate);
766} 775}
diff --git a/src/util/helper.c b/src/util/helper.c
index 1a79c477a..a84b06e66 100644
--- a/src/util/helper.c
+++ b/src/util/helper.c
@@ -323,7 +323,7 @@ static void
323helper_read (void *cls) 323helper_read (void *cls)
324{ 324{
325 struct GNUNET_HELPER_Handle *h = cls; 325 struct GNUNET_HELPER_Handle *h = cls;
326 char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE] GNUNET_ALIGN; 326 char buf[GNUNET_MAX_MESSAGE_SIZE] GNUNET_ALIGN;
327 ssize_t t; 327 ssize_t t;
328 328
329 h->read_task = NULL; 329 h->read_task = NULL;
diff --git a/src/util/mst.c b/src/util/mst.c
index 9f1d30d7a..0d90c5d10 100644
--- a/src/util/mst.c
+++ b/src/util/mst.c
@@ -90,8 +90,8 @@ GNUNET_MST_create (GNUNET_MessageTokenizerCallback cb,
90 struct GNUNET_MessageStreamTokenizer *ret; 90 struct GNUNET_MessageStreamTokenizer *ret;
91 91
92 ret = GNUNET_new (struct GNUNET_MessageStreamTokenizer); 92 ret = GNUNET_new (struct GNUNET_MessageStreamTokenizer);
93 ret->hdr = GNUNET_malloc (GNUNET_SERVER_MIN_BUFFER_SIZE); 93 ret->hdr = GNUNET_malloc (GNUNET_MIN_MESSAGE_SIZE);
94 ret->curr_buf = GNUNET_SERVER_MIN_BUFFER_SIZE; 94 ret->curr_buf = GNUNET_MIN_MESSAGE_SIZE;
95 ret->cb = cb; 95 ret->cb = cb;
96 ret->cb_cls = cb_cls; 96 ret->cb_cls = cb_cls;
97 return ret; 97 return ret;
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index f33c31f1c..0c915932c 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -876,7 +876,7 @@ GNUNET_RESOLVER_ip_get (const char *hostname,
876 876
877 slen = strlen (hostname) + 1; 877 slen = strlen (hostname) + 1;
878 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= 878 if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
879 GNUNET_SERVER_MAX_MESSAGE_SIZE) 879 GNUNET_MAX_MESSAGE_SIZE)
880 { 880 {
881 GNUNET_break (0); 881 GNUNET_break (0);
882 return NULL; 882 return NULL;
diff --git a/src/util/server_mst.c b/src/util/server_mst.c
deleted file mode 100644
index 5155b54da..000000000
--- a/src/util/server_mst.c
+++ /dev/null
@@ -1,313 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file util/server_mst.c
23 * @brief convenience functions for handling inbound message buffers
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30
31#if HAVE_UNALIGNED_64_ACCESS
32#define ALIGN_FACTOR 4
33#else
34#define ALIGN_FACTOR 8
35#endif
36
37#define LOG(kind,...) GNUNET_log_from (kind, "util-server-mst", __VA_ARGS__)
38
39
40/**
41 * Handle to a message stream tokenizer.
42 */
43struct GNUNET_SERVER_MessageStreamTokenizer
44{
45
46 /**
47 * Function to call on completed messages.
48 */
49 GNUNET_SERVER_MessageTokenizerCallback cb;
50
51 /**
52 * Closure for @e cb.
53 */
54 void *cb_cls;
55
56 /**
57 * Size of the buffer (starting at @e hdr).
58 */
59 size_t curr_buf;
60
61 /**
62 * How many bytes in buffer have we already processed?
63 */
64 size_t off;
65
66 /**
67 * How many bytes in buffer are valid right now?
68 */
69 size_t pos;
70
71 /**
72 * Beginning of the buffer. Typed like this to force alignment.
73 */
74 struct GNUNET_MessageHeader *hdr;
75
76};
77
78
79
80/**
81 * Create a message stream tokenizer.
82 *
83 * @param cb function to call on completed messages
84 * @param cb_cls closure for @a cb
85 * @return handle to tokenizer
86 */
87struct GNUNET_SERVER_MessageStreamTokenizer *
88GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
89 void *cb_cls)
90{
91 struct GNUNET_SERVER_MessageStreamTokenizer *ret;
92
93 ret = GNUNET_new (struct GNUNET_SERVER_MessageStreamTokenizer);
94 ret->hdr = GNUNET_malloc (GNUNET_SERVER_MIN_BUFFER_SIZE);
95 ret->curr_buf = GNUNET_SERVER_MIN_BUFFER_SIZE;
96 ret->cb = cb;
97 ret->cb_cls = cb_cls;
98 return ret;
99}
100
101
102/**
103 * Add incoming data to the receive buffer and call the
104 * callback for all complete messages.
105 *
106 * @param mst tokenizer to use
107 * @param client_identity ID of client for which this is a buffer
108 * @param buf input data to add
109 * @param size number of bytes in @a buf
110 * @param purge should any excess bytes in the buffer be discarded
111 * (i.e. for packet-based services like UDP)
112 * @param one_shot only call callback once, keep rest of message in buffer
113 * @return #GNUNET_OK if we are done processing (need more data)
114 * #GNUNET_NO if @a one_shot was set and we have another message ready
115 * #GNUNET_SYSERR if the data stream is corrupt
116 */
117int
118GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
119 void *client_identity,
120 const char *buf, size_t size,
121 int purge, int one_shot)
122{
123 const struct GNUNET_MessageHeader *hdr;
124 size_t delta;
125 uint16_t want;
126 char *ibuf;
127 int need_align;
128 unsigned long offset;
129 int ret;
130
131 GNUNET_assert (mst->off <= mst->pos);
132 GNUNET_assert (mst->pos <= mst->curr_buf);
133 LOG (GNUNET_ERROR_TYPE_DEBUG,
134 "Server-mst receives %u bytes with %u bytes already in private buffer\n",
135 (unsigned int) size, (unsigned int) (mst->pos - mst->off));
136 ret = GNUNET_OK;
137 ibuf = (char *) mst->hdr;
138 while (mst->pos > 0)
139 {
140do_align:
141 GNUNET_assert (mst->pos >= mst->off);
142 if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
143 (0 != (mst->off % ALIGN_FACTOR)))
144 {
145 /* need to align or need more space */
146 mst->pos -= mst->off;
147 memmove (ibuf, &ibuf[mst->off], mst->pos);
148 mst->off = 0;
149 }
150 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
151 {
152 delta =
153 GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) -
154 (mst->pos - mst->off), size);
155 GNUNET_memcpy (&ibuf[mst->pos], buf, delta);
156 mst->pos += delta;
157 buf += delta;
158 size -= delta;
159 }
160 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
161 {
162 if (purge)
163 {
164 mst->off = 0;
165 mst->pos = 0;
166 }
167 return GNUNET_OK;
168 }
169 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
170 want = ntohs (hdr->size);
171 if (want < sizeof (struct GNUNET_MessageHeader))
172 {
173 GNUNET_break_op (0);
174 return GNUNET_SYSERR;
175 }
176 if ( (mst->curr_buf - mst->off < want) &&
177 (mst->off > 0) )
178 {
179 /* can get more space by moving */
180 mst->pos -= mst->off;
181 memmove (ibuf, &ibuf[mst->off], mst->pos);
182 mst->off = 0;
183 }
184 if (mst->curr_buf < want)
185 {
186 /* need to get more space by growing buffer */
187 GNUNET_assert (0 == mst->off);
188 mst->hdr = GNUNET_realloc (mst->hdr, want);
189 ibuf = (char *) mst->hdr;
190 mst->curr_buf = want;
191 }
192 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
193 if (mst->pos - mst->off < want)
194 {
195 delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
196 GNUNET_assert (mst->pos + delta <= mst->curr_buf);
197 GNUNET_memcpy (&ibuf[mst->pos], buf, delta);
198 mst->pos += delta;
199 buf += delta;
200 size -= delta;
201 }
202 if (mst->pos - mst->off < want)
203 {
204 if (purge)
205 {
206 mst->off = 0;
207 mst->pos = 0;
208 }
209 return GNUNET_OK;
210 }
211 if (one_shot == GNUNET_SYSERR)
212 {
213 /* cannot call callback again, but return value saying that
214 * we have another full message in the buffer */
215 ret = GNUNET_NO;
216 goto copy;
217 }
218 if (one_shot == GNUNET_YES)
219 one_shot = GNUNET_SYSERR;
220 mst->off += want;
221 if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr))
222 return GNUNET_SYSERR;
223 if (mst->off == mst->pos)
224 {
225 /* reset to beginning of buffer, it's free right now! */
226 mst->off = 0;
227 mst->pos = 0;
228 }
229 }
230 GNUNET_assert (0 == mst->pos);
231 while (size > 0)
232 {
233 LOG (GNUNET_ERROR_TYPE_DEBUG,
234 "Server-mst has %u bytes left in inbound buffer\n",
235 (unsigned int) size);
236 if (size < sizeof (struct GNUNET_MessageHeader))
237 break;
238 offset = (unsigned long) buf;
239 need_align = (0 != (offset % ALIGN_FACTOR)) ? GNUNET_YES : GNUNET_NO;
240 if (GNUNET_NO == need_align)
241 {
242 /* can try to do zero-copy and process directly from original buffer */
243 hdr = (const struct GNUNET_MessageHeader *) buf;
244 want = ntohs (hdr->size);
245 if (want < sizeof (struct GNUNET_MessageHeader))
246 {
247 GNUNET_break_op (0);
248 mst->off = 0;
249 return GNUNET_SYSERR;
250 }
251 if (size < want)
252 break; /* or not: buffer incomplete, so copy to private buffer... */
253 if (one_shot == GNUNET_SYSERR)
254 {
255 /* cannot call callback again, but return value saying that
256 * we have another full message in the buffer */
257 ret = GNUNET_NO;
258 goto copy;
259 }
260 if (one_shot == GNUNET_YES)
261 one_shot = GNUNET_SYSERR;
262 if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr))
263 return GNUNET_SYSERR;
264 buf += want;
265 size -= want;
266 }
267 else
268 {
269 /* need to copy to private buffer to align;
270 * yes, we go a bit more spagetti than usual here */
271 goto do_align;
272 }
273 }
274copy:
275 if ((size > 0) && (!purge))
276 {
277 if (size + mst->pos > mst->curr_buf)
278 {
279 mst->hdr = GNUNET_realloc (mst->hdr, size + mst->pos);
280 ibuf = (char *) mst->hdr;
281 mst->curr_buf = size + mst->pos;
282 }
283 GNUNET_assert (size + mst->pos <= mst->curr_buf);
284 GNUNET_memcpy (&ibuf[mst->pos], buf, size);
285 mst->pos += size;
286 }
287 if (purge)
288 {
289 mst->off = 0;
290 mst->pos = 0;
291 }
292 LOG (GNUNET_ERROR_TYPE_DEBUG,
293 "Server-mst leaves %u bytes in private buffer\n",
294 (unsigned int) (mst->pos - mst->off));
295 return ret;
296}
297
298
299/**
300 * Destroys a tokenizer.
301 *
302 * @param mst tokenizer to destroy
303 */
304void
305GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst)
306{
307 GNUNET_free (mst->hdr);
308 GNUNET_free (mst);
309}
310
311
312
313/* end of server_mst.c */
diff --git a/src/util/server_nc.c b/src/util/server_nc.c
deleted file mode 100644
index a95cd7f6d..000000000
--- a/src/util/server_nc.c
+++ /dev/null
@@ -1,472 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file util/server_nc.c
23 * @brief convenience functions for transmission of
24 * a notification stream
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31#define LOG(kind,...) GNUNET_log_from (kind, "util-server-nc", __VA_ARGS__)
32
33
34/**
35 * Entry in list of messages pending to be transmitted.
36 */
37struct PendingMessageList
38{
39
40 /**
41 * This is a doubly-linked list.
42 */
43 struct PendingMessageList *next;
44
45 /**
46 * This is a doubly-linked list.
47 */
48 struct PendingMessageList *prev;
49
50 /**
51 * Message to transmit (allocated at the end of this
52 * struct, do not free)
53 */
54 const struct GNUNET_MessageHeader *msg;
55
56 /**
57 * Can this message be dropped?
58 */
59 int can_drop;
60
61};
62
63
64/**
65 * Lists of clients we manage for notifications.
66 */
67struct ClientList
68{
69
70 /**
71 * This is a doubly linked list.
72 */
73 struct ClientList *next;
74
75 /**
76 * This is a doubly linked list.
77 */
78 struct ClientList *prev;
79
80 /**
81 * Overall context this client belongs to.
82 */
83 struct GNUNET_SERVER_NotificationContext *nc;
84
85 /**
86 * Handle to the client.
87 */
88 struct GNUNET_SERVER_Client *client;
89
90 /**
91 * Handle for pending transmission request to the client (or NULL).
92 */
93 struct GNUNET_SERVER_TransmitHandle *th;
94
95 /**
96 * Head of linked list of requests queued for transmission.
97 */
98 struct PendingMessageList *pending_head;
99
100 /**
101 * Tail of linked list of requests queued for transmission.
102 */
103 struct PendingMessageList *pending_tail;
104
105 /**
106 * Number of messages currently in the list.
107 */
108 unsigned int num_pending;
109
110};
111
112
113/**
114 * The notification context is the key datastructure for a convenience
115 * API used for transmission of notifications to the client until the
116 * client disconnects (or the notification context is destroyed, in
117 * which case we disconnect these clients). Essentially, all
118 * (notification) messages are queued up until the client is able to
119 * read them.
120 */
121struct GNUNET_SERVER_NotificationContext
122{
123
124 /**
125 * Server we do notifications for.
126 */
127 struct GNUNET_SERVER_Handle *server;
128
129 /**
130 * Head of list of clients receiving notifications.
131 */
132 struct ClientList *clients_head;
133
134 /**
135 * Tail of list of clients receiving notifications.
136 */
137 struct ClientList *clients_tail;
138
139 /**
140 * Maximum number of optional messages to queue per client.
141 */
142 unsigned int queue_length;
143
144};
145
146
147/**
148 * Client has disconnected, clean up.
149 *
150 * @param cls our `struct GNUNET_SERVER_NotificationContext *`
151 * @param client handle of client that disconnected
152 */
153static void
154handle_client_disconnect (void *cls,
155 struct GNUNET_SERVER_Client *client)
156{
157 struct GNUNET_SERVER_NotificationContext *nc = cls;
158 struct ClientList *pos;
159 struct PendingMessageList *pml;
160
161 if (NULL == client)
162 {
163 nc->server = NULL;
164 return;
165 }
166 for (pos = nc->clients_head; NULL != pos; pos = pos->next)
167 if (pos->client == client)
168 break;
169 if (NULL == pos)
170 return;
171 LOG (GNUNET_ERROR_TYPE_DEBUG,
172 "Client disconnected, cleaning up %u messages in NC queue\n",
173 pos->num_pending);
174 GNUNET_CONTAINER_DLL_remove (nc->clients_head,
175 nc->clients_tail,
176 pos);
177 while (NULL != (pml = pos->pending_head))
178 {
179 GNUNET_CONTAINER_DLL_remove (pos->pending_head,
180 pos->pending_tail,
181 pml);
182 GNUNET_free (pml);
183 pos->num_pending--;
184 }
185 if (NULL != pos->th)
186 {
187 GNUNET_SERVER_notify_transmit_ready_cancel (pos->th);
188 pos->th = NULL;
189 }
190 GNUNET_SERVER_client_drop (client);
191 GNUNET_assert (0 == pos->num_pending);
192 GNUNET_free (pos);
193}
194
195
196/**
197 * Create a new notification context.
198 *
199 * @param server server for which this function creates the context
200 * @param queue_length maximum number of messages to keep in
201 * the notification queue; optional messages are dropped
202 * if the queue gets longer than this number of messages
203 * @return handle to the notification context
204 */
205struct GNUNET_SERVER_NotificationContext *
206GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server,
207 unsigned int queue_length)
208{
209 struct GNUNET_SERVER_NotificationContext *ret;
210
211 ret = GNUNET_new (struct GNUNET_SERVER_NotificationContext);
212 ret->server = server;
213 ret->queue_length = queue_length;
214 GNUNET_SERVER_disconnect_notify (server,
215 &handle_client_disconnect,
216 ret);
217 return ret;
218}
219
220
221/**
222 * Destroy the context, force disconnect for all clients.
223 *
224 * @param nc context to destroy.
225 */
226void
227GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc)
228{
229 struct ClientList *pos;
230 struct PendingMessageList *pml;
231
232 while (NULL != (pos = nc->clients_head))
233 {
234 GNUNET_CONTAINER_DLL_remove (nc->clients_head,
235 nc->clients_tail,
236 pos);
237 if (NULL != pos->th)
238 {
239 GNUNET_SERVER_notify_transmit_ready_cancel (pos->th);
240 pos->th = NULL;
241 }
242 GNUNET_SERVER_client_drop (pos->client);
243 while (NULL != (pml = pos->pending_head))
244 {
245 GNUNET_CONTAINER_DLL_remove (pos->pending_head,
246 pos->pending_tail,
247 pml);
248 GNUNET_free (pml);
249 pos->num_pending--;
250 }
251 GNUNET_assert (0 == pos->num_pending);
252 GNUNET_free (pos);
253 }
254 if (NULL != nc->server)
255 GNUNET_SERVER_disconnect_notify_cancel (nc->server,
256 &handle_client_disconnect,
257 nc);
258 GNUNET_free (nc);
259}
260
261
262/**
263 * Add a client to the notification context.
264 *
265 * @param nc context to modify
266 * @param client client to add
267 */
268void
269GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc,
270 struct GNUNET_SERVER_Client *client)
271{
272 struct ClientList *cl;
273
274 for (cl = nc->clients_head; NULL != cl; cl = cl->next)
275 if (cl->client == client)
276 return; /* already present */
277 cl = GNUNET_new (struct ClientList);
278 GNUNET_CONTAINER_DLL_insert (nc->clients_head,
279 nc->clients_tail,
280 cl);
281 cl->nc = nc;
282 cl->client = client;
283 GNUNET_SERVER_client_keep (client);
284}
285
286
287/**
288 * Function called to notify a client about the socket begin ready to
289 * queue more data. @a buf will be NULL and @a size zero if the socket
290 * was closed for writing in the meantime.
291 *
292 * @param cls the `struct ClientList *`
293 * @param size number of bytes available in @a buf
294 * @param buf where the callee should write the message
295 * @return number of bytes written to buf
296 */
297static size_t
298transmit_message (void *cls,
299 size_t size,
300 void *buf)
301{
302 struct ClientList *cl = cls;
303 char *cbuf = buf;
304 struct PendingMessageList *pml;
305 uint16_t msize;
306 size_t ret;
307
308 cl->th = NULL;
309 if (NULL == buf)
310 {
311 /* 'cl' should be freed via disconnect notification shortly */
312 LOG (GNUNET_ERROR_TYPE_DEBUG,
313 "Failed to transmit message from NC queue to client\n");
314 return 0;
315 }
316 ret = 0;
317 while (NULL != (pml = cl->pending_head))
318 {
319 msize = ntohs (pml->msg->size);
320 if (size < msize)
321 break;
322 GNUNET_CONTAINER_DLL_remove (cl->pending_head,
323 cl->pending_tail,
324 pml);
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Copying message of type %u and size %u from pending queue to transmission buffer\n",
327 ntohs (pml->msg->type),
328 msize);
329 GNUNET_memcpy (&cbuf[ret], pml->msg, msize);
330 ret += msize;
331 size -= msize;
332 GNUNET_free (pml);
333 cl->num_pending--;
334 }
335 if (NULL != pml)
336 {
337 LOG (GNUNET_ERROR_TYPE_DEBUG,
338 "Have %u messages left in NC queue, will try transmission again\n",
339 cl->num_pending);
340 cl->th =
341 GNUNET_SERVER_notify_transmit_ready (cl->client,
342 ntohs (pml->msg->size),
343 GNUNET_TIME_UNIT_FOREVER_REL,
344 &transmit_message, cl);
345 }
346 else
347 {
348 GNUNET_assert (0 == cl->num_pending);
349 }
350 return ret;
351}
352
353
354/**
355 * Send a message to a particular client.
356 *
357 * @param nc context to modify
358 * @param client client to transmit to
359 * @param msg message to send
360 * @param can_drop can this message be dropped due to queue length limitations
361 */
362static void
363do_unicast (struct GNUNET_SERVER_NotificationContext *nc,
364 struct ClientList *client,
365 const struct GNUNET_MessageHeader *msg,
366 int can_drop)
367{
368 struct PendingMessageList *pml;
369 uint16_t size;
370
371 if ( (client->num_pending > nc->queue_length) &&
372 (GNUNET_YES == can_drop) )
373 {
374 LOG (GNUNET_ERROR_TYPE_INFO,
375 "Dropping message of type %u and size %u due to full queue (%u entries)\n",
376 ntohs (msg->type), ntohs (msg->size), (unsigned int) nc->queue_length);
377 return; /* drop! */
378 }
379 if (client->num_pending > nc->queue_length)
380 {
381 /* FIXME: consider checking for other messages in the
382 * queue that are 'droppable' */
383 }
384 client->num_pending++;
385 size = ntohs (msg->size);
386 pml = GNUNET_malloc (sizeof (struct PendingMessageList) + size);
387 pml->msg = (const struct GNUNET_MessageHeader *) &pml[1];
388 pml->can_drop = can_drop;
389 LOG (GNUNET_ERROR_TYPE_DEBUG,
390 "Adding message of type %u and size %u to pending queue (which has %u entries)\n",
391 ntohs (msg->type),
392 ntohs (msg->size),
393 (unsigned int) nc->queue_length);
394 GNUNET_memcpy (&pml[1], msg, size);
395 /* append */
396 GNUNET_CONTAINER_DLL_insert_tail (client->pending_head,
397 client->pending_tail,
398 pml);
399 if (NULL == client->th)
400 client->th =
401 GNUNET_SERVER_notify_transmit_ready (client->client,
402 ntohs (client->pending_head->
403 msg->size),
404 GNUNET_TIME_UNIT_FOREVER_REL,
405 &transmit_message, client);
406}
407
408
409/**
410 * Send a message to a particular client; must have
411 * already been added to the notification context.
412 *
413 * @param nc context to modify
414 * @param client client to transmit to
415 * @param msg message to send
416 * @param can_drop can this message be dropped due to queue length limitations
417 */
418void
419GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc,
420 struct GNUNET_SERVER_Client *client,
421 const struct GNUNET_MessageHeader *msg,
422 int can_drop)
423{
424 struct ClientList *pos;
425
426 for (pos = nc->clients_head; NULL != pos; pos = pos->next)
427 if (pos->client == client)
428 break;
429 GNUNET_assert (NULL != pos);
430 do_unicast (nc, pos, msg, can_drop);
431}
432
433
434/**
435 * Send a message to all clients of this context.
436 *
437 * @param nc context to modify
438 * @param msg message to send
439 * @param can_drop can this message be dropped due to queue length limitations
440 */
441void
442GNUNET_SERVER_notification_context_broadcast (struct
443 GNUNET_SERVER_NotificationContext *nc,
444 const struct GNUNET_MessageHeader *msg,
445 int can_drop)
446{
447 struct ClientList *pos;
448
449 for (pos = nc->clients_head; NULL != pos; pos = pos->next)
450 do_unicast (nc, pos, msg, can_drop);
451}
452
453
454/**
455 * Return active number of subscribers in this context.
456 *
457 * @param nc context to query
458 * @return number of current subscribers
459 */
460unsigned int
461GNUNET_SERVER_notification_context_get_size (struct GNUNET_SERVER_NotificationContext *nc)
462{
463 unsigned int num;
464 struct ClientList *pos;
465
466 num = 0;
467 for (pos = nc->clients_head; NULL != pos; pos = pos->next)
468 num++;
469 return num;
470}
471
472/* end of server_nc.c */
diff --git a/src/util/server_tc.c b/src/util/server_tc.c
deleted file mode 100644
index 8ae380a85..000000000
--- a/src/util/server_tc.c
+++ /dev/null
@@ -1,242 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file util/server_tc.c
23 * @brief convenience functions for transmission of
24 * complex responses as a server
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31
32#define LOG(kind,...) GNUNET_log_from (kind, "util-server-tc", __VA_ARGS__)
33
34
35/**
36 * How much buffer space do we want to have at least
37 * before transmitting another increment?
38 */
39#define MIN_BLOCK_SIZE 128
40
41
42
43struct GNUNET_SERVER_TransmitContext
44{
45 /**
46 * Which client are we transmitting to?
47 */
48 struct GNUNET_SERVER_Client *client;
49
50 /**
51 * Transmission buffer. (current offset for writing).
52 */
53 char *buf;
54
55 /**
56 * Number of bytes in buf.
57 */
58 size_t total;
59
60 /**
61 * Offset for writing in buf.
62 */
63 size_t off;
64
65 /**
66 * Timeout for this request.
67 */
68 struct GNUNET_TIME_Absolute timeout;
69};
70
71
72/**
73 * Helper function for incremental transmission of the response.
74 */
75static size_t
76transmit_response (void *cls, size_t size, void *buf)
77{
78 struct GNUNET_SERVER_TransmitContext *tc = cls;
79 size_t msize;
80
81 if (NULL == buf)
82 {
83 GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR);
84 return 0;
85 }
86 if (tc->total - tc->off > size)
87 msize = size;
88 else
89 msize = tc->total - tc->off;
90 GNUNET_memcpy (buf, &tc->buf[tc->off], msize);
91 tc->off += msize;
92 if (tc->total == tc->off)
93 {
94 GNUNET_SERVER_receive_done (tc->client, GNUNET_OK);
95 GNUNET_SERVER_client_drop (tc->client);
96 GNUNET_free_non_null (tc->buf);
97 GNUNET_free (tc);
98 }
99 else
100 {
101 if (NULL ==
102 GNUNET_SERVER_notify_transmit_ready (tc->client,
103 GNUNET_MIN (MIN_BLOCK_SIZE,
104 tc->total - tc->off),
105 GNUNET_TIME_absolute_get_remaining
106 (tc->timeout), &transmit_response,
107 tc))
108 {
109 GNUNET_break (0);
110 GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR);
111 }
112 }
113 return msize;
114}
115
116
117/**
118 * Create a new transmission context for the
119 * given client.
120 *
121 * @param client client to create the context for.
122 * @return NULL on error
123 */
124struct GNUNET_SERVER_TransmitContext *
125GNUNET_SERVER_transmit_context_create (struct GNUNET_SERVER_Client *client)
126{
127 struct GNUNET_SERVER_TransmitContext *tc;
128
129 GNUNET_assert (NULL != client);
130 tc = GNUNET_new (struct GNUNET_SERVER_TransmitContext);
131 GNUNET_SERVER_client_keep (client);
132 tc->client = client;
133 return tc;
134}
135
136
137/**
138 * Append a message to the transmission context.
139 * All messages in the context will be sent by
140 * the transmit_context_run method.
141 *
142 * @param tc context to use
143 * @param data what to append to the result message
144 * @param length length of data
145 * @param type type of the message
146 */
147void
148GNUNET_SERVER_transmit_context_append_data (struct GNUNET_SERVER_TransmitContext
149 *tc, const void *data,
150 size_t length, uint16_t type)
151{
152 struct GNUNET_MessageHeader *msg;
153 size_t size;
154
155 GNUNET_assert (length < GNUNET_SERVER_MAX_MESSAGE_SIZE);
156 size = length + sizeof (struct GNUNET_MessageHeader);
157 GNUNET_assert (size > length);
158 tc->buf = GNUNET_realloc (tc->buf, tc->total + size);
159 msg = (struct GNUNET_MessageHeader *) &tc->buf[tc->total];
160 tc->total += size;
161 msg->size = htons (size);
162 msg->type = htons (type);
163 GNUNET_memcpy (&msg[1], data, length);
164}
165
166
167/**
168 * Append a message to the transmission context.
169 * All messages in the context will be sent by
170 * the transmit_context_run method.
171 *
172 * @param tc context to use
173 * @param msg message to append
174 */
175void
176GNUNET_SERVER_transmit_context_append_message (struct
177 GNUNET_SERVER_TransmitContext
178 *tc,
179 const struct GNUNET_MessageHeader
180 *msg)
181{
182 struct GNUNET_MessageHeader *m;
183 uint16_t size;
184
185 size = ntohs (msg->size);
186 tc->buf = GNUNET_realloc (tc->buf, tc->total + size);
187 m = (struct GNUNET_MessageHeader *) &tc->buf[tc->total];
188 tc->total += size;
189 GNUNET_memcpy (m, msg, size);
190}
191
192
193/**
194 * Execute a transmission context. If there is
195 * an error in the transmission, the #GNUNET_SERVER_receive_done()
196 * method will be called with an error code (#GNUNET_SYSERR),
197 * otherwise with #GNUNET_OK.
198 *
199 * @param tc transmission context to use
200 * @param timeout when to time out and abort the transmission
201 */
202void
203GNUNET_SERVER_transmit_context_run (struct GNUNET_SERVER_TransmitContext *tc,
204 struct GNUNET_TIME_Relative timeout)
205{
206 tc->timeout = GNUNET_TIME_relative_to_absolute (timeout);
207 if (NULL ==
208 GNUNET_SERVER_notify_transmit_ready (tc->client,
209 GNUNET_MIN (MIN_BLOCK_SIZE,
210 tc->total), timeout,
211 &transmit_response, tc))
212 {
213 GNUNET_break (0);
214 GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR);
215 }
216}
217
218
219/**
220 * Destroy a transmission context. This function must not be called
221 * after 'GNUNET_SERVER_transmit_context_run'.
222 *
223 * @param tc transmission context to destroy
224 * @param success code to give to 'GNUNET_SERVER_receive_done' for
225 * the client: GNUNET_OK to keep the connection open and
226 * continue to receive
227 * GNUNET_NO to close the connection (normal behavior)
228 * GNUNET_SYSERR to close the connection (signal
229 * serious error)
230 */
231void
232GNUNET_SERVER_transmit_context_destroy (struct GNUNET_SERVER_TransmitContext
233 *tc, int success)
234{
235 GNUNET_SERVER_receive_done (tc->client, success);
236 GNUNET_SERVER_client_drop (tc->client);
237 GNUNET_free_non_null (tc->buf);
238 GNUNET_free (tc);
239}
240
241
242/* end of server_tc.c */
diff --git a/src/util/service.c b/src/util/service.c
index b4d03c17c..800d09a42 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1596,7 +1596,7 @@ teardown_service (struct GNUNET_SERVICE_Handle *sh)
1596 * dropped. Additionally, clients can be dropped at any time using 1596 * dropped. Additionally, clients can be dropped at any time using
1597 * #GNUNET_SERVICE_client_drop(). 1597 * #GNUNET_SERVICE_client_drop().
1598 * 1598 *
1599 * The service must be stopped using #GNUNET_SERVICE_stoP(). 1599 * The service must be stopped using #GNUNET_SERVICE_stop().
1600 * 1600 *
1601 * @param service_name name of the service to run 1601 * @param service_name name of the service to run
1602 * @param cfg configuration to use 1602 * @param cfg configuration to use
@@ -1609,7 +1609,7 @@ teardown_service (struct GNUNET_SERVICE_Handle *sh)
1609 * @return NULL on error 1609 * @return NULL on error
1610 */ 1610 */
1611struct GNUNET_SERVICE_Handle * 1611struct GNUNET_SERVICE_Handle *
1612GNUNET_SERVICE_starT (const char *service_name, 1612GNUNET_SERVICE_start (const char *service_name,
1613 const struct GNUNET_CONFIGURATION_Handle *cfg, 1613 const struct GNUNET_CONFIGURATION_Handle *cfg,
1614 GNUNET_SERVICE_ConnectHandler connect_cb, 1614 GNUNET_SERVICE_ConnectHandler connect_cb,
1615 GNUNET_SERVICE_DisconnectHandler disconnect_cb, 1615 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
@@ -1637,12 +1637,12 @@ GNUNET_SERVICE_starT (const char *service_name,
1637 1637
1638 1638
1639/** 1639/**
1640 * Stops a service that was started with #GNUNET_SERVICE_starT(). 1640 * Stops a service that was started with #GNUNET_SERVICE_start().
1641 * 1641 *
1642 * @param srv service to stop 1642 * @param srv service to stop
1643 */ 1643 */
1644void 1644void
1645GNUNET_SERVICE_stoP (struct GNUNET_SERVICE_Handle *srv) 1645GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv)
1646{ 1646{
1647 struct GNUNET_SERVICE_Client *client; 1647 struct GNUNET_SERVICE_Client *client;
1648 1648
@@ -1697,7 +1697,7 @@ GNUNET_SERVICE_stoP (struct GNUNET_SERVICE_Handle *srv)
1697 * @return 0 on success, non-zero on error 1697 * @return 0 on success, non-zero on error
1698 */ 1698 */
1699int 1699int
1700GNUNET_SERVICE_ruN_ (int argc, 1700GNUNET_SERVICE_run_ (int argc,
1701 char *const *argv, 1701 char *const *argv,
1702 const char *service_name, 1702 const char *service_name,
1703 enum GNUNET_SERVICE_Options options, 1703 enum GNUNET_SERVICE_Options options,
diff --git a/src/util/test_client.c b/src/util/test_client.c
index f60e5b7f7..527b400b0 100644
--- a/src/util/test_client.c
+++ b/src/util/test_client.c
@@ -179,7 +179,7 @@ main (int argc,
179 test_argv[2] = "test_client_unix.conf"; 179 test_argv[2] = "test_client_unix.conf";
180 global_ret = 1; 180 global_ret = 1;
181 if (0 != 181 if (0 !=
182 GNUNET_SERVICE_ruN_ (3, 182 GNUNET_SERVICE_run_ (3,
183 test_argv, 183 test_argv,
184 "test_client", 184 "test_client",
185 GNUNET_SERVICE_OPTION_NONE, 185 GNUNET_SERVICE_OPTION_NONE,
diff --git a/src/util/test_service.c b/src/util/test_service.c
index d2136b42f..1567c97ce 100644
--- a/src/util/test_service.c
+++ b/src/util/test_service.c
@@ -148,7 +148,7 @@ check (const char *sname)
148 sname); 148 sname);
149 global_ret = 1; 149 global_ret = 1;
150 GNUNET_assert (0 == 150 GNUNET_assert (0 ==
151 GNUNET_SERVICE_ruN_ (3, 151 GNUNET_SERVICE_run_ (3,
152 argv, 152 argv,
153 sname, 153 sname,
154 GNUNET_SERVICE_OPTION_NONE, 154 GNUNET_SERVICE_OPTION_NONE,