diff options
Diffstat (limited to 'src/arm/gnunet-service-manager.c')
-rw-r--r-- | src/arm/gnunet-service-manager.c | 699 |
1 files changed, 311 insertions, 388 deletions
diff --git a/src/arm/gnunet-service-manager.c b/src/arm/gnunet-service-manager.c index 01ede9f33..c80c12aa5 100644 --- a/src/arm/gnunet-service-manager.c +++ b/src/arm/gnunet-service-manager.c | |||
@@ -35,111 +35,85 @@ | |||
35 | 35 | ||
36 | 36 | ||
37 | #define DEBUG_SERVICE_MANAGER GNUNET_NO | 37 | #define DEBUG_SERVICE_MANAGER GNUNET_NO |
38 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
39 | #define BUFFER_SIZE (63 * 1024) | ||
40 | #define REASON_CLIENT 1 | ||
41 | #define REASON_SERVICE 2 | ||
42 | |||
43 | static char **defaultServicesList; | ||
44 | static int numDefaultServices = 0; | ||
45 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
46 | static struct GNUNET_SCHEDULER_Handle *scheduler; | ||
47 | 38 | ||
48 | struct StartedService | 39 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) |
49 | { | ||
50 | const char *serviceName; | ||
51 | struct StartedService *next; | ||
52 | }; | ||
53 | 40 | ||
54 | static struct StartedService *startedServices = NULL; | 41 | #define BUFFER_SIZE (63 * 1024) |
55 | 42 | ||
43 | #define REASON_CLIENT 1 | ||
56 | 44 | ||
57 | /* Functions prototypes */ | 45 | #define REASON_SERVICE 2 |
58 | static void | ||
59 | receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
60 | static void | ||
61 | receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
62 | 46 | ||
63 | 47 | ||
64 | struct ServiceListeningInfo | 48 | struct ServiceListeningInfo |
65 | { | 49 | { |
66 | struct ServiceListeningInfo *next; | 50 | struct ServiceListeningInfo *next; |
51 | |||
67 | struct ServiceListeningInfo *prev; | 52 | struct ServiceListeningInfo *prev; |
68 | const char *serviceName; | 53 | |
54 | char *serviceName; | ||
55 | |||
69 | struct sockaddr *service_addr; | 56 | struct sockaddr *service_addr; |
57 | |||
70 | socklen_t service_addr_len; | 58 | socklen_t service_addr_len; |
71 | struct sockaddr client_addr; | 59 | |
72 | socklen_t client_addr_len; | ||
73 | struct GNUNET_NETWORK_Handle *listeningSocket; | 60 | struct GNUNET_NETWORK_Handle *listeningSocket; |
61 | |||
74 | GNUNET_SCHEDULER_TaskIdentifier acceptTask; | 62 | GNUNET_SCHEDULER_TaskIdentifier acceptTask; |
75 | }; | 63 | }; |
76 | 64 | ||
77 | static struct ServiceListeningInfo *serviceListeningInfoList_head; | ||
78 | static struct ServiceListeningInfo *serviceListeningInfoList_tail; | ||
79 | |||
80 | /** | 65 | /** |
81 | * Information of the connection: client-arm-service | 66 | * Information of the connection: client-arm-service |
82 | */ | 67 | */ |
83 | struct ServiceInfo | 68 | struct ForwardedConnection |
84 | { | 69 | { |
85 | const char *serviceName; | ||
86 | struct GNUNET_NETWORK_Handle *armClientSocket; | 70 | struct GNUNET_NETWORK_Handle *armClientSocket; |
71 | |||
87 | struct GNUNET_NETWORK_Handle *armServiceSocket; | 72 | struct GNUNET_NETWORK_Handle *armServiceSocket; |
88 | struct sockaddr *service_addr; | 73 | |
89 | socklen_t service_addr_len; | 74 | struct ServiceListeningInfo *listen_info; |
75 | |||
76 | char serviceBuffer[BUFFER_SIZE]; | ||
77 | |||
90 | char clientBuffer[BUFFER_SIZE]; | 78 | char clientBuffer[BUFFER_SIZE]; |
91 | ssize_t clientBufferDataLength; | 79 | |
80 | char client_addr[32]; | ||
81 | |||
92 | char *clientBufferPos; | 82 | char *clientBufferPos; |
93 | char serviceBuffer[BUFFER_SIZE]; | 83 | |
94 | ssize_t serviceBufferDataLength; | ||
95 | char *serviceBufferPos; | 84 | char *serviceBufferPos; |
85 | |||
96 | GNUNET_SCHEDULER_TaskIdentifier clientReceivingTask; | 86 | GNUNET_SCHEDULER_TaskIdentifier clientReceivingTask; |
87 | |||
97 | GNUNET_SCHEDULER_TaskIdentifier serviceReceivingTask; | 88 | GNUNET_SCHEDULER_TaskIdentifier serviceReceivingTask; |
98 | GNUNET_SCHEDULER_TaskIdentifier acceptTask; | 89 | |
90 | ssize_t clientBufferDataLength; | ||
91 | |||
92 | ssize_t serviceBufferDataLength; | ||
93 | |||
94 | socklen_t client_addr_len; | ||
95 | |||
99 | }; | 96 | }; |
100 | 97 | ||
101 | 98 | ||
102 | static struct ServiceInfo * | 99 | static char **defaultServicesList; |
103 | newServiceInfo (const char *serviceName, struct sockaddr *service_addr, | ||
104 | socklen_t service_addr_len) | ||
105 | { | ||
106 | struct ServiceInfo *serviceInfo = | ||
107 | GNUNET_malloc (sizeof (struct ServiceInfo)); | ||
108 | serviceInfo->serviceName = serviceName; | ||
109 | serviceInfo->service_addr = service_addr; | ||
110 | serviceInfo->service_addr_len = service_addr_len; | ||
111 | serviceInfo->serviceBufferPos = serviceInfo->serviceBuffer; | ||
112 | serviceInfo->clientBufferPos = serviceInfo->clientBuffer; | ||
113 | return serviceInfo; | ||
114 | } | ||
115 | 100 | ||
101 | static unsigned int numDefaultServices; | ||
116 | 102 | ||
117 | static struct ServiceListeningInfo * | 103 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
118 | newServiceListeningInfo (const char *serviceName, | ||
119 | struct sockaddr *sa, socklen_t service_addr_len, | ||
120 | struct GNUNET_NETWORK_Handle *listeningSocket) | ||
121 | { | ||
122 | struct ServiceListeningInfo *serviceListeningInfo = | ||
123 | GNUNET_malloc (sizeof (struct ServiceListeningInfo)); | ||
124 | 104 | ||
125 | serviceListeningInfo->client_addr_len = | 105 | static struct GNUNET_SCHEDULER_Handle *scheduler; |
126 | sizeof (serviceListeningInfo->client_addr); | 106 | |
127 | serviceListeningInfo->serviceName = serviceName; | 107 | static struct ServiceListeningInfo *serviceListeningInfoList_head; |
128 | serviceListeningInfo->service_addr = sa; | 108 | |
129 | serviceListeningInfo->service_addr_len = service_addr_len; | 109 | static struct ServiceListeningInfo *serviceListeningInfoList_tail; |
130 | serviceListeningInfo->listeningSocket = listeningSocket; | ||
131 | GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head, | ||
132 | serviceListeningInfoList_tail, | ||
133 | serviceListeningInfo); | ||
134 | return serviceListeningInfo; | ||
135 | } | ||
136 | 110 | ||
137 | 111 | ||
138 | #if DEBUG_SERVICE_MANAGER | 112 | #if DEBUG_SERVICE_MANAGER |
139 | static void | 113 | static void |
140 | printDefaultServicesList () | 114 | printDefaultServicesList () |
141 | { | 115 | { |
142 | int i; | 116 | unsigned int i; |
143 | for (i = 0; i < numDefaultServices; i++) | 117 | for (i = 0; i < numDefaultServices; i++) |
144 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Service: %s\n", | 118 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Service: %s\n", |
145 | defaultServicesList[i]); | 119 | defaultServicesList[i]); |
@@ -153,30 +127,34 @@ printDefaultServicesList () | |||
153 | * @param services space separated string of default services | 127 | * @param services space separated string of default services |
154 | */ | 128 | */ |
155 | static void | 129 | static void |
156 | addDefaultServicesToList (char *services) | 130 | addDefaultServicesToList (const char *services) |
157 | { | 131 | { |
158 | int i = 0; | 132 | unsigned int i = 0; |
159 | char *token; | 133 | char *token; |
134 | char *s; | ||
160 | 135 | ||
161 | /* How many services are there */ | 136 | if (strlen (services) == 0) |
162 | while (services[i] != '\0') | 137 | return; |
138 | s = GNUNET_strdup (services); | ||
139 | token = strtok (s, " "); | ||
140 | while (NULL != token) | ||
163 | { | 141 | { |
164 | if (services[i] == ' ') | 142 | numDefaultServices++; |
165 | { | 143 | token = strtok (NULL, " "); |
166 | numDefaultServices++; | ||
167 | } | ||
168 | i++; | ||
169 | } | 144 | } |
170 | numDefaultServices++; | 145 | GNUNET_free (s); |
171 | defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *)); | ||
172 | token = strtok ((char *) services, " "); | ||
173 | 146 | ||
147 | defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *)); | ||
174 | i = 0; | 148 | i = 0; |
149 | s = GNUNET_strdup (services); | ||
150 | token = strtok (s, " "); | ||
175 | while (NULL != token) | 151 | while (NULL != token) |
176 | { | 152 | { |
177 | defaultServicesList[i++] = token; | 153 | defaultServicesList[i++] = GNUNET_strdup (token); |
178 | token = strtok (NULL, " "); | 154 | token = strtok (NULL, " "); |
179 | } | 155 | } |
156 | GNUNET_free (s); | ||
157 | GNUNET_assert (i == numDefaultServices); | ||
180 | } | 158 | } |
181 | 159 | ||
182 | /** | 160 | /** |
@@ -187,245 +165,217 @@ addDefaultServicesToList (char *services) | |||
187 | static int | 165 | static int |
188 | isInDefaultList (const char *serviceName) | 166 | isInDefaultList (const char *serviceName) |
189 | { | 167 | { |
190 | int i; | 168 | unsigned int i; |
191 | for (i = 0; i < numDefaultServices; i++) | 169 | for (i = 0; i < numDefaultServices; i++) |
192 | { | 170 | if (strcmp (serviceName, defaultServicesList[i]) == 0) |
193 | if (strcmp (serviceName, defaultServicesList[i]) == 0) | 171 | return GNUNET_YES; |
194 | return GNUNET_YES; | ||
195 | } | ||
196 | return GNUNET_NO; | ||
197 | } | ||
198 | |||
199 | |||
200 | static int | ||
201 | isServiceAlreadyStarted (const char *serviceName) | ||
202 | { | ||
203 | struct StartedService *service; | ||
204 | service = startedServices; | ||
205 | while (NULL != service) | ||
206 | { | ||
207 | if (strcmp (service->serviceName, serviceName) == 0) | ||
208 | return GNUNET_OK; | ||
209 | service = service->next; | ||
210 | } | ||
211 | return GNUNET_NO; | 172 | return GNUNET_NO; |
212 | } | 173 | } |
213 | 174 | ||
214 | 175 | ||
215 | static void | 176 | static void |
216 | setStartedService (const char *serviceName) | 177 | closeClientAndServiceSockets (struct ForwardedConnection *fc, int reason) |
217 | { | ||
218 | if (startedServices == NULL) | ||
219 | { | ||
220 | startedServices = GNUNET_malloc (sizeof (struct StartedService)); | ||
221 | startedServices->serviceName = GNUNET_strdup (serviceName); | ||
222 | startedServices->next = NULL; | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | struct StartedService *service = | ||
227 | GNUNET_malloc (sizeof (struct StartedService)); | ||
228 | service->serviceName = GNUNET_strdup (serviceName); | ||
229 | service->next = startedServices; | ||
230 | startedServices = service; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | |||
235 | static void | ||
236 | closeClientAndServiceSockets (struct ServiceInfo *serviceInfo, int reason) | ||
237 | { | 178 | { |
238 | if (NULL != serviceInfo->armClientSocket) | 179 | if (NULL != fc->armClientSocket) |
239 | { | 180 | { |
240 | if (0 != (REASON_SERVICE & reason)) | 181 | if (0 != (REASON_SERVICE & reason)) |
241 | GNUNET_SCHEDULER_cancel (scheduler, serviceInfo->clientReceivingTask); | 182 | GNUNET_SCHEDULER_cancel (scheduler, fc->clientReceivingTask); |
242 | if (GNUNET_SYSERR == | 183 | if (GNUNET_SYSERR == |
243 | GNUNET_NETWORK_socket_close (serviceInfo->armClientSocket)) | 184 | GNUNET_NETWORK_socket_close (fc->armClientSocket)) |
244 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close"); | 185 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close"); |
245 | serviceInfo->armClientSocket = NULL; | 186 | fc->armClientSocket = NULL; |
246 | } | 187 | } |
247 | if (NULL != serviceInfo->armServiceSocket) | 188 | if (NULL != fc->armServiceSocket) |
248 | { | 189 | { |
249 | if (0 != (REASON_CLIENT & reason)) | 190 | if (0 != (REASON_CLIENT & reason)) |
250 | GNUNET_SCHEDULER_cancel (scheduler, | 191 | GNUNET_SCHEDULER_cancel (scheduler, |
251 | serviceInfo->serviceReceivingTask); | 192 | fc->serviceReceivingTask); |
252 | 193 | ||
253 | if (GNUNET_SYSERR == | 194 | if (GNUNET_SYSERR == |
254 | GNUNET_NETWORK_socket_close (serviceInfo->armServiceSocket)) | 195 | GNUNET_NETWORK_socket_close (fc->armServiceSocket)) |
255 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close"); | 196 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close"); |
256 | serviceInfo->armServiceSocket = NULL; | 197 | fc->armServiceSocket = NULL; |
257 | } | 198 | } |
258 | 199 | GNUNET_free (fc->listen_info->serviceName); | |
259 | GNUNET_free (serviceInfo); | 200 | GNUNET_free (fc->listen_info->service_addr); |
201 | GNUNET_free (fc->listen_info); | ||
202 | GNUNET_free (fc); | ||
260 | } | 203 | } |
261 | 204 | ||
262 | 205 | ||
206 | static void | ||
207 | receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
208 | |||
209 | static void | ||
210 | receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
211 | |||
212 | |||
263 | /** | 213 | /** |
264 | * Forward messages sent from service to client | 214 | * Forward messages sent from service to client |
265 | * | 215 | * |
266 | * @param cls callback data, for the communication between client and service | 216 | * @param cls callback data, struct ForwardedConnection for the communication between client and service |
267 | * @param tc context | 217 | * @param tc context |
268 | */ | 218 | */ |
269 | static void | 219 | static void |
270 | forwardToClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 220 | forwardToClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
271 | { | 221 | { |
272 | struct ServiceInfo *serviceInfo = cls; | 222 | struct ForwardedConnection *fc = cls; |
273 | ssize_t numberOfBytesSent; | 223 | ssize_t numberOfBytesSent; |
274 | 224 | ||
275 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 225 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
276 | { | 226 | { |
277 | /* Ignore shutdown signal, reschedule yourself */ | 227 | /* Ignore shutdown signal, reschedule yourself */ |
278 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 228 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
279 | serviceInfo->armClientSocket, | 229 | fc->armClientSocket, |
280 | &forwardToClient, serviceInfo); | 230 | &forwardToClient, fc); |
281 | return; | 231 | return; |
282 | } | 232 | } |
283 | 233 | ||
284 | /* Forwarding service response to client */ | 234 | /* Forwarding service response to client */ |
285 | numberOfBytesSent = | 235 | numberOfBytesSent = |
286 | GNUNET_NETWORK_socket_send (serviceInfo->armClientSocket, | 236 | GNUNET_NETWORK_socket_send (fc->armClientSocket, |
287 | serviceInfo->serviceBufferPos, | 237 | fc->serviceBufferPos, |
288 | serviceInfo->serviceBufferDataLength); | 238 | fc->serviceBufferDataLength); |
289 | if ((numberOfBytesSent == GNUNET_SYSERR) || (numberOfBytesSent == 0)) | 239 | if ((numberOfBytesSent == GNUNET_SYSERR) || (numberOfBytesSent == 0)) |
290 | { | 240 | { |
291 | /* Error occured or connection closed by client */ | 241 | /* Error occured or connection closed by client */ |
292 | closeClientAndServiceSockets (serviceInfo, | 242 | closeClientAndServiceSockets (fc, |
293 | (REASON_CLIENT & REASON_SERVICE)); | 243 | (REASON_CLIENT & REASON_SERVICE)); |
294 | return; | 244 | return; |
295 | } | 245 | } |
296 | else if (numberOfBytesSent < serviceInfo->serviceBufferDataLength) | 246 | else if (numberOfBytesSent < fc->serviceBufferDataLength) |
297 | { | 247 | { |
298 | /* Not all service data were sent to client */ | 248 | /* Not all service data were sent to client */ |
299 | serviceInfo->serviceBufferPos += numberOfBytesSent; | 249 | fc->serviceBufferPos += numberOfBytesSent; |
300 | serviceInfo->serviceBufferDataLength = | 250 | fc->serviceBufferDataLength -= numberOfBytesSent; |
301 | serviceInfo->serviceBufferDataLength - numberOfBytesSent; | ||
302 | 251 | ||
303 | /* Scheduling writing again for completing the remaining data to be sent */ | 252 | /* Scheduling writing again for completing the remaining data to be sent */ |
304 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 253 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
305 | serviceInfo->armClientSocket, | 254 | fc->armClientSocket, |
306 | &forwardToClient, serviceInfo); | 255 | &forwardToClient, fc); |
307 | } | 256 | } |
308 | else | 257 | else |
309 | { | 258 | { |
310 | /* Data completely sent */ | 259 | /* Data completely sent */ |
311 | serviceInfo->serviceBufferPos = serviceInfo->serviceBuffer; | 260 | fc->serviceBufferPos = fc->serviceBuffer; |
312 | } | 261 | } |
313 | 262 | ||
314 | /* Now we are ready to receive more data, rescheduling receiving from Service */ | 263 | /* Now we are ready to receive more data, rescheduling receiving from Service */ |
315 | serviceInfo->serviceReceivingTask = | 264 | fc->serviceReceivingTask = |
316 | GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 265 | GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
317 | serviceInfo->armServiceSocket, | 266 | fc->armServiceSocket, |
318 | &receiveFromService, serviceInfo); | 267 | &receiveFromService, fc); |
319 | } | 268 | } |
320 | 269 | ||
321 | 270 | ||
322 | /** | 271 | /** |
323 | * Receive service messages sent by the service and forward it to client | 272 | * Receive service messages sent by the service and forward it to client |
324 | * | 273 | * |
325 | * @param cls callback data, serviceInfo struct for the communication between client and service | 274 | * @param cls callback data, struct ForwardedConnection for the communication between client and service |
326 | * @param tc context | 275 | * @param tc context |
327 | */ | 276 | */ |
328 | static void | 277 | static void |
329 | receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 278 | receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
330 | { | 279 | { |
331 | 280 | struct ForwardedConnection *fc = cls; | |
332 | struct ServiceInfo *serviceInfo = cls; | ||
333 | 281 | ||
334 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 282 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
335 | { | 283 | { |
336 | /* Neglect shutdown signal, reschedule yourself */ | 284 | /* Neglect shutdown signal, reschedule yourself */ |
337 | serviceInfo->serviceReceivingTask = | 285 | fc->serviceReceivingTask = |
338 | GNUNET_SCHEDULER_add_read_net (scheduler, | 286 | GNUNET_SCHEDULER_add_read_net (scheduler, |
339 | GNUNET_TIME_UNIT_FOREVER_REL, | 287 | GNUNET_TIME_UNIT_FOREVER_REL, |
340 | serviceInfo->armServiceSocket, | 288 | fc->armServiceSocket, |
341 | &receiveFromService, serviceInfo); | 289 | &receiveFromService, fc); |
342 | return; | 290 | return; |
343 | } | 291 | } |
344 | 292 | ||
345 | serviceInfo->serviceBufferDataLength = | 293 | fc->serviceBufferDataLength = |
346 | GNUNET_NETWORK_socket_recv (serviceInfo->armServiceSocket, | 294 | GNUNET_NETWORK_socket_recv (fc->armServiceSocket, |
347 | serviceInfo->serviceBuffer, BUFFER_SIZE); | 295 | fc->serviceBuffer, BUFFER_SIZE); |
348 | 296 | ||
349 | if (serviceInfo->serviceBufferDataLength <= 0) | 297 | if (fc->serviceBufferDataLength <= 0) |
350 | { | 298 | { |
351 | /* The service has closed the connection or an error occured */ | 299 | /* The service has closed the connection or an error occured */ |
352 | if (serviceInfo->serviceBufferDataLength == 0) | 300 | if (fc->serviceBufferDataLength == 0) |
353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 301 | { |
354 | _("Service `%s' closed connection! \n"), | 302 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
355 | serviceInfo->serviceName); | 303 | _("Service `%s' closed connection! \n"), |
304 | fc->listen_info->serviceName); | ||
305 | } | ||
356 | else | 306 | else |
357 | { | 307 | { |
358 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 308 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
359 | _("Error receiving from service:%d\n"), errno); | 309 | _("Error receiving from service: %s\n"), |
310 | STRERROR (errno)); | ||
360 | } | 311 | } |
361 | closeClientAndServiceSockets (serviceInfo, REASON_SERVICE); | 312 | closeClientAndServiceSockets (fc, REASON_SERVICE); |
362 | return; | 313 | return; |
363 | } | 314 | } |
364 | 315 | ||
365 | /* Forwarding Service data to Client */ | 316 | /* Forwarding Service data to Client */ |
366 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 317 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
367 | serviceInfo->armClientSocket, | 318 | fc->armClientSocket, |
368 | &forwardToClient, serviceInfo); | 319 | &forwardToClient, fc); |
369 | } | 320 | } |
370 | 321 | ||
371 | 322 | ||
372 | /** | 323 | /** |
373 | * Forward client message to service | 324 | * Forward client message to service |
374 | * | 325 | * |
375 | * @param cls callback data, serviceInfo struct for the communication between client and service | 326 | * @param cls callback data, struct ForwardedConnection for the communication between client and service |
376 | * @param tc context | 327 | * @param tc context |
377 | */ | 328 | */ |
378 | static void | 329 | static void |
379 | forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 330 | forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
380 | { | 331 | { |
381 | struct ServiceInfo *serviceInfo = cls; | 332 | struct ForwardedConnection *fc = cls; |
382 | ssize_t numberOfBytesSent; | 333 | ssize_t numberOfBytesSent; |
383 | 334 | ||
384 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 335 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
385 | { | 336 | { |
386 | /* Neglect shutdown signal, reschedule yourself */ | 337 | /* Neglect shutdown signal, reschedule ourself */ |
387 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 338 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
388 | serviceInfo->armServiceSocket, | 339 | fc->armServiceSocket, |
389 | &forwardToService, serviceInfo); | 340 | &forwardToService, fc); |
390 | return; | 341 | return; |
391 | } | 342 | } |
392 | 343 | ||
393 | 344 | ||
394 | /* Forwarding client's message to service */ | 345 | /* Forwarding client's message to service */ |
395 | numberOfBytesSent = | 346 | numberOfBytesSent = |
396 | GNUNET_NETWORK_socket_send (serviceInfo->armServiceSocket, | 347 | GNUNET_NETWORK_socket_send (fc->armServiceSocket, |
397 | serviceInfo->clientBufferPos, | 348 | fc->clientBufferPos, |
398 | serviceInfo->clientBufferDataLength); | 349 | fc->clientBufferDataLength); |
399 | if ((numberOfBytesSent == GNUNET_SYSERR) || (numberOfBytesSent == 0)) | 350 | if ((numberOfBytesSent == GNUNET_SYSERR) || (numberOfBytesSent == 0)) |
400 | { | 351 | { |
401 | /* Error occured or connection closed by service */ | 352 | /* Error occured or connection closed by service */ |
402 | closeClientAndServiceSockets (serviceInfo, | 353 | closeClientAndServiceSockets (fc, |
403 | (REASON_CLIENT & REASON_SERVICE)); | 354 | (REASON_CLIENT & REASON_SERVICE)); |
404 | return; | 355 | return; |
405 | } | 356 | } |
406 | else if (numberOfBytesSent < serviceInfo->clientBufferDataLength) | 357 | if (numberOfBytesSent < fc->clientBufferDataLength) |
407 | { | 358 | { |
408 | /* Not all client data were sent to the service */ | 359 | /* Not all client data were sent to the service */ |
409 | serviceInfo->clientBufferPos += numberOfBytesSent; | 360 | fc->clientBufferPos += numberOfBytesSent; |
410 | serviceInfo->clientBufferDataLength = | 361 | fc->clientBufferDataLength -= numberOfBytesSent; |
411 | serviceInfo->clientBufferDataLength - numberOfBytesSent; | ||
412 | 362 | ||
413 | /* Scheduling writing again for completing the remaining data to be sent */ | 363 | /* Scheduling writing again for completing the remaining data to be sent */ |
414 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 364 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
415 | serviceInfo->armServiceSocket, | 365 | fc->armServiceSocket, |
416 | &forwardToService, serviceInfo); | 366 | &forwardToService, fc); |
417 | } | 367 | } |
418 | else | 368 | else |
419 | { | 369 | { |
420 | /* Data completely sent */ | 370 | /* Data completely sent */ |
421 | serviceInfo->clientBufferPos = serviceInfo->clientBuffer; | 371 | fc->clientBufferPos = fc->clientBuffer; |
422 | } | 372 | } |
423 | 373 | ||
424 | /* Now, we are ready to receive more data. Rescheduling the receiving from client */ | 374 | /* Now, we are ready to receive more data. Rescheduling the receiving from client */ |
425 | serviceInfo->clientReceivingTask = | 375 | fc->clientReceivingTask = |
426 | GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 376 | GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
427 | serviceInfo->armClientSocket, | 377 | fc->armClientSocket, |
428 | &receiveFromClient, serviceInfo); | 378 | &receiveFromClient, fc); |
429 | } | 379 | } |
430 | 380 | ||
431 | 381 | ||
@@ -434,48 +384,49 @@ forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
434 | * Message sent from client to service (faked by ARM, since it's the first connection), | 384 | * Message sent from client to service (faked by ARM, since it's the first connection), |
435 | * ARM will receive the message and forward it to the running service | 385 | * ARM will receive the message and forward it to the running service |
436 | * | 386 | * |
437 | * @param cls callback data, serviceInfo struct for the communication between client and service | 387 | * @param cls callback data, struct ForwardedConnection for the communication between client and service |
438 | * @param tc context | 388 | * @param tc context |
439 | */ | 389 | */ |
440 | static void | 390 | static void |
441 | receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 391 | receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
442 | { | 392 | { |
443 | struct ServiceInfo *serviceInfo = cls; | 393 | struct ForwardedConnection *fc = cls; |
444 | 394 | ||
445 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 395 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
446 | { | 396 | { |
447 | /* Neglect the shutdown signal, schedule yourself */ | 397 | /* Neglect the shutdown signal, schedule ourselves */ |
448 | serviceInfo->clientReceivingTask = | 398 | fc->clientReceivingTask = |
449 | GNUNET_SCHEDULER_add_read_net (scheduler, | 399 | GNUNET_SCHEDULER_add_read_net (scheduler, |
450 | GNUNET_TIME_UNIT_FOREVER_REL, | 400 | GNUNET_TIME_UNIT_FOREVER_REL, |
451 | serviceInfo->armClientSocket, | 401 | fc->armClientSocket, |
452 | &receiveFromClient, serviceInfo); | 402 | &receiveFromClient, fc); |
453 | return; | 403 | return; |
454 | } | 404 | } |
455 | 405 | ||
456 | /* Receive client's message */ | 406 | /* Receive client's message */ |
457 | serviceInfo->clientBufferDataLength = | 407 | fc->clientBufferDataLength = |
458 | GNUNET_NETWORK_socket_recv (serviceInfo->armClientSocket, | 408 | GNUNET_NETWORK_socket_recv (fc->armClientSocket, |
459 | serviceInfo->clientBuffer, BUFFER_SIZE); | 409 | fc->clientBuffer, BUFFER_SIZE); |
460 | 410 | ||
461 | if (serviceInfo->clientBufferDataLength <= 0) | 411 | if (fc->clientBufferDataLength <= 0) |
462 | { | 412 | { |
463 | /* The client has closed the connection or and error occured */ | 413 | /* The client has closed the connection or and error occured */ |
464 | if (serviceInfo->clientBufferDataLength == 0) | 414 | if (fc->clientBufferDataLength == 0) |
465 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 415 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
466 | _("Client closed connection with service:`%s'\n"), | 416 | _("Client closed connection with service:`%s'\n"), |
467 | serviceInfo->serviceName); | 417 | fc->listen_info->serviceName); |
468 | else | 418 | else |
469 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 419 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
470 | _("Error receiving from client!:%d \n"), errno); | 420 | _("Error receiving from client: %s \n"), |
471 | closeClientAndServiceSockets (serviceInfo, REASON_CLIENT); | 421 | STRERROR (errno)); |
422 | closeClientAndServiceSockets (fc, REASON_CLIENT); | ||
472 | return; | 423 | return; |
473 | } | 424 | } |
474 | 425 | ||
475 | /* Forwarding request to service */ | 426 | /* Forwarding request to service */ |
476 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 427 | GNUNET_SCHEDULER_add_write_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, |
477 | serviceInfo->armServiceSocket, | 428 | fc->armServiceSocket, |
478 | &forwardToService, serviceInfo); | 429 | &forwardToService, fc); |
479 | } | 430 | } |
480 | 431 | ||
481 | 432 | ||
@@ -483,21 +434,21 @@ receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
483 | * ARM connects to the just created service, | 434 | * ARM connects to the just created service, |
484 | * starts the processes for relaying messages between the client and the service | 435 | * starts the processes for relaying messages between the client and the service |
485 | * | 436 | * |
486 | * @param cls callback data, serviceInfo struct for the communication between client and service | 437 | * @param cls callback data, struct ForwardedConnection for the communication between client and service |
487 | * @param tc context | 438 | * @param tc context |
488 | */ | 439 | */ |
489 | static void | 440 | static void |
490 | connectToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 441 | connectToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
491 | { | 442 | { |
492 | struct ServiceInfo *serviceInfo = cls; | 443 | struct ForwardedConnection *fc = cls; |
493 | 444 | ||
494 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) | 445 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) |
495 | { | 446 | { |
496 | /* Service is not up. Unable to proceed */ | 447 | /* Service is not up. Unable to proceed */ |
497 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 448 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
498 | _("Unable to start service `%s': timeout\n"), | 449 | _("Unable to start service `%s': timeout\n"), |
499 | serviceInfo->serviceName); | 450 | fc->listen_info->serviceName); |
500 | closeClientAndServiceSockets (serviceInfo, | 451 | closeClientAndServiceSockets (fc, |
501 | (REASON_CLIENT & REASON_SERVICE)); | 452 | (REASON_CLIENT & REASON_SERVICE)); |
502 | return; | 453 | return; |
503 | } | 454 | } |
@@ -505,80 +456,72 @@ connectToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
505 | { | 456 | { |
506 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 457 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
507 | _("Unable to start service `%s': shutdown\n"), | 458 | _("Unable to start service `%s': shutdown\n"), |
508 | serviceInfo->serviceName); | 459 | fc->listen_info->serviceName); |
509 | closeClientAndServiceSockets (serviceInfo, | 460 | closeClientAndServiceSockets (fc, |
510 | (REASON_CLIENT & REASON_SERVICE)); | 461 | (REASON_CLIENT & REASON_SERVICE)); |
511 | return; | 462 | return; |
512 | } | 463 | } |
513 | GNUNET_break (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)); | 464 | GNUNET_break (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)); |
514 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' started\n"), | 465 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' started\n"), |
515 | serviceInfo->serviceName); | 466 | fc->listen_info->serviceName); |
516 | 467 | fc->armServiceSocket = | |
517 | /* Now service is up and running, connect to it */ | 468 | GNUNET_NETWORK_socket_create (fc->listen_info->service_addr->sa_family, |
518 | serviceInfo->armServiceSocket = | ||
519 | GNUNET_NETWORK_socket_create (serviceInfo->service_addr->sa_family, | ||
520 | SOCK_STREAM, 0); | 469 | SOCK_STREAM, 0); |
521 | if (NULL == serviceInfo->armServiceSocket) | 470 | if (NULL == fc->armServiceSocket) |
522 | { | 471 | { |
523 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 472 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
524 | _ | 473 | _ ("Unable to start service `%s': %s\n"), |
525 | ("Unable to start service `%s': failed to create socket\n"), | 474 | fc->listen_info->serviceName, |
526 | serviceInfo->serviceName); | 475 | STRERROR (errno)); |
527 | closeClientAndServiceSockets (serviceInfo, | 476 | closeClientAndServiceSockets (fc, |
528 | (REASON_CLIENT & REASON_SERVICE)); | 477 | (REASON_CLIENT & REASON_SERVICE)); |
529 | return; | 478 | return; |
530 | } | 479 | } |
531 | |||
532 | if ((GNUNET_SYSERR == | 480 | if ((GNUNET_SYSERR == |
533 | GNUNET_NETWORK_socket_connect (serviceInfo->armServiceSocket, | 481 | GNUNET_NETWORK_socket_connect (fc->armServiceSocket, |
534 | serviceInfo->service_addr, | 482 | fc->listen_info->service_addr, |
535 | serviceInfo->service_addr_len)) | 483 | fc->listen_info->service_addr_len)) |
536 | && (EINPROGRESS != errno)) | 484 | && (EINPROGRESS != errno)) |
537 | { | 485 | { |
538 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 486 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
539 | _("Unable to start service `%s': failed to connect\n"), | 487 | _("Unable to start service `%s': failed to connect\n"), |
540 | serviceInfo->serviceName); | 488 | fc->listen_info->serviceName); |
541 | closeClientAndServiceSockets (serviceInfo, | 489 | closeClientAndServiceSockets (fc, |
542 | (REASON_CLIENT & REASON_SERVICE)); | 490 | (REASON_CLIENT & REASON_SERVICE)); |
543 | return; | 491 | return; |
544 | } | 492 | } |
545 | /* Handling requests from client to service */ | 493 | fc->clientReceivingTask = |
546 | serviceInfo->clientReceivingTask = | 494 | GNUNET_SCHEDULER_add_read_net (scheduler, |
547 | GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 495 | GNUNET_TIME_UNIT_FOREVER_REL, |
548 | serviceInfo->armClientSocket, | 496 | fc->armClientSocket, |
549 | &receiveFromClient, serviceInfo); | 497 | &receiveFromClient, fc); |
550 | 498 | fc->serviceReceivingTask = | |
551 | /* Handling service responses to client */ | 499 | GNUNET_SCHEDULER_add_read_net (scheduler, |
552 | serviceInfo->serviceReceivingTask = | 500 | GNUNET_TIME_UNIT_FOREVER_REL, |
553 | GNUNET_SCHEDULER_add_read_net (scheduler, GNUNET_TIME_UNIT_FOREVER_REL, | 501 | fc->armServiceSocket, |
554 | serviceInfo->armServiceSocket, | 502 | &receiveFromService, fc); |
555 | &receiveFromService, serviceInfo); | ||
556 | } | 503 | } |
557 | 504 | ||
558 | 505 | ||
559 | static void | 506 | void stop_listening (const char *serviceName) |
560 | stopServiceListeningSockets (struct ServiceListeningInfo | ||
561 | *serviceListeningInfo) | ||
562 | { | 507 | { |
563 | struct ServiceListeningInfo *pos = serviceListeningInfoList_head; | 508 | struct ServiceListeningInfo *pos; |
564 | struct ServiceListeningInfo *tmp; | 509 | struct ServiceListeningInfo *next; |
565 | 510 | ||
566 | while (NULL != pos) | 511 | next = serviceListeningInfoList_head; |
512 | while (NULL != (pos = next)) | ||
567 | { | 513 | { |
568 | if ((strcmp (pos->serviceName, serviceListeningInfo->serviceName) == 0) | 514 | next = pos->next; |
569 | && (pos != serviceListeningInfo)) | 515 | if (strcmp (pos->serviceName, serviceName) != 0) |
570 | { | 516 | continue; |
571 | GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask); | 517 | GNUNET_SCHEDULER_cancel (scheduler, pos->acceptTask); |
572 | GNUNET_NETWORK_socket_close (pos->listeningSocket); | 518 | GNUNET_NETWORK_socket_close (pos->listeningSocket); |
573 | tmp = pos; | 519 | GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, |
574 | pos = pos->next; | 520 | serviceListeningInfoList_tail, |
575 | GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, | 521 | pos); |
576 | serviceListeningInfoList_tail, tmp); | 522 | GNUNET_free (pos->serviceName); |
577 | GNUNET_free (tmp->service_addr); | 523 | GNUNET_free (pos->service_addr); |
578 | GNUNET_free (tmp); | 524 | GNUNET_free (pos); |
579 | continue; | ||
580 | } | ||
581 | pos = pos->next; | ||
582 | } | 525 | } |
583 | } | 526 | } |
584 | 527 | ||
@@ -587,136 +530,124 @@ stopServiceListeningSockets (struct ServiceListeningInfo | |||
587 | * First connection has come to the listening socket associated with the service, | 530 | * First connection has come to the listening socket associated with the service, |
588 | * create the service in order to relay the incoming connection to it | 531 | * create the service in order to relay the incoming connection to it |
589 | * | 532 | * |
590 | * @param cls callback data, serviceInfo struct for the communication between client and service | 533 | * @param cls callback data, struct ServiceListeningInfo describing a listen socket |
591 | * @param tc context | 534 | * @param tc context |
592 | */ | 535 | */ |
593 | static void | 536 | static void |
594 | acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 537 | acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
595 | { | 538 | { |
596 | struct ServiceListeningInfo *serviceListeningInfo = cls; | 539 | struct ServiceListeningInfo *serviceListeningInfo = cls; |
597 | struct ServiceInfo *serviceInfo; | 540 | struct ForwardedConnection *fc; |
598 | 541 | ||
542 | serviceListeningInfo->acceptTask = GNUNET_SCHEDULER_NO_TASK; | ||
599 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 543 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
600 | return; | 544 | return; |
601 | 545 | fc = GNUNET_malloc (sizeof (struct ForwardedConnection)); | |
602 | if ((NULL == startedServices) | 546 | fc->listen_info = serviceListeningInfo; |
603 | || (GNUNET_NO == | 547 | fc->serviceBufferPos = fc->serviceBuffer; |
604 | isServiceAlreadyStarted (serviceListeningInfo->serviceName))) | 548 | fc->clientBufferPos = fc->clientBuffer; |
549 | fc->client_addr_len = sizeof (fc->client_addr); | ||
550 | fc->armClientSocket = GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket, | ||
551 | (struct sockaddr*) fc->client_addr, | ||
552 | &fc->client_addr_len); | ||
553 | if (NULL == fc->armClientSocket) | ||
605 | { | 554 | { |
606 | /* First request to receive at all, or first request to connect to that service */ | 555 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
607 | /* Accept client's connection */ | 556 | _("Unable to accept connection for service `%s': %s\n"), |
608 | serviceInfo = | 557 | serviceListeningInfo->serviceName, |
609 | newServiceInfo (serviceListeningInfo->serviceName, | 558 | STRERROR (errno)); |
610 | serviceListeningInfo->service_addr, | 559 | GNUNET_free (fc); |
611 | serviceListeningInfo->service_addr_len); | 560 | serviceListeningInfo->acceptTask = |
612 | serviceInfo->armClientSocket = | 561 | GNUNET_SCHEDULER_add_read_net (scheduler, |
613 | GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket, | 562 | GNUNET_TIME_UNIT_FOREVER_REL, |
614 | &(serviceListeningInfo->client_addr), | 563 | serviceListeningInfo->listeningSocket, |
615 | &(serviceListeningInfo-> | 564 | &acceptConnection, |
616 | client_addr_len)); | 565 | serviceListeningInfo); |
617 | if (NULL == serviceInfo->armClientSocket) | 566 | return; |
618 | { | ||
619 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
620 | _ | ||
621 | ("Unable to accept connection for service `%s': Invalid socket\n"), | ||
622 | serviceListeningInfo->serviceName); | ||
623 | return; | ||
624 | } | ||
625 | |||
626 | |||
627 | /* | ||
628 | * Close listening socket, start service, | ||
629 | * and stop all listening sockets associated with that service | ||
630 | * and free their correspondent ServiceInfo objects | ||
631 | */ | ||
632 | GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket); | ||
633 | start_service (NULL, serviceListeningInfo->serviceName); | ||
634 | setStartedService (serviceListeningInfo->serviceName); | ||
635 | stopServiceListeningSockets (serviceListeningInfo); | ||
636 | |||
637 | /* Notify me when the service is up and running */ | ||
638 | GNUNET_CLIENT_service_test (scheduler, | ||
639 | serviceListeningInfo->serviceName, cfg, | ||
640 | TIMEOUT, &connectToService, serviceInfo); | ||
641 | } | 567 | } |
568 | GNUNET_NETWORK_socket_close (serviceListeningInfo->listeningSocket); | ||
569 | GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, | ||
570 | serviceListeningInfoList_tail, | ||
571 | serviceListeningInfo); | ||
572 | start_service (NULL, serviceListeningInfo->serviceName); | ||
573 | GNUNET_CLIENT_service_test (scheduler, | ||
574 | serviceListeningInfo->serviceName, | ||
575 | cfg, | ||
576 | TIMEOUT, | ||
577 | &connectToService, | ||
578 | fc); | ||
642 | } | 579 | } |
643 | 580 | ||
644 | 581 | ||
645 | /** | 582 | /** |
646 | * Creating a listening socket for each of the service's addresses and wait for the first incoming connection to it | 583 | * Creating a listening socket for each of the service's addresses and |
584 | * wait for the first incoming connection to it | ||
647 | * | 585 | * |
648 | * @param addrs list of addresses associated with the service | 586 | * @param sa address associated with the service |
649 | * @param addr_lens list containing length for each of the addresses in addrs | 587 | * @param addr_len length of sa |
650 | * @param numOfAddresses length of the addr_lens array | ||
651 | * @param serviceName the name of the service in question | 588 | * @param serviceName the name of the service in question |
652 | */ | 589 | */ |
653 | static void | 590 | static void |
654 | createListeningSocket (struct sockaddr **addrs, socklen_t * addr_lens, | 591 | createListeningSocket (struct sockaddr *sa, |
655 | int numOfAddresses, char *serviceName) | 592 | socklen_t addr_len, |
593 | const char *serviceName) | ||
656 | { | 594 | { |
657 | int i; | ||
658 | struct GNUNET_NETWORK_Handle *socket; | 595 | struct GNUNET_NETWORK_Handle *socket; |
659 | struct sockaddr *sa; | ||
660 | socklen_t addr_len; | ||
661 | struct ServiceListeningInfo *serviceListeningInfo; | 596 | struct ServiceListeningInfo *serviceListeningInfo; |
662 | 597 | ||
663 | for (i = 0; i < numOfAddresses; i++) | 598 | switch (sa->sa_family) |
664 | { | 599 | { |
665 | sa = addrs[i]; | 600 | case AF_INET: |
666 | addr_len = addr_lens[i]; | 601 | socket = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); |
667 | switch (sa->sa_family) | 602 | break; |
668 | { | 603 | case AF_INET6: |
669 | case AF_INET: | 604 | socket = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); |
670 | socket = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); | 605 | break; |
671 | break; | 606 | default: |
672 | case AF_INET6: | 607 | socket = NULL; |
673 | socket = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); | 608 | break; |
674 | break; | 609 | } |
675 | default: | 610 | if (NULL == socket) |
676 | socket = NULL; | 611 | { |
677 | break; | 612 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
678 | } | 613 | "Unable to create socket for service %s", serviceName); |
679 | if (NULL == socket) | 614 | GNUNET_free (sa); |
680 | { | 615 | return; |
681 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 616 | } |
682 | "Unable to create socket for service %s", serviceName); | 617 | if (GNUNET_NETWORK_socket_bind |
683 | continue; | 618 | (socket, (const struct sockaddr *) sa, addr_len) != GNUNET_OK) |
684 | } | 619 | { |
685 | 620 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | |
686 | /* Bind */ | 621 | _("Unable to bind listening socket for service `%s'\n"), |
687 | if (GNUNET_NETWORK_socket_bind | 622 | serviceName); |
688 | (socket, (const struct sockaddr *) sa, addr_len) != GNUNET_OK) | 623 | GNUNET_free (sa); |
689 | { | 624 | return; |
690 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 625 | } |
691 | _("Unable to bind listening socket for service `%s'\n"), | 626 | if (GNUNET_NETWORK_socket_listen (socket, 5) != GNUNET_OK) |
692 | serviceName); | 627 | { |
693 | continue; | 628 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
694 | } | 629 | _("Error listening socket for service `%s'\n"), |
695 | 630 | serviceName); | |
696 | /* Listen */ | 631 | GNUNET_NETWORK_socket_close (socket); |
697 | if (GNUNET_NETWORK_socket_listen (socket, 5) != GNUNET_OK) | 632 | GNUNET_free (sa); |
698 | { | 633 | return; |
699 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
700 | _("Error listening socket for service `%s'\n"), | ||
701 | serviceName); | ||
702 | } | ||
703 | |||
704 | serviceListeningInfo = | ||
705 | newServiceListeningInfo (serviceName, sa, addr_len, socket); | ||
706 | serviceListeningInfo->listeningSocket = socket; | ||
707 | serviceListeningInfo->serviceName = serviceName; | ||
708 | serviceListeningInfo->service_addr = sa; | ||
709 | serviceListeningInfo->service_addr_len = addr_len; | ||
710 | |||
711 | /* Wait for the first incoming connection */ | ||
712 | serviceListeningInfo->acceptTask = | ||
713 | GNUNET_SCHEDULER_add_read_net (scheduler, | ||
714 | GNUNET_TIME_UNIT_FOREVER_REL, socket, | ||
715 | &acceptConnection, | ||
716 | serviceListeningInfo); | ||
717 | } | 634 | } |
635 | serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo)); | ||
636 | serviceListeningInfo->serviceName = GNUNET_strdup (serviceName); | ||
637 | serviceListeningInfo->service_addr = sa; | ||
638 | serviceListeningInfo->service_addr_len = addr_len; | ||
639 | serviceListeningInfo->listeningSocket = socket; | ||
640 | serviceListeningInfo->acceptTask = | ||
641 | GNUNET_SCHEDULER_add_read_net (scheduler, | ||
642 | GNUNET_TIME_UNIT_FOREVER_REL, socket, | ||
643 | &acceptConnection, | ||
644 | serviceListeningInfo); | ||
645 | GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head, | ||
646 | serviceListeningInfoList_tail, | ||
647 | serviceListeningInfo); | ||
718 | } | 648 | } |
719 | 649 | ||
650 | |||
720 | /** | 651 | /** |
721 | * Callback function, checks whether the current tokens are representing a service, | 652 | * Callback function, checks whether the current tokens are representing a service, |
722 | * gets its addresses and create listening socket for it. | 653 | * gets its addresses and create listening socket for it. |
@@ -728,37 +659,30 @@ createListeningSocket (struct sockaddr **addrs, socklen_t * addr_lens, | |||
728 | */ | 659 | */ |
729 | static void | 660 | static void |
730 | checkPortNumberCB (void *cls, | 661 | checkPortNumberCB (void *cls, |
731 | const char *section, const char *option, const char *value) | 662 | const char *section, |
663 | const char *option, | ||
664 | const char *value) | ||
732 | { | 665 | { |
733 | /* The service shouldn't be a default service */ | 666 | struct sockaddr **addrs; |
734 | if ((strcmp (section, "arm") != 0) | 667 | socklen_t *addr_lens; |
735 | && (strcmp (option, "PORT") == 0) | 668 | int ret; |
736 | && (isInDefaultList (section) == GNUNET_NO)) | 669 | unsigned int i; |
737 | { | 670 | |
738 | /* then the section is representing a service */ | 671 | if ( (strcmp (section, "arm") == 0) || |
739 | struct sockaddr **addrs; | 672 | (strcmp (option, "PORT") != 0) || |
740 | socklen_t *addr_lens; | 673 | (isInDefaultList (section) == GNUNET_YES) ) |
741 | int ret; | 674 | return; |
742 | 675 | if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, | |
743 | ret = | 676 | &addr_lens))) |
744 | GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, | 677 | return; |
745 | &addr_lens); | 678 | /* this will free (or capture) addrs[i] for i in 0..ret */ |
746 | if (ret == GNUNET_SYSERR) | 679 | for (i = 0; i < ret; i++) |
747 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 680 | createListeningSocket (addrs[i], addr_lens[i], section); |
748 | _("Unable to resolve host name for service `%s'\n"), | 681 | GNUNET_free (addrs); |
749 | section); | 682 | GNUNET_free (addr_lens); |
750 | else if (ret != GNUNET_NO) | ||
751 | { | ||
752 | /* Addresses found for service */ | ||
753 | createListeningSocket (addrs, addr_lens, ret, (char *) section); | ||
754 | } | ||
755 | else | ||
756 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
757 | _("No addresses for service `%s' in configuration\n"), | ||
758 | section); | ||
759 | } | ||
760 | } | 683 | } |
761 | 684 | ||
685 | |||
762 | /** | 686 | /** |
763 | * Entry point to the Service Manager | 687 | * Entry point to the Service Manager |
764 | * | 688 | * |
@@ -770,18 +694,17 @@ prepareServices (const struct GNUNET_CONFIGURATION_Handle | |||
770 | *configurationHandle, struct GNUNET_SCHEDULER_Handle *sched) | 694 | *configurationHandle, struct GNUNET_SCHEDULER_Handle *sched) |
771 | { | 695 | { |
772 | char *defaultServicesString; | 696 | char *defaultServicesString; |
697 | |||
773 | scheduler = sched; | 698 | scheduler = sched; |
774 | cfg = configurationHandle; | 699 | cfg = configurationHandle; |
775 | |||
776 | /* Split the default services into a list */ | 700 | /* Split the default services into a list */ |
777 | GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES", | 701 | GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES", |
778 | &defaultServicesString); | 702 | &defaultServicesString); |
779 | addDefaultServicesToList (defaultServicesString); | 703 | addDefaultServicesToList (defaultServicesString); |
780 | 704 | GNUNET_free (defaultServicesString); | |
781 | #if DEBUG_SERVICE_MANAGER | 705 | #if DEBUG_SERVICE_MANAGER |
782 | printDefaultServicesList (); | 706 | printDefaultServicesList (); |
783 | #endif | 707 | #endif |
784 | |||
785 | /* Spot the services from the configuration and create a listening socket for each */ | 708 | /* Spot the services from the configuration and create a listening socket for each */ |
786 | GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL); | 709 | GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL); |
787 | } | 710 | } |