Revision 16c26378

View differences:

Makefile.am
1
SUBDIRS = . tests
2

  
1 3
INCLUDES = -I$(top_srcdir)/include/ -I$(top_srcdir)/dclog
2 4
noinst_LIBRARIES = libml.a
3 5
libml_a_SOURCES = BUGS.txt ml.c transmissionHandler.c util/stun.c \
4 6
	util/udpSocket.c
5 7

  
6
bin_PROGRAMS = echoServer
7

  
8
echoServer_SOURCES = echoServer.c
9
LDADD = $(top_builddir)/common/libcommon.a libml.a $(top_builddir)/dclog/libdclog.a -lm
10

  
11

  
12 8
# testMessaginglayer: echoServer.c ml.h ml.c transmissionHandler.h transmissionHandler.c util/stun.h util/stun.c util/udpSocket.h util/udpSocket.c
13 9
#        ${COMPILER} -o echoServer.o echoServer.c ml.h ml.c transmissionHandler.h transmissionHandler.c util/stun.h util/stun.c util/udpSocket.h util/udpSocket.c ${EVENT} ${MATH} ${GDB}
14 10

  
15

  
16 11
libml_a_LIBADD = $(top_builddir)/dclog/libdclog.a
echoServer.c
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
      send_params sParams;
133
  
134
      send_Data(connectionID,buffer,size,msgtype,&sParams);
135

  
136
}
137

  
138
/**
139
  * Send a file to a peer. This function is implemented as timeout callback in the libevent
140
  * @param fd A file descriptor
141
  * @param event A libevent event 
142
  * @param arg An arg pointer
143
  */
144

  
145
void send_file_to_peer(int fd, short event,void *arg){
146

  
147

  
148
  printf("--echoServer: Send file to peer 3 \n");
149

  
150
  char buf[20000];
151
  FILE *testfileread;
152
  testfileread  = fopen("testfile.txt","r");
153

  
154
  if (testfileread == NULL)
155
    {
156
      fprintf(stderr,"Could not open file for reading!\n");
157
    }
158

  
159
  /// open a file and write it into a buffer 
160
  fseek (testfileread , 0 , SEEK_END);
161
  long lSize = ftell (testfileread);
162
  rewind (testfileread);
163
  int result = fread(buf,1,lSize,testfileread);
164
  fclose(testfileread);
165

  
166
  int bufsize = sizeof(buf);
167
  unsigned char msgtype = 13;
168
  int connectionID = 0;
169
  send_params sParams;
170

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

  
177
}
178

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

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

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

  
191
  if(peerID == 1){
192

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

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

  
209
} 
210

  
211

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

  
220
  int con_id = open_connection(rm_socketID,&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(con_id < 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
}
tests/Makefile.am
1
INCLUDES = -I$(top_srcdir)/include/ -I$(top_srcdir)/dclog -I$(top_srcdir)/ml
2

  
3
bin_PROGRAMS = echoServer
4

  
5
echoServer_SOURCES = echoServer.c
6
echoServer_LDADD = $(top_builddir)/common/libcommon.a $(top_builddir)/ml/libml.a $(top_builddir)/dclog/libdclog.a -lm
tests/echoServer.c
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
      send_params sParams;
133
  
134
      send_Data(connectionID,buffer,size,msgtype,&sParams);
135

  
136
}
137

  
138
/**
139
  * Send a file to a peer. This function is implemented as timeout callback in the libevent
140
  * @param fd A file descriptor
141
  * @param event A libevent event 
142
  * @param arg An arg pointer
143
  */
144

  
145
void send_file_to_peer(int fd, short event,void *arg){
146

  
147

  
148
  printf("--echoServer: Send file to peer 3 \n");
149

  
150
  char buf[20000];
151
  FILE *testfileread;
152
  testfileread  = fopen("testfile.txt","r");
153

  
154
  if (testfileread == NULL)
155
    {
156
      fprintf(stderr,"Could not open file for reading!\n");
157
    }
158

  
159
  /// open a file and write it into a buffer 
160
  fseek (testfileread , 0 , SEEK_END);
161
  long lSize = ftell (testfileread);
162
  rewind (testfileread);
163
  int result = fread(buf,1,lSize,testfileread);
164
  fclose(testfileread);
165

  
166
  int bufsize = sizeof(buf);
167
  unsigned char msgtype = 13;
168
  int connectionID = 0;
169
  send_params sParams;
170

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

  
177
}
178

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

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

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

  
191
  if(peerID == 1){
192

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

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

  
209
} 
210

  
211

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

  
220
  int con_id = open_connection(rm_socketID,&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(con_id < 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
}

Also available in: Unified diff