Statistics
| Branch: | Revision:

ml / echoServer.c @ 8b17961c

History | View | Annotate | Download (16.6 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 "../includes/ml.h"
54

    
55
/**
56
  * A pointer to a libevent 
57
  */
58
struct event_base *base;
59

    
60
/**
61
  * A peerID provided at application start
62
  */
63
int peerID;
64

    
65
/**
66
  * define a maximum number of connections
67
  */
68
#define maxConnections 10000
69

    
70
/**
71
  * an connections array
72
  */
73
int connections[maxConnections];
74

    
75
/**
76
  * the initial number of connections
77
  */
78
int nr_connections = 0;
79

    
80
/**
81
  * A local socketID handle 
82
  */
83
socketID_handle my_socketID;
84

    
85
/**
86
  * A remote socketID handle
87
  */
88
socketID_handle rm_socketID;
89

    
90
/**
91
 * An integer that is passed as an argument in open_connection
92
 */
93
int connection_argument;
94

    
95
/**
96
  * create a callback for the periodic printouts on the screen
97
  * @param fd A file descriptor
98
  * @param event A libevent event 
99
  * @param arg An arg pointer
100
  */
101
void print_peerID_cb(int fd, short event,void *arg){
102

    
103
  ///print the peerID
104
  printf("--echoServer: This peers ID is %d \n",peerID);
105
  ///Add a timeout event to the event list
106
  struct timeval timeout_value_print = {3,0};
107
  struct event *ev;
108
  ev = evtimer_new(base,print_peerID_cb,NULL);
109
  event_add(ev,&timeout_value_print);
110

    
111
}
112

    
113

    
114
/**
115
  * Send data to another peer. This function is implemented as timeout callback in the libevent
116
  * @param fd A file descriptor
117
  * @param event A libevent event 
118
  * @param arg An arg pointer
119
  */
120
void send_data_to_peer(int fd, short event,void *arg){
121

    
122
  printf("--echoServer: Send data to peer 2 \n");
123
  printf("               ++sending 10.000 'a'  \n");
124
      /// transmit data to peer 2  
125
      int size = 10000;
126
      char buffer[size];
127
      memset(buffer,'a',size);
128
      unsigned char msgtype = 12;
129
      int connectionID = 0;
130
      //strcpy(buffer, "Message for peer 2 \n");
131
      send_params sParams;
132
  
133
      send_Data(connectionID,buffer,size,msgtype,&sParams);
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
  send_params sParams;
169

    
170
  fprintf(stderr,"The buffersize is %i\n",bufsize);
171
  if (result != lSize){ fprintf(stderr,"Could not read file!\n");  }
172
  else { printf("The size of the file is %ld \n",lSize); }
173
  
174
  send_Data(connectionID,buf,(int)lSize,msgtype,&sParams);
175

    
176
}
177

    
178
/**
179
  * A callback function that tells a connection has been established. 
180
  * @param connectionID The connection ID
181
  * @param *arg An argument for data about the connection 
182
  */
183
void receive_conn_cb (int connectionID, void *arg){
184

    
185
  printf("--echoServer: Received incoming connection connectionID %d  \n",connectionID );
186

    
187
  connections[nr_connections] = connectionID;
188
  nr_connections++;
189

    
190
  if(peerID == 1){
191

    
192
  struct timeval timeout_value = {5,0};
193
  struct event *ev;
194
  ev = evtimer_new(base,send_data_to_peer,NULL);
195
  event_add(ev,&timeout_value);
196
  
197
  }else 
198
    if(peerID == 3){
199

    
200
      /* send a file to peer 1 */
201
      struct timeval timeout_value_send_file = {12,0};
202
      struct event *ev3;
203
      ev3 = evtimer_new(base,send_file_to_peer,NULL);
204
      event_add(ev3,&timeout_value_send_file);
205
    
206
    }
207

    
208
} 
209

    
210

    
211
/**
212
  * A connection is poened callback
213
  * @param fd A file descriptor
214
  * @param event A libevent event 
215
  * @param arg An arg pointer
216
  */
217
void open_connection_cb(int fd, short event,void *arg){
218

    
219
  int connectionID;
220
  int result = open_connection(rm_socketID,&connectionID,&receive_conn_cb,&connection_argument); ///< try to open a connection to another peer. 
221
  ///If the result is zero the event is resheduled into the event list.
222
  if(result == 0){
223

    
224
    printf("open_connection failed : resheduling event\n");
225

    
226
    /* ReTry to open a connection after 3 seconds */
227
    struct timeval timeout_value_open_conn = {3,0};
228
    struct event *ev;
229
    ev = evtimer_new(base,open_connection_cb,NULL);
230
    event_add(ev,&timeout_value_open_conn);
231

    
232
  }
233

    
234
}
235

    
236
/**
237
  * The peer reveives data per polling. Implemented as a callback that is preiodically resheduled.
238
  * @param fd A file descriptor
239
  * @param event A libevent event 
240
  * @param arg An arg pointer
241
  */
242
void recv_data_from_peer_poll(int fd, short event,void *arg){
243

    
244
  printf("--echoServer: Polling for recv data \n" );
245
  
246
  char buffer[20000];
247
  int size = 0;
248
  //unsigned char msgtype = 12;
249
  //int connectionID = 0;
250
  int returnValue = 0;
251
  recv_params recvp;
252
  int i = 0;
253
  int connectionID;
254

    
255
  printf("--echoServer: before recv_Data \n");
256
  
257
  printf("nr_connections %d \n ",nr_connections );
258

    
259
  //iterate through all connections
260
  for(i=0; i <  nr_connections;i++){
261

    
262
    connectionID = connections[i];
263
    
264

    
265
  returnValue = recv_Data(connectionID,buffer,&size,&recvp);
266

    
267
  //printf("--echoServer: after recv_Data \n");
268

    
269
  
270
  if (returnValue == 1){
271

    
272
    //printf("--echoServer: after recv_Data  \n");
273

    
274
    unsigned char msgtype  = recvp.msgtype;
275
    int connectionID = recvp.connectionID;
276

    
277
    printf("--echoServer: msgtype is %d \n",msgtype);
278
    printf("--echoServer: size is %d \n",size);
279
    printf("--echoServer: connectionID is %d \n",connectionID);
280

    
281
    if(msgtype == 12){
282
    
283
    char recv_buf[size];
284
    memcpy(recv_buf,buffer,size);
285

    
286
    printf("--echoServer: Received data from polling: \n\t %s \n\t buflen %d \n",recv_buf,size);
287
    
288
    // set the event again
289
    struct timeval timeout_value_recv = {10,0};
290
    struct event *ev;
291
    ev = evtimer_new(base,recv_data_from_peer_poll,NULL);
292
    event_add(ev,&timeout_value_recv);
293
    }else 
294
      if(msgtype == 13){
295

    
296
        printf("received testfile: msgtype 13 \n");
297

    
298
        //printf("%s \n" , buffer );
299
        /*
300
        FILE *testfile1 = NULL;
301
        
302
        printf("received testfile: msgtype 13 \n");
303

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

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

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

310
        int cur_char;
311
        for(cur_char = 0; cur_char < size;++cur_char)
312
          {
313
            fputc(buffer[cur_char],testfile1);
314
          }
315
        
316
        fclose(testfile1);
317
        
318
        printf(" testfile fully worked  \n ");
319
        */
320
      }
321
 
322
  }else{
323

    
324
    printf("--echoServer: polling ...no data arrived \n");
325
    // set the event again
326
  struct timeval timeout_value_recv = {8,0};
327
  struct event *ev;
328
  ev = evtimer_new(base,recv_data_from_peer_poll,NULL);
329
  event_add(ev,&timeout_value_recv);
330

    
331
    }
332
  }
333
}
334

    
335
/**
336
  * The peer receives data per callback from the messaging layer. 
337
  * @param *buffer A pointer to the buffer
338
  * @param buflen The length of the buffer
339
  * @param msgtype The message type 
340
  * @param *arg An argument that receives metadata about the received data
341
  */
342
void recv_data_from_peer_cb(char *buffer,int buflen,unsigned char msgtype,void *arg){
343

    
344
  printf("--echoServer: Received data from callback: \n\t %s \t msgtype %d \t buflen %d \n",buffer,msgtype,buflen ); 
345

    
346
  if(peerID == 2){
347

    
348
    printf("--echoServer: Send data to peer 1 \n");
349
    
350
    /* transmit data to peer 1  */
351

    
352
    int size = 10000;
353
    char buffer[size];
354
    memset(buffer,'a',size);
355
    int connectionID = 0;
356
    send_params sParams;
357

    
358
    send_Data(connectionID,buffer,size,msgtype,&sParams);
359

    
360
  }
361
  
362
}
363

    
364
/**
365
  * A funtion that prints a connection establishment has failed
366
  * @param connectionID The connection ID
367
  * @param *arg An argument for data about the connection
368
  */
369
void conn_fail_cb(int connectionID,void *arg){
370

    
371
  printf("--echoServer: ConnectionID %d  could not be established \n ",connectionID);
372

    
373
}
374

    
375
/**
376
  * callback for a received packet notification from the messaging layer
377
  * @param *arg An argument for a recv packet infromation struct
378
  */
379
void received_a_packet_monitoring_cb(void *arg){
380

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

    
385
/**
386
 * A funtion that is a callback for the messaging layer when a new socketId is ready to be used
387
 * SocketIDhandle is a handle for the local socketID
388
 * 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
389
*/
390
void receive_local_socketID_cb(socketID_handle local_socketID,int errorstatus){
391

    
392
  printf("--Monitoring module: received a packet notification \n");
393

    
394
}
395

    
396
/**
397
  * callback before a message is send: set the monitoring module packet header 
398
  * @param *arg An pointer to an packet inf struct
399
  * @param send_pkt_inf A send_pkt_type_and_dst_inf struct that holds information about the data destination
400
  * @return 1 because a monitoring data header is set 
401
  */
402
int set_monitoring_module_packet_header(void *arg,send_pkt_type_and_dst_inf *send_pkt_inf){
403

    
404
  printf("--Monitoring module: set monitoring module packet header \n");
405

    
406
  char monitoring_module_packet_header[16];
407
  memset(monitoring_module_packet_header,'1',16);
408

    
409
  arg = (void *)monitoring_module_packet_header;
410

    
411
  return 1;
412

    
413
}
414

    
415

    
416
/**
417
  * callback when data is send 
418
  * @param *arg An pointer to an packet inf struct 
419
  */
420
void received_data_monitoring_cb(void *arg){
421

    
422
  printf("--Monitoring module: received data notification \n");
423

    
424
}
425

    
426
/**
427
  * callback when data is send
428
  * @param *arg A pointer to a monitoring data information struct
429
  */
430
void send_data_monitoring_cb(void *arg){
431

    
432
  printf("--Monitoring module: send data notification  \n");
433

    
434
}
435

    
436
/**
437
  * callback before data is send: monitoring module data header
438
  * @param arg A monitoring data information struct
439
  * @param send_pkt_inf A send_pkt_type_and_dst_inf struct that holds information about the data destination
440
  * @return returns 0 for no header set and 1 for header set
441
  */
442
int set_monitoring_module_data_header(void *arg, send_pkt_type_and_dst_inf *send_pkt_inf){
443

    
444
  printf("--Monitoring module: set monitoring module data header \n");
445

    
446
  char monitoring_module_data_header[16];
447
  memset(monitoring_module_data_header,'1',16);
448

    
449
  arg = (void *)monitoring_module_data_header;
450
  return 1;
451
}
452

    
453
/**
454
  * This is just a dummy funtion that creates a socketID
455
  * @param peerID
456
  * @return A socketID handle
457
  */
458
socketID_handle getRemoteSocketID(int peerID){
459

    
460
  socketID_handle remote_socketID = malloc(SOCKETID_SIZE);
461
  int port;
462

    
463
  switch (peerID){
464

    
465
  case 1:
466
    port = 9001;
467
    break;
468

    
469
  case 2:
470
    port = 9002;
471
    break;
472
    
473
  case 3:
474
    port = 9003;
475
    break;
476

    
477
  }
478

    
479
  struct sockaddr_in udpaddr;
480
  udpaddr.sin_family = AF_INET;
481
  udpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
482
  udpaddr.sin_port = htons(port);
483
  
484
  socketaddrgen udpgen;
485
  udpgen.udpaddr = udpaddr;
486
  remote_socketID->internal_addr = udpgen;
487
  remote_socketID->external_addr = udpgen;
488

    
489
  return remote_socketID;
490

    
491
}
492

    
493

    
494
/**
495
  * The main function of the echo server demo application for the messaging layer. 
496
  * @param argc The argument count
497
  * @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
498
  * @return 1 if an error occurred 0 if everything went allright
499
  */
500
int main(int argc, char *argv[]){
501

    
502
 
503
  if (argc < 2){
504

    
505
    fprintf(stderr, "Usage: %s <peerID>\n", argv[0]);
506
    exit(1);
507

    
508
  }
509

    
510
  if (atoi(argv[1]) > 3 || atoi(argv[1]) < 1){
511

    
512
    fprintf(stderr, "Usage: <peerID> has to be 1,2 or 3\n");
513
    exit(1);
514
  }
515

    
516
  /// register the monitoring module callbacks 
517
  /// packet level callbacks 
518
  register_Get_recv_pkt_inf(&received_a_packet_monitoring_cb);
519
  register_Set_monitoring_header_pkt_cb(&set_monitoring_module_packet_header);
520
  /// data level callbacks 
521
  register_get_recv_data_inf(&received_data_monitoring_cb);
522
  register_get_send_data_inf(&send_data_monitoring_cb);
523
  register_set_monitoring_header_data_cb(&set_monitoring_module_data_header);
524

    
525
  /// register transmission callbacks
526
  register_Recv_connection_cb(&receive_conn_cb);
527
  register_Error_connection_cb(&conn_fail_cb);
528

    
529
  /// register a stun server on localhost with port 3478 
530
  //set_Stun_Server(3478,NULL);
531

    
532
  //int peerID;
533
  peerID = atoi(argv[1]);
534

    
535
  /* initiate a libevent instance  */
536
  //event_init();
537

    
538
  /// initiate a libevent vers.2 
539
  //struct event_base *base;
540
  base = event_base_new();
541
  
542
  /// set a recv timeout value of 2 seconds and 5 miliseconds
543
  struct timeval timeout_value;
544
  timeout_value.tv_sec = 3;
545
  timeout_value.tv_usec = 5;
546
  //set_Recv_Timeout(timeout_value);
547

    
548
  /// create an event that prints the peerID on the screen periodically 
549
  struct timeval timeout_value_print = {8,0};
550
  struct event *ev;
551
  ev = evtimer_new(base,print_peerID_cb,NULL);
552
  event_add(ev,&timeout_value_print);
553

    
554
  switch(peerID){
555

    
556
    case 1:
557

    
558
      printf("--echoServer: This is peer 1 \n ");
559

    
560
      /// call the init method and set the recv_data method to polling 
561
      boolean recv_data_cb1 = false;
562
      init_messaging_layer(recv_data_cb1,timeout_value,9001,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
563

    
564
      /// 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
565
      rm_socketID = getRemoteSocketID(2);
566

    
567
      /// poll the messaging layer every 2 seconds if data has arrived. Start after 5 seconds.
568
      struct timeval timeout_value_recv = {5,0};
569
      struct event *ev;    
570
      ev = evtimer_new(base,recv_data_from_peer_poll,NULL);
571
      event_add(ev,&timeout_value_recv);      
572

    
573
      /// Try to open a connection after 4 seconds
574
      struct timeval timeout_value_open_conn = {4,0};
575
      struct event *ev1;
576
      ev1 = evtimer_new(base,open_connection_cb,NULL);
577
      event_add(ev1,&timeout_value_open_conn);
578

    
579
    break;
580

    
581
    case 2: 
582

    
583
      printf("--echoServer: This is peer 2 \n ");
584

    
585
      /// call the init method and set the recv_data method to callback 
586
      boolean recv_data_cb2 = true;
587
      init_messaging_layer(recv_data_cb2,timeout_value,9002,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
588

    
589
      /// register a recv data callback for the  
590
      register_Recv_data_cb(&recv_data_from_peer_cb,12);
591

    
592
    break; 
593

    
594

    
595
    case 3:
596
      
597
      printf("--echoServer: This is peer 3 \n ");
598

    
599
      /// call the init method and set the recv_data method to callback
600
      boolean recv_data_cb3 = false;
601
      init_messaging_layer(recv_data_cb3,timeout_value,9003,NULL,3478,NULL,&receive_local_socketID_cb,(void*)base);
602

    
603
      /// 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
604
      rm_socketID = getRemoteSocketID(1);
605

    
606
      /// Try to open a connection after 4 seconds 
607
      struct timeval timeout_value_open_conn_1 = {6,0};
608
      struct event *ev3;
609
      ev3 = evtimer_new(base,open_connection_cb,NULL);
610
      event_add(ev3,&timeout_value_open_conn_1);
611

    
612
    break;
613
    
614
  }
615

    
616
  printf("event base dispatch \n");
617
  event_base_dispatch(base);
618

    
619
  return 0;
620

    
621
}