Statistics
| Branch: | Revision:

ml / tests / echoServer.c @ 6f256447

History | View | Annotate | Download (16.5 KB)

1
/*
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
#include "ml.h"
54
#include "transmissionHandler.h"
55

    
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
 * An integer that is passed as an argument in open_connection
93
 */
94
int connection_argument;
95

    
96
/**
97
  * 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

    
104
  ///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

    
112
}
113

    
114

    
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
  
133
      mlSendData(connectionID,buffer,size,msgtype,NULL);
134

    
135
}
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
  mlSendData(connectionID,buf,(int)lSize,msgtype,NULL);
174

    
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
/**
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

    
218
  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
  ///If the result is zero the event is resheduled into the event list.
221
  if(con_id < 0){
222

    
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
  returnValue = mlRecvData(connectionID,buffer,&size,&recvp);
265

    
266
  //printf("--echoServer: after mlRecvData \n");
267

    
268
  
269
  if (returnValue == 1){
270

    
271
    //printf("--echoServer: after mlRecvData  \n");
272

    
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
    mlSendData(connectionID,buffer,size,msgtype,NULL);
357

    
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
  * callback for a received packet notification from the messaging layer
375
  * @param *arg An argument for a recv packet infromation struct
376
  */
377
void received_a_packet_monitoring_cb(void *arg){
378

    
379
  printf("--Monitoring module: received a packet notification \n");
380
  
381
}
382

    
383
/**
384
 * 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

    
390
  printf("--Monitoring module: received a packet notification \n");
391

    
392
}
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

    
458
  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

    
489
}
490

    
491

    
492
/**
493
  * The main function of the echo server demo application for the messaging layer. 
494
  * @param argc The argument count
495
  * @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
  * @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
  mlRegisterGetRecvPktInf(&received_a_packet_monitoring_cb);
517
  mlRegisterSetMonitoringHeaderPktCb(&set_monitoring_module_packet_header);
518
  /// data level callbacks 
519
  mlRegisterGetRecvDataInf(&received_data_monitoring_cb);
520
  mlRegisterGetSendDataInf(&send_data_monitoring_cb);
521
  mlRegisterSetMonitoringHeaderDataCb(&set_monitoring_module_data_header);
522

    
523
  /// register transmission callbacks
524
  mlRegisterRecvConnectionCb(&receive_conn_cb);
525
  mlRegisterErrorConnectionCb(&conn_fail_cb);
526

    
527
  /// register a stun server on localhost with port 3478 
528
  //mlSetStunServer(3478,NULL);
529

    
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
      mlInit(recv_data_cb1,timeout_value,9001,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
561

    
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
      mlInit(recv_data_cb2,timeout_value,9002,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
586

    
587
      /// register a recv data callback for the  
588
      mlRegisterRecvDataCb(&recv_data_from_peer_cb,12);
589

    
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
      mlInit(recv_data_cb3,timeout_value,9003,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
600

    
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
}