diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-05 13:10:53 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-05 13:10:53 +0000 |
commit | ac3a1c494fd48fc1d01fcc4eafa0b3f4878f5441 (patch) | |
tree | a21b54452171f582444a199e70426b4c4266152b /src/conversation/gnunet-service-conversation.c | |
parent | 45c9ba99503eaf130b3d298062c612e281893d6a (diff) | |
download | gnunet-ac3a1c494fd48fc1d01fcc4eafa0b3f4878f5441.tar.gz gnunet-ac3a1c494fd48fc1d01fcc4eafa0b3f4878f5441.zip |
-rename fest: new to default
Diffstat (limited to 'src/conversation/gnunet-service-conversation.c')
-rw-r--r-- | src/conversation/gnunet-service-conversation.c | 2485 |
1 files changed, 940 insertions, 1545 deletions
diff --git a/src/conversation/gnunet-service-conversation.c b/src/conversation/gnunet-service-conversation.c index 4c4bdc133..d379931f7 100644 --- a/src/conversation/gnunet-service-conversation.c +++ b/src/conversation/gnunet-service-conversation.c | |||
@@ -22,56 +22,140 @@ | |||
22 | * @brief conversation service implementation | 22 | * @brief conversation service implementation |
23 | * @author Simon Dieterle | 23 | * @author Simon Dieterle |
24 | * @author Andreas Fuchs | 24 | * @author Andreas Fuchs |
25 | * STRUCTURE: | 25 | * @author Christian Grothoff |
26 | * - Variables | ||
27 | * - AUXILIARY FUNCTIONS | ||
28 | * - SENDING FUNCTIONS CL -> SERVER | ||
29 | * - RECEIVE FUNCTIONS CL -> SERVER | ||
30 | * - SENDING FUNCTIONS MESH | ||
31 | * - RECEIVE FUNCTIONS MESH | ||
32 | * - HELPER | ||
33 | * - TUNNEL HANDLING | ||
34 | * - CLIENT HANDLING | ||
35 | */ | 26 | */ |
36 | #include "platform.h" | 27 | #include "platform.h" |
37 | #include "gnunet_util_lib.h" | 28 | #include "gnunet_util_lib.h" |
38 | #include "gnunet_protocols.h" | 29 | #include "gnunet_protocols.h" |
30 | #include "gnunet_applications.h" | ||
39 | #include "gnunet_constants.h" | 31 | #include "gnunet_constants.h" |
32 | #include "gnunet_signatures.h" | ||
40 | #include "gnunet_mesh_service.h" | 33 | #include "gnunet_mesh_service.h" |
41 | #include "gnunet_conversation_service.h" | 34 | #include "gnunet_conversation_service.h" |
42 | #include "conversation.h" | 35 | #include "conversation.h" |
43 | 36 | ||
44 | 37 | ||
38 | /** | ||
39 | * How long is our signature on a call valid? Needs to be long enough for time zone | ||
40 | * differences and network latency to not matter. No strong need for it to be short, | ||
41 | * but we simply like all signatures to eventually expire. | ||
42 | */ | ||
43 | #define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS | ||
45 | 44 | ||
46 | /* | 45 | |
47 | * The possible connection status | 46 | /** |
48 | */ | 47 | * The possible connection status |
49 | enum connection_status | 48 | */ |
49 | enum LineStatus | ||
50 | { | 50 | { |
51 | LISTEN, | 51 | /** |
52 | CALLER, | 52 | * We are waiting for incoming calls. |
53 | CALLEE, | 53 | */ |
54 | CONNECTED | 54 | LS_CALLEE_LISTEN, |
55 | |||
56 | /** | ||
57 | * Our phone is ringing, waiting for the client to pick up. | ||
58 | */ | ||
59 | LS_CALLEE_RINGING, | ||
60 | |||
61 | /** | ||
62 | * We are talking! | ||
63 | */ | ||
64 | LS_CALLEE_CONNECTED, | ||
65 | |||
66 | /** | ||
67 | * We're in shutdown, sending hangup messages before cleaning up. | ||
68 | */ | ||
69 | LS_CALLEE_SHUTDOWN, | ||
70 | |||
71 | /** | ||
72 | * We are waiting for the phone to be picked up. | ||
73 | */ | ||
74 | LS_CALLER_CALLING, | ||
75 | |||
76 | /** | ||
77 | * We are talking! | ||
78 | */ | ||
79 | LS_CALLER_CONNECTED, | ||
80 | |||
81 | /** | ||
82 | * We're in shutdown, sending hangup messages before cleaning up. | ||
83 | */ | ||
84 | LS_CALLER_SHUTDOWN | ||
55 | }; | 85 | }; |
56 | 86 | ||
57 | 87 | ||
58 | /******************************************************** | 88 | /** |
59 | * Ugly hack because of not working MESH API | 89 | * A line connects a local client with a mesh tunnel (or, if it is an |
60 | */ | 90 | * open line, is waiting for a mesh tunnel). |
61 | typedef uint32_t MESH_TunnelNumber; | 91 | */ |
62 | struct GNUNET_MESH_Tunnel | 92 | struct Line |
63 | { | 93 | { |
64 | struct GNUNET_MESH_Tunnel *next; | 94 | /** |
65 | struct GNUNET_MESH_Tunnel *prev; | 95 | * Kept in a DLL. |
66 | struct GNUNET_MESH_Handle *mesh; | 96 | */ |
67 | MESH_TunnelNumber tid; | 97 | struct Line *next; |
68 | uint32_t port; | 98 | |
69 | GNUNET_PEER_Id peer; | 99 | /** |
70 | void *ctx; | 100 | * Kept in a DLL. |
71 | unsigned int packet_size; | 101 | */ |
72 | int buffering; | 102 | struct Line *prev; |
73 | int reliable; | 103 | |
74 | int allow_send; | 104 | /** |
105 | * Handle for the reliable tunnel (contol data) | ||
106 | */ | ||
107 | struct GNUNET_MESH_Tunnel *tunnel_reliable; | ||
108 | |||
109 | /** | ||
110 | * Handle for unreliable tunnel (audio data) | ||
111 | */ | ||
112 | struct GNUNET_MESH_Tunnel *tunnel_unreliable; | ||
113 | |||
114 | /** | ||
115 | * Transmit handle for pending audio messages | ||
116 | */ | ||
117 | struct GNUNET_MESH_TransmitHandle *unreliable_mth; | ||
118 | |||
119 | /** | ||
120 | * Message queue for control messages | ||
121 | */ | ||
122 | struct GNUNET_MQ_Handle *reliable_mq; | ||
123 | |||
124 | /** | ||
125 | * Handle to the line client. | ||
126 | */ | ||
127 | struct GNUNET_SERVER_Client *client; | ||
128 | |||
129 | /** | ||
130 | * Target of the line, if we are the caller. | ||
131 | */ | ||
132 | struct GNUNET_PeerIdentity target; | ||
133 | |||
134 | /** | ||
135 | * Temporary buffer for audio data. | ||
136 | */ | ||
137 | void *audio_data; | ||
138 | |||
139 | /** | ||
140 | * Number of bytes in @e audio_data. | ||
141 | */ | ||
142 | size_t audio_size; | ||
143 | |||
144 | /** | ||
145 | * Our line number. | ||
146 | */ | ||
147 | uint32_t local_line; | ||
148 | |||
149 | /** | ||
150 | * Remote line number. | ||
151 | */ | ||
152 | uint32_t remote_line; | ||
153 | |||
154 | /** | ||
155 | * Current status of this line. | ||
156 | */ | ||
157 | enum LineStatus status; | ||
158 | |||
75 | }; | 159 | }; |
76 | 160 | ||
77 | 161 | ||
@@ -81,1421 +165,831 @@ struct GNUNET_MESH_Tunnel | |||
81 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 165 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
82 | 166 | ||
83 | /** | 167 | /** |
84 | * Head of the list of current clients. | ||
85 | */ | ||
86 | static struct GNUNET_CONTAINER_SList *clients; | ||
87 | |||
88 | /** | ||
89 | * Notification context containing all connected clients. | 168 | * Notification context containing all connected clients. |
90 | */ | 169 | */ |
91 | struct GNUNET_SERVER_NotificationContext *nc = NULL; | 170 | static struct GNUNET_SERVER_NotificationContext *nc; |
92 | |||
93 | /** | ||
94 | * The connection status | ||
95 | */ | ||
96 | static struct ConnectionStatus connection; | ||
97 | 171 | ||
98 | /** | 172 | /** |
99 | * Handle for the record helper | 173 | * Handle for mesh |
100 | */ | ||
101 | static struct GNUNET_HELPER_Handle *record_helper; | ||
102 | |||
103 | /** Handle for the playback handler | ||
104 | * | ||
105 | */ | ||
106 | static struct GNUNET_HELPER_Handle *playback_helper; | ||
107 | |||
108 | /** | ||
109 | * Handle for mesh | ||
110 | */ | ||
111 | static struct GNUNET_MESH_Handle *mesh; | ||
112 | |||
113 | /** | ||
114 | * Transmit handle for audio messages | ||
115 | */ | ||
116 | static struct GNUNET_MESH_TransmitHandle *mth = NULL; | ||
117 | |||
118 | /** | ||
119 | * Handle for the reliable tunnel (contol data) | ||
120 | */ | ||
121 | static struct GNUNET_MESH_Tunnel *tunnel_reliable; | ||
122 | |||
123 | /** | ||
124 | * Handle for unreliable tunnel (audio data) | ||
125 | */ | ||
126 | static struct GNUNET_MESH_Tunnel *tunnel_unreliable; | ||
127 | |||
128 | /** | ||
129 | * List for missed calls | ||
130 | */ | ||
131 | static struct GNUNET_CONTAINER_SList *missed_calls; | ||
132 | |||
133 | /** | ||
134 | * List for peers to notify that we are available again | ||
135 | */ | ||
136 | static struct GNUNET_CONTAINER_SList *peers_to_notify; | ||
137 | |||
138 | /** | ||
139 | * Audio buffer (outgoing) | ||
140 | */ | ||
141 | static struct GNUNET_CONTAINER_SList *audio_buffer; | ||
142 | |||
143 | /** | ||
144 | * The pointer to the task for sending audio | ||
145 | */ | ||
146 | static GNUNET_SCHEDULER_TaskIdentifier audio_task; | ||
147 | |||
148 | /** | ||
149 | * The pointer to the task for checking timeouts an calling a peer | ||
150 | */ | ||
151 | static GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
152 | |||
153 | /** | ||
154 | * Timestamp for call statistics | ||
155 | */ | ||
156 | static struct GNUNET_TIME_Absolute start_time; | ||
157 | |||
158 | /** | ||
159 | * Number of payload packes sent | ||
160 | */ | 174 | */ |
161 | static int data_sent; | 175 | static struct GNUNET_MESH_Handle *mesh; |
162 | static int data_sent_size; | ||
163 | 176 | ||
164 | /** | 177 | /** |
165 | * Number of payload packets received | 178 | * Identity of this peer. |
166 | */ | 179 | */ |
167 | static int data_received; | 180 | static struct GNUNET_PeerIdentity my_identity; |
168 | static int data_received_size; | ||
169 | |||
170 | 181 | ||
171 | /** | 182 | /** |
172 | * Transmit a mesh message | 183 | * Head of DLL of active lines. |
173 | * @param cls closure, NULL | ||
174 | * @param size number of bytes available in buf | ||
175 | * @param buf where the callee should write the error message | ||
176 | * @return number of bytes written to buf | ||
177 | */ | 184 | */ |
178 | static size_t transmit_mesh_message (void *cls, size_t size, void *buf); | 185 | static struct Line *lines_head; |
179 | 186 | ||
180 | /** | 187 | /** |
181 | * Function called to send a peer no answer message to the client. | 188 | * Tail of DLL of active lines. |
182 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
183 | * the meantime. | ||
184 | * | ||
185 | * @param cls closure, NULL | ||
186 | * @param size number of bytes available in buf | ||
187 | * @param buf where the callee should write the peer no answer message | ||
188 | * @return number of bytes written to buf | ||
189 | */ | 189 | */ |
190 | static size_t | 190 | static struct Line *lines_tail; |
191 | transmit_server_no_answer_message (void *cls, size_t size, void *buf); | ||
192 | 191 | ||
193 | /** | 192 | /** |
194 | * Task to schedule a audio transmission. | 193 | * Counter for generating local line numbers. |
195 | * | 194 | * FIXME: randomize generation in the future |
196 | * @param cls Closure. | 195 | * to eliminate information leakage. |
197 | * @param tc Task Context. | ||
198 | */ | 196 | */ |
199 | static void | 197 | static uint32_t local_line_cnt; |
200 | transmit_audio_task (void *cls, | ||
201 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
202 | 198 | ||
203 | /** | ||
204 | * Start the audio helpers | ||
205 | */ | ||
206 | int start_helpers (void); | ||
207 | 199 | ||
208 | /** | 200 | /** |
209 | * Stop the audio helpers | 201 | * Function to register a phone. |
210 | */ | ||
211 | void stop_helpers (void); | ||
212 | |||
213 | |||
214 | |||
215 | /******************************************************************************/ | ||
216 | /*********************** AUXILIARY FUNCTIONS *************************/ | ||
217 | /******************************************************************************/ | ||
218 | |||
219 | /** | ||
220 | * Function which displays some call stats | ||
221 | */ | ||
222 | static void | ||
223 | show_end_data (void) | ||
224 | { | ||
225 | static struct GNUNET_TIME_Absolute end_time; | ||
226 | static struct GNUNET_TIME_Relative total_time; | ||
227 | |||
228 | end_time = GNUNET_TIME_absolute_get (); | ||
229 | total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time); | ||
230 | FPRINTF (stderr, "\nResults of send\n"); | ||
231 | FPRINTF (stderr, "Test time %s\n", | ||
232 | GNUNET_STRINGS_relative_time_to_string (total_time, | ||
233 | GNUNET_NO)); | ||
234 | FPRINTF (stderr, "Test total packets: %d\n", | ||
235 | data_sent); | ||
236 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", | ||
237 | data_sent_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us | ||
238 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", | ||
239 | data_sent * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us | ||
240 | |||
241 | FPRINTF (stderr, "\nResults of recv\n"); | ||
242 | FPRINTF (stderr, "Test time %s\n", | ||
243 | GNUNET_STRINGS_relative_time_to_string (total_time, | ||
244 | GNUNET_NO)); | ||
245 | FPRINTF (stderr, "Test total packets: %d\n", | ||
246 | data_received); | ||
247 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", | ||
248 | data_received_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us | ||
249 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", | ||
250 | data_received * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * Function which sets the connection state to LISTEN | ||
255 | */ | ||
256 | static void | ||
257 | status_to_listen (void) | ||
258 | { | ||
259 | |||
260 | if (CONNECTED == connection.status) | ||
261 | { | ||
262 | show_end_data (); | ||
263 | } | ||
264 | |||
265 | if (timeout_task != GNUNET_SCHEDULER_NO_TASK) | ||
266 | { | ||
267 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
268 | timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
269 | } | ||
270 | |||
271 | stop_helpers (); | ||
272 | |||
273 | connection.status = LISTEN; | ||
274 | connection.client = NULL; | ||
275 | |||
276 | data_sent = 0; | ||
277 | data_sent_size = 0; | ||
278 | data_received = 0; | ||
279 | data_received_size = 0; | ||
280 | |||
281 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"), | ||
282 | "LISTEN"); | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * Function to terminate the active call | ||
287 | */ | ||
288 | static void | ||
289 | terminate_call () | ||
290 | { | ||
291 | size_t msg_size; | ||
292 | msg_size = sizeof (struct MeshSessionTerminateMessage); | ||
293 | struct MeshSessionTerminateMessage *message_mesh_terminate = | ||
294 | (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size); | ||
295 | |||
296 | if (NULL == message_mesh_terminate) | ||
297 | { | ||
298 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
299 | _("Could not create MeshSessionTerminateMessage\n")); | ||
300 | status_to_listen (); | ||
301 | |||
302 | return; | ||
303 | } | ||
304 | |||
305 | message_mesh_terminate->header.size = htons (msg_size); | ||
306 | message_mesh_terminate->header.type = | ||
307 | htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE); | ||
308 | |||
309 | if (NULL == | ||
310 | GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0, | ||
311 | MAX_TRANSMIT_DELAY, msg_size, | ||
312 | &transmit_mesh_message, | ||
313 | (void *) message_mesh_terminate)) | ||
314 | { | ||
315 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
316 | _("Could not queue MeshSessionTerminateMessage\n")); | ||
317 | GNUNET_free (message_mesh_terminate); | ||
318 | status_to_listen (); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * Function to reject a call | ||
324 | * | ||
325 | * @param tunnel the tunnel where to reject the incoming call | ||
326 | * @param reason te reson why the call is rejected | ||
327 | */ | ||
328 | static void | ||
329 | reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason) | ||
330 | { | ||
331 | size_t msg_size; | ||
332 | msg_size = sizeof (struct MeshSessionRejectMessage); | ||
333 | struct MeshSessionRejectMessage *message_mesh_reject = | ||
334 | (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size); | ||
335 | |||
336 | if (NULL == message_mesh_reject) | ||
337 | { | ||
338 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
339 | _("Could not create MeshSessionRejectMessage\n")); | ||
340 | status_to_listen (); | ||
341 | |||
342 | return; | ||
343 | } | ||
344 | |||
345 | message_mesh_reject->header.size = htons (msg_size); | ||
346 | message_mesh_reject->header.type = | ||
347 | htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT); | ||
348 | message_mesh_reject->reason = htons (reason); | ||
349 | |||
350 | if (NULL == | ||
351 | GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0, | ||
352 | MAX_TRANSMIT_DELAY, msg_size, | ||
353 | &transmit_mesh_message, | ||
354 | (void *) message_mesh_reject)) | ||
355 | { | ||
356 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
357 | _("Could not queue MeshSessionRejectMessage\n")); | ||
358 | GNUNET_free (message_mesh_reject); | ||
359 | status_to_listen (); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * Check for timeout when calling a peer | ||
365 | * | 202 | * |
366 | * @param cls closure, NULL | 203 | * @param cls closure, NULL |
367 | * @param tc the task context (can be NULL) | 204 | * @param client the client from which the message is |
205 | * @param message the message from the client | ||
368 | */ | 206 | */ |
369 | static void | 207 | static void |
370 | check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 208 | handle_client_register_message (void *cls, |
371 | { | 209 | struct GNUNET_SERVER_Client *client, |
372 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n"); | 210 | const struct GNUNET_MessageHeader *message) |
373 | |||
374 | if (NULL == | ||
375 | GNUNET_SERVER_notify_transmit_ready (connection.client, | ||
376 | sizeof (struct | ||
377 | ServerClientNoAnswerMessage), | ||
378 | MAX_TRANSMIT_DELAY, | ||
379 | &transmit_server_no_answer_message, | ||
380 | NULL)) | ||
381 | { | ||
382 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
383 | _("Could not queue ServerClientNoAnswerMessage\n")); | ||
384 | } | ||
385 | |||
386 | terminate_call (); | ||
387 | } | ||
388 | |||
389 | /******************************************************************************/ | ||
390 | /*********************** SENDING FUNCTIONS CL -> SERVER *******************/ | ||
391 | /******************************************************************************/ | ||
392 | |||
393 | /** | ||
394 | * Function called to send a session initiate message to the client. | ||
395 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
396 | * the meantime. | ||
397 | * | ||
398 | * @param cls closure, NULL | ||
399 | * @param size number of bytes available in buf | ||
400 | * @param buf where the callee should write the initiate message | ||
401 | * @return number of bytes written to buf | ||
402 | */ | ||
403 | static size_t | ||
404 | transmit_server_initiate_message (void *cls, size_t size, void *buf) | ||
405 | { | ||
406 | struct ServerClientSessionInitiateMessage *msg; | ||
407 | size_t msg_size; | ||
408 | |||
409 | msg_size = sizeof (struct ServerClientSessionInitiateMessage); | ||
410 | |||
411 | GNUNET_assert (size >= msg_size); | ||
412 | |||
413 | msg = (struct ServerClientSessionInitiateMessage *) buf; | ||
414 | msg->header.size = htons (msg_size); | ||
415 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE); | ||
416 | memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls, | ||
417 | sizeof (struct GNUNET_PeerIdentity)); | ||
418 | |||
419 | return msg_size; | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * Function called to send a session accept message to the client. | ||
424 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
425 | * the meantime. | ||
426 | * | ||
427 | * @param cls closure, NULL | ||
428 | * @param size number of bytes available in buf | ||
429 | * @param buf where the callee should write the accept message | ||
430 | * @return number of bytes written to buf | ||
431 | */ | ||
432 | static size_t | ||
433 | transmit_server_accept_message (void *cls, size_t size, void *buf) | ||
434 | { | 211 | { |
435 | struct ServerClientSessionAcceptMessage *msg; | 212 | const struct ClientPhoneRegisterMessage *msg; |
436 | size_t msg_size; | 213 | struct Line *line; |
437 | 214 | ||
438 | msg_size = sizeof (struct ServerClientSessionAcceptMessage); | 215 | msg = (struct ClientPhoneRegisterMessage *) message; |
439 | 216 | line = GNUNET_SERVER_client_get_user_context (client, struct Line); | |
440 | GNUNET_assert (size >= msg_size); | 217 | if (NULL != line) |
441 | 218 | { | |
442 | msg = (struct ServerClientSessionAcceptMessage *) buf; | 219 | GNUNET_break (0); |
443 | msg->header.size = htons (msg_size); | 220 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
444 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT); | 221 | return; |
445 | 222 | } | |
446 | return msg_size; | 223 | line = GNUNET_new (struct Line); |
224 | line->client = client; | ||
225 | GNUNET_SERVER_notification_context_add (nc, client); | ||
226 | GNUNET_CONTAINER_DLL_insert (lines_head, | ||
227 | lines_tail, | ||
228 | line); | ||
229 | line->local_line = ntohl (msg->line); | ||
230 | GNUNET_SERVER_client_set_user_context (client, line); | ||
231 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
447 | } | 232 | } |
448 | 233 | ||
449 | /** | ||
450 | * Function called to send a session reject message to the client. | ||
451 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
452 | * the meantime. | ||
453 | * | ||
454 | * @param cls closure, NULL | ||
455 | * @param size number of bytes available in buf | ||
456 | * @param buf where the callee should write the reject message | ||
457 | * @return number of bytes written to buf | ||
458 | */ | ||
459 | static size_t | ||
460 | transmit_server_reject_message (void *cls, size_t size, void *buf) | ||
461 | { | ||
462 | struct ServerClientSessionRejectMessage *msg; | ||
463 | size_t msg_size; | ||
464 | |||
465 | msg_size = sizeof (struct ServerClientSessionRejectMessage); | ||
466 | |||
467 | GNUNET_assert (size >= msg_size); | ||
468 | |||
469 | msg = (struct ServerClientSessionRejectMessage *) buf; | ||
470 | msg->header.size = htons (msg_size); | ||
471 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT); | ||
472 | |||
473 | if (NULL == cls) | ||
474 | { | ||
475 | msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_AVAILABLE); | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason; | ||
480 | } | ||
481 | |||
482 | return msg_size; | ||
483 | } | ||
484 | 234 | ||
485 | /** | 235 | /** |
486 | * Function called to send a session terminate message to the client. | 236 | * Function to handle a pickup request message from the client |
487 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
488 | * the meantime. | ||
489 | * | 237 | * |
490 | * @param cls closure, NULL | 238 | * @param cls closure, NULL |
491 | * @param size number of bytes available in buf | 239 | * @param client the client from which the message is |
492 | * @param buf where the callee should write the terminate message | 240 | * @param message the message from the client |
493 | * @return number of bytes written to buf | ||
494 | */ | 241 | */ |
495 | static size_t | 242 | static void |
496 | transmit_server_terminate_message (void *cls, size_t size, void *buf) | 243 | handle_client_pickup_message (void *cls, |
244 | struct GNUNET_SERVER_Client *client, | ||
245 | const struct GNUNET_MessageHeader *message) | ||
497 | { | 246 | { |
498 | struct ServerClientSessionTerminateMessage *msg; | 247 | const struct ClientPhonePickupMessage *msg; |
499 | size_t msg_size; | 248 | struct GNUNET_MQ_Envelope *e; |
500 | 249 | struct MeshPhonePickupMessage *mppm; | |
501 | msg_size = sizeof (struct ServerClientSessionTerminateMessage); | 250 | const char *meta; |
502 | 251 | struct Line *line; | |
503 | GNUNET_assert (size >= msg_size); | 252 | size_t len; |
504 | 253 | ||
505 | msg = (struct ServerClientSessionTerminateMessage *) buf; | 254 | msg = (struct ClientPhonePickupMessage *) message; |
506 | msg->header.size = htons (msg_size); | 255 | meta = (const char *) &msg[1]; |
507 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE); | 256 | len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage); |
508 | 257 | if ( (0 == len) || | |
509 | return msg_size; | 258 | ('\0' != meta[len - 1]) ) |
259 | { | ||
260 | meta = NULL; | ||
261 | len = 0; | ||
262 | } | ||
263 | line = GNUNET_SERVER_client_get_user_context (client, struct Line); | ||
264 | if (NULL == line) | ||
265 | { | ||
266 | GNUNET_break (0); | ||
267 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
268 | return; | ||
269 | } | ||
270 | switch (line->status) | ||
271 | { | ||
272 | case LS_CALLEE_LISTEN: | ||
273 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
274 | "Ignoring client's PICKUP message, caller has HUNG UP already\n"); | ||
275 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
276 | break; | ||
277 | case LS_CALLEE_RINGING: | ||
278 | line->status = LS_CALLEE_CONNECTED; | ||
279 | break; | ||
280 | case LS_CALLEE_CONNECTED: | ||
281 | GNUNET_break (0); | ||
282 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
283 | return; | ||
284 | case LS_CALLEE_SHUTDOWN: | ||
285 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
286 | "Ignoring client's PICKUP message, line is in SHUTDOWN\n"); | ||
287 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
288 | break; | ||
289 | case LS_CALLER_CALLING: | ||
290 | case LS_CALLER_CONNECTED: | ||
291 | case LS_CALLER_SHUTDOWN: | ||
292 | GNUNET_break (0); | ||
293 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
294 | return; | ||
295 | } | ||
296 | line->status = LS_CALLEE_CONNECTED; | ||
297 | e = GNUNET_MQ_msg_extra (mppm, | ||
298 | len, | ||
299 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP); | ||
300 | memcpy (&mppm[1], meta, len); | ||
301 | GNUNET_MQ_send (line->reliable_mq, e); | ||
302 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
510 | } | 303 | } |
511 | 304 | ||
512 | /** | ||
513 | * Function called to send a missed call message to the client. | ||
514 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
515 | * the meantime. | ||
516 | * | ||
517 | * @param cls closure, NULL | ||
518 | * @param size number of bytes available in buf | ||
519 | * @param buf where the callee should write the missed call message | ||
520 | * @return number of bytes written to buf | ||
521 | */ | ||
522 | static size_t | ||
523 | transmit_server_missed_call_message (void *cls, size_t size, void *buf) | ||
524 | { | ||
525 | struct ServerClientMissedCallMessage *msg; | ||
526 | msg = (struct ServerClientMissedCallMessage *) cls; | ||
527 | |||
528 | memcpy (buf, msg, size); | ||
529 | GNUNET_free (msg); | ||
530 | |||
531 | return size; | ||
532 | } | ||
533 | 305 | ||
534 | /** | 306 | /** |
535 | * Function called to send a service blocked message to the client. | 307 | * Destroy the mesh tunnels of a line. |
536 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
537 | * the meantime. | ||
538 | * | 308 | * |
539 | * @param cls closure, NULL | 309 | * @param line line to shutdown tunnels of |
540 | * @param size number of bytes available in buf | ||
541 | * @param buf where the callee should write the service blocked message | ||
542 | * @return number of bytes written to buf | ||
543 | */ | 310 | */ |
544 | static size_t | 311 | static void |
545 | transmit_server_service_blocked_message (void *cls, size_t size, void *buf) | 312 | destroy_line_mesh_tunnels (struct Line *line) |
546 | { | 313 | { |
547 | struct ServerClientServiceBlockedMessage *msg; | 314 | if (NULL != line->reliable_mq) |
548 | size_t msg_size; | 315 | { |
549 | 316 | GNUNET_MQ_destroy (line->reliable_mq); | |
550 | msg_size = sizeof (struct ServerClientServiceBlockedMessage); | 317 | line->reliable_mq = NULL; |
551 | 318 | } | |
552 | GNUNET_assert (size >= msg_size); | 319 | if (NULL != line->unreliable_mth) |
553 | 320 | { | |
554 | msg = (struct ServerClientServiceBlockedMessage *) buf; | 321 | GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth); |
555 | msg->header.size = htons (msg_size); | 322 | line->unreliable_mth = NULL; |
556 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED); | 323 | } |
557 | 324 | if (NULL != line->tunnel_unreliable) | |
558 | return msg_size; | 325 | { |
326 | GNUNET_MESH_tunnel_destroy (line->tunnel_unreliable); | ||
327 | line->tunnel_unreliable = NULL; | ||
328 | } | ||
329 | if (NULL != line->tunnel_reliable) | ||
330 | { | ||
331 | GNUNET_MESH_tunnel_destroy (line->tunnel_reliable); | ||
332 | line->tunnel_reliable = NULL; | ||
333 | } | ||
559 | } | 334 | } |
560 | 335 | ||
561 | /** | ||
562 | * Function called to send a peer not connected message to the client. | ||
563 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
564 | * the meantime. | ||
565 | * | ||
566 | * @param cls closure, NULL | ||
567 | * @param size number of bytes available in buf | ||
568 | * @param buf where the callee should write the peer not connected message | ||
569 | * @return number of bytes written to buf | ||
570 | */ | ||
571 | static size_t | ||
572 | transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf) | ||
573 | { | ||
574 | struct ServerClientPeerNotConnectedMessage *msg; | ||
575 | size_t msg_size; | ||
576 | |||
577 | msg_size = sizeof (struct ServerClientPeerNotConnectedMessage); | ||
578 | |||
579 | GNUNET_assert (size >= msg_size); | ||
580 | |||
581 | msg = (struct ServerClientPeerNotConnectedMessage *) buf; | ||
582 | msg->header.size = htons (msg_size); | ||
583 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED); | ||
584 | |||
585 | return msg_size; | ||
586 | } | ||
587 | 336 | ||
588 | /** | 337 | /** |
589 | * Function called to send a peer no answer message to the client. | 338 | * We are done signalling shutdown to the other peer. Close down |
590 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | 339 | * (or reset) the line. |
591 | * the meantime. | ||
592 | * | 340 | * |
593 | * @param cls closure, NULL | 341 | * @param cls the `struct Line` to reset/terminate |
594 | * @param size number of bytes available in buf | ||
595 | * @param buf where the callee should write the peer no answer message | ||
596 | * @return number of bytes written to buf | ||
597 | */ | 342 | */ |
598 | static size_t | 343 | static void |
599 | transmit_server_no_answer_message (void *cls, size_t size, void *buf) | 344 | mq_done_finish_caller_shutdown (void *cls) |
600 | { | ||
601 | struct ServerClientNoAnswerMessage *msg; | ||
602 | size_t msg_size; | ||
603 | |||
604 | msg_size = sizeof (struct ServerClientNoAnswerMessage); | ||
605 | |||
606 | GNUNET_assert (size >= msg_size); | ||
607 | |||
608 | msg = (struct ServerClientNoAnswerMessage *) buf; | ||
609 | msg->header.size = htons (msg_size); | ||
610 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER); | ||
611 | |||
612 | return msg_size; | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * Function called to send a error message to the client. | ||
617 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
618 | * the meantime. | ||
619 | * | ||
620 | * @param cls closure, NULL | ||
621 | * @param size number of bytes available in buf | ||
622 | * @param buf where the callee should write the error message | ||
623 | * @return number of bytes written to buf | ||
624 | */ | ||
625 | static size_t | ||
626 | transmit_server_error_message (void *cls, size_t size, void *buf) | ||
627 | { | 345 | { |
628 | struct ServerClientErrorMessage *msg; | 346 | struct Line *line = cls; |
629 | size_t msg_size; | 347 | |
630 | 348 | switch (line->status) | |
631 | msg_size = sizeof (struct ServerClientErrorMessage); | 349 | { |
632 | 350 | case LS_CALLEE_LISTEN: | |
633 | GNUNET_assert (size >= msg_size); | 351 | GNUNET_break (0); |
634 | 352 | break; | |
635 | msg = (struct ServerClientErrorMessage *) buf; | 353 | case LS_CALLEE_RINGING: |
636 | msg->header.size = htons (msg_size); | 354 | GNUNET_break (0); |
637 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR); | 355 | break; |
638 | 356 | case LS_CALLEE_CONNECTED: | |
639 | return msg_size; | 357 | GNUNET_break (0); |
358 | break; | ||
359 | case LS_CALLEE_SHUTDOWN: | ||
360 | line->status = LS_CALLEE_LISTEN; | ||
361 | destroy_line_mesh_tunnels (line); | ||
362 | return; | ||
363 | case LS_CALLER_CALLING: | ||
364 | line->status = LS_CALLER_SHUTDOWN; | ||
365 | break; | ||
366 | case LS_CALLER_CONNECTED: | ||
367 | line->status = LS_CALLER_SHUTDOWN; | ||
368 | break; | ||
369 | case LS_CALLER_SHUTDOWN: | ||
370 | destroy_line_mesh_tunnels (line); | ||
371 | GNUNET_CONTAINER_DLL_remove (lines_head, | ||
372 | lines_tail, | ||
373 | line); | ||
374 | GNUNET_free_non_null (line->audio_data); | ||
375 | GNUNET_free (line); | ||
376 | break; | ||
377 | } | ||
640 | } | 378 | } |
641 | 379 | ||
642 | /******************************************************************************/ | ||
643 | /*********************** RECEIVE FUNCTIONS CL -> SERVER ********************/ | ||
644 | /******************************************************************************/ | ||
645 | 380 | ||
646 | /** | 381 | /** |
647 | * Function to handle a session initiate message from the client | 382 | * Function to handle a hangup request message from the client |
648 | * | 383 | * |
649 | * @param cls closure, NULL | 384 | * @param cls closure, NULL |
650 | * @param client the client from which the message is | 385 | * @param client the client from which the message is |
651 | * @param message the message from the client | 386 | * @param message the message from the client |
652 | */ | 387 | */ |
653 | static void | 388 | static void |
654 | handle_session_initiate_message (void *cls, | 389 | handle_client_hangup_message (void *cls, |
655 | struct GNUNET_SERVER_Client *client, | 390 | struct GNUNET_SERVER_Client *client, |
656 | const struct GNUNET_MessageHeader *message) | 391 | const struct GNUNET_MessageHeader *message) |
657 | { | 392 | { |
658 | static uint32_t port = 50002; | 393 | const struct ClientPhoneHangupMessage *msg; |
659 | size_t msg_size; | 394 | struct GNUNET_MQ_Envelope *e; |
660 | struct ClientServerSessionInitiateMessage *msg = | 395 | struct MeshPhoneHangupMessage *mhum; |
661 | (struct ClientServerSessionInitiateMessage *) message; | 396 | const char *meta; |
662 | struct GNUNET_PeerIdentity *peer = &(msg->peer); | 397 | struct Line *line; |
663 | 398 | size_t len; | |
399 | |||
400 | msg = (struct ClientPhoneHangupMessage *) message; | ||
401 | meta = (const char *) &msg[1]; | ||
402 | len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage); | ||
403 | if ( (0 == len) || | ||
404 | ('\0' != meta[len - 1]) ) | ||
405 | { | ||
406 | meta = NULL; | ||
407 | len = 0; | ||
408 | } | ||
409 | line = GNUNET_SERVER_client_get_user_context (client, struct Line); | ||
410 | if (NULL == line) | ||
411 | { | ||
412 | GNUNET_break (0); | ||
413 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
414 | return; | ||
415 | } | ||
416 | switch (line->status) | ||
417 | { | ||
418 | case LS_CALLEE_LISTEN: | ||
419 | GNUNET_break (0); | ||
420 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
421 | return; | ||
422 | case LS_CALLEE_RINGING: | ||
423 | line->status = LS_CALLEE_SHUTDOWN; | ||
424 | break; | ||
425 | case LS_CALLEE_CONNECTED: | ||
426 | line->status = LS_CALLEE_SHUTDOWN; | ||
427 | break; | ||
428 | case LS_CALLEE_SHUTDOWN: | ||
429 | GNUNET_break (0); | ||
430 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
431 | return; | ||
432 | case LS_CALLER_CALLING: | ||
433 | line->status = LS_CALLER_SHUTDOWN; | ||
434 | break; | ||
435 | case LS_CALLER_CONNECTED: | ||
436 | line->status = LS_CALLER_SHUTDOWN; | ||
437 | break; | ||
438 | case LS_CALLER_SHUTDOWN: | ||
439 | GNUNET_break (0); | ||
440 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
441 | return; | ||
442 | } | ||
443 | e = GNUNET_MQ_msg_extra (mhum, | ||
444 | len, | ||
445 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP); | ||
446 | memcpy (&mhum[1], meta, len); | ||
447 | GNUNET_MQ_notify_sent (e, | ||
448 | &mq_done_finish_caller_shutdown, | ||
449 | line); | ||
450 | GNUNET_MQ_send (line->reliable_mq, e); | ||
664 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 451 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
665 | |||
666 | if (NULL != connection.client) | ||
667 | { | ||
668 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
669 | _("There is already a peer in interaction\n")); | ||
670 | GNUNET_SERVER_notify_transmit_ready (client, | ||
671 | sizeof (struct | ||
672 | ServerClientServiceBlockedMessage), | ||
673 | MAX_TRANSMIT_DELAY, | ||
674 | &transmit_server_service_blocked_message, | ||
675 | NULL); | ||
676 | |||
677 | return; | ||
678 | } | ||
679 | |||
680 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"), | ||
681 | GNUNET_i2s_full (peer)); | ||
682 | tunnel_reliable = | ||
683 | GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO); | ||
684 | if (NULL == tunnel_reliable) | ||
685 | { | ||
686 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
687 | _("Could not create reliable tunnel\n")); | ||
688 | GNUNET_SERVER_notify_transmit_ready (client, | ||
689 | sizeof (struct | ||
690 | ServerClientPeerNotConnectedMessage), | ||
691 | MAX_TRANSMIT_DELAY, | ||
692 | &transmit_server_peer_not_connected_message, | ||
693 | NULL); | ||
694 | |||
695 | return; | ||
696 | } | ||
697 | |||
698 | msg_size = sizeof (struct MeshSessionInitiateMessage); | ||
699 | struct MeshSessionInitiateMessage *message_mesh_initiate = | ||
700 | (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size); | ||
701 | |||
702 | if (NULL == message_mesh_initiate) | ||
703 | { | ||
704 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
705 | _("Could not create MeshSessionInitiateMessage\n")); | ||
706 | GNUNET_MESH_tunnel_destroy (tunnel_reliable); | ||
707 | tunnel_reliable = NULL; | ||
708 | GNUNET_SERVER_notify_transmit_ready (client, | ||
709 | sizeof (struct | ||
710 | ServerClientErrorMessage), | ||
711 | MAX_TRANSMIT_DELAY, | ||
712 | &transmit_server_error_message, | ||
713 | NULL); | ||
714 | |||
715 | return; | ||
716 | } | ||
717 | |||
718 | message_mesh_initiate->header.size = htons (msg_size); | ||
719 | message_mesh_initiate->header.type = | ||
720 | htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE); | ||
721 | |||
722 | if (NULL == | ||
723 | GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0, | ||
724 | MAX_TRANSMIT_DELAY, msg_size, | ||
725 | &transmit_mesh_message, | ||
726 | (void *) message_mesh_initiate)) | ||
727 | { | ||
728 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
729 | _("Could not queue MeshSessionInitiateMessage\n")); | ||
730 | GNUNET_MESH_tunnel_destroy (tunnel_reliable); | ||
731 | tunnel_reliable = NULL; | ||
732 | GNUNET_free (message_mesh_initiate); | ||
733 | GNUNET_SERVER_notify_transmit_ready (client, | ||
734 | sizeof (struct | ||
735 | ServerClientErrorMessage), | ||
736 | MAX_TRANSMIT_DELAY, | ||
737 | &transmit_server_error_message, | ||
738 | NULL); | ||
739 | |||
740 | return; | ||
741 | } | ||
742 | |||
743 | connection.status = CALLER; | ||
744 | connection.client = client; | ||
745 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"), | ||
746 | connection.status); | ||
747 | memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity)); | ||
748 | |||
749 | return; | ||
750 | } | 452 | } |
751 | 453 | ||
454 | |||
752 | /** | 455 | /** |
753 | * Function to handle a session accept message from the client | 456 | * Function to handle call request the client |
754 | * | 457 | * |
755 | * @param cls closure, NULL | 458 | * @param cls closure, NULL |
756 | * @param client the client from which the message is | 459 | * @param client the client from which the message is |
757 | * @param message the message from the client | 460 | * @param message the message from the client |
758 | */ | 461 | */ |
759 | static void | 462 | static void |
760 | handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client, | 463 | handle_client_call_message (void *cls, |
761 | const struct GNUNET_MessageHeader *message) | 464 | struct GNUNET_SERVER_Client *client, |
465 | const struct GNUNET_MessageHeader *message) | ||
762 | { | 466 | { |
763 | size_t msg_size; | 467 | const struct ClientCallMessage *msg; |
764 | 468 | struct Line *line; | |
469 | struct GNUNET_MQ_Envelope *e; | ||
470 | struct MeshPhoneRingMessage *ring; | ||
471 | |||
472 | msg = (struct ClientCallMessage *) message; | ||
473 | line = GNUNET_SERVER_client_get_user_context (client, struct Line); | ||
474 | if (NULL != line) | ||
475 | { | ||
476 | GNUNET_break (0); | ||
477 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
478 | return; | ||
479 | } | ||
480 | line = GNUNET_new (struct Line); | ||
481 | line->target = msg->target; | ||
482 | GNUNET_CONTAINER_DLL_insert (lines_head, | ||
483 | lines_tail, | ||
484 | line); | ||
485 | line->remote_line = ntohl (msg->line); | ||
486 | line->status = LS_CALLER_CALLING; | ||
487 | line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh, | ||
488 | line, | ||
489 | &msg->target, | ||
490 | GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL, | ||
491 | GNUNET_NO, | ||
492 | GNUNET_YES); | ||
493 | line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable); | ||
494 | line->local_line = local_line_cnt++; | ||
495 | e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING); | ||
496 | ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); | ||
497 | ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 + | ||
498 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
499 | sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
500 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey)); | ||
501 | GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id, | ||
502 | &ring->caller_id); | ||
503 | ring->remote_line = msg->line; | ||
504 | ring->source_line = line->local_line; | ||
505 | ring->target = msg->target; | ||
506 | ring->source = my_identity; | ||
507 | ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT)); | ||
508 | GNUNET_CRYPTO_ecc_sign (&msg->caller_id, | ||
509 | &ring->purpose, | ||
510 | &ring->signature); | ||
511 | GNUNET_MQ_send (line->reliable_mq, e); | ||
512 | GNUNET_SERVER_client_set_user_context (client, line); | ||
765 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 513 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
766 | |||
767 | if (connection.status != CALLEE) | ||
768 | { | ||
769 | // TODO send illegal command | ||
770 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
771 | _ | ||
772 | ("handle_session_accept_message called when not allowed\n")); | ||
773 | return; | ||
774 | } | ||
775 | |||
776 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"), | ||
777 | GNUNET_i2s_full (&(connection.peer))); | ||
778 | |||
779 | msg_size = sizeof (struct MeshSessionAcceptMessage); | ||
780 | struct MeshSessionAcceptMessage *message_mesh_accept = | ||
781 | (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size); | ||
782 | |||
783 | if (NULL == message_mesh_accept) | ||
784 | { | ||
785 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
786 | _("Could not create MeshSessionAcceptMessage\n")); | ||
787 | return; | ||
788 | } | ||
789 | |||
790 | message_mesh_accept->header.size = htons (msg_size); | ||
791 | message_mesh_accept->header.type = | ||
792 | htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT); | ||
793 | |||
794 | if (NULL == | ||
795 | GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0, | ||
796 | MAX_TRANSMIT_DELAY, msg_size, | ||
797 | &transmit_mesh_message, | ||
798 | (void *) message_mesh_accept)) | ||
799 | { | ||
800 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
801 | _("Could not queue MeshSessionAcceptMessage\n")); | ||
802 | GNUNET_free (message_mesh_accept); | ||
803 | return; | ||
804 | } | ||
805 | |||
806 | connection.status = CONNECTED; | ||
807 | connection.client = client; | ||
808 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"), | ||
809 | connection.status); | ||
810 | |||
811 | return; | ||
812 | } | 514 | } |
813 | 515 | ||
516 | |||
814 | /** | 517 | /** |
815 | * Function to handle a session reject message from the client | 518 | * Transmit audio data via unreliable mesh channel. |
816 | * | 519 | * |
817 | * @param cls closure, NULL | 520 | * @param cls the `struct Line` we are transmitting for |
818 | * @param client the client from which the message is | 521 | * @param size number of bytes available in @a buf |
819 | * @param message the message from the client | 522 | * @param buf where to copy the data |
820 | */ | 523 | * @return number of bytes copied to @buf |
821 | static void | 524 | */ |
822 | handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client, | 525 | static size_t |
823 | const struct GNUNET_MessageHeader *message) | 526 | transmit_line_audio (void *cls, |
527 | size_t size, | ||
528 | void *buf) | ||
824 | { | 529 | { |
825 | struct ClientServerSessionRejectMessage *message_received; | 530 | struct Line *line = cls; |
826 | 531 | struct MeshAudioMessage *mam = buf; | |
827 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 532 | |
828 | 533 | line->unreliable_mth = NULL; | |
829 | if (connection.status != CALLEE) | 534 | if ( (NULL == buf) || |
535 | (size < sizeof (struct MeshAudioMessage) + line->audio_size) ) | ||
830 | { | 536 | { |
831 | // TODO send illegal command | 537 | /* eh, other error handling? */ |
832 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 538 | return 0; |
833 | _ | 539 | } |
834 | ("handle_session_reject_message called when not allowed\n")); | 540 | mam->header.size = htons (sizeof (struct MeshAudioMessage) + line->audio_size); |
835 | return; | 541 | mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO); |
836 | } | 542 | mam->remote_line = htonl (line->remote_line); |
837 | 543 | memcpy (&mam[1], line->audio_data, line->audio_size); | |
838 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"), | 544 | GNUNET_free (line->audio_data); |
839 | GNUNET_i2s_full (&(connection.peer))); | 545 | line->audio_data = NULL; |
840 | message_received = (struct ClientServerSessionRejectMessage *) message; | 546 | return sizeof (struct MeshAudioMessage) + line->audio_size; |
841 | reject_call (tunnel_reliable, ntohs (message_received->reason)); | ||
842 | |||
843 | return; | ||
844 | } | 547 | } |
845 | 548 | ||
549 | |||
846 | /** | 550 | /** |
847 | * Function to handle a session terminate message from the client | 551 | * Function to handle audio data from the client |
848 | * | 552 | * |
849 | * @param cls closure, NULL | 553 | * @param cls closure, NULL |
850 | * @param client the client from which the message is | 554 | * @param client the client from which the message is |
851 | * @param message the message from the client | 555 | * @param message the message from the client |
852 | */ | 556 | */ |
853 | static void | 557 | static void |
854 | handle_session_terminate_message (void *cls, | 558 | handle_client_audio_message (void *cls, |
855 | struct GNUNET_SERVER_Client *client, | 559 | struct GNUNET_SERVER_Client *client, |
856 | const struct GNUNET_MessageHeader *message) | 560 | const struct GNUNET_MessageHeader *message) |
857 | { | 561 | { |
562 | const struct ClientAudioMessage *msg; | ||
563 | struct Line *line; | ||
564 | size_t size; | ||
565 | |||
566 | size = ntohs (message->size) - sizeof (struct ClientAudioMessage); | ||
567 | msg = (struct ClientAudioMessage *) message; | ||
568 | line = GNUNET_SERVER_client_get_user_context (client, struct Line); | ||
569 | if (NULL == line) | ||
570 | { | ||
571 | GNUNET_break (0); | ||
572 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
573 | return; | ||
574 | } | ||
575 | switch (line->status) | ||
576 | { | ||
577 | case LS_CALLEE_LISTEN: | ||
578 | case LS_CALLEE_RINGING: | ||
579 | case LS_CALLER_CALLING: | ||
580 | GNUNET_break (0); | ||
581 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
582 | return; | ||
583 | case LS_CALLEE_CONNECTED: | ||
584 | case LS_CALLER_CONNECTED: | ||
585 | /* common case, handled below */ | ||
586 | break; | ||
587 | case LS_CALLEE_SHUTDOWN: | ||
588 | case LS_CALLER_SHUTDOWN: | ||
589 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
590 | "Mesh audio channel in shutdown; audio data dropped\n"); | ||
591 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
592 | return; | ||
593 | } | ||
594 | if (NULL == line->tunnel_unreliable) | ||
595 | { | ||
596 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
597 | _("Mesh audio channel not ready; audio data dropped\n")); | ||
598 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
599 | return; | ||
600 | } | ||
601 | if (NULL != line->unreliable_mth) | ||
602 | { | ||
603 | /* NOTE: we may want to not do this and instead combine the data */ | ||
604 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
605 | "Dropping previous audio data segment with %u bytes\n", | ||
606 | line->audio_size); | ||
607 | GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth); | ||
608 | GNUNET_free (line->audio_data); | ||
609 | } | ||
610 | line->audio_size = size; | ||
611 | line->audio_data = GNUNET_malloc (line->audio_size); | ||
612 | memcpy (line->audio_data, | ||
613 | &msg[1], | ||
614 | size); | ||
615 | line->unreliable_mth = GNUNET_MESH_notify_transmit_ready (line->tunnel_unreliable, | ||
616 | GNUNET_NO, | ||
617 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
618 | sizeof (struct MeshAudioMessage) | ||
619 | + line->audio_size, | ||
620 | &transmit_line_audio, | ||
621 | line); | ||
858 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 622 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
859 | |||
860 | if (connection.client == NULL || connection.status == CALLEE) | ||
861 | { | ||
862 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
863 | _ | ||
864 | ("handle_session_terminate_message called when not allowed\n")); | ||
865 | return; | ||
866 | } | ||
867 | |||
868 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"), | ||
869 | GNUNET_i2s_full (&(connection.peer))); | ||
870 | terminate_call (); | ||
871 | } | 623 | } |
872 | 624 | ||
873 | /******************************************************************************/ | ||
874 | /*********************** SENDING FUNCTIONS MESH *******************/ | ||
875 | /******************************************************************************/ | ||
876 | 625 | ||
877 | /** | 626 | /** |
878 | * Transmit a mesh message | 627 | * We are done signalling shutdown to the other peer. |
879 | * @param cls closure, NULL | 628 | * Destroy the tunnel. |
880 | * @param size number of bytes available in buf | 629 | * |
881 | * @param buf where the callee should write the message | 630 | * @param cls the `struct GNUNET_MESH_tunnel` to destroy |
882 | * @return number of bytes written to buf | ||
883 | */ | ||
884 | static size_t | ||
885 | transmit_mesh_message (void *cls, size_t size, void *buf) | ||
886 | { | ||
887 | struct VoIPMeshMessageHeader *msg_header = | ||
888 | (struct VoIPMeshMessageHeader *) cls; | ||
889 | |||
890 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n")); | ||
891 | |||
892 | memcpy (buf, cls, size); | ||
893 | // Check if this is correct | ||
894 | |||
895 | |||
896 | if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE == | ||
897 | ntohs (msg_header->header.type)) | ||
898 | || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT == | ||
899 | ntohs (msg_header->header.type))) | ||
900 | { | ||
901 | status_to_listen (); | ||
902 | } | ||
903 | else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE == | ||
904 | ntohs (msg_header->header.type)) | ||
905 | { | ||
906 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n")); | ||
907 | timeout_task = | ||
908 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
909 | (GNUNET_TIME_UNIT_SECONDS, 30), | ||
910 | &check_timeout, NULL); | ||
911 | } | ||
912 | |||
913 | GNUNET_free (cls); | ||
914 | |||
915 | return size; | ||
916 | } | ||
917 | |||
918 | /** | ||
919 | * Transmit a audo message over mesh | ||
920 | * @param cls closure, NULL | ||
921 | * @param size number of bytes available in buf | ||
922 | * @param buf where the callee should write the message | ||
923 | * @return number of bytes written to buf | ||
924 | */ | ||
925 | static size_t | ||
926 | transmit_mesh_audio_message (void *cls, size_t size, void *buf) | ||
927 | { | ||
928 | struct AudioMessage *message = (struct AudioMessage *) cls; | ||
929 | |||
930 | if (size < sizeof (struct AudioMessage) || NULL == buf) | ||
931 | { | ||
932 | GNUNET_break (0); | ||
933 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
934 | "size %u, buf %p, data_sent %u, data_received %u\n", | ||
935 | size, buf, data_sent, data_received); | ||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | memcpy (buf, message, size); | ||
940 | |||
941 | data_sent++; | ||
942 | data_sent_size += size; | ||
943 | |||
944 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent); | ||
945 | |||
946 | audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL); | ||
947 | |||
948 | return size; | ||
949 | } | ||
950 | |||
951 | /** | ||
952 | * Task to schedule a audio transmission. | ||
953 | * | ||
954 | * @param cls Closure. | ||
955 | * @param tc Task Context. | ||
956 | */ | 631 | */ |
957 | static void | 632 | static void |
958 | transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 633 | mq_done_destroy_tunnel (void *cls) |
959 | { | 634 | { |
960 | struct GNUNET_CONTAINER_SList_Iterator iterator; | 635 | struct GNUNET_MESH_Tunnel *tunnel = cls; |
961 | struct AudioMessage *msg; | 636 | |
962 | int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer); | 637 | GNUNET_MESH_tunnel_destroy (tunnel); |
963 | |||
964 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length); | ||
965 | |||
966 | if (NULL == cls) | ||
967 | { | ||
968 | if (0 == ab_length && CONNECTED == connection.status) | ||
969 | { | ||
970 | audio_task = | ||
971 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
972 | (GNUNET_TIME_UNIT_MILLISECONDS, 10), | ||
973 | &transmit_audio_task, NULL); | ||
974 | return; | ||
975 | } | ||
976 | |||
977 | iterator = GNUNET_CONTAINER_slist_begin (audio_buffer); | ||
978 | msg = | ||
979 | (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL); | ||
980 | GNUNET_CONTAINER_slist_erase (&iterator); | ||
981 | GNUNET_CONTAINER_slist_iter_destroy (&iterator); | ||
982 | } | ||
983 | else | ||
984 | { | ||
985 | msg = (struct AudioMessage *) cls; | ||
986 | } | ||
987 | |||
988 | if (NULL == tunnel_unreliable) | ||
989 | { | ||
990 | GNUNET_CONTAINER_slist_clear (audio_buffer); | ||
991 | return; | ||
992 | } | ||
993 | |||
994 | mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO, | ||
995 | MAX_TRANSMIT_DELAY, | ||
996 | sizeof (struct AudioMessage), | ||
997 | &transmit_mesh_audio_message, | ||
998 | (void *) msg); | ||
999 | |||
1000 | if (NULL == mth) | ||
1001 | { | ||
1002 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1003 | "Need to retransmit audio packet\n"); | ||
1004 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n"); | ||
1005 | audio_task = | ||
1006 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
1007 | &transmit_audio_task, (void *) msg); | ||
1008 | } | ||
1009 | } | 638 | } |
1010 | 639 | ||
1011 | /******************************************************************************/ | ||
1012 | /*********************** RECEIVE FUNCTIONS MESH ********************/ | ||
1013 | /******************************************************************************/ | ||
1014 | 640 | ||
1015 | /** | 641 | /** |
1016 | * Function to handle a initiation messaage incoming over mesh | 642 | * Function to handle a ring message incoming over mesh |
643 | * | ||
1017 | * @param cls closure, NULL | 644 | * @param cls closure, NULL |
1018 | * @param tunnel the tunnel over which the message arrived | 645 | * @param tunnel the tunnel over which the message arrived |
1019 | * @param tunnel_ctx the tunnel context, can be NULL | 646 | * @param tunnel_ctx the tunnel context, can be NULL |
1020 | * @param message the incoming message | 647 | * @param message the incoming message |
1021 | * | 648 | * @return #GNUNET_OK |
1022 | * @return GNUNET_OK | 649 | */ |
1023 | */ | 650 | static int |
1024 | int | 651 | handle_mesh_ring_message (void *cls, |
1025 | handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | 652 | struct GNUNET_MESH_Tunnel *tunnel, |
1026 | void **tunnel_ctx, | 653 | void **tunnel_ctx, |
1027 | const struct GNUNET_MessageHeader *message) | 654 | const struct GNUNET_MessageHeader *message) |
1028 | { | 655 | { |
1029 | int reject_reason; | 656 | const struct MeshPhoneRingMessage *msg; |
1030 | //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; | 657 | struct Line *line; |
1031 | const struct GNUNET_PeerIdentity *peer = | 658 | struct GNUNET_MQ_Envelope *e; |
1032 | GNUNET_PEER_resolve2 (tunnel->peer); | 659 | struct MeshPhoneBusyMessage *busy; |
1033 | 660 | struct ClientPhoneRingMessage cring; | |
1034 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 661 | |
1035 | _("Handling MeshSessionInitiateMessage from peer: %s\n"), | 662 | msg = (const struct MeshPhoneRingMessage *) message; |
1036 | GNUNET_i2s_full (peer)); | 663 | if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 + |
664 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
665 | sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
666 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey))) || | ||
667 | (GNUNET_OK != | ||
668 | GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING, | ||
669 | &msg->purpose, | ||
670 | &msg->signature, | ||
671 | &msg->caller_id)) ) | ||
672 | { | ||
673 | GNUNET_break_op (0); | ||
674 | return GNUNET_SYSERR; | ||
675 | } | ||
676 | for (line = lines_head; NULL != line; line = line->next) | ||
677 | if ( (line->local_line == ntohl (msg->remote_line)) && | ||
678 | (LS_CALLEE_LISTEN == line->status) ) | ||
679 | break; | ||
680 | if (NULL == line) | ||
681 | { | ||
682 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
683 | _("No available phone for incoming call on line %u, sending BUSY signal\n"), | ||
684 | ntohl (msg->remote_line)); | ||
685 | e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY); | ||
686 | GNUNET_MQ_notify_sent (e, | ||
687 | &mq_done_destroy_tunnel, | ||
688 | tunnel); | ||
689 | GNUNET_MQ_send (line->reliable_mq, e); | ||
690 | GNUNET_MESH_receive_done (tunnel); /* needed? */ | ||
691 | return GNUNET_OK; | ||
692 | } | ||
693 | line->status = LS_CALLEE_RINGING; | ||
694 | line->remote_line = ntohl (msg->source_line); | ||
695 | line->tunnel_reliable = tunnel; | ||
696 | line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable); | ||
697 | *tunnel_ctx = line; | ||
698 | cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING); | ||
699 | cring.header.size = htons (sizeof (cring)); | ||
700 | cring.reserved = htonl (0); | ||
701 | cring.caller_id = msg->caller_id; | ||
702 | GNUNET_SERVER_notification_context_unicast (nc, | ||
703 | line->client, | ||
704 | &cring.header, | ||
705 | GNUNET_NO); | ||
1037 | GNUNET_MESH_receive_done (tunnel); | 706 | GNUNET_MESH_receive_done (tunnel); |
1038 | |||
1039 | if (LISTEN != connection.status | ||
1040 | || 1 > GNUNET_CONTAINER_slist_count (clients)) | ||
1041 | { | ||
1042 | |||
1043 | if (CONNECTED == connection.status) | ||
1044 | { | ||
1045 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1046 | _ | ||
1047 | ("Rejected call from %s because there is an active call"), | ||
1048 | GNUNET_i2s_full (peer)); | ||
1049 | reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_ACTIVE_CALL); | ||
1050 | |||
1051 | // Notifying client about missed call | ||
1052 | size_t msg_size = | ||
1053 | sizeof (struct ServerClientMissedCallMessage) + | ||
1054 | sizeof (struct MissedCall); | ||
1055 | struct ServerClientMissedCallMessage *message = | ||
1056 | GNUNET_malloc (msg_size); | ||
1057 | |||
1058 | message->header.size = htons (msg_size); | ||
1059 | message->header.type = | ||
1060 | htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL); | ||
1061 | message->number = 1; | ||
1062 | |||
1063 | memcpy (&(message->missed_call->peer), peer, | ||
1064 | sizeof (struct GNUNET_PeerIdentity)); | ||
1065 | message->missed_call->time = GNUNET_TIME_absolute_get (); | ||
1066 | |||
1067 | if (NULL == | ||
1068 | GNUNET_SERVER_notify_transmit_ready (connection.client, | ||
1069 | sizeof (struct | ||
1070 | ServerClientMissedCallMessage), | ||
1071 | MAX_TRANSMIT_DELAY, | ||
1072 | &transmit_server_missed_call_message, | ||
1073 | (void *) message)) | ||
1074 | { | ||
1075 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1076 | _ | ||
1077 | ("Could not queue ServerClientMissedCallMessage\n")); | ||
1078 | GNUNET_free (message); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | if (1 > GNUNET_CONTAINER_slist_count (clients)) | ||
1083 | { | ||
1084 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1085 | _("Got a call from %s while no client connected.\n"), | ||
1086 | GNUNET_i2s_full (peer)); | ||
1087 | reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NO_CLIENT); | ||
1088 | // Store missed calls | ||
1089 | struct MissedCall call; | ||
1090 | memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity)); | ||
1091 | call.time = GNUNET_TIME_absolute_get (); | ||
1092 | GNUNET_CONTAINER_slist_add_end (missed_calls, | ||
1093 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1094 | &call, sizeof (struct MissedCall)); | ||
1095 | |||
1096 | } | ||
1097 | |||
1098 | reject_call (tunnel, reject_reason); | ||
1099 | } | ||
1100 | else | ||
1101 | { | ||
1102 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"), | ||
1103 | GNUNET_i2s_full (peer)); | ||
1104 | tunnel_reliable = tunnel; | ||
1105 | connection.status = CALLEE; | ||
1106 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1107 | _("Changed connection status to %d\n"), connection.status); | ||
1108 | memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity)); | ||
1109 | |||
1110 | struct GNUNET_CONTAINER_SList_Iterator iterator = | ||
1111 | GNUNET_CONTAINER_slist_begin (clients); | ||
1112 | do | ||
1113 | { | ||
1114 | struct VoipClient *conversation_client = | ||
1115 | (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator, | ||
1116 | NULL); | ||
1117 | struct GNUNET_SERVER_Client *client = conversation_client->client; | ||
1118 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"), | ||
1119 | client); | ||
1120 | |||
1121 | if (NULL == | ||
1122 | GNUNET_SERVER_notify_transmit_ready (client, | ||
1123 | sizeof (struct | ||
1124 | ServerClientSessionInitiateMessage), | ||
1125 | MAX_TRANSMIT_DELAY, | ||
1126 | &transmit_server_initiate_message, | ||
1127 | (void *) peer)) | ||
1128 | { | ||
1129 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1130 | _ | ||
1131 | ("Could not queue ServerClientSessionInitiateMessage\n")); | ||
1132 | } | ||
1133 | |||
1134 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n")); | ||
1135 | } | ||
1136 | while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator)); | ||
1137 | |||
1138 | GNUNET_CONTAINER_slist_iter_destroy (&iterator); | ||
1139 | |||
1140 | } | ||
1141 | |||
1142 | return GNUNET_OK; | 707 | return GNUNET_OK; |
1143 | } | 708 | } |
1144 | 709 | ||
710 | |||
1145 | /** | 711 | /** |
1146 | * Function to handle an accept messaage incoming over mesh | 712 | * Function to handle a hangup message incoming over mesh |
713 | * | ||
1147 | * @param cls closure, NULL | 714 | * @param cls closure, NULL |
1148 | * @param tunnel the tunnel over which the message arrived | 715 | * @param tunnel the tunnel over which the message arrived |
1149 | * @param tunnel_ctx the tunnel context, can be NULL | 716 | * @param tunnel_ctx the tunnel context, can be NULL |
1150 | * @param message the incoming message | 717 | * @param message the incoming message |
1151 | * | 718 | * @return #GNUNET_OK |
1152 | * @return GNUNET_OK | 719 | */ |
1153 | */ | 720 | static int |
1154 | int | 721 | handle_mesh_hangup_message (void *cls, |
1155 | handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | 722 | struct GNUNET_MESH_Tunnel *tunnel, |
1156 | void **tunnel_ctx, | 723 | void **tunnel_ctx, |
1157 | const struct GNUNET_MessageHeader *message) | 724 | const struct GNUNET_MessageHeader *message) |
1158 | { | 725 | { |
1159 | static uint32_t port = 50003; | 726 | struct Line *line = *tunnel_ctx; |
1160 | //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; | 727 | const struct MeshPhoneHangupMessage *msg; |
1161 | const struct GNUNET_PeerIdentity *peer = | 728 | const char *reason; |
1162 | GNUNET_PEER_resolve2 (tunnel->peer); | 729 | size_t len = ntohs (message->size) - sizeof (struct MeshPhoneHangupMessage); |
1163 | 730 | char buf[len + sizeof (struct ClientPhoneHangupMessage)]; | |
1164 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 731 | struct ClientPhoneHangupMessage *hup; |
1165 | _ | 732 | |
1166 | ("Handling MeshSessionAccpetMessage from peer: %s (connection.peer: %s)\n"), | 733 | msg = (const struct MeshPhoneHangupMessage *) message; |
1167 | GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer))); | 734 | len = ntohs (msg->header.size) - sizeof (struct MeshPhoneHangupMessage); |
735 | reason = (const char *) &msg[1]; | ||
736 | if ( (0 == len) || | ||
737 | ('\0' != reason[len - 1]) ) | ||
738 | { | ||
739 | reason = NULL; | ||
740 | len = 0; | ||
741 | } | ||
742 | if (NULL == line) | ||
743 | { | ||
744 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
745 | "HANGUP message received for non-existing line, dropping tunnel.\n"); | ||
746 | return GNUNET_SYSERR; | ||
747 | } | ||
748 | *tunnel_ctx = NULL; | ||
749 | switch (line->status) | ||
750 | { | ||
751 | case LS_CALLEE_LISTEN: | ||
752 | GNUNET_break (0); | ||
753 | return GNUNET_SYSERR; | ||
754 | case LS_CALLEE_RINGING: | ||
755 | line->status = LS_CALLEE_LISTEN; | ||
756 | destroy_line_mesh_tunnels (line); | ||
757 | break; | ||
758 | case LS_CALLEE_CONNECTED: | ||
759 | line->status = LS_CALLEE_LISTEN; | ||
760 | destroy_line_mesh_tunnels (line); | ||
761 | break; | ||
762 | case LS_CALLEE_SHUTDOWN: | ||
763 | line->status = LS_CALLEE_LISTEN; | ||
764 | destroy_line_mesh_tunnels (line); | ||
765 | return GNUNET_OK; | ||
766 | case LS_CALLER_CALLING: | ||
767 | line->status = LS_CALLER_SHUTDOWN; | ||
768 | mq_done_finish_caller_shutdown (line); | ||
769 | break; | ||
770 | case LS_CALLER_CONNECTED: | ||
771 | line->status = LS_CALLER_SHUTDOWN; | ||
772 | mq_done_finish_caller_shutdown (line); | ||
773 | break; | ||
774 | case LS_CALLER_SHUTDOWN: | ||
775 | mq_done_finish_caller_shutdown (line); | ||
776 | return GNUNET_OK; | ||
777 | } | ||
778 | hup = (struct ClientPhoneHangupMessage *) buf; | ||
779 | hup->header.size = sizeof (buf); | ||
780 | hup->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); | ||
781 | memcpy (&hup[1], reason, len); | ||
782 | GNUNET_SERVER_notification_context_unicast (nc, | ||
783 | line->client, | ||
784 | &hup->header, | ||
785 | GNUNET_NO); | ||
1168 | GNUNET_MESH_receive_done (tunnel); | 786 | GNUNET_MESH_receive_done (tunnel); |
1169 | |||
1170 | if (0 == | ||
1171 | memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity)) | ||
1172 | && connection.status == CALLER) | ||
1173 | { | ||
1174 | tunnel_unreliable = | ||
1175 | GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, | ||
1176 | GNUNET_NO); | ||
1177 | if (NULL == tunnel_unreliable) | ||
1178 | { | ||
1179 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1180 | _("Could not create unreliable tunnel\n")); | ||
1181 | |||
1182 | status_to_listen (); | ||
1183 | |||
1184 | GNUNET_SERVER_notify_transmit_ready (connection.client, | ||
1185 | sizeof (struct | ||
1186 | ServerClientSessionRejectMessage), | ||
1187 | MAX_TRANSMIT_DELAY, | ||
1188 | &transmit_server_reject_message, | ||
1189 | NULL); | ||
1190 | return GNUNET_SYSERR; | ||
1191 | } | ||
1192 | |||
1193 | if (timeout_task != GNUNET_SCHEDULER_NO_TASK) | ||
1194 | { | ||
1195 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
1196 | timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1197 | } | ||
1198 | |||
1199 | connection.status = CONNECTED; | ||
1200 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1201 | _("Changed connection status to %d\n"), connection.status); | ||
1202 | |||
1203 | if (NULL == | ||
1204 | GNUNET_SERVER_notify_transmit_ready (connection.client, | ||
1205 | sizeof (struct | ||
1206 | ServerClientSessionAcceptMessage), | ||
1207 | MAX_TRANSMIT_DELAY, | ||
1208 | &transmit_server_accept_message, | ||
1209 | (void *) message)) | ||
1210 | { | ||
1211 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1212 | _ | ||
1213 | ("Could not queue ServerClientSessionAcceptMessage\n")); | ||
1214 | return GNUNET_SYSERR; | ||
1215 | } | ||
1216 | |||
1217 | start_time = GNUNET_TIME_absolute_get (); | ||
1218 | start_helpers (); | ||
1219 | audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL); | ||
1220 | } | ||
1221 | |||
1222 | return GNUNET_OK; | 787 | return GNUNET_OK; |
1223 | } | 788 | } |
1224 | 789 | ||
790 | |||
1225 | /** | 791 | /** |
1226 | * Function to handle a reject messaage incoming over mesh | 792 | * Function to handle a pickup message incoming over mesh |
793 | * | ||
1227 | * @param cls closure, NULL | 794 | * @param cls closure, NULL |
1228 | * @param tunnel the tunnel over which the message arrived | 795 | * @param tunnel the tunnel over which the message arrived |
1229 | * @param tunnel_ctx the tunnel context, can be NULL | 796 | * @param tunnel_ctx the tunnel context, can be NULL |
1230 | * @param message the incoming message | 797 | * @param message the incoming message |
1231 | * | 798 | * @return #GNUNET_OK |
1232 | * @return GNUNET_OK | 799 | */ |
1233 | */ | 800 | static int |
1234 | int | 801 | handle_mesh_pickup_message (void *cls, |
1235 | handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | 802 | struct GNUNET_MESH_Tunnel *tunnel, |
1236 | void **tunnel_ctx, | 803 | void **tunnel_ctx, |
1237 | const struct GNUNET_MessageHeader *message) | 804 | const struct GNUNET_MessageHeader *message) |
1238 | { | 805 | { |
1239 | //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; | 806 | const struct MeshPhonePickupMessage *msg; |
1240 | const struct GNUNET_PeerIdentity *peer = | 807 | struct Line *line = *tunnel_ctx; |
1241 | GNUNET_PEER_resolve2 (tunnel->peer); | 808 | const char *metadata; |
1242 | 809 | size_t len = ntohs (message->size) - sizeof (struct MeshPhonePickupMessage); | |
1243 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 810 | char buf[len + sizeof (struct ClientPhonePickupMessage)]; |
1244 | _ | 811 | struct ClientPhonePickupMessage *pick; |
1245 | ("Handling MeshSessionRejectMessage from peer: %s (connection.peer: %s)\n"), | 812 | |
1246 | GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer))); | 813 | msg = (const struct MeshPhonePickupMessage *) message; |
814 | len = ntohs (msg->header.size) - sizeof (struct MeshPhonePickupMessage); | ||
815 | metadata = (const char *) &msg[1]; | ||
816 | if ( (0 == len) || | ||
817 | ('\0' != metadata[len - 1]) ) | ||
818 | { | ||
819 | metadata = NULL; | ||
820 | len = 0; | ||
821 | } | ||
822 | if (NULL == line) | ||
823 | { | ||
824 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
825 | "PICKUP message received for non-existing line, dropping tunnel.\n"); | ||
826 | return GNUNET_SYSERR; | ||
827 | } | ||
1247 | GNUNET_MESH_receive_done (tunnel); | 828 | GNUNET_MESH_receive_done (tunnel); |
1248 | 829 | switch (line->status) | |
1249 | if (0 == | 830 | { |
1250 | memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity)) | 831 | case LS_CALLEE_LISTEN: |
1251 | && connection.status == CALLER) | 832 | GNUNET_break (0); |
1252 | { | 833 | return GNUNET_SYSERR; |
1253 | if (NULL == | 834 | case LS_CALLEE_RINGING: |
1254 | GNUNET_SERVER_notify_transmit_ready (connection.client, | 835 | case LS_CALLEE_CONNECTED: |
1255 | sizeof (struct | 836 | GNUNET_break_op (0); |
1256 | ServerClientSessionRejectMessage), | 837 | destroy_line_mesh_tunnels (line); |
1257 | MAX_TRANSMIT_DELAY, | 838 | line->status = LS_CALLEE_LISTEN; |
1258 | &transmit_server_reject_message, | 839 | return GNUNET_SYSERR; |
1259 | (void *) message)) | 840 | case LS_CALLEE_SHUTDOWN: |
1260 | { | 841 | GNUNET_break_op (0); |
1261 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 842 | line->status = LS_CALLEE_LISTEN; |
1262 | _ | 843 | destroy_line_mesh_tunnels (line); |
1263 | ("Could not queue ServerClientSessionRejectMessage\n")); | 844 | break; |
1264 | } | 845 | case LS_CALLER_CALLING: |
1265 | 846 | line->status = LS_CALLER_CONNECTED; | |
1266 | status_to_listen (); | 847 | break; |
1267 | 848 | case LS_CALLER_CONNECTED: | |
1268 | if (NULL != tunnel_reliable) | 849 | GNUNET_break_op (0); |
1269 | { | 850 | return GNUNET_OK; |
1270 | GNUNET_MESH_tunnel_destroy (tunnel_reliable); | 851 | case LS_CALLER_SHUTDOWN: |
1271 | tunnel_reliable = NULL; | 852 | GNUNET_break_op (0); |
1272 | } | 853 | mq_done_finish_caller_shutdown (line); |
1273 | } | 854 | return GNUNET_SYSERR; |
1274 | 855 | } | |
856 | pick = (struct ClientPhonePickupMessage *) buf; | ||
857 | pick->header.size = sizeof (buf); | ||
858 | pick->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP); | ||
859 | memcpy (&pick[1], metadata, len); | ||
860 | GNUNET_SERVER_notification_context_unicast (nc, | ||
861 | line->client, | ||
862 | &pick->header, | ||
863 | GNUNET_NO); | ||
864 | line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh, | ||
865 | line, | ||
866 | &line->target, | ||
867 | GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO, | ||
868 | GNUNET_YES, | ||
869 | GNUNET_NO); | ||
1275 | return GNUNET_OK; | 870 | return GNUNET_OK; |
1276 | } | 871 | } |
1277 | 872 | ||
873 | |||
1278 | /** | 874 | /** |
1279 | * Function to handle a terminate messaage incoming over mesh | 875 | * Function to handle a busy message incoming over mesh |
876 | * | ||
1280 | * @param cls closure, NULL | 877 | * @param cls closure, NULL |
1281 | * @param tunnel the tunnel over which the message arrived | 878 | * @param tunnel the tunnel over which the message arrived |
1282 | * @param tunnel_ctx the tunnel context, can be NULL | 879 | * @param tunnel_ctx the tunnel context, can be NULL |
1283 | * @param message the incoming message | 880 | * @param message the incoming message |
1284 | * | 881 | * @return #GNUNET_OK |
1285 | * @return GNUNET_OK | 882 | */ |
1286 | */ | 883 | static int |
1287 | int | 884 | handle_mesh_busy_message (void *cls, |
1288 | handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | 885 | struct GNUNET_MESH_Tunnel *tunnel, |
1289 | void **tunnel_ctx, | 886 | void **tunnel_ctx, |
1290 | const struct GNUNET_MessageHeader *message) | 887 | const struct GNUNET_MessageHeader *message) |
1291 | { | 888 | { |
1292 | //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer; | 889 | struct Line *line = *tunnel_ctx; |
1293 | const struct GNUNET_PeerIdentity *peer = | 890 | struct ClientPhoneBusyMessage busy; |
1294 | GNUNET_PEER_resolve2 (tunnel->peer); | 891 | |
1295 | 892 | if (NULL == line) | |
1296 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 893 | { |
1297 | _ | 894 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1298 | ("Handling MeshSessionTerminateMessage from peer: %s (connection.peer: %s)\n"), | 895 | "HANGUP message received for non-existing line, dropping tunnel.\n"); |
1299 | GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer))); | 896 | return GNUNET_SYSERR; |
897 | } | ||
898 | busy.header.size = sizeof (busy); | ||
899 | busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY); | ||
900 | GNUNET_SERVER_notification_context_unicast (nc, | ||
901 | line->client, | ||
902 | &busy.header, | ||
903 | GNUNET_NO); | ||
1300 | GNUNET_MESH_receive_done (tunnel); | 904 | GNUNET_MESH_receive_done (tunnel); |
1301 | 905 | *tunnel_ctx = NULL; | |
1302 | if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity)) | 906 | switch (line->status) |
1303 | && (connection.status == CONNECTED || connection.status == CALLEE)) | 907 | { |
1304 | { | 908 | case LS_CALLEE_LISTEN: |
1305 | status_to_listen (); | 909 | GNUNET_break (0); |
1306 | 910 | return GNUNET_SYSERR; | |
1307 | if (NULL != tunnel_unreliable) | 911 | case LS_CALLEE_RINGING: |
1308 | { | 912 | GNUNET_break_op (0); |
1309 | GNUNET_MESH_tunnel_destroy (tunnel_unreliable); | 913 | break; |
1310 | tunnel_unreliable = NULL; | 914 | case LS_CALLEE_CONNECTED: |
1311 | } | 915 | GNUNET_break_op (0); |
1312 | 916 | break; | |
1313 | if (NULL != tunnel_reliable) | 917 | case LS_CALLEE_SHUTDOWN: |
1314 | { | 918 | GNUNET_break_op (0); |
1315 | GNUNET_MESH_tunnel_destroy (tunnel_reliable); | 919 | break; |
1316 | tunnel_reliable = NULL; | 920 | case LS_CALLER_CALLING: |
1317 | } | 921 | line->status = LS_CALLER_SHUTDOWN; |
1318 | } | 922 | mq_done_finish_caller_shutdown (line); |
1319 | 923 | break; | |
924 | case LS_CALLER_CONNECTED: | ||
925 | line->status = LS_CALLER_SHUTDOWN; | ||
926 | mq_done_finish_caller_shutdown (line); | ||
927 | break; | ||
928 | case LS_CALLER_SHUTDOWN: | ||
929 | mq_done_finish_caller_shutdown (line); | ||
930 | break; | ||
931 | } | ||
1320 | return GNUNET_OK; | 932 | return GNUNET_OK; |
1321 | } | 933 | } |
1322 | 934 | ||
935 | |||
1323 | /** | 936 | /** |
1324 | * Function to handle a audio messaage incoming over mesh | 937 | * Function to handle an audio message incoming over mesh |
938 | * | ||
1325 | * @param cls closure, NULL | 939 | * @param cls closure, NULL |
1326 | * @param tunnel the tunnel over which the message arrived | 940 | * @param tunnel the tunnel over which the message arrived |
1327 | * @param tunnel_ctx the tunnel context, can be NULL | 941 | * @param tunnel_ctx the tunnel context, can be NULL |
1328 | * @param message the incoming message | 942 | * @param message the incoming message |
1329 | * | 943 | * @return #GNUNET_OK |
1330 | * @return GNUNET_OK | 944 | */ |
1331 | */ | ||
1332 | int | ||
1333 | handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | ||
1334 | void **tunnel_ctx, | ||
1335 | const struct GNUNET_MessageHeader *message) | ||
1336 | { | ||
1337 | const struct AudioMessage *audio; | ||
1338 | audio = (const struct AudioMessage *) message; | ||
1339 | |||
1340 | GNUNET_MESH_receive_done (tunnel); | ||
1341 | if (CONNECTED != connection.status) | ||
1342 | return GNUNET_OK; | ||
1343 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1344 | "[RECV] %dbytes\n", | ||
1345 | ntohs (audio->header.size)); | ||
1346 | if (NULL == playback_helper) | ||
1347 | return GNUNET_OK; | ||
1348 | (void) GNUNET_HELPER_send (playback_helper, | ||
1349 | message, GNUNET_YES, NULL, NULL); | ||
1350 | return GNUNET_OK; | ||
1351 | } | ||
1352 | |||
1353 | /******************************************************************************/ | ||
1354 | /*********************** HELPER *******************/ | ||
1355 | /******************************************************************************/ | ||
1356 | |||
1357 | /** | ||
1358 | * Function to process the audio from the record helper | ||
1359 | * @param cls closure, NULL | ||
1360 | * @param client NULL | ||
1361 | * @param msg the message from the helper | ||
1362 | * | ||
1363 | * @return GNUNET_OK | ||
1364 | */ | ||
1365 | static int | 945 | static int |
1366 | process_record_messages (void *cls GNUNET_UNUSED, void *client, | 946 | handle_mesh_audio_message (void *cls, |
1367 | const struct GNUNET_MessageHeader *msg) | 947 | struct GNUNET_MESH_Tunnel *tunnel, |
948 | void **tunnel_ctx, | ||
949 | const struct GNUNET_MessageHeader *message) | ||
1368 | { | 950 | { |
1369 | const struct AudioMessage *message = (const struct AudioMessage *) msg; | 951 | const struct MeshAudioMessage *msg; |
1370 | 952 | struct Line *line = *tunnel_ctx; | |
1371 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 953 | struct GNUNET_PeerIdentity sender; |
1372 | " [REC] %dbyte\n", | 954 | size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage); |
1373 | ntohs (message->header.size)); | 955 | char buf[msize + sizeof (struct ClientAudioMessage)]; |
1374 | GNUNET_CONTAINER_slist_add_end (audio_buffer, | 956 | struct ClientAudioMessage *cam; |
1375 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | 957 | |
1376 | message, ntohs (message->header.size)); | 958 | msg = (const struct MeshAudioMessage *) message; |
1377 | 959 | if (NULL == line) | |
1378 | return GNUNET_OK; | 960 | { |
1379 | } | 961 | sender = *GNUNET_MESH_tunnel_get_info (tunnel, |
1380 | 962 | GNUNET_MESH_OPTION_PEER)->peer; | |
1381 | /** | 963 | for (line = lines_head; NULL != line; line = line->next) |
1382 | * Function to to start the playback helper | 964 | if ( (line->local_line == ntohl (msg->remote_line)) && |
1383 | * | 965 | (LS_CALLEE_CONNECTED == line->status) && |
1384 | * @return 0 ok, 1 on error | 966 | (0 == memcmp (&line->target, |
1385 | */ | 967 | &sender, |
1386 | int | 968 | sizeof (struct GNUNET_PeerIdentity))) && |
1387 | start_playback_helper (void) | 969 | (NULL == line->tunnel_unreliable) ) |
1388 | { | 970 | break; |
1389 | static char *playback_helper_argv[1]; | 971 | if (NULL == line) |
1390 | int success = 1; | ||
1391 | |||
1392 | playback_helper_argv[0] = "gnunet-helper-audio-playback"; | ||
1393 | playback_helper = GNUNET_HELPER_start (GNUNET_NO, | ||
1394 | "gnunet-helper-audio-playback", | ||
1395 | playback_helper_argv, | ||
1396 | NULL, NULL, NULL); | ||
1397 | |||
1398 | if (NULL == playback_helper) | ||
1399 | { | ||
1400 | success = 0; | ||
1401 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1402 | _("Could not start playback audio helper.\n")); | ||
1403 | } | ||
1404 | |||
1405 | return success; | ||
1406 | } | ||
1407 | |||
1408 | /** | ||
1409 | * Function to to start the record helper | ||
1410 | * | ||
1411 | * @return 0 ok, 1 on error | ||
1412 | */ | ||
1413 | int | ||
1414 | start_record_helper (void) | ||
1415 | { | ||
1416 | static char *record_helper_argv[1]; | ||
1417 | int success = 1; | ||
1418 | |||
1419 | record_helper_argv[0] = "gnunet-helper-audio-record"; | ||
1420 | record_helper = GNUNET_HELPER_start (GNUNET_NO, | ||
1421 | "gnunet-helper-audio-record", | ||
1422 | record_helper_argv, | ||
1423 | &process_record_messages, NULL, NULL); | ||
1424 | |||
1425 | if (NULL == record_helper) | ||
1426 | { | ||
1427 | success = 0; | ||
1428 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1429 | _("Could not start record audio helper\n")); | ||
1430 | } | ||
1431 | |||
1432 | return success; | ||
1433 | } | ||
1434 | |||
1435 | |||
1436 | /** | ||
1437 | * Function to to start both helpers | ||
1438 | * | ||
1439 | * @return 0 ok, 1 on error | ||
1440 | */ | ||
1441 | int | ||
1442 | start_helpers (void) | ||
1443 | { | ||
1444 | |||
1445 | if (0 == start_playback_helper () || 0 == start_record_helper ()) | ||
1446 | { | ||
1447 | stop_helpers (); | ||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n")); | ||
1452 | |||
1453 | return 1; | ||
1454 | } | ||
1455 | |||
1456 | /** | ||
1457 | * Function to to stop the playback helper | ||
1458 | */ | ||
1459 | void | ||
1460 | stop_playback_helper (void) | ||
1461 | { | ||
1462 | if (NULL != playback_helper) | ||
1463 | { | ||
1464 | GNUNET_HELPER_stop (playback_helper, GNUNET_NO); | ||
1465 | playback_helper = NULL; | ||
1466 | |||
1467 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n")); | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | /** | ||
1472 | * Function to to stop the record helper | ||
1473 | */ | ||
1474 | void | ||
1475 | stop_record_helper (void) | ||
1476 | { | ||
1477 | if (NULL != record_helper) | ||
1478 | { | 972 | { |
1479 | GNUNET_HELPER_stop (record_helper, GNUNET_NO); | 973 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1480 | record_helper = NULL; | 974 | "Received AUDIO data for non-existing line %u, dropping.\n", |
1481 | 975 | ntohl (msg->remote_line)); | |
1482 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n")); | 976 | return GNUNET_SYSERR; |
1483 | } | 977 | } |
978 | line->tunnel_unreliable = tunnel; | ||
979 | *tunnel_ctx = line; | ||
980 | } | ||
981 | cam = (struct ClientAudioMessage *) buf; | ||
982 | cam->header.size = htons (sizeof (buf)); | ||
983 | cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); | ||
984 | memcpy (&cam[1], &msg[1], msize); | ||
985 | GNUNET_SERVER_notification_context_unicast (nc, | ||
986 | line->client, | ||
987 | &cam->header, | ||
988 | GNUNET_YES); | ||
989 | GNUNET_MESH_receive_done (tunnel); | ||
990 | return GNUNET_OK; | ||
1484 | } | 991 | } |
1485 | 992 | ||
1486 | /** | ||
1487 | * Function to stop both audio helpers | ||
1488 | */ | ||
1489 | void | ||
1490 | stop_helpers (void) | ||
1491 | { | ||
1492 | stop_playback_helper (); | ||
1493 | stop_record_helper (); | ||
1494 | } | ||
1495 | |||
1496 | /******************************************************************************/ | ||
1497 | /*********************** TUNNEL HANDLING *******************/ | ||
1498 | /******************************************************************************/ | ||
1499 | 993 | ||
1500 | /** | 994 | /** |
1501 | * Method called whenever another peer has added us to a tunnel | 995 | * Method called whenever another peer has added us to a tunnel |
@@ -1508,21 +1002,14 @@ stop_helpers (void) | |||
1508 | * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) | 1002 | * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) |
1509 | */ | 1003 | */ |
1510 | static void * | 1004 | static void * |
1511 | inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | 1005 | inbound_tunnel (void *cls, |
1512 | const struct GNUNET_PeerIdentity *initiator, uint32_t port) | 1006 | struct GNUNET_MESH_Tunnel *tunnel, |
1007 | const struct GNUNET_PeerIdentity *initiator, | ||
1008 | uint32_t port) | ||
1513 | { | 1009 | { |
1514 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1010 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1515 | _("Received incoming tunnel on port %d\n"), port); | 1011 | _("Received incoming tunnel on port %d\n"), |
1516 | if (50003 == port) | 1012 | port); |
1517 | { | ||
1518 | tunnel_unreliable = tunnel; | ||
1519 | |||
1520 | start_time = GNUNET_TIME_absolute_get (); | ||
1521 | |||
1522 | start_helpers (); | ||
1523 | audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL); | ||
1524 | } | ||
1525 | |||
1526 | return NULL; | 1013 | return NULL; |
1527 | } | 1014 | } |
1528 | 1015 | ||
@@ -1531,115 +1018,68 @@ inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | |||
1531 | * Function called whenever an inbound tunnel is destroyed. Should clean up | 1018 | * Function called whenever an inbound tunnel is destroyed. Should clean up |
1532 | * any associated state. | 1019 | * any associated state. |
1533 | * | 1020 | * |
1534 | * @param cls closure (set from GNUNET_MESH_connect) | 1021 | * @param cls closure (set from #GNUNET_MESH_connect) |
1535 | * @param tunnel connection to the other end (henceforth invalid) | 1022 | * @param tunnel connection to the other end (henceforth invalid) |
1536 | * @param tunnel_ctx place where local state associated | 1023 | * @param tunnel_ctx place where local state associated |
1537 | * with the tunnel is stored | 1024 | * with the tunnel is stored |
1538 | */ | 1025 | */ |
1539 | static void | 1026 | static void |
1540 | inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, | 1027 | inbound_end (void *cls, |
1028 | const struct GNUNET_MESH_Tunnel *tunnel, | ||
1541 | void *tunnel_ctx) | 1029 | void *tunnel_ctx) |
1542 | { | 1030 | { |
1543 | if (tunnel == tunnel_unreliable) | 1031 | struct Line *line = tunnel_ctx; |
1544 | { | 1032 | struct ClientPhoneHangupMessage hup; |
1545 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n"); | 1033 | |
1546 | 1034 | if (NULL == line) | |
1547 | stop_helpers (); | 1035 | return; |
1548 | tunnel_unreliable = NULL; | 1036 | if (line->tunnel_unreliable == tunnel) |
1549 | } | 1037 | { |
1550 | 1038 | line->tunnel_unreliable = NULL; | |
1551 | if (tunnel == tunnel_reliable) | 1039 | return; |
1552 | { | 1040 | } |
1553 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n"); | 1041 | hup.header.size = sizeof (hup); |
1554 | 1042 | hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); | |
1555 | if (LISTEN != connection.status && NULL != connection.client) | 1043 | switch (line->status) |
1556 | { | 1044 | { |
1557 | if (NULL == | 1045 | case LS_CALLEE_LISTEN: |
1558 | GNUNET_SERVER_notify_transmit_ready (connection.client, | 1046 | GNUNET_break (0); |
1559 | sizeof (struct | 1047 | return; |
1560 | ServerClientSessionTerminateMessage), | 1048 | case LS_CALLEE_RINGING: |
1561 | MAX_TRANSMIT_DELAY, | 1049 | case LS_CALLEE_CONNECTED: |
1562 | &transmit_server_terminate_message, | 1050 | GNUNET_SERVER_notification_context_unicast (nc, |
1563 | NULL)) | 1051 | line->client, |
1564 | { | 1052 | &hup.header, |
1565 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1053 | GNUNET_NO); |
1566 | _ | 1054 | line->status = LS_CALLEE_LISTEN; |
1567 | ("Could not queue ServerClientSessionTerminateMessage\n")); | 1055 | break; |
1568 | } | 1056 | case LS_CALLEE_SHUTDOWN: |
1569 | } | 1057 | line->status = LS_CALLEE_LISTEN; |
1570 | 1058 | destroy_line_mesh_tunnels (line); | |
1571 | status_to_listen (); | 1059 | break; |
1572 | } | 1060 | case LS_CALLER_CALLING: |
1061 | case LS_CALLER_CONNECTED: | ||
1062 | GNUNET_SERVER_notification_context_unicast (nc, | ||
1063 | line->client, | ||
1064 | &hup.header, | ||
1065 | GNUNET_NO); | ||
1066 | destroy_line_mesh_tunnels (line); | ||
1067 | GNUNET_CONTAINER_DLL_remove (lines_head, | ||
1068 | lines_tail, | ||
1069 | line); | ||
1070 | GNUNET_free_non_null (line->audio_data); | ||
1071 | GNUNET_free (line); | ||
1072 | break; | ||
1073 | case LS_CALLER_SHUTDOWN: | ||
1074 | destroy_line_mesh_tunnels (line); | ||
1075 | GNUNET_CONTAINER_DLL_remove (lines_head, | ||
1076 | lines_tail, | ||
1077 | line); | ||
1078 | GNUNET_free (line); | ||
1079 | break; | ||
1080 | } | ||
1573 | } | 1081 | } |
1574 | 1082 | ||
1575 | /******************************************************************************/ | ||
1576 | /*********************** CLIENT HANDLING *******************/ | ||
1577 | /******************************************************************************/ | ||
1578 | |||
1579 | /** | ||
1580 | * A client connected. | ||
1581 | * | ||
1582 | * @param cls closure, NULL | ||
1583 | * @param client identification of the client | ||
1584 | */ | ||
1585 | |||
1586 | static void | ||
1587 | handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl) | ||
1588 | { | ||
1589 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n"); | ||
1590 | struct ServerClientMissedCallMessage *message; | ||
1591 | size_t msg_size; | ||
1592 | struct VoipClient c; | ||
1593 | c.client = cl; | ||
1594 | |||
1595 | GNUNET_CONTAINER_slist_add_end (clients, | ||
1596 | GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, | ||
1597 | &c, sizeof (struct VoipClient)); | ||
1598 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl); | ||
1599 | |||
1600 | if (0 < GNUNET_CONTAINER_slist_count (missed_calls)) | ||
1601 | { | ||
1602 | int i = 0; | ||
1603 | msg_size = | ||
1604 | sizeof (struct ServerClientMissedCallMessage) + | ||
1605 | GNUNET_CONTAINER_slist_count (missed_calls) * | ||
1606 | sizeof (struct MissedCall); | ||
1607 | message = | ||
1608 | (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size); | ||
1609 | |||
1610 | message->header.size = htons (msg_size); | ||
1611 | message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL); | ||
1612 | message->number = GNUNET_CONTAINER_slist_count (missed_calls); | ||
1613 | |||
1614 | struct GNUNET_CONTAINER_SList_Iterator iterator = | ||
1615 | GNUNET_CONTAINER_slist_begin (missed_calls); | ||
1616 | do | ||
1617 | { | ||
1618 | memcpy (&(message->missed_call[i]), | ||
1619 | GNUNET_CONTAINER_slist_get (&iterator, NULL), | ||
1620 | sizeof (struct MissedCall)); | ||
1621 | i++; | ||
1622 | } | ||
1623 | while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator)); | ||
1624 | |||
1625 | GNUNET_CONTAINER_slist_iter_destroy (&iterator); | ||
1626 | GNUNET_CONTAINER_slist_clear (missed_calls); | ||
1627 | |||
1628 | |||
1629 | if (NULL == | ||
1630 | GNUNET_SERVER_notify_transmit_ready (cl, msg_size, | ||
1631 | MAX_TRANSMIT_DELAY, | ||
1632 | &transmit_server_missed_call_message, | ||
1633 | (void *) message)) | ||
1634 | { | ||
1635 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1636 | _("Could not queue ServerClientMissedCallMessage\n")); | ||
1637 | GNUNET_free (message); | ||
1638 | } | ||
1639 | } | ||
1640 | |||
1641 | return; | ||
1642 | } | ||
1643 | 1083 | ||
1644 | /** | 1084 | /** |
1645 | * A client disconnected. Remove all of its data structure entries. | 1085 | * A client disconnected. Remove all of its data structure entries. |
@@ -1648,42 +1088,21 @@ handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl) | |||
1648 | * @param client identification of the client | 1088 | * @param client identification of the client |
1649 | */ | 1089 | */ |
1650 | static void | 1090 | static void |
1651 | handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl) | 1091 | handle_client_disconnect (void *cls, |
1092 | struct GNUNET_SERVER_Client *client) | ||
1652 | { | 1093 | { |
1653 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n"); | 1094 | struct Line *line; |
1654 | 1095 | ||
1655 | if (connection.client == cl) | 1096 | line = GNUNET_SERVER_client_get_user_context (client, struct Line); |
1656 | { | 1097 | if (NULL == line) |
1657 | if (CONNECTED == connection.status) | 1098 | return; |
1658 | { | 1099 | GNUNET_CONTAINER_DLL_remove (lines_head, |
1659 | terminate_call (); | 1100 | lines_tail, |
1660 | } | 1101 | line); |
1661 | else | 1102 | GNUNET_free (line); |
1662 | { | 1103 | GNUNET_SERVER_client_set_user_context (client, NULL); |
1663 | status_to_listen (); | ||
1664 | } | ||
1665 | } | ||
1666 | |||
1667 | struct GNUNET_CONTAINER_SList_Iterator iterator = | ||
1668 | GNUNET_CONTAINER_slist_begin (clients); | ||
1669 | do | ||
1670 | { | ||
1671 | if (((struct VoipClient *) | ||
1672 | GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl) | ||
1673 | { | ||
1674 | GNUNET_CONTAINER_slist_erase (&iterator); | ||
1675 | } | ||
1676 | } | ||
1677 | while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator)); | ||
1678 | |||
1679 | GNUNET_CONTAINER_slist_iter_destroy (&iterator); | ||
1680 | |||
1681 | return; | ||
1682 | } | 1104 | } |
1683 | 1105 | ||
1684 | /******************************************************************************/ | ||
1685 | /*********************** SERVICE *******************/ | ||
1686 | /******************************************************************************/ | ||
1687 | 1106 | ||
1688 | /** | 1107 | /** |
1689 | * Shutdown nicely | 1108 | * Shutdown nicely |
@@ -1692,60 +1111,23 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl) | |||
1692 | * @param tc the task context | 1111 | * @param tc the task context |
1693 | */ | 1112 | */ |
1694 | static void | 1113 | static void |
1695 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 1114 | do_shutdown (void *cls, |
1115 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1696 | { | 1116 | { |
1697 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n"); | ||
1698 | |||
1699 | stop_helpers (); | ||
1700 | |||
1701 | if (NULL != tunnel_reliable) | ||
1702 | { | ||
1703 | GNUNET_MESH_tunnel_destroy (tunnel_reliable); | ||
1704 | } | ||
1705 | |||
1706 | if (NULL != tunnel_unreliable) | ||
1707 | { | ||
1708 | GNUNET_MESH_tunnel_destroy (tunnel_unreliable); | ||
1709 | } | ||
1710 | |||
1711 | if (NULL != mesh) | 1117 | if (NULL != mesh) |
1712 | { | 1118 | { |
1713 | GNUNET_MESH_disconnect (mesh); | 1119 | GNUNET_MESH_disconnect (mesh); |
1714 | } | 1120 | mesh = NULL; |
1715 | 1121 | } | |
1716 | if (NULL != nc) | 1122 | if (NULL != nc) |
1717 | { | 1123 | { |
1718 | GNUNET_SERVER_notification_context_destroy (nc); | 1124 | GNUNET_SERVER_notification_context_destroy (nc); |
1719 | nc = NULL; | 1125 | nc = NULL; |
1720 | } | 1126 | } |
1721 | |||
1722 | GNUNET_CONTAINER_slist_destroy (audio_buffer); | ||
1723 | GNUNET_CONTAINER_slist_destroy (clients); | ||
1724 | GNUNET_CONTAINER_slist_destroy (missed_calls); | ||
1725 | GNUNET_CONTAINER_slist_destroy (peers_to_notify); | ||
1726 | } | 1127 | } |
1727 | 1128 | ||
1728 | 1129 | ||
1729 | /** | 1130 | /** |
1730 | * Handler array for traffic received | ||
1731 | */ | ||
1732 | static struct GNUNET_MESH_MessageHandler mesh_handlers[] = { | ||
1733 | {&handle_mesh_initiate_message, | ||
1734 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE, | ||
1735 | sizeof (struct MeshSessionInitiateMessage)}, | ||
1736 | {&handle_mesh_accept_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT, | ||
1737 | sizeof (struct MeshSessionAcceptMessage)}, | ||
1738 | {&handle_mesh_reject_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT, | ||
1739 | sizeof (struct MeshSessionRejectMessage)}, | ||
1740 | {&handle_mesh_terminate_message, | ||
1741 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE, | ||
1742 | sizeof (struct MeshSessionTerminateMessage)}, | ||
1743 | {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO, | ||
1744 | sizeof (struct AudioMessage)}, | ||
1745 | {NULL, 0, 0} | ||
1746 | }; | ||
1747 | |||
1748 | /** | ||
1749 | * Main function that will be run by the scheduler. | 1131 | * Main function that will be run by the scheduler. |
1750 | * | 1132 | * |
1751 | * @param cls closure | 1133 | * @param cls closure |
@@ -1753,67 +1135,77 @@ static struct GNUNET_MESH_MessageHandler mesh_handlers[] = { | |||
1753 | * @param c configuration | 1135 | * @param c configuration |
1754 | */ | 1136 | */ |
1755 | static void | 1137 | static void |
1756 | run (void *cls, struct GNUNET_SERVER_Handle *server, | 1138 | run (void *cls, |
1139 | struct GNUNET_SERVER_Handle *server, | ||
1757 | const struct GNUNET_CONFIGURATION_Handle *c) | 1140 | const struct GNUNET_CONFIGURATION_Handle *c) |
1758 | { | 1141 | { |
1142 | static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { | ||
1143 | {&handle_client_register_message, NULL, | ||
1144 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER, | ||
1145 | sizeof (struct ClientPhoneRegisterMessage)}, | ||
1146 | {&handle_client_pickup_message, NULL, | ||
1147 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP, | ||
1148 | 0}, | ||
1149 | {&handle_client_hangup_message, NULL, | ||
1150 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP, | ||
1151 | 0}, | ||
1152 | {&handle_client_call_message, NULL, | ||
1153 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL, | ||
1154 | 0}, | ||
1155 | {&handle_client_audio_message, NULL, | ||
1156 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO, | ||
1157 | 0}, | ||
1158 | {NULL, NULL, 0, 0} | ||
1159 | }; | ||
1160 | static struct GNUNET_MESH_MessageHandler mesh_handlers[] = { | ||
1161 | {&handle_mesh_ring_message, | ||
1162 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING, | ||
1163 | sizeof (struct MeshPhoneRingMessage)}, | ||
1164 | {&handle_mesh_hangup_message, | ||
1165 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP, | ||
1166 | 0}, | ||
1167 | {&handle_mesh_pickup_message, | ||
1168 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP, | ||
1169 | 0}, | ||
1170 | {&handle_mesh_busy_message, | ||
1171 | GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY, | ||
1172 | sizeof (struct MeshPhoneBusyMessage)}, | ||
1173 | {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO, | ||
1174 | 0}, | ||
1175 | {NULL, 0, 0} | ||
1176 | }; | ||
1177 | static uint32_t ports[] = { | ||
1178 | GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL, | ||
1179 | GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO, | ||
1180 | 0 | ||
1181 | }; | ||
1759 | 1182 | ||
1760 | static uint32_t ports[] = { 50002, 50003, 0 }; | ||
1761 | cfg = c; | 1183 | cfg = c; |
1762 | 1184 | GNUNET_assert (GNUNET_OK == | |
1185 | GNUNET_CRYPTO_get_host_identity (cfg, | ||
1186 | &my_identity)); | ||
1763 | mesh = GNUNET_MESH_connect (cfg, | 1187 | mesh = GNUNET_MESH_connect (cfg, |
1764 | NULL, | 1188 | NULL, |
1765 | &inbound_tunnel, | 1189 | &inbound_tunnel, |
1766 | &inbound_end, mesh_handlers, ports); | 1190 | &inbound_end, |
1191 | mesh_handlers, | ||
1192 | ports); | ||
1767 | 1193 | ||
1768 | if (NULL == mesh) | 1194 | if (NULL == mesh) |
1769 | { | 1195 | { |
1770 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n"); | 1196 | GNUNET_break (0); |
1771 | return; | 1197 | GNUNET_SCHEDULER_shutdown (); |
1772 | } | 1198 | return; |
1773 | else | 1199 | } |
1774 | { | ||
1775 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n"); | ||
1776 | } | ||
1777 | |||
1778 | static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { | ||
1779 | {&handle_session_initiate_message, NULL, | ||
1780 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE, | ||
1781 | sizeof (struct ClientServerSessionInitiateMessage)}, | ||
1782 | {&handle_session_accept_message, NULL, | ||
1783 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT, | ||
1784 | sizeof (struct ClientServerSessionAcceptMessage)}, | ||
1785 | {&handle_session_reject_message, NULL, | ||
1786 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT, | ||
1787 | sizeof (struct ClientServerSessionRejectMessage)}, | ||
1788 | {&handle_session_terminate_message, NULL, | ||
1789 | GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE, | ||
1790 | sizeof (struct ClientServerSessionTerminateMessage)}, | ||
1791 | {NULL, NULL, 0, 0} | ||
1792 | }; | ||
1793 | |||
1794 | connection.status = LISTEN; | ||
1795 | |||
1796 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"), | ||
1797 | connection.status); | ||
1798 | |||
1799 | nc = GNUNET_SERVER_notification_context_create (server, 16); | 1200 | nc = GNUNET_SERVER_notification_context_create (server, 16); |
1800 | |||
1801 | GNUNET_SERVER_add_handlers (server, server_handlers); | 1201 | GNUNET_SERVER_add_handlers (server, server_handlers); |
1802 | GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL); | ||
1803 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); | 1202 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); |
1804 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, | 1203 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, |
1204 | &do_shutdown, | ||
1805 | NULL); | 1205 | NULL); |
1806 | |||
1807 | clients = GNUNET_CONTAINER_slist_create (); | ||
1808 | |||
1809 | // Missed calls | ||
1810 | missed_calls = GNUNET_CONTAINER_slist_create (); | ||
1811 | peers_to_notify = GNUNET_CONTAINER_slist_create (); | ||
1812 | audio_buffer = GNUNET_CONTAINER_slist_create (); | ||
1813 | |||
1814 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n")); | ||
1815 | } | 1206 | } |
1816 | 1207 | ||
1208 | |||
1817 | /** | 1209 | /** |
1818 | * The main function for the conversation service. | 1210 | * The main function for the conversation service. |
1819 | * | 1211 | * |
@@ -1822,10 +1214,13 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
1822 | * @return 0 ok, 1 on error | 1214 | * @return 0 ok, 1 on error |
1823 | */ | 1215 | */ |
1824 | int | 1216 | int |
1825 | main (int argc, char *const *argv) | 1217 | main (int argc, |
1218 | char *const *argv) | ||
1826 | { | 1219 | { |
1827 | return (GNUNET_OK == | 1220 | return (GNUNET_OK == |
1828 | GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE, | 1221 | GNUNET_SERVICE_run (argc, argv, |
1222 | "conversation", | ||
1223 | GNUNET_SERVICE_OPTION_NONE, | ||
1829 | &run, NULL)) ? 0 : 1; | 1224 | &run, NULL)) ? 0 : 1; |
1830 | } | 1225 | } |
1831 | 1226 | ||