]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_messages.c
d98b9ed56f225c3a82627f6aac44924a78a45257
[frescor/fna.git] / src_frescan / frescan_bwres_messages.c
1 /*!
2  * @file frescan_bwres_messages.c
3  *
4  * @brief FRESCAN bandwidth reservation layer: negotiation messages formating
5  *
6  * This module contains the data types that define the FRESCAN negotiation
7  * message format and operations to convert them into or from negotiation
8  * requests
9  *
10  * @version 0.01
11  *
12  * @date 2-Apr-2008
13  *
14  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
15  *
16  * @license
17  *
18  * -----------------------------------------------------------------------
19  *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
20  *
21  *    Universidad de Cantabria,              SPAIN
22  *    University of York,                    UK
23  *    Scuola Superiore Sant'Anna,            ITALY
24  *    Kaiserslautern University,             GERMANY
25  *    Univ. Politécnica  Valencia,           SPAIN
26  *    Czech Technical University in Prague,  CZECH REPUBLIC
27  *    ENEA                                   SWEDEN
28  *    Thales Communication S.A.              FRANCE
29  *    Visual Tools S.A.                      SPAIN
30  *    Rapita Systems Ltd                     UK
31  *    Evidence                               ITALY
32  *
33  *    See http://www.frescor.org for a link to partners' websites
34  *
35  *           FRESCOR project (FP6/2005/IST/5-034026) is funded
36  *        in part by the European Union Sixth Framework Programme
37  *        The European Union is not liable of any use that may be
38  *        made of this code.
39  *
40  *  This file is part of FRESCAN
41  *
42  *  FRESCAN is free software; you can  redistribute it and/or  modify
43  *  it under the terms of  the GNU General Public License as published by
44  *  the Free Software Foundation;  either  version 2, or (at  your option)
45  *  any later version.
46  *
47  *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
48  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
49  *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
50  *  General Public License for more details.
51  *
52  *  You should have  received a  copy of  the  GNU  General Public License
53  *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
54  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
55  *  02111-1307, USA.
56  *
57  * As a special exception, including FRESCAN header files in a file,
58  * instantiating FRESCAN generics or templates, or linking other files
59  * with FRESCAN objects to produce an executable application, does not
60  * by itself cause the resulting executable application to be covered
61  * by the GNU General Public License. This exception does not
62  * however invalidate any other reasons why the executable file might be
63  * covered by the GNU Public License.
64  * -----------------------------------------------------------------------
65  *
66  */
67
68 #include <string.h>
69 #include "frescan_bwres_messages.h"
70 #include "frescan_bwres_requests.h"
71 #include "frescan.h"
72 #include "frescan_servers.h"
73 #include "frescan_data.h"
74 #include "frescan_config.h"
75 #include "frescan_debug.h"
76 #include "frsh_distributed.h"
77
78 #define FRESCAN_BWRES_MX_MSG_SIZE 5000  // TODO: adjust to the accurate value
79
80 /**
81  * frescan_messages_init()
82  */
83
84 static frescan_send_params_t send_params[FRESCAN_MX_NETWORKS];
85 static frescan_recv_params_t recv_params[FRESCAN_MX_NETWORKS];
86
87 int frescan_messages_init(frescan_network_t net)
88 {
89         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "initialization\n");
90
91         send_params[net].net     = net;
92         send_params[net].channel = FRESCAN_BWRES_NEG_MSG_CHAN;
93         send_params[net].flags   = FRESCAN_SS | FRESCAN_ASYNC;
94         send_params[net].ss      = frescan_data[net].neg_messages_ss_id;
95         send_params[net].to      = FRESCAN_BWRES_MASTER_NODE;
96
97         recv_params[net].net     = net;
98         recv_params[net].channel = FRESCAN_BWRES_NEG_MSG_CHAN;
99         recv_params[net].flags   = FRESCAN_SYNC;
100
101         return 0;
102 }
103
104 /**
105  *  FRESCAN_BWRES_REQ_GN
106  *  ====================
107  *  This message is sent from a SLAVE to the MASTER when the slave wants
108  *  to make a negotiation (including creating new vres, renegotiations and
109  *  cancellations).
110  */
111
112 static int frescan_request_to_gn_message
113                                 (const frescan_bwres_request_data_t *data,
114                                  uint8_t *msg,
115                                  size_t  *size)
116 {
117         int ret, i;
118         uint8_t *msg_begin, *msg_tmp;
119         size_t bytes_written;
120
121         msg_begin = msg;
122
123         // type: FRESCAN_GN_MESSAGE
124         *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_GN;
125         bytes_written = sizeof(uint8_t);
126         msg = msg + bytes_written;
127
128         // req
129         *((frescan_bwres_request_id_t *)msg) = data->req;
130         bytes_written = sizeof(frescan_bwres_request_id_t);
131         msg = msg + bytes_written;
132
133         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
134               "GN message req:%u\n", data->req);
135
136         // NEG-GROUP
137         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
138               "NEG-GROUP num contracts:%d\n", data->contracts_to_neg->size);
139
140         *((uint8_t *)msg) = (uint8_t)data->contracts_to_neg->size;
141         bytes_written = sizeof(uint8_t);
142         msg = msg + bytes_written;
143
144         for (i=0; i<data->contracts_to_neg->size; i++) {
145                 // reserve 2 bytes for the size of the marshalled contract
146                 msg_tmp = msg;
147                 msg     = msg + sizeof(uint16_t);
148                 // marshal the contract
149                 ret = frsh_contract_marshal
150                                 (&data->contracts_to_neg->contracts[i],
151                                  msg,
152                                  FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin),
153                                  &bytes_written);
154                 if (ret != 0) {
155                         FRESCAN_ERROR("frsh_contract_marshal return -1\n");
156                         return -1;
157                 }
158                 // write the size and update the message pointer msg
159                 *((uint16_t *)msg_tmp) = (uint16_t)bytes_written;
160                 msg = msg + bytes_written;
161
162                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
163                       "contract[%d].size:%u\n", i, bytes_written);
164         }
165
166         // RENEG-GROUP
167         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
168               "RENEG-GROUP num contracts:%d\n",data->contracts_to_reneg->size);
169
170         *((uint8_t *)msg) = (uint8_t)data->contracts_to_reneg->size;
171         bytes_written = sizeof(uint8_t);
172         msg = msg + bytes_written;
173
174         for (i=0; i<data->contracts_to_reneg->size; i++) {
175                 // write the ss
176                 *((uint16_t *)msg) = (uint16_t)data->ss_to_reneg->ss[i];
177                 bytes_written = sizeof(uint16_t);
178                 msg = msg + bytes_written;
179                 // reserve 2 bytes for the size of the marshalled contract
180                 msg_tmp = msg;
181                 msg     = msg + sizeof(uint16_t);
182                 // marshal the contract
183                 ret = frsh_contract_marshal
184                                 (&data->contracts_to_reneg->contracts[i],
185                                  msg,
186                                  FRESCAN_BWRES_MX_MSG_SIZE - (msg - msg_begin),
187                                  &bytes_written);
188                 if (ret != 0) {
189                         FRESCAN_ERROR("frsh_contract_marshal return -1\n");
190                         return -1;
191                 }
192                 // write the size and update the message pointer msg
193                 *((uint16_t *)msg_tmp) = (uint16_t)bytes_written;
194                 msg = msg + bytes_written;
195
196                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
197                       "contract[%d].size:%u ss[%d]:%u\n",
198                       i, bytes_written, i, data->ss_to_reneg->ss[i]);
199         }
200
201         // CANCEL-GROUP
202         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "CANCEL-GROUP num ss:%d\n",
203               data->ss_to_cancel->size);
204
205         *((uint8_t *)msg) = (uint8_t)data->ss_to_cancel->size;
206         bytes_written = sizeof(uint8_t);
207         msg = msg + bytes_written;
208
209         for (i=0; i<data->ss_to_cancel->size; i++) {
210                 // write the ss
211                 *((uint16_t *)msg) = (uint16_t)data->ss_to_cancel->ss[i];
212                 bytes_written = sizeof(uint16_t);
213                 msg = msg + bytes_written;
214
215                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
216                       "ss[%d]:%u\n", i, data->ss_to_cancel->ss[i]);
217         }
218
219         *size = msg - msg_begin;
220
221         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
222
223         return 0;
224 }
225
226 static int frescan_gn_message_to_request(const uint8_t *msg_to_parse,
227                                          frescan_bwres_request_data_t *data,
228                                          size_t size)
229 {
230         int ret, i;
231         uint8_t *msg;
232         size_t bytes_read, contract_size;
233
234         msg = (uint8_t *)msg_to_parse;
235
236         data->contracts_to_neg   = &data->contracts_to_neg_data;
237         data->contracts_to_reneg = &data->contracts_to_reneg_data;
238         data->ss_to_reneg        = &data->ss_to_reneg_data;
239         data->ss_to_cancel       = &data->ss_to_cancel_data;
240         data->ss_new             = &data->ss_new_data;
241
242         // req
243         data->req = *((frescan_bwres_request_id_t *)msg);
244         bytes_read = sizeof(frescan_bwres_request_id_t);
245         msg = msg + bytes_read;
246
247         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
248               "GN message req:%u\n", data->req);
249
250         // NEG-GROUP
251         data->contracts_to_neg->size = *((uint8_t *)msg);
252         bytes_read = sizeof(uint8_t);
253         msg = msg + bytes_read;
254
255         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
256               "NEG-GROUP num contracts:%u\n", data->contracts_to_neg->size);
257
258         for (i=0; i<data->contracts_to_neg->size; i++) {
259                 contract_size = *((uint16_t *)msg);
260                 bytes_read = sizeof(uint16_t);
261                 msg = msg + bytes_read;
262
263                 // unmarshal the contract
264                 ret = frsh_contract_unmarshal
265                                 (&data->contracts_to_neg->contracts[i],
266                                  msg,
267                                  contract_size);
268                 if (ret != 0) {
269                         FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
270                         return -1;
271                 }
272
273                 bytes_read = contract_size;
274                 msg = msg + bytes_read;
275
276                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
277                       "contract[%d].size:%u\n", i, contract_size);
278         }
279
280          // RENEG-GROUP
281         data->contracts_to_reneg->size = *((uint8_t *)msg);
282         bytes_read = sizeof(uint8_t);
283         msg = msg + bytes_read;
284
285         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
286               "RENEG-GROUP num contracts:%u\n",data->contracts_to_reneg->size);
287
288         for (i=0; i<data->contracts_to_reneg->size; i++) {
289                 data->ss_to_reneg->ss[i] = *((uint16_t *)msg);
290                 bytes_read = sizeof(uint16_t);
291                 msg = msg + bytes_read;
292
293                 contract_size = *((uint16_t *)msg);
294                 bytes_read = sizeof(uint16_t);
295                 msg = msg + bytes_read;
296
297                 // unmarshal the contract
298                 ret = frsh_contract_unmarshal
299                                 (&data->contracts_to_reneg->contracts[i],
300                                  msg,
301                                  contract_size);
302                 if (ret != 0) {
303                         FRESCAN_ERROR("frsh_contract_unmarshal return -1\n");
304                         return -1;
305                 }
306
307                 bytes_read = contract_size;
308                 msg = msg + bytes_read;
309
310                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
311                       "contract[%d].size:%u ss[%d]:%u\n",
312                       i, contract_size, i, data->ss_to_reneg->ss[i]);
313         }
314
315         // CANCEL-GROUP
316         data->ss_to_cancel->size = *((uint8_t *)msg);
317         bytes_read = sizeof(uint8_t);
318         msg = msg + bytes_read;
319
320         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
321               "CANCEL-GROUP num ss:%u\n", data->ss_to_cancel->size);
322
323         for (i=0; i<data->ss_to_cancel->size; i++) {
324                 // write the ss
325                 data->ss_to_cancel->ss[i] = *((uint16_t *)msg);
326                 bytes_read = sizeof(uint16_t);
327                 msg = msg + bytes_read;
328
329                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
330                       "ss[%d]:%u\n", i, data->ss_to_cancel->ss[i]);
331         }
332
333         return 0;
334 }
335
336 /**
337  *  FRESCAN_BWRES_REQ_MC
338  *  ====================
339  *  This message is sent from the MASTER to a slave when there is a change
340  *  in the budget value assigned by the spare capacity algorithm.
341  */
342
343 static int frescan_request_to_mc_message
344                                 (const frescan_bwres_request_data_t *data,
345                                  uint8_t *msg,
346                                  size_t  *size)
347 {
348         frescan_bwres_vres_t *vres;
349         uint8_t *msg_begin;
350         size_t bytes_written;
351
352         msg_begin = msg;
353
354         // type: FRESCAN_GN_MESSAGE
355         *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REQ_MC;
356         bytes_written = sizeof(uint8_t);
357         msg = msg + bytes_written;
358
359         // write the SS-mode_change_type-values fields
360         list_for_each_entry(vres,
361                             &frescan_data[data->net].mode_change_list
362                                                         [data->request_node],
363                             mode_change_list)
364         {
365                 if ((vres->mode_change_type & data->mode_change_type) !=
366                      data->mode_change_type) continue;
367
368                 *((frescan_ss_t *)msg) = vres->ss;
369                 bytes_written = sizeof(frescan_ss_t);
370                 msg = msg + bytes_written;
371
372                 *((uint8_t *)msg) = (uint8_t)data->mode_change_type;
373                 bytes_written = sizeof(uint8_t);
374                 msg = msg + bytes_written;
375
376                 if (data->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC |
377                                               FRESCAN_BWRES_MC_BUDGET_DEC)) {
378                         *((frsh_sa_time_t *)msg) = vres->old_c;
379                         bytes_written = sizeof(frsh_sa_time_t);
380                         msg = msg + bytes_written;
381                 }
382
383                 if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC |
384                                               FRESCAN_BWRES_MC_PERIOD_DEC)) {
385                         *((frsh_sa_time_t *)msg) = vres->old_t;
386                         bytes_written = sizeof(frsh_sa_time_t);
387                         msg = msg + bytes_written;
388                 }
389
390                 if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC |
391                                               FRESCAN_BWRES_MC_PRIO_DEC)) {
392                         *((frsh_sa_prio_t *)msg) = vres->old_p;
393                         bytes_written = sizeof(frsh_sa_prio_t);
394                         msg = msg + bytes_written;
395                 }
396         }
397
398         *size = msg - msg_begin;
399
400         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
401
402         return 0;
403 }
404
405 static int frescan_mc_message_to_request(const uint8_t *msg_to_parse,
406                                          frescan_bwres_request_data_t *data,
407                                          size_t size)
408 {
409         uint8_t *msg;
410         size_t bytes_read;
411         frescan_ss_t ss;
412         frescan_bwres_vres_t *vres;
413         frescan_node_t me;
414
415         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "MC message\n");
416
417         msg = (uint8_t *)msg_to_parse;
418         me = frescan_data[data->net].local_node;
419         data->mode_change_type = 0;
420
421         while(msg < msg_to_parse + size) {
422                 ss = *((frescan_ss_t *)msg);
423                 bytes_read = sizeof(frescan_ss_t);
424                 msg = msg + bytes_read;
425
426                 vres = &frescan_data[data->net].scenario.vres_pool[me][ss];
427
428                 vres->mode_change_type = *((uint8_t *)msg);
429                 bytes_read = sizeof(uint8_t);
430                 msg = msg + bytes_read;
431
432                 if (vres->mode_change_type & (FRESCAN_BWRES_MC_BUDGET_INC |
433                                               FRESCAN_BWRES_MC_BUDGET_DEC)) {
434                         vres->old_c = *((frsh_sa_time_t *)msg);
435                         bytes_read = sizeof(frsh_sa_time_t);
436                         msg = msg + bytes_read;
437                 }
438
439                 if (data->mode_change_type & (FRESCAN_BWRES_MC_PERIOD_INC |
440                                               FRESCAN_BWRES_MC_PERIOD_DEC)) {
441                         vres->old_t = *((frsh_sa_time_t *)msg);
442                         bytes_read = sizeof(frsh_sa_time_t);
443                         msg = msg + bytes_read;
444                 }
445
446                 if (data->mode_change_type & (FRESCAN_BWRES_MC_PRIO_INC |
447                                               FRESCAN_BWRES_MC_PRIO_DEC)) {
448                         vres->old_p = *((frsh_sa_prio_t *)msg);
449                         bytes_read = sizeof(frsh_sa_prio_t);
450                         msg = msg + bytes_read;
451                 }
452
453                 if (vres->mode_change_type != 0) {
454                         list_add_tail(&(vres->mode_change_list),
455                                       &(frescan_data[data->net].
456                                                       mode_change_list[me]));
457                 }
458
459                 data->mode_change_type |= vres->mode_change_type;
460         }
461
462         return 0;
463 }
464
465 /**
466  *  FRESCAN_BWRES_REP_GN
467  *  ====================
468  *  This message is sent from the MASTER to a slave as a reply to a
469  *  FRESCAN_BWRES_REQ_GN message
470  */
471
472 static int frescan_request_to_rep_gn_message
473                         (const frescan_bwres_request_data_t *data,
474                          uint8_t *msg,
475                          size_t  *size)
476 {
477         int i;
478         uint8_t *msg_begin;
479         size_t bytes_written;
480         frescan_bwres_vres_t *vres;
481
482         msg_begin = msg;
483
484         // type
485         *((uint8_t *)msg) = (uint8_t)FRESCAN_BWRES_REP_GN;
486         bytes_written = sizeof(uint8_t);
487         msg = msg + bytes_written;
488
489         // req
490         *((frescan_bwres_request_id_t *)msg) = data->req;
491         bytes_written = sizeof(frescan_bwres_request_id_t);
492         msg = msg + bytes_written;
493
494         // return value
495         *((uint8_t *)msg) = data->return_value;
496         bytes_written = sizeof(uint8_t);
497         msg = msg + bytes_written;
498
499         if (data->return_value == FRESCAN_BWRES_REQ_ACCEPTED) {
500                 // new ss values
501                 for(i=0; i<data->contracts_to_neg->size; i++) {
502                         // SS
503                         *((uint16_t *)msg) = data->ss_new->ss[i];
504                         bytes_written = sizeof(uint16_t);
505                         msg = msg + bytes_written;
506
507                         // B - T - P
508                         vres = &frescan_data[data->net].scenario.
509                                                 vres_pool[data->request_node]
510                                                          [data->ss_new->ss[i]];
511
512                         *((frsh_sa_time_t *)msg) = vres->old_c;
513                         bytes_written = sizeof(frsh_sa_time_t);
514                         msg = msg + bytes_written;
515
516                         *((frsh_sa_time_t *)msg) = vres->old_t;
517                         bytes_written = sizeof(frsh_sa_time_t);
518                         msg = msg + bytes_written;
519
520                         *((frsh_sa_prio_t *)msg) = vres->old_p;
521                         bytes_written = sizeof(frsh_sa_prio_t);
522                         msg = msg + bytes_written;
523
524                         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
525                               "ss[%d]:%u\n", i, data->ss_new->ss[i]);
526                 }
527         }
528
529         *size = msg - msg_begin;
530
531         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG, "size:%u\n", *size);
532
533         return 0;
534 }
535
536 static int frescan_rep_gn_message_to_request
537                                         (const uint8_t *msg_to_parse,
538                                          frescan_bwres_request_data_t *data,
539                                          size_t size)
540 {
541         int ret;
542         uint8_t *msg;
543         size_t bytes_read;
544         frescan_ss_t ss;
545         frescan_server_params_t server_params;
546
547         msg = (uint8_t *)msg_to_parse;
548
549         // req
550         data->req = *((frescan_bwres_request_id_t *)msg);
551         bytes_read = sizeof(frescan_bwres_request_id_t);
552         msg = msg + bytes_read;
553
554         // return_value
555         data->return_value = *((uint8_t *)msg);
556         bytes_read = sizeof(uint8_t);
557         msg = msg + bytes_read;
558
559         // create the new sporadic servers
560         data->ss_new->size = 0;
561
562         while(msg < msg_to_parse + size) {
563                 // SS
564                 data->ss_new->ss[data->ss_new->size] = *((uint16_t *)msg);
565                 bytes_read = sizeof(uint16_t);
566                 msg = msg + bytes_read;
567
568                 // Budget
569                 server_params.budget =
570                         frsh_rel_time_to_usec
571                         (frsh_sa_time_to_rel_time(*((frsh_sa_time_t *)msg))) /
572                                                 FRESCAN_FRAME_TX_TIME_US;
573                 bytes_read = sizeof(frsh_sa_time_t);
574                 msg = msg + bytes_read;
575
576                 // Period
577                 server_params.period = frsh_sa_time_to_rel_time
578                                                 (*((frsh_sa_time_t *)msg));
579                 bytes_read = sizeof(frsh_sa_time_t);
580                 msg = msg + bytes_read;
581
582                 // Prio
583                 server_params.prio = *((frsh_sa_prio_t *)msg);
584                 bytes_read = sizeof(frsh_sa_prio_t);
585                 msg = msg + bytes_read;
586
587                 // Create server
588                 ret = frescan_servers_create(data->net, &server_params, &ss);
589                 if (ret != 0) return ret;
590
591                 DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
592                       "ss_master[%d]:%u ss_created[%d]:%u\n",
593                       data->ss_new->size, data->ss_new->ss[data->ss_new->size],
594                       data->ss_new->size, ss);
595
596                 if (ss != data->ss_new->ss[data->ss_new->size]) {
597                         FRESCAN_ERROR("ss from master != ss created\n");
598                         return -1;
599                 }
600
601                 data->ss_new->size++;
602         }
603
604         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
605               "data->ss_new->size:%u\n", data->ss_new->size);
606
607         return 0;
608 }
609
610 /**
611  * frescan_messages_send_request()
612  *
613  * this function converts a request with the necessary data into a message
614  * and sends it.
615  *
616  * @req_data: the request to be sent (NOTE: the network is in req_data)
617  *
618  */
619
620 int frescan_messages_send_request(const frescan_bwres_request_data_t *req_data)
621 {
622         int ret;
623         uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
624         size_t size;
625
626         switch(req_data->type) {
627                 case FRESCAN_BWRES_REQ_GN:
628                         ret = frescan_request_to_gn_message
629                                                         (req_data, msg, &size);
630                         if (ret != 0) return ret;
631                         send_params[req_data->net].to =
632                                                 FRESCAN_BWRES_MASTER_NODE;
633                         break;
634                 case FRESCAN_BWRES_REQ_MC:
635                         ret = frescan_request_to_mc_message
636                                                         (req_data, msg, &size);
637                         if (ret != 0) return ret;
638                         send_params[req_data->net].to = req_data->request_node;
639                         break;
640                 case FRESCAN_BWRES_REP_GN:
641                         ret = frescan_request_to_rep_gn_message
642                                                         (req_data, msg, &size);
643                         if (ret != 0) return ret;
644                         send_params[req_data->net].to = req_data->request_node;
645                         break;
646                 case FRESCAN_BWRES_REQ_RES:
647                 case FRESCAN_BWRES_REQ_RES_GET:
648                 case FRESCAN_BWRES_REP_RES_GET:
649                 case FRESCAN_BWRES_REQ_RES_SET:
650                 case FRESCAN_BWRES_REQ_RES_COMMIT:
651                 case FRESCAN_BWRES_REQ_RES_CANCEL:
652                 default:
653                         FRESCAN_ERROR("request type not supported\n");
654                         return -1;
655         }
656
657         ret = frescan_send(&send_params[req_data->net], msg, size);
658         if (ret != 0) return ret;
659
660         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
661               "sent request, type:%X size:%u\n",
662               req_data->type, size);
663
664         return 0;
665 }
666
667 /**
668  * frescan_messages_recv_request()
669  *
670  * this function BLOCKS the calling thread until receives a message
671  * and transforms it into a request.
672  *
673  * @req_data: the request data to fill from the message bytes (out)
674  *
675  */
676
677 int frescan_messages_recv_request(frescan_network_t    net,
678                                   frescan_bwres_request_id_t *req)
679 {
680         int ret;
681         uint8_t msg[FRESCAN_BWRES_MX_MSG_SIZE];
682         uint8_t *msg_to_parse;
683         size_t recv_bytes;
684         frescan_node_t from;
685         frescan_prio_t prio;
686         frescan_bwres_request_data_t *req_data;
687
688         ret = frescan_bwres_requests_alloc(req);
689         if (ret != 0) return ret;
690
691         ret = frescan_bwres_requests_get_data(*req, &req_data);
692         if (ret != 0) return ret;
693
694         ret = frescan_recv(&recv_params[net],
695                             msg,
696                             sizeof(msg),
697                             &recv_bytes,
698                             &from,
699                             &prio);
700         if (ret != 0) return ret;
701
702         DEBUG(FRESCAN_BWRES_MESSAGES_ENABLE_DEBUG,
703               "msg received! from:%u size:%u prio:%u chan:%u flags:%X\n",
704               from, recv_bytes, prio, recv_params[net].channel,
705               recv_params[net].flags);
706
707         req_data->request_node = from;
708         req_data->net          = net;
709         req_data->type         = *((uint8_t *)msg);
710
711         msg_to_parse = msg + sizeof(uint8_t);
712         recv_bytes   = recv_bytes - sizeof(uint8_t);
713
714         switch(req_data->type) {
715                 case FRESCAN_BWRES_REQ_GN:
716                         return frescan_gn_message_to_request(msg_to_parse,
717                                                              req_data,
718                                                              recv_bytes);
719                 case FRESCAN_BWRES_REQ_MC:
720                         return frescan_mc_message_to_request(msg_to_parse,
721                                                              req_data,
722                                                              recv_bytes);
723                 case FRESCAN_BWRES_REP_GN:
724                         return frescan_rep_gn_message_to_request(msg_to_parse,
725                                                                  req_data,
726                                                                  recv_bytes);
727                 case FRESCAN_BWRES_REQ_RES:
728                 case FRESCAN_BWRES_REQ_RES_GET:
729                 case FRESCAN_BWRES_REP_RES_GET:
730                 case FRESCAN_BWRES_REQ_RES_SET:
731                 case FRESCAN_BWRES_REQ_RES_COMMIT:
732                 case FRESCAN_BWRES_REQ_RES_CANCEL:
733                 default:
734                         FRESCAN_ERROR("request type %d not supported\n",
735                                       req_data->type);
736                         return -1;
737         }
738 }