Statistics
| Branch: | Revision:

ml / tests / echoServer.c @ 6f256447

History | View | Annotate | Download (16.5 KB)

1 a0a1f630 KristianBeckers
/*
2
 * @note Policy Management
3
 *
4
 *          NEC Europe Ltd. PROPRIETARY INFORMATION
5
 *
6
 * This software is supplied under the terms of a license agreement
7
 * or nondisclosure agreement with NEC Europe Ltd. and may not be
8
 * copied or disclosed except in accordance with the terms of that
9
 * agreement.
10
 *
11
 *      Copyright (c) 2009 NEC Europe Ltd. All Rights Reserved.
12
 *
13
 * Authors: Kristian Beckers  <beckers@nw.neclab.eu>
14
 *    Sebastian Kiesel  <kiesel@nw.neclab.eu>
15
 *          
16
 *
17
 * NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
18
 * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
19
 * AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT
20
 * DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING
21
 * DOCUMENTATION.
22
 *
23
 * No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe
24
 * Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY
25
 * DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
26
 * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR
27
 * OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL,
28
 * ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY
29
 * TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGES.
31
 *
32
 *     THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
33
 */
34
35
/**
36
 * @file echoServer.c
37
 * @brief A simple demo application for the messaging layer.   
38
 *
39
 * @author Kristian Beckers  <beckers@nw.neclab.eu>                             
40
 * @author Sebastian Kiesel  <kiesel@nw.neclab.eu> 
41
 *                                                                              
42
 * @date 7/28/2009 
43
 */
44
45
46
#include <fcntl.h>
47
#include <event2/event.h>
48
#include <errno.h>
49
#include <stdio.h>
50
#include <string.h>
51
#include <stdlib.h>
52
#include <unistd.h>
53 472bb222 RobertBirke
#include "ml.h"
54 90cb1b52 TivadarSzemethy
#include "transmissionHandler.h"
55 a0a1f630 KristianBeckers
56
/**
57
  * A pointer to a libevent 
58
  */
59
struct event_base *base;
60
61
/**
62
  * A peerID provided at application start
63
  */
64
int peerID;
65
66
/**
67
  * define a maximum number of connections
68
  */
69
#define maxConnections 10000
70
71
/**
72
  * an connections array
73
  */
74
int connections[maxConnections];
75
76
/**
77
  * the initial number of connections
78
  */
79
int nr_connections = 0;
80
81
/**
82
  * A local socketID handle 
83
  */
84
socketID_handle my_socketID;
85
86
/**
87
  * A remote socketID handle
88
  */
89
socketID_handle rm_socketID;
90
91
/**
92 2a178954 KristianBeckers
 * An integer that is passed as an argument in open_connection
93
 */
94
int connection_argument;
95
96
/**
97 a0a1f630 KristianBeckers
  * create a callback for the periodic printouts on the screen
98
  * @param fd A file descriptor
99
  * @param event A libevent event 
100
  * @param arg An arg pointer
101
  */
102
void print_peerID_cb(int fd, short event,void *arg){
103 6759fdd0 AlessandroRusso
104 a0a1f630 KristianBeckers
  ///print the peerID
105
  printf("--echoServer: This peers ID is %d \n",peerID);
106
  ///Add a timeout event to the event list
107
  struct timeval timeout_value_print = {3,0};
108
  struct event *ev;
109
  ev = evtimer_new(base,print_peerID_cb,NULL);
110
  event_add(ev,&timeout_value_print);
111 6759fdd0 AlessandroRusso
112 a0a1f630 KristianBeckers
}
113
114 2a178954 KristianBeckers
115
/**
116
  * Send data to another peer. This function is implemented as timeout callback in the libevent
117
  * @param fd A file descriptor
118
  * @param event A libevent event 
119
  * @param arg An arg pointer
120
  */
121
void send_data_to_peer(int fd, short event,void *arg){
122
123
  printf("--echoServer: Send data to peer 2 \n");
124
  printf("               ++sending 10.000 'a'  \n");
125
      /// transmit data to peer 2  
126
      int size = 10000;
127
      char buffer[size];
128
      memset(buffer,'a',size);
129
      unsigned char msgtype = 12;
130
      int connectionID = 0;
131
      //strcpy(buffer, "Message for peer 2 \n");
132 6759fdd0 AlessandroRusso
  
133 6f256447 TivadarSzemethy
      mlSendData(connectionID,buffer,size,msgtype,NULL);
134 6759fdd0 AlessandroRusso
135 2a178954 KristianBeckers
}
136
137
/**
138
  * Send a file to a peer. This function is implemented as timeout callback in the libevent
139
  * @param fd A file descriptor
140
  * @param event A libevent event 
141
  * @param arg An arg pointer
142
  */
143
144
void send_file_to_peer(int fd, short event,void *arg){
145
146
147
  printf("--echoServer: Send file to peer 3 \n");
148
149
  char buf[20000];
150
  FILE *testfileread;
151
  testfileread  = fopen("testfile.txt","r");
152
153
  if (testfileread == NULL)
154
    {
155
      fprintf(stderr,"Could not open file for reading!\n");
156
    }
157
158
  /// open a file and write it into a buffer 
159
  fseek (testfileread , 0 , SEEK_END);
160
  long lSize = ftell (testfileread);
161
  rewind (testfileread);
162
  int result = fread(buf,1,lSize,testfileread);
163
  fclose(testfileread);
164
165
  int bufsize = sizeof(buf);
166
  unsigned char msgtype = 13;
167
  int connectionID = 0;
168
169
  fprintf(stderr,"The buffersize is %i\n",bufsize);
170
  if (result != lSize){ fprintf(stderr,"Could not read file!\n");  }
171
  else { printf("The size of the file is %ld \n",lSize); }
172
  
173 6f256447 TivadarSzemethy
  mlSendData(connectionID,buf,(int)lSize,msgtype,NULL);
174 2a178954 KristianBeckers
175
}
176
177
/**
178
  * A callback function that tells a connection has been established. 
179
  * @param connectionID The connection ID
180
  * @param *arg An argument for data about the connection 
181
  */
182
void receive_conn_cb (int connectionID, void *arg){
183
184
  printf("--echoServer: Received incoming connection connectionID %d  \n",connectionID );
185
186
  connections[nr_connections] = connectionID;
187
  nr_connections++;
188
189
  if(peerID == 1){
190
191
  struct timeval timeout_value = {5,0};
192
  struct event *ev;
193
  ev = evtimer_new(base,send_data_to_peer,NULL);
194
  event_add(ev,&timeout_value);
195
  
196
  }else 
197
    if(peerID == 3){
198
199
      /* send a file to peer 1 */
200
      struct timeval timeout_value_send_file = {12,0};
201
      struct event *ev3;
202
      ev3 = evtimer_new(base,send_file_to_peer,NULL);
203
      event_add(ev3,&timeout_value_send_file);
204
    
205
    }
206
207
} 
208
209
210 a0a1f630 KristianBeckers
/**
211
  * A connection is poened callback
212
  * @param fd A file descriptor
213
  * @param event A libevent event 
214
  * @param arg An arg pointer
215
  */
216
void open_connection_cb(int fd, short event,void *arg){
217 6759fdd0 AlessandroRusso
218 6f256447 TivadarSzemethy
  send_params defaultSendParams;
219
  int con_id = mlOpenConnection(rm_socketID,&receive_conn_cb,&connection_argument, defaultSendParams); ///< try to open a connection to another peer.
220 a0a1f630 KristianBeckers
  ///If the result is zero the event is resheduled into the event list.
221 380cf1b9 RobertBirke
  if(con_id < 0){
222 a0a1f630 KristianBeckers
223
    printf("open_connection failed : resheduling event\n");
224
225
    /* ReTry to open a connection after 3 seconds */
226
    struct timeval timeout_value_open_conn = {3,0};
227
    struct event *ev;
228
    ev = evtimer_new(base,open_connection_cb,NULL);
229
    event_add(ev,&timeout_value_open_conn);
230
231
  }
232
233
}
234
235
/**
236
  * The peer reveives data per polling. Implemented as a callback that is preiodically resheduled.
237
  * @param fd A file descriptor
238
  * @param event A libevent event 
239
  * @param arg An arg pointer
240
  */
241
void recv_data_from_peer_poll(int fd, short event,void *arg){
242
243
  printf("--echoServer: Polling for recv data \n" );
244
  
245
  char buffer[20000];
246
  int size = 0;
247
  //unsigned char msgtype = 12;
248
  //int connectionID = 0;
249
  int returnValue = 0;
250
  recv_params recvp;
251
  int i = 0;
252
  int connectionID;
253
254
  printf("--echoServer: before recv_Data \n");
255
  
256
  printf("nr_connections %d \n ",nr_connections );
257
258
  //iterate through all connections
259
  for(i=0; i <  nr_connections;i++){
260
261
    connectionID = connections[i];
262
    
263
264 da5dade7 MarcoBiazzini
  returnValue = mlRecvData(connectionID,buffer,&size,&recvp);
265 a0a1f630 KristianBeckers
266 da5dade7 MarcoBiazzini
  //printf("--echoServer: after mlRecvData \n");
267 a0a1f630 KristianBeckers
268
  
269
  if (returnValue == 1){
270
271 da5dade7 MarcoBiazzini
    //printf("--echoServer: after mlRecvData  \n");
272 a0a1f630 KristianBeckers
273
    unsigned char msgtype  = recvp.msgtype;
274
    int connectionID = recvp.connectionID;
275
276
    printf("--echoServer: msgtype is %d \n",msgtype);
277
    printf("--echoServer: size is %d \n",size);
278
    printf("--echoServer: connectionID is %d \n",connectionID);
279
280
    if(msgtype == 12){
281
    
282
    char recv_buf[size];
283
    memcpy(recv_buf,buffer,size);
284
285
    printf("--echoServer: Received data from polling: \n\t %s \n\t buflen %d \n",recv_buf,size);
286
    
287
    // set the event again
288
    struct timeval timeout_value_recv = {10,0};
289
    struct event *ev;
290
    ev = evtimer_new(base,recv_data_from_peer_poll,NULL);
291
    event_add(ev,&timeout_value_recv);
292
    }else 
293
      if(msgtype == 13){
294
295
        printf("received testfile: msgtype 13 \n");
296
297
        //printf("%s \n" , buffer );
298
        /*
299
        FILE *testfile1 = NULL;
300
        
301
        printf("received testfile: msgtype 13 \n");
302

303
        testfile1 = fopen("recv.txt","r");
304

305
        printf("received testfile: msgtype 13 \n");
306

307
        if (testfile1 == NULL) {fprintf(stderr,"Could not open file for writing!\n"); }
308

309
        int cur_char;
310
        for(cur_char = 0; cur_char < size;++cur_char)
311
          {
312
            fputc(buffer[cur_char],testfile1);
313
          }
314
        
315
        fclose(testfile1);
316
        
317
        printf(" testfile fully worked  \n ");
318
        */
319
      }
320
 
321
  }else{
322
323
    printf("--echoServer: polling ...no data arrived \n");
324
    // set the event again
325
  struct timeval timeout_value_recv = {8,0};
326
  struct event *ev;
327
  ev = evtimer_new(base,recv_data_from_peer_poll,NULL);
328
  event_add(ev,&timeout_value_recv);
329
330
    }
331
  }
332
}
333
334
/**
335
  * The peer receives data per callback from the messaging layer. 
336
  * @param *buffer A pointer to the buffer
337
  * @param buflen The length of the buffer
338
  * @param msgtype The message type 
339
  * @param *arg An argument that receives metadata about the received data
340
  */
341
void recv_data_from_peer_cb(char *buffer,int buflen,unsigned char msgtype,void *arg){
342
343
  printf("--echoServer: Received data from callback: \n\t %s \t msgtype %d \t buflen %d \n",buffer,msgtype,buflen ); 
344
345
  if(peerID == 2){
346
347
    printf("--echoServer: Send data to peer 1 \n");
348
    
349
    /* transmit data to peer 1  */
350
351
    int size = 10000;
352
    char buffer[size];
353
    memset(buffer,'a',size);
354
    int connectionID = 0;
355
356 6f256447 TivadarSzemethy
    mlSendData(connectionID,buffer,size,msgtype,NULL);
357 a0a1f630 KristianBeckers
358
  }
359
  
360
}
361
362
/**
363
  * A funtion that prints a connection establishment has failed
364
  * @param connectionID The connection ID
365
  * @param *arg An argument for data about the connection
366
  */
367
void conn_fail_cb(int connectionID,void *arg){
368
369
  printf("--echoServer: ConnectionID %d  could not be established \n ",connectionID);
370
371
}
372
373
/**
374 2a178954 KristianBeckers
  * callback for a received packet notification from the messaging layer
375
  * @param *arg An argument for a recv packet infromation struct
376 a0a1f630 KristianBeckers
  */
377 2a178954 KristianBeckers
void received_a_packet_monitoring_cb(void *arg){
378 a0a1f630 KristianBeckers
379 2a178954 KristianBeckers
  printf("--Monitoring module: received a packet notification \n");
380 a0a1f630 KristianBeckers
  
381
}
382
383
/**
384 2a178954 KristianBeckers
 * A funtion that is a callback for the messaging layer when a new socketId is ready to be used
385
 * SocketIDhandle is a handle for the local socketID
386
 * Errorstatus is set to -1 if an socket error occurred and the socket is not usable and 1 if the NAT traversal failed and 0 if no error occurred
387
*/
388
void receive_local_socketID_cb(socketID_handle local_socketID,int errorstatus){
389 a0a1f630 KristianBeckers
390
  printf("--Monitoring module: received a packet notification \n");
391 2a178954 KristianBeckers
392 a0a1f630 KristianBeckers
}
393
394
/**
395
  * callback before a message is send: set the monitoring module packet header 
396
  * @param *arg An pointer to an packet inf struct
397
  * @param send_pkt_inf A send_pkt_type_and_dst_inf struct that holds information about the data destination
398
  * @return 1 because a monitoring data header is set 
399
  */
400
int set_monitoring_module_packet_header(void *arg,send_pkt_type_and_dst_inf *send_pkt_inf){
401
402
  printf("--Monitoring module: set monitoring module packet header \n");
403
404
  char monitoring_module_packet_header[16];
405
  memset(monitoring_module_packet_header,'1',16);
406
407
  arg = (void *)monitoring_module_packet_header;
408
409
  return 1;
410
411
}
412
413
414
/**
415
  * callback when data is send 
416
  * @param *arg An pointer to an packet inf struct 
417
  */
418
void received_data_monitoring_cb(void *arg){
419
420
  printf("--Monitoring module: received data notification \n");
421
422
}
423
424
/**
425
  * callback when data is send
426
  * @param *arg A pointer to a monitoring data information struct
427
  */
428
void send_data_monitoring_cb(void *arg){
429
430
  printf("--Monitoring module: send data notification  \n");
431
432
}
433
434
/**
435
  * callback before data is send: monitoring module data header
436
  * @param arg A monitoring data information struct
437
  * @param send_pkt_inf A send_pkt_type_and_dst_inf struct that holds information about the data destination
438
  * @return returns 0 for no header set and 1 for header set
439
  */
440
int set_monitoring_module_data_header(void *arg, send_pkt_type_and_dst_inf *send_pkt_inf){
441
442
  printf("--Monitoring module: set monitoring module data header \n");
443
444
  char monitoring_module_data_header[16];
445
  memset(monitoring_module_data_header,'1',16);
446
447
  arg = (void *)monitoring_module_data_header;
448
  return 1;
449
}
450
451
/**
452
  * This is just a dummy funtion that creates a socketID
453
  * @param peerID
454
  * @return A socketID handle
455
  */
456
socketID_handle getRemoteSocketID(int peerID){
457 6759fdd0 AlessandroRusso
458 a0a1f630 KristianBeckers
  socketID_handle remote_socketID = malloc(SOCKETID_SIZE);
459
  int port;
460
461
  switch (peerID){
462
463
  case 1:
464
    port = 9001;
465
    break;
466
467
  case 2:
468
    port = 9002;
469
    break;
470
    
471
  case 3:
472
    port = 9003;
473
    break;
474
475
  }
476
477
  struct sockaddr_in udpaddr;
478
  udpaddr.sin_family = AF_INET;
479
  udpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
480
  udpaddr.sin_port = htons(port);
481
  
482
  socketaddrgen udpgen;
483
  udpgen.udpaddr = udpaddr;
484
  remote_socketID->internal_addr = udpgen;
485
  remote_socketID->external_addr = udpgen;
486
487
  return remote_socketID;
488 6759fdd0 AlessandroRusso
489 a0a1f630 KristianBeckers
}
490
491
492
/**
493
  * The main function of the echo server demo application for the messaging layer. 
494
  * @param argc The argument count
495 6759fdd0 AlessandroRusso
  * @param *argv[] The demo application needs a peer ID as argument. In the current version the peerID has to be either 1,2,or 3
496 a0a1f630 KristianBeckers
  * @return 1 if an error occurred 0 if everything went allright
497
  */
498
int main(int argc, char *argv[]){
499
500
 
501
  if (argc < 2){
502
503
    fprintf(stderr, "Usage: %s <peerID>\n", argv[0]);
504
    exit(1);
505
506
  }
507
508
  if (atoi(argv[1]) > 3 || atoi(argv[1]) < 1){
509
510
    fprintf(stderr, "Usage: <peerID> has to be 1,2 or 3\n");
511
    exit(1);
512
  }
513
514
  /// register the monitoring module callbacks 
515
  /// packet level callbacks 
516 da5dade7 MarcoBiazzini
  mlRegisterGetRecvPktInf(&received_a_packet_monitoring_cb);
517
  mlRegisterSetMonitoringHeaderPktCb(&set_monitoring_module_packet_header);
518 a0a1f630 KristianBeckers
  /// data level callbacks 
519 da5dade7 MarcoBiazzini
  mlRegisterGetRecvDataInf(&received_data_monitoring_cb);
520
  mlRegisterGetSendDataInf(&send_data_monitoring_cb);
521
  mlRegisterSetMonitoringHeaderDataCb(&set_monitoring_module_data_header);
522 a0a1f630 KristianBeckers
523
  /// register transmission callbacks
524 da5dade7 MarcoBiazzini
  mlRegisterRecvConnectionCb(&receive_conn_cb);
525
  mlRegisterErrorConnectionCb(&conn_fail_cb);
526 a0a1f630 KristianBeckers
527
  /// register a stun server on localhost with port 3478 
528 da5dade7 MarcoBiazzini
  //mlSetStunServer(3478,NULL);
529 a0a1f630 KristianBeckers
530
  //int peerID;
531
  peerID = atoi(argv[1]);
532
533
  /* initiate a libevent instance  */
534
  //event_init();
535
536
  /// initiate a libevent vers.2 
537
  //struct event_base *base;
538
  base = event_base_new();
539
  
540
  /// set a recv timeout value of 2 seconds and 5 miliseconds
541
  struct timeval timeout_value;
542
  timeout_value.tv_sec = 3;
543
  timeout_value.tv_usec = 5;
544
  //set_Recv_Timeout(timeout_value);
545
546
  /// create an event that prints the peerID on the screen periodically 
547
  struct timeval timeout_value_print = {8,0};
548
  struct event *ev;
549
  ev = evtimer_new(base,print_peerID_cb,NULL);
550
  event_add(ev,&timeout_value_print);
551
552
  switch(peerID){
553
554
    case 1:
555
556
      printf("--echoServer: This is peer 1 \n ");
557
558
      /// call the init method and set the recv_data method to polling 
559
      boolean recv_data_cb1 = false;
560 da5dade7 MarcoBiazzini
      mlInit(recv_data_cb1,timeout_value,9001,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
561 a0a1f630 KristianBeckers
562
      /// create a remote socketID --> implemented as a hack right now. In the final application a more clean solution of how to get the nodeIDs is required
563
      rm_socketID = getRemoteSocketID(2);
564
565
      /// poll the messaging layer every 2 seconds if data has arrived. Start after 5 seconds.
566
      struct timeval timeout_value_recv = {5,0};
567
      struct event *ev;    
568
      ev = evtimer_new(base,recv_data_from_peer_poll,NULL);
569
      event_add(ev,&timeout_value_recv);      
570
571
      /// Try to open a connection after 4 seconds
572
      struct timeval timeout_value_open_conn = {4,0};
573
      struct event *ev1;
574
      ev1 = evtimer_new(base,open_connection_cb,NULL);
575
      event_add(ev1,&timeout_value_open_conn);
576
577
    break;
578
579
    case 2: 
580
581
      printf("--echoServer: This is peer 2 \n ");
582
583
      /// call the init method and set the recv_data method to callback 
584
      boolean recv_data_cb2 = true;
585 da5dade7 MarcoBiazzini
      mlInit(recv_data_cb2,timeout_value,9002,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
586 a0a1f630 KristianBeckers
587
      /// register a recv data callback for the  
588 da5dade7 MarcoBiazzini
      mlRegisterRecvDataCb(&recv_data_from_peer_cb,12);
589 a0a1f630 KristianBeckers
590
    break; 
591
592
593
    case 3:
594
      
595
      printf("--echoServer: This is peer 3 \n ");
596
597
      /// call the init method and set the recv_data method to callback
598
      boolean recv_data_cb3 = false;
599 da5dade7 MarcoBiazzini
      mlInit(recv_data_cb3,timeout_value,9003,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
600 a0a1f630 KristianBeckers
601
      /// create a remote socketID --> implemented as a hack right now. In the final application a more clean solution of how to get the nodeIDs is required
602
      rm_socketID = getRemoteSocketID(1);
603
604
      /// Try to open a connection after 4 seconds 
605
      struct timeval timeout_value_open_conn_1 = {6,0};
606
      struct event *ev3;
607
      ev3 = evtimer_new(base,open_connection_cb,NULL);
608
      event_add(ev3,&timeout_value_open_conn_1);
609
610
    break;
611
    
612
  }
613
614
  printf("event base dispatch \n");
615
  event_base_dispatch(base);
616
617
  return 0;
618
619
}