aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-06-21 21:42:07 +0000
committerChristian Grothoff <christian@grothoff.org>2010-06-21 21:42:07 +0000
commitc7f9e2399e5d703f0137ebb0038173c56894b8e2 (patch)
tree805e29ae09749d4e95920ccda080413a4cea265f
parent46cfd0e998c3946f75b7dd7376fc7587a6f4b562 (diff)
downloadgnunet-c7f9e2399e5d703f0137ebb0038173c56894b8e2.tar.gz
gnunet-c7f9e2399e5d703f0137ebb0038173c56894b8e2.zip
yay spagetti
-rw-r--r--src/include/gnunet_server_lib.h15
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/server_mst.c212
3 files changed, 226 insertions, 2 deletions
diff --git a/src/include/gnunet_server_lib.h b/src/include/gnunet_server_lib.h
index ababbeea9..7af133b89 100644
--- a/src/include/gnunet_server_lib.h
+++ b/src/include/gnunet_server_lib.h
@@ -637,19 +637,30 @@ typedef void (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls,
637 * GNUNET_SERVER_MAX_MESSAGE_SIZE) 637 * GNUNET_SERVER_MAX_MESSAGE_SIZE)
638 * @param client_identity ID of client for which this is a buffer, 638 * @param client_identity ID of client for which this is a buffer,
639 * can be NULL (will be passed back to 'cb') 639 * can be NULL (will be passed back to 'cb')
640 * @param cb function to call on completed messages
641 * @param cb_cls closure for cb
640 * @return handle to tokenizer 642 * @return handle to tokenizer
641 */ 643 */
642struct GNUNET_SERVER_MessageStreamTokenizer * 644struct GNUNET_SERVER_MessageStreamTokenizer *
643GNUNET_SERVER_mst_create (size_t maxbuf, 645GNUNET_SERVER_mst_create (size_t maxbuf,
644 void *client_identity, 646 void *client_identity,
645 GNUNET_SERVER_MessageTokenizerCallback cb, 647 GNUNET_SERVER_MessageTokenizerCallback cb,
646 void *cls); 648 void *cb_cls);
647 649
648 650
649/** 651/**
652 * Add incoming data to the receive buffer and call the
653 * callback for all complete messages.
650 * 654 *
655 * @param mst tokenizer to use
656 * @param buf input data to add
657 * @param size number of bytes in buf
658 * @param purge should any excess bytes in the buffer be discarded
659 * (i.e. for packet-based services like UDP)
660 * @return GNUNET_NO if the data stream is corrupt
661 * GNUNET_SYSERR if the data stream is corrupt beyond repair
651 */ 662 */
652void 663int
653GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst, 664GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
654 const char *buf, 665 const char *buf,
655 size_t size, 666 size_t size,
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 2d8fa90aa..9aa96d13a 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -60,6 +60,7 @@ libgnunetutil_la_SOURCES = \
60 resolver_api.c resolver.h \ 60 resolver_api.c resolver.h \
61 scheduler.c \ 61 scheduler.c \
62 server.c \ 62 server.c \
63 server_mst.c \
63 server_nc.c \ 64 server_nc.c \
64 server_tc.c \ 65 server_tc.c \
65 service.c \ 66 service.c \
diff --git a/src/util/server_mst.c b/src/util/server_mst.c
new file mode 100644
index 000000000..53cae7035
--- /dev/null
+++ b/src/util/server_mst.c
@@ -0,0 +1,212 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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 2, 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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, 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_common.h"
29#include "gnunet_connection_lib.h"
30#include "gnunet_scheduler_lib.h"
31#include "gnunet_server_lib.h"
32#include "gnunet_time_lib.h"
33
34
35/**
36 * Handle to a message stream tokenizer.
37 */
38struct GNUNET_SERVER_MessageStreamTokenizer
39{
40
41 size_t maxbuf;
42
43 size_t off;
44
45 void *client_identity;
46
47 GNUNET_SERVER_MessageTokenizerCallback cb;
48
49 void *cb_cls;
50
51 /**
52 * Beginning of the buffer.
53 */
54 struct GNUNET_MessageHeader hdr;
55
56};
57
58
59
60/**
61 * Create a message stream tokenizer.
62 *
63 * @param maxbuf maximum message size to support (typically
64 * GNUNET_SERVER_MAX_MESSAGE_SIZE)
65 * @param client_identity ID of client for which this is a buffer,
66 * can be NULL (will be passed back to 'cb')
67 * @return handle to tokenizer
68 */
69struct GNUNET_SERVER_MessageStreamTokenizer *
70GNUNET_SERVER_mst_create (size_t maxbuf,
71 void *client_identity,
72 GNUNET_SERVER_MessageTokenizerCallback cb,
73 void *cb_cls)
74{
75 struct GNUNET_SERVER_MessageStreamTokenizer *ret;
76
77 ret = GNUNET_malloc (maxbuf + sizeof (struct GNUNET_SERVER_MessageStreamTokenizer));
78 ret->maxbuf = maxbuf;
79 ret->client_identity = client_identity;
80 ret->cb = cb;
81 ret->cb_cls = cb_cls;
82 return ret;
83}
84
85
86/**
87 * Add incoming data to the receive buffer and call the
88 * callback for all complete messages.
89 *
90 * @param mst tokenizer to use
91 * @param buf input data to add
92 * @param size number of bytes in buf
93 * @param purge should any excess bytes in the buffer be discarded
94 * (i.e. for packet-based services like UDP)
95 * @return GNUNET_NO if the data stream is corrupt
96 * GNUNET_SYSERR if the data stream is corrupt beyond repair
97 */
98int
99GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
100 const char *buf,
101 size_t size,
102 int purge)
103{
104 const struct GNUNET_MessageHeader *hdr;
105 size_t delta;
106 size_t want;
107 char *ibuf;
108 int need_align;
109 unsigned long offset;
110
111 ibuf = (char*) &mst->hdr;
112 if (mst->off > 0)
113 {
114 do_align:
115 if (mst->off < sizeof (struct GNUNET_MessageHeader))
116 {
117 delta = GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) - mst->off,
118 size);
119 memcpy (&ibuf[mst->off],
120 buf,
121 delta);
122 mst->off += delta;
123 buf += delta;
124 size -= delta;
125 }
126 if (mst->off < sizeof (struct GNUNET_MessageHeader))
127 {
128 if (purge)
129 mst->off = 0;
130 return GNUNET_OK;
131 }
132 want = ntohs (mst->hdr.size);
133 if (want < sizeof (struct GNUNET_MessageHeader))
134 {
135 GNUNET_break_op (0);
136 if (purge)
137 return GNUNET_NO;
138 return GNUNET_SYSERR;
139 }
140 if (want < mst->off)
141 {
142 delta = GNUNET_MIN (want - mst->off,
143 size);
144 memcpy (&ibuf[mst->off],
145 buf,
146 delta);
147 mst->off += delta;
148 buf += delta;
149 size -= delta;
150 }
151 if (want < mst->off)
152 {
153 if (purge)
154 mst->off = 0;
155 return GNUNET_OK;
156 }
157 mst->cb (mst->cb_cls, mst->client_identity, &mst->hdr);
158 mst->off = 0;
159 }
160 while (size > 0)
161 {
162 if (size < sizeof (struct GNUNET_MessageHeader))
163 break;
164 offset = (unsigned long) buf;
165#if HAVE_UNALIGNED_64_ACCESS
166 need_align = (0 != offset % 4) ? GNUNET_YES : GNUNET_NO;
167#else
168 need_align = (0 != offset % 8) ? GNUNET_YES : GNUNET_NO;
169#endif
170 if (GNUNET_NO == need_align)
171 {
172 /* can try to do zero-copy */
173 hdr = (const struct GNUNET_MessageHeader *) buf;
174 want = ntohs (hdr->size);
175 if (size < want)
176 break; /* or not, buffer incomplete... */
177 mst->cb (mst->cb_cls, mst->client_identity, hdr);
178 buf += want;
179 size -= want;
180 }
181 else
182 {
183 /* yes, we go a bit more spagetti than usual here */
184 goto do_align;
185 }
186 }
187 if ( (size > 0) && (! purge) )
188 {
189 memcpy (&mst->hdr, buf, size);
190 mst->off = size;
191 size = 0;
192 }
193 if (purge)
194 mst->off = 0;
195 return GNUNET_OK;
196}
197
198
199/**
200 * Destroys a tokenizer.
201 *
202 * @param mst tokenizer to destroy
203 */
204void
205GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst)
206{
207 GNUNET_free (mst);
208}
209
210
211
212/* end of server_mst.c */