~ubuntu-branches/ubuntu/intrepid/gnunet/intrepid

« back to all changes in this revision

Viewing changes to src/applications/testbed/commands.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-07-03 14:17:00 UTC
  • mfrom: (1.2.11 upstream) (16 hardy)
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: james.westby@ubuntu.com-20080703141700-355g0g164kaw2kwk
Tags: 0.8.0-2
* Creating /var/run/gnunetd in initscript in case /var/run is on a tmpfs.
* Adding versioned conflicts/replaces against gnunet in order to allow etch to
  lenny upgrades.
* Updating contact address in po files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
     This file is part of GNUnet.
3
 
     (C) 2003, 2004 Christian Grothoff (and other contributing authors)
4
 
 
5
 
     GNUnet is free software; you can redistribute it and/or modify
6
 
     it under the terms of the GNU General Public License as published
7
 
     by the Free Software Foundation; either version 2, or (at your
8
 
     option) any later version.
9
 
 
10
 
     GNUnet is distributed in the hope that it will be useful, but
11
 
     WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
     General Public License for more details.
14
 
 
15
 
     You should have received a copy of the GNU General Public License
16
 
     along with GNUnet; see the file COPYING.  If not, write to the
17
 
     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
 
     Boston, MA 02111-1307, USA.
19
 
*/
20
 
 
21
 
/**
22
 
 * @file applications/testbed/commands.c
23
 
 * @brief the commands available in the testbed
24
 
 * @author Ronaldo Alves Ferreira
25
 
 * @author Christian Grothoff
26
 
 * @author Murali Krishan Ramanathan
27
 
 *
28
 
 * Todo:
29
 
 * - test add-ssh-node
30
 
 * - implement shutdown (in particular, kill ssh connections / processes!)
31
 
 * - design and implement better topology management
32
 
 * - test
33
 
 */
34
 
 
35
 
#include "platform.h"
36
 
#include "gnunet_protocols.h"
37
 
#include "gnunet_getoption_lib.h"
38
 
#include "gnunet_stats_lib.h"
39
 
#include "testbed.h"
40
 
#include "commands.h"
41
 
#include "socket.h"
42
 
 
43
 
/**
44
 
 * @brief struct keeping per-peer information for the testbed
45
 
 */
46
 
typedef struct {
47
 
  /** IP address of the peer */
48
 
  IPaddr             ip;
49
 
  /** CS port of the peer */
50
 
  unsigned short     port;
51
 
  /** string describing the peer address */
52
 
  char  * ips;
53
 
  /** socket to communicate with the peer */
54
 
  GNUNET_TCP_SOCKET sock;
55
 
  /** hello message identifying the peer in the network */
56
 
  P2P_hello_MESSAGE * helo;
57
 
  /** if we're using ssh, what is the PID of the
58
 
      ssh process? (-1 for unencrypted direct connections) */
59
 
  pid_t ssh;
60
 
} NODE_INFO;
61
 
 
62
 
/**
63
 
 * List of nodes known to the testbed.
64
 
 */
65
 
static NODE_INFO * nodes = NULL;
66
 
 
67
 
/**
68
 
 * Number of known nodes, size of the nodes array.
69
 
 */
70
 
static unsigned int nnodes = 0;
71
 
 
72
 
/**
73
 
 * Should the driver exit?
74
 
 */
75
 
int do_quit = NO;
76
 
 
77
 
/**
78
 
 * Convert the strings ss and ds to peer-identifiers (ints) s and d
79
 
 * respectively.  Aborts the method containing the macro with an error
80
 
 * message if the peer-IDs are not within range.
81
 
 */
82
 
#define CHECK_SRC_DST(s, d, ss, ds)     \
83
 
  s = atoi(ss);                 \
84
 
  d = atoi(ds);                             \
85
 
  if (s < 0 || s >= nnodes || d < 0 || d >= nnodes) {  \
86
 
    XPRINTF("Invalid src (%s) or dst (%s)\n", ss, ds);  \
87
 
    return -1;                                         \
88
 
  }
89
 
 
90
 
/**
91
 
 * Convert the string ps to a peer-id p and abort the current method
92
 
 * with an error message if ps is not a valid peer-id.
93
 
 */
94
 
#define CHECK_PEER(p, ps)       \
95
 
  p = atoi(ps);                         \
96
 
  if (p < 0 || p >= nnodes) {                   \
97
 
    XPRINTF("Invalid peer value %s\n", ps);     \
98
 
    return -1;                                  \
99
 
  }
100
 
 
101
 
/**
102
 
 * Send a message to peer 'peer' of type 'msgType'
103
 
 * the given size and data.
104
 
 */
105
 
static int sendMessage(unsigned msgType,
106
 
                       int peer,
107
 
                       unsigned short argSize,
108
 
                       void *arg) {
109
 
  TESTBED_CS_MESSAGE * msg;
110
 
  int msgsz;
111
 
 
112
 
  /* Assume peer value is valid. */
113
 
  if (argSize + sizeof(TESTBED_CS_MESSAGE) > 65535)
114
 
    errexit("Message body too big for sendMessage: %s\n",
115
 
            argSize);
116
 
 
117
 
  msgsz = sizeof(TESTBED_CS_MESSAGE)+argSize;
118
 
  msg = MALLOC(msgsz);
119
 
  msg->header.size
120
 
    = htons(msgsz);
121
 
  msg->header.type
122
 
    = htons(CS_PROTO_testbed_REQUEST);
123
 
  msg->msgType
124
 
    = htonl(msgType);
125
 
  memcpy(&((TESTBED_CS_MESSAGE_GENERIC*)msg)->data[0],
126
 
         arg,
127
 
         argSize);
128
 
  msgsz = writeToSocket(&nodes[peer].sock,
129
 
                        &msg->header);
130
 
  FREE(msg);
131
 
  if (msgsz == SYSERR) {
132
 
    XPRINTF(" Could not send message to peer %s.\n",
133
 
           nodes[peer].ips);
134
 
    return SYSERR;
135
 
  }
136
 
  return OK;
137
 
}
138
 
 
139
 
/**
140
 
 * Read a result from the given peer.  Print
141
 
 * an error message if the peer fails to respond.
142
 
 *
143
 
 * @return OK on success, SYSERR on error
144
 
 */
145
 
static int readResult(int peer,
146
 
                      int * result) {
147
 
  if (OK != readTCPResult(&nodes[peer].sock,
148
 
                          result)) {
149
 
    XPRINTF(" peer %s is not responding.\n",
150
 
           nodes[peer].ips);
151
 
    return SYSERR;
152
 
  }
153
 
  return OK;
154
 
}
155
 
 
156
 
/* ****************** individual commands ********** */
157
 
 
158
 
 
159
 
/**
160
 
 * Add a node to the configuration.
161
 
 * Arguments must be IP PORT of the peer.
162
 
 */
163
 
static int addNode(int argc, char * argv[]) {
164
 
  int currindex;
165
 
  TESTBED_hello_MESSAGE * hdr;
166
 
  TESTBED_GET_hello_MESSAGE req;
167
 
  int port;
168
 
  int i;
169
 
 
170
 
  if (argc != 2) {
171
 
    XPRINTF("Syntax: add-node IP PORT.\n");
172
 
    return -1;
173
 
  }
174
 
  port = atoi(argv[1]);
175
 
  for (i=0;i<nnodes;i++) {
176
 
    if ( (0 == strcmp(argv[0],
177
 
                      nodes[i].ips)) &&
178
 
         (port == nodes[i].port) ) {
179
 
      XPRINTF("Node already in use!\n");
180
 
      return -1;
181
 
    }
182
 
  }
183
 
 
184
 
 
185
 
  req.proto = 0;
186
 
  req.reserved = 0;
187
 
  /* connect */
188
 
  currindex = nnodes;
189
 
  GROW(nodes, nnodes, nnodes+1);
190
 
  nodes[currindex].ips = STRDUP(argv[0]);
191
 
  nodes[currindex].port = atoi(argv[1]);
192
 
  nodes[currindex].ssh = -1;
193
 
#ifndef MINGW
194
 
  inet_aton(argv[0], (struct in_addr*) &nodes[currindex].ip);
195
 
#else
196
 
  nodes[currindex].ip.addr.S_un.S_addr = inet_addr(argv[0]);
197
 
#endif
198
 
 
199
 
  if (SYSERR == initGNUnetClientSocket(nodes[currindex].port,
200
 
                                       nodes[currindex].ips,
201
 
                                       &nodes[currindex].sock)) {
202
 
    XPRINTF(" could not connect to %s:%d.\n",
203
 
           nodes[currindex].ips,
204
 
           nodes[currindex].port);
205
 
    return -1;
206
 
  }
207
 
 
208
 
  /* request hello */
209
 
  if (OK != sendMessage(TESTBED_GET_hello,
210
 
                        currindex,
211
 
                        sizeof(TESTBED_GET_hello_MESSAGE)-sizeof(TESTBED_CS_MESSAGE),
212
 
                        &req.proto)) {
213
 
    /* send message already printed an error message */
214
 
    destroySocket(&nodes[currindex].sock);
215
 
    FREE(nodes[currindex].ips);
216
 
    GROW(nodes,
217
 
         nnodes,
218
 
         nnodes-1);
219
 
    return -1;
220
 
  }
221
 
 
222
 
  hdr = NULL;
223
 
  if (SYSERR == readFromSocket(&nodes[currindex].sock,
224
 
                               (CS_MESSAGE_HEADER**)&hdr)) {
225
 
    XPRINTF(" peer %s is not responding.\n",
226
 
           nodes[currindex].ips);
227
 
    destroySocket(&nodes[currindex].sock);
228
 
    FREE(nodes[currindex].ips);
229
 
    GROW(nodes, nnodes, nnodes-1);
230
 
    return -1;
231
 
  }
232
 
  if ( (ntohs(hdr->header.header.type) == CS_PROTO_testbed_REPLY) &&
233
 
       (ntohs(hdr->header.header.size) >= sizeof(TESTBED_hello_MESSAGE)) &&
234
 
       (ntohl(hdr->header.msgType) == TESTBED_hello_RESPONSE) &&
235
 
       (ntohs(hdr->header.header.size) - sizeof(TESTBED_CS_MESSAGE) >= sizeof(P2P_hello_MESSAGE)) &&
236
 
       (ntohs(hdr->header.header.size) - sizeof(TESTBED_CS_MESSAGE) == P2P_hello_MESSAGE_size(&hdr->helo)) ) {
237
 
    nodes[currindex].helo
238
 
      = MALLOC(P2P_hello_MESSAGE_size(&hdr->helo));
239
 
    memcpy(nodes[currindex].helo,
240
 
           &hdr->helo,
241
 
           P2P_hello_MESSAGE_size(&hdr->helo));
242
 
  } else {
243
 
    FREE(hdr);
244
 
    destroySocket(&nodes[currindex].sock);
245
 
    XPRINTF(" peer %s did not respond with proper hello.\n",
246
 
           nodes[currindex].ips);
247
 
    FREE(nodes[currindex].ips);
248
 
    GROW(nodes, nnodes, nnodes-1);
249
 
    return -1;
250
 
  }
251
 
  FREE(hdr);
252
 
  XPRINTF("%d\n",
253
 
         currindex);
254
 
  return 0;
255
 
}
256
 
 
257
 
 
258
 
 
259
 
/**
260
 
 * Add an node reachable via ssh-tunnel to the configuration.
261
 
 * Arguments must be LOGIN, IP PORT of the peer.  Sshd must
262
 
 * be running on the default port.
263
 
 */
264
 
static int addSshNode(int argc, char * argv[]) {
265
 
  int currindex;
266
 
  TESTBED_hello_MESSAGE * hdr;
267
 
  TESTBED_GET_hello_MESSAGE req;
268
 
  int port;
269
 
  int i;
270
 
  pid_t pid;
271
 
  unsigned short lport;
272
 
  int rtc;
273
 
  int ret;
274
 
  int status;
275
 
 
276
 
  if (argc != 3) {
277
 
    XPRINTF("Syntax: add-ssh-node LOGIN IP PORT.\n");
278
 
    return -1;
279
 
  }
280
 
  port = atoi(argv[2]);
281
 
  for (i=0;i<nnodes;i++) {
282
 
    if ( (0 == strcmp(argv[1],
283
 
                      nodes[i].ips)) &&
284
 
         (port == nodes[i].port) ) {
285
 
      XPRINTF("Node already in use!\n");
286
 
      return -1;
287
 
    }
288
 
  }
289
 
 
290
 
  /* find available local port to bind to */
291
 
  for (lport=10000;lport<65535;lport++) {
292
 
    struct sockaddr_in addr;
293
 
    int s;
294
 
    const int on = 1;
295
 
 
296
 
    s = SOCKET(PF_INET, SOCK_STREAM, 0);
297
 
    if (s == -1) {
298
 
      XPRINTF("Cannot open socket: %s\n",
299
 
             STRERROR(errno));
300
 
      return -1;
301
 
    }
302
 
    if ( SETSOCKOPT(s,
303
 
                    SOL_SOCKET,
304
 
                    SO_REUSEADDR,
305
 
                    &on, sizeof(on)) < 0 )
306
 
      perror("setsockopt");
307
 
    memset(&addr,
308
 
           0,
309
 
           sizeof(addr));
310
 
    addr.sin_family
311
 
      = AF_INET;
312
 
    addr.sin_addr.s_addr
313
 
      = htonl(INADDR_ANY);
314
 
    addr.sin_port
315
 
      = htons(lport);
316
 
    if (0 == BIND(s,
317
 
                  (const struct sockaddr *) &addr,
318
 
                  sizeof(struct sockaddr_in))) {
319
 
      closefile(s);
320
 
      break; /* found port! */
321
 
    } else {
322
 
      closefile(s); /* not available, try another one... */
323
 
    }
324
 
  }
325
 
  if (lport == 65535) {
326
 
    XPRINTF(" Cannot find available local port!\n");
327
 
    return -1;
328
 
  }
329
 
 
330
 
  pid = fork();
331
 
  if (pid == 0) {
332
 
    char * sargv[7];
333
 
    char pohopo[64];
334
 
    sargv[0] = "ssh";
335
 
    sargv[1] = "-l";
336
 
    sargv[2] = argv[0]; /* login */
337
 
    sargv[3] = "-L";
338
 
    SNPRINTF(pohopo,
339
 
             64,
340
 
             "%d:%s:%d",
341
 
             lport, /* local port */
342
 
             "localhost", /* loopback on remote host */
343
 
             port /* remote port */);
344
 
    sargv[4] = pohopo;
345
 
    sargv[5] = argv[1]; /* remote hostname */
346
 
    sargv[6] = NULL; /* last argument */
347
 
    execvp("ssh",
348
 
           sargv);
349
 
    LOG(LOG_ERROR,
350
 
        " execvp failed: %s\n",
351
 
        STRERROR(errno));
352
 
    exit(-1);
353
 
  }
354
 
  if (pid == -1) {
355
 
    XPRINTF("Failed to fork: %s\n",
356
 
           STRERROR(errno));
357
 
    return -1;
358
 
  }
359
 
 
360
 
 
361
 
  req.proto = 0;
362
 
  req.reserved = 0;
363
 
  /* connect */
364
 
  currindex = nnodes;
365
 
  GROW(nodes, nnodes, nnodes+1);
366
 
  nodes[currindex].ips = STRDUP("localhost");
367
 
  nodes[currindex].port = lport;
368
 
  nodes[currindex].ssh = pid;
369
 
#ifndef MINGW
370
 
  inet_aton(argv[0], (struct in_addr*) &nodes[currindex].ip);
371
 
#else
372
 
  nodes[currindex].ip.addr.S_un.S_addr = inet_addr(argv[0]);
373
 
#endif
374
 
 
375
 
  /* FIXME: wait a bit to give ssh a chance to connect... */
376
 
  rtc = 0; /* number of retries */
377
 
  while (rtc < 5) {
378
 
    ret = initGNUnetClientSocket(nodes[currindex].port,
379
 
                                 nodes[currindex].ips,
380
 
                                 &nodes[currindex].sock);
381
 
    if (ret == OK)
382
 
      break;
383
 
    rtc++;
384
 
    gnunet_util_sleep(cronSECONDS);
385
 
  }
386
 
  if (ret == SYSERR) {
387
 
    XPRINTF(" could not connect to %s:%d.\n",
388
 
           nodes[currindex].ips,
389
 
           nodes[currindex].port);
390
 
    kill(nodes[currindex].ssh,
391
 
         SIGTERM);
392
 
    waitpid(nodes[currindex].ssh,
393
 
            &status,
394
 
            0);
395
 
    GROW(nodes, nnodes, nnodes-1);
396
 
    return -1;
397
 
  }
398
 
 
399
 
  /* request hello */
400
 
  if (OK != sendMessage(TESTBED_GET_hello,
401
 
                        currindex,
402
 
                        sizeof(TESTBED_GET_hello_MESSAGE)-sizeof(TESTBED_CS_MESSAGE),
403
 
                        &req.proto)) {
404
 
    /* send message already printed an error message */
405
 
    destroySocket(&nodes[currindex].sock);
406
 
    FREE(nodes[currindex].ips);
407
 
    /* fixme: check error conditions on kill/waidpid! */
408
 
    kill(nodes[currindex].ssh,
409
 
         SIGTERM);
410
 
    waitpid(nodes[currindex].ssh,
411
 
            &status,
412
 
            0);
413
 
    GROW(nodes,
414
 
         nnodes,
415
 
         nnodes-1);
416
 
    return -1;
417
 
  }
418
 
 
419
 
  hdr = NULL;
420
 
  if (SYSERR == readFromSocket(&nodes[currindex].sock,
421
 
                               (CS_MESSAGE_HEADER**)&hdr)) {
422
 
    XPRINTF(" peer %s is not responding.\n",
423
 
           nodes[currindex].ips);
424
 
    destroySocket(&nodes[currindex].sock);
425
 
    FREE(nodes[currindex].ips);
426
 
    /* fixme: check error conditions on kill/waidpid! */
427
 
    kill(nodes[currindex].ssh,
428
 
         SIGTERM);
429
 
    waitpid(nodes[currindex].ssh,
430
 
            &status,
431
 
            0);
432
 
    GROW(nodes, nnodes, nnodes-1);
433
 
    return -1;
434
 
  }
435
 
  if ( (ntohs(hdr->header.header.type) == CS_PROTO_testbed_REPLY) &&
436
 
       (ntohs(hdr->header.header.size) >= sizeof(TESTBED_hello_MESSAGE)) &&
437
 
       (ntohl(hdr->header.msgType) == TESTBED_hello_RESPONSE) &&
438
 
       (ntohs(hdr->header.header.size) - sizeof(TESTBED_CS_MESSAGE) >= sizeof(P2P_hello_MESSAGE)) &&
439
 
       (ntohs(hdr->header.header.size) - sizeof(TESTBED_CS_MESSAGE) == P2P_hello_MESSAGE_size(&hdr->helo)) ) {
440
 
    nodes[currindex].helo
441
 
      = MALLOC(P2P_hello_MESSAGE_size(&hdr->helo));
442
 
    memcpy(nodes[currindex].helo,
443
 
           &hdr->helo,
444
 
           P2P_hello_MESSAGE_size(&hdr->helo));
445
 
  } else {
446
 
    FREE(hdr);
447
 
    destroySocket(&nodes[currindex].sock);
448
 
    XPRINTF(" peer %s did not respond with proper hello.\n",
449
 
           nodes[currindex].ips);
450
 
    FREE(nodes[currindex].ips);
451
 
    /* fixme: check error conditions on kill/waidpid! */
452
 
    kill(nodes[currindex].ssh,
453
 
         SIGTERM);
454
 
    waitpid(nodes[currindex].ssh,
455
 
            &status,
456
 
            0);
457
 
    GROW(nodes, nnodes, nnodes-1);
458
 
    return -1;
459
 
  }
460
 
  FREE(hdr);
461
 
  XPRINTF("%d\n",
462
 
         currindex);
463
 
  return 0;
464
 
}
465
 
 
466
 
 
467
 
/**
468
 
 * Tear down the connection between two peers.
469
 
 */
470
 
static int delConnection(int argc,
471
 
                         char * argv[]) {
472
 
  int src, dst, ack;
473
 
 
474
 
  if (argc != 2) {
475
 
    XPRINTF("Syntax: disconnect PEERID PEERID\n");
476
 
    return -1;
477
 
  }
478
 
  CHECK_SRC_DST(src, dst, argv[0], argv[1]);
479
 
  if (OK != sendMessage(TESTBED_DEL_PEER,
480
 
                        src,
481
 
                        sizeof(PeerIdentity),
482
 
                        &nodes[dst].helo->senderIdentity))
483
 
    return -1;
484
 
  if (OK != readResult(src,
485
 
                       &ack))
486
 
    return -1;
487
 
  if (ack == OK) {
488
 
    XPRINTF("OK.\n");
489
 
    return 0;
490
 
  } else {
491
 
    XPRINTF(" Connection NOT deleted.\n");
492
 
    return -1;
493
 
  }
494
 
}
495
 
 
496
 
/**
497
 
 * Tear down all connections of a peer.
498
 
 */
499
 
static int delAllConnections(int argc,
500
 
                             char * argv[]) {
501
 
  int dst, ack;
502
 
 
503
 
  if (argc != 1) {
504
 
    XPRINTF("Syntax: disconnect-all PEERID\n");
505
 
    return -1;
506
 
  }
507
 
  CHECK_PEER(dst, argv[0]);
508
 
  if (OK != sendMessage(TESTBED_DEL_ALL_PEERS,
509
 
                        dst,
510
 
                        0,
511
 
                        NULL))
512
 
    return -1;
513
 
  if (OK != readResult(dst,
514
 
                       &ack))
515
 
    return -1;
516
 
  if (ack == OK) {
517
 
    XPRINTF("OK.\n");
518
 
    return 0;
519
 
  } else {
520
 
    XPRINTF(" Connections NOT deleted.\n");
521
 
    return -1;
522
 
  }
523
 
}
524
 
 
525
 
/**
526
 
 * Add a connection between two peers.
527
 
 */
528
 
static int addConnection(int argc,
529
 
                         char * argv[]) {
530
 
  int src, dst, ack;
531
 
 
532
 
  if (argc != 2) {
533
 
    XPRINTF("Syntax: connect PEERID PEERID\n");
534
 
    return -1;
535
 
  }
536
 
  CHECK_SRC_DST(src, dst, argv[0], argv[1]);
537
 
  if (SYSERR == sendMessage(TESTBED_ADD_PEER,
538
 
                            src,
539
 
                            P2P_hello_MESSAGE_size(nodes[dst].helo),
540
 
                            nodes[dst].helo))
541
 
    return -1;
542
 
  if (OK != readResult(src,
543
 
                       &ack))
544
 
    return -1;
545
 
  if (ack == OK) {
546
 
    XPRINTF("OK.\n");
547
 
    return 0;
548
 
  } else {
549
 
    XPRINTF(" peer cannot connect.\n");
550
 
    return -1;
551
 
  }
552
 
}
553
 
 
554
 
/**
555
 
 * Set the level of trust that one peer has in
556
 
 * another.
557
 
 */
558
 
static int setTrust(int argc, char * argv[]) {
559
 
  int src, dst, value, ack;
560
 
  TESTBED_SET_TVALUE_MESSAGE msg;
561
 
 
562
 
  if (argc != 3) {
563
 
    XPRINTF("Syntax: set-trust PEERID PEERID TRUST\n");
564
 
    return -1;
565
 
  }
566
 
  CHECK_SRC_DST(src, dst, argv[0], argv[1]);
567
 
  value = atoi(argv[2]);
568
 
  msg.trust = htonl(value);
569
 
  memcpy(&msg.otherPeer,
570
 
         &nodes[dst].helo->senderIdentity,
571
 
         sizeof(PeerIdentity));
572
 
  if (SYSERR == sendMessage(TESTBED_SET_TVALUE,
573
 
                            src,
574
 
                            sizeof(PeerIdentity)+sizeof(unsigned int),
575
 
                            &msg.otherPeer))
576
 
    return -1;
577
 
  if (OK != readResult(src,
578
 
                       &ack))
579
 
    return -1;
580
 
  if (htonl(ack) != OK) {
581
 
    XPRINTF(" peer could not set trust value.\n");
582
 
    return -1;
583
 
  } else {
584
 
    XPRINTF("OK.\n");
585
 
    return 0;
586
 
  }
587
 
}
588
 
 
589
 
/**
590
 
 * Get the amount of trust that A has in B.
591
 
 */
592
 
static int getTrust(int argc, char *argv[]) {
593
 
  int src, dst, value;
594
 
 
595
 
  if (argc != 2) {
596
 
    XPRINTF("Syntax: get-trust PEERID PEERID\n");
597
 
    return -1;
598
 
  }
599
 
  CHECK_SRC_DST(src, dst, argv[0], argv[1]);
600
 
  if (SYSERR == sendMessage(TESTBED_GET_TVALUE,
601
 
                            src,
602
 
                            sizeof(PeerIdentity),
603
 
                            &nodes[dst].helo->senderIdentity))
604
 
    return -1;
605
 
  if (SYSERR == readResult(src, &value))
606
 
    return -1;
607
 
  if (value < 0) {
608
 
    XPRINTF(" could not get trust value.\n");
609
 
    return -1;
610
 
  } else {
611
 
    XPRINTF("%d\n",
612
 
           value);
613
 
    return 0;
614
 
  }
615
 
}
616
 
 
617
 
/**
618
 
 * Disable hello at a peer.
619
 
 */
620
 
static int disablehello(int argc, char *argv[]) {
621
 
  int dst, value;
622
 
 
623
 
  if (argc != 1) {
624
 
    XPRINTF("Syntax: helo-disable PEERID\n");
625
 
    return -1;
626
 
  }
627
 
  CHECK_PEER(dst, argv[0]);
628
 
  if (SYSERR == sendMessage(TESTBED_DISABLE_hello,
629
 
                            dst,
630
 
                            0,
631
 
                            NULL))
632
 
    return -1;
633
 
  if (SYSERR == readResult(dst, &value))
634
 
    return -1;
635
 
  if (value != OK) {
636
 
    XPRINTF(" could disable hello\n");
637
 
    return -1;
638
 
  } else {
639
 
    XPRINTF("OK.\n");
640
 
    return 0;
641
 
  }
642
 
}
643
 
 
644
 
/**
645
 
 * Enable hello at a peer.
646
 
 */
647
 
static int enablehello(int argc, char *argv[]) {
648
 
  int dst, value;
649
 
 
650
 
  if (argc != 1) {
651
 
    XPRINTF("Syntax: helo-enable PEERID\n");
652
 
    return -1;
653
 
  }
654
 
  CHECK_PEER(dst, argv[0]);
655
 
  if (SYSERR == sendMessage(TESTBED_ENABLE_hello,
656
 
                            dst,
657
 
                            0,
658
 
                            NULL))
659
 
    return -1;
660
 
  if (SYSERR == readResult(dst, &value))
661
 
    return -1;
662
 
  if (value != OK) {
663
 
    XPRINTF(" could enable hello\n");
664
 
    return -1;
665
 
  } else {
666
 
    XPRINTF("OK.\n");
667
 
    return 0;
668
 
  }
669
 
}
670
 
 
671
 
/**
672
 
 * Disable AUTOCONNECT at a peer.
673
 
 */
674
 
static int disableAUTOCONNECT(int argc, char *argv[]) {
675
 
  int dst, value;
676
 
 
677
 
  if (argc != 1) {
678
 
    XPRINTF("Syntax: autoconnect-disable PEERID\n");
679
 
    return -1;
680
 
  }
681
 
  CHECK_PEER(dst, argv[0]);
682
 
  if (SYSERR == sendMessage(TESTBED_DISABLE_AUTOCONNECT,
683
 
                            dst,
684
 
                            0,
685
 
                            NULL))
686
 
    return -1;
687
 
  if (SYSERR == readResult(dst, &value))
688
 
    return -1;
689
 
  if (value != OK) {
690
 
    XPRINTF(" could disable AUTOCONNECT\n");
691
 
    return -1;
692
 
  } else {
693
 
    XPRINTF("OK.\n");
694
 
    return 0;
695
 
  }
696
 
}
697
 
 
698
 
/**
699
 
 * Enable AUTOCONNECT at a peer.
700
 
 */
701
 
static int enableAUTOCONNECT(int argc, char *argv[]) {
702
 
  int dst, value;
703
 
 
704
 
  if (argc != 1) {
705
 
    XPRINTF("Syntax: autoconnect-enable PEERID\n");
706
 
    return -1;
707
 
  }
708
 
  CHECK_PEER(dst, argv[0]);
709
 
  if (SYSERR == sendMessage(TESTBED_ENABLE_AUTOCONNECT,
710
 
                            dst,
711
 
                            0,
712
 
                            NULL))
713
 
    return -1;
714
 
  if (SYSERR == readResult(dst, &value))
715
 
    return -1;
716
 
  if (value != OK) {
717
 
    XPRINTF(" could enable AUTOCONNECT\n");
718
 
    return -1;
719
 
  } else {
720
 
    XPRINTF("OK.\n");
721
 
    return 0;
722
 
  }
723
 
}
724
 
 
725
 
 
726
 
static int allowDenyConnectHelper(unsigned int argc,
727
 
                                  char * argv[],
728
 
                                  int type) {
729
 
  int dst, value;
730
 
  PeerIdentity * list;
731
 
  int i;
732
 
  int idx = 0;
733
 
 
734
 
  CHECK_PEER(dst, argv[0]);
735
 
  if (argc > (65532 - sizeof(TESTBED_CS_MESSAGE)) / sizeof(PeerIdentity)) {
736
 
    XPRINTF("Too many peers specified.  Ask a wizard to enlarge limit.\n");
737
 
    return -1;
738
 
  }
739
 
 
740
 
  list = NULL;
741
 
  for (i=1;i<argc;i++)
742
 
    CHECK_PEER(idx, argv[i]); /* may return, do before MALLOC! */
743
 
  if (argc > 1)
744
 
    list = MALLOC(sizeof(PeerIdentity)*(argc-1));
745
 
  for (i=1;i<argc;i++) {
746
 
    CHECK_PEER(idx, argv[i]);
747
 
    memcpy(&list[i-1],
748
 
           &nodes[idx].helo->senderIdentity,
749
 
           sizeof(PeerIdentity));
750
 
  }
751
 
  if (SYSERR == sendMessage(type,
752
 
                            dst,
753
 
                            sizeof(PeerIdentity)*(argc-1),
754
 
                            list)) {
755
 
    FREENONNULL(list);
756
 
    return -1;
757
 
  }
758
 
  FREENONNULL(list);
759
 
  if (SYSERR == readResult(dst, &value))
760
 
    return -1;
761
 
  if (value != OK) {
762
 
    XPRINTF(" could change setting.\n");
763
 
    return -1;
764
 
  } else {
765
 
    XPRINTF("OK.\n");
766
 
    return 0;
767
 
  }
768
 
}
769
 
 
770
 
/**
771
 
 * Deny connections to certain peers at a peer.
772
 
 */
773
 
static int denyConnect(int argc, char *argv[]) {
774
 
  if (argc < 1) {
775
 
    XPRINTF("Syntax: connect-deny PEERID [PEERID]*\n");
776
 
    return -1;
777
 
  }
778
 
  return allowDenyConnectHelper(argc, argv,
779
 
                                TESTBED_DENY_CONNECT);
780
 
}
781
 
 
782
 
/**
783
 
 * Allow connections to certain peers at a peer.
784
 
 */
785
 
static int allowConnect(int argc, char *argv[]) {
786
 
  if (argc < 1) {
787
 
    XPRINTF("Syntax: connect-allow PEERID [PEERID]*\n");
788
 
    return -1;
789
 
  }
790
 
  return allowDenyConnectHelper(argc, argv,
791
 
                                TESTBED_ALLOW_CONNECT);
792
 
}
793
 
 
794
 
/**
795
 
 * Helper function for (un)loadModule.
796
 
 * @param type load or unload requested?
797
 
 */
798
 
static int loadModuleHelper(unsigned short type,
799
 
                            char * peerId,
800
 
                            char * modulename) {
801
 
  int ok, dst;
802
 
 
803
 
  CHECK_PEER(dst, peerId);
804
 
  if (OK != sendMessage(type,
805
 
                        dst,
806
 
                        strlen(modulename),
807
 
                        modulename))
808
 
    return -1;
809
 
  if (OK != readResult(dst,
810
 
                       &ok))
811
 
    return -1;
812
 
  if (ok != OK) {
813
 
    XPRINTF(" peer %s refused.\n",
814
 
           nodes[dst].ips);
815
 
    return -1;
816
 
  }
817
 
  XPRINTF("OK.\n");
818
 
  return 0;
819
 
}
820
 
 
821
 
/**
822
 
 * Load an application module at the given peer.
823
 
 */
824
 
static int loadModule(int argc, char *argv[]) {
825
 
  if (argc != 2) {
826
 
    XPRINTF("Syntax: load-module PEERID MODULENAME\n");
827
 
    return -1;
828
 
  }
829
 
  return loadModuleHelper(TESTBED_LOAD_MODULE,
830
 
                          argv[0],
831
 
                          argv[1]);
832
 
}
833
 
 
834
 
/**
835
 
 * Unload an application module.
836
 
 */
837
 
static int unloadModule(int argc, char *argv[]) {
838
 
  if (argc != 2) {
839
 
    XPRINTF("Syntax: unload-module PEERID MODULENAME\n");
840
 
    return -1;
841
 
  }
842
 
  return loadModuleHelper(TESTBED_UNLOAD_MODULE,
843
 
                          argv[0],
844
 
                          argv[1]);
845
 
}
846
 
 
847
 
/**
848
 
 * Fork a client process.  Captures the output and makes it
849
 
 * available via process-output.  The client can be killed
850
 
 * using process-signal.  The process identifier is printed.
851
 
 */
852
 
static int startProcess(int argc,
853
 
                        char *argv[]) {
854
 
  char * cmdLine;
855
 
  int size;
856
 
  int i;
857
 
  int dst;
858
 
  int ack;
859
 
  int pos;
860
 
 
861
 
  if (argc < 2) {
862
 
    XPRINTF("Syntax: process-start PEERID COMMAND [ARGUMENTS]\n");
863
 
    return -1;
864
 
  }
865
 
  CHECK_PEER(dst, argv[0]);
866
 
  size = 0;
867
 
  for (i=1;i<argc;i++)
868
 
    size += 1 + strlen(argv[i]);
869
 
  cmdLine = MALLOC(size);
870
 
  pos = 0;
871
 
  for (i=1;i<argc;i++) {
872
 
    memcpy(&cmdLine[pos],
873
 
           argv[i],
874
 
           strlen(argv[i])+1);
875
 
    pos += strlen(argv[i])+1;
876
 
  }
877
 
 
878
 
  if (OK != sendMessage(TESTBED_EXEC,
879
 
                        dst,
880
 
                        size,
881
 
                        cmdLine)) {
882
 
    FREE(cmdLine);
883
 
    return -1;
884
 
  }
885
 
  FREE(cmdLine);
886
 
  if (OK != readResult(dst,
887
 
                       &ack))
888
 
    return -1;
889
 
  if (ack != SYSERR) {
890
 
    XPRINTF("%d\n",
891
 
           ack);
892
 
    return 0;
893
 
  } else {
894
 
    XPRINTF(" Peer could not fork process.\n");
895
 
    return -1;
896
 
  }
897
 
}
898
 
 
899
 
/**
900
 
 * Send a signal to a client process.  Use signal
901
 
 * 0 to test if the process is still live.  Use
902
 
 * -1 to obtain the return value from a dead
903
 
 * process and to free all associated resources.
904
 
 * For -1 the return value is printed, otherwise OK.
905
 
 * Note that if the signal is -1 and the process
906
 
 * is still running, -1 is returned (which can then
907
 
 * NOT be distinguished from the process returning -1)
908
 
 */
909
 
static int signalProcess(int argc, char *argv[]) {
910
 
  int dst;
911
 
  int ack;
912
 
  TESTBED_SIGNAL_MESSAGE msg;
913
 
 
914
 
  if (argc != 3) {
915
 
    XPRINTF("Syntax: process-signal PEERID PROCESSID SIGNAL\n");
916
 
    return -1;
917
 
  }
918
 
  CHECK_PEER(dst, argv[0]);
919
 
  msg.pid = htonl(atoi(argv[1]));
920
 
  msg.signal = htonl(atoi(argv[2]));
921
 
  if (OK != sendMessage(TESTBED_SIGNAL,
922
 
                        dst,
923
 
                        sizeof(TESTBED_SIGNAL_MESSAGE) - sizeof(TESTBED_CS_MESSAGE),
924
 
                        &msg.pid))
925
 
    return -1;
926
 
  if (OK != readResult(dst,
927
 
                       &ack))
928
 
    return -1;
929
 
  if (ntohl(msg.signal) == -1) {
930
 
    XPRINTF("%d\n", ack);
931
 
    return 0;
932
 
  }
933
 
  if (ack == OK) {
934
 
    XPRINTF("OK.\n");
935
 
    return 0;
936
 
  } else {
937
 
    XPRINTF(" Peer could not signal process.\n");
938
 
    return -1;
939
 
  }
940
 
}
941
 
 
942
 
/**
943
 
 * Get the recorded output of a process.
944
 
 */
945
 
static int dumpProcessOutput(int argc,
946
 
                             char * argv[]) {
947
 
  int dst;
948
 
  int pid;
949
 
  unsigned int ack;
950
 
 
951
 
  if (argc != 2) {
952
 
    XPRINTF("Syntax: process-output PEERID PROCESSID\n");
953
 
    return -1;
954
 
  }
955
 
  CHECK_PEER(dst, argv[0]);
956
 
  pid = htonl(atoi(argv[1]));
957
 
  if (OK != sendMessage(TESTBED_GET_OUTPUT,
958
 
                        dst,
959
 
                        sizeof(int),
960
 
                        &pid))
961
 
    return -1;
962
 
  if (OK != readResult(dst,
963
 
                       (int*) &ack))
964
 
    return -1;
965
 
  if (ack != SYSERR) {
966
 
    char * tmp;
967
 
    unsigned int pos = 0;
968
 
    while (pos < ack) {
969
 
      unsigned short size;
970
 
      TESTBED_OUTPUT_REPLY_MESSAGE * reply;
971
 
 
972
 
      reply = NULL;
973
 
      if (SYSERR == readFromSocket(&nodes[dst].sock,
974
 
                                   (CS_MESSAGE_HEADER**)&reply)) {
975
 
        XPRINTF(" peer %s is not responding after %d of %d bytes.\n",
976
 
               nodes[dst].ips,
977
 
               pos,
978
 
               ack);
979
 
        return -1;
980
 
      }
981
 
      /* FIXME: check that this is the correct reply format */
982
 
      size = ntohs(reply->header.header.size) - sizeof(TESTBED_OUTPUT_REPLY_MESSAGE);
983
 
      tmp = MALLOC(size+1);
984
 
      memcpy(tmp,
985
 
             &((TESTBED_OUTPUT_REPLY_MESSAGE_GENERIC*)reply)->data[0],
986
 
             size);
987
 
      tmp[size] = '\0';
988
 
      XPRINTF("%s",
989
 
             tmp);      
990
 
      FREE(tmp);
991
 
      FREE(reply);
992
 
      pos += size;
993
 
    }
994
 
    return 0;
995
 
  } else {
996
 
    XPRINTF(" Peer could not return process output.\n");
997
 
    return -1;
998
 
  }
999
 
}
1000
 
 
1001
 
/**
1002
 
 * Set bandwidth limitations for a peer.
1003
 
 */
1004
 
static int setBW(int argc, char * argv[]) {
1005
 
  TESTBED_SET_BW_MESSAGE msg;
1006
 
  int dst, in, out, ack;
1007
 
 
1008
 
  if (argc != 3) {
1009
 
    XPRINTF("Syntax: set-bw PEERID DOWN-BPS UP-BPS\n");
1010
 
    return -1;
1011
 
  }
1012
 
  CHECK_PEER(dst, argv[0]);
1013
 
  in  = atoi(argv[1]);
1014
 
  out = atoi(argv[2]);
1015
 
  if ((in < 0) || (out < 0)) {
1016
 
    XPRINTF(" Invalid bandwidth specification.\n");
1017
 
    return -1;
1018
 
  }
1019
 
  msg.in_bw  = htonl(in);
1020
 
  msg.out_bw = htonl(out);
1021
 
  if (SYSERR == sendMessage(TESTBED_SET_BW,
1022
 
                            dst,
1023
 
                            sizeof(TESTBED_SET_BW_MESSAGE) - sizeof(TESTBED_CS_MESSAGE),
1024
 
                            &msg.in_bw))
1025
 
    return -1;
1026
 
  if (OK != readResult(dst, &ack))
1027
 
    return -1;
1028
 
  if (ack != OK) {
1029
 
    XPRINTF(" peer could not set the specified bandwith.\n");
1030
 
    return -1;
1031
 
  } else {
1032
 
    XPRINTF("OK.\n");
1033
 
    return 0;
1034
 
  }
1035
 
}
1036
 
 
1037
 
/**
1038
 
 * Set artifical message loss rates for a peer.
1039
 
 */
1040
 
static int setLoss(int argc, char * argv[]) {
1041
 
  int dst;
1042
 
  int ack;
1043
 
  TESTBED_SET_LOSS_RATE_MESSAGE msg;
1044
 
 
1045
 
  if (argc != 3) {
1046
 
    XPRINTF("Syntax: set-loss PEERID DOWN-LOSS UP-LOSS\n");
1047
 
    return -1;
1048
 
  }
1049
 
  CHECK_PEER(dst, argv[0]);
1050
 
  msg.percentageLossInbound
1051
 
    = htonl(atoi(argv[1]));
1052
 
  msg.percentageLossOutbound
1053
 
    = htonl(atoi(argv[2]));
1054
 
 
1055
 
  if (SYSERR == sendMessage(TESTBED_SET_LOSS_RATE,
1056
 
                            dst,
1057
 
                            sizeof(TESTBED_SET_LOSS_RATE_MESSAGE) - sizeof(TESTBED_CS_MESSAGE),
1058
 
                            &msg.percentageLossInbound))
1059
 
    return -1;
1060
 
  if (OK != readResult(dst, &ack))
1061
 
    return -1;
1062
 
  if (ack != OK) {
1063
 
    XPRINTF(" peer could not set the specified loss rates.\n");
1064
 
    return -1;
1065
 
  } else {
1066
 
    XPRINTF("OK.\n");
1067
 
    return 0;
1068
 
  }
1069
 
}
1070
 
 
1071
 
static int printStatistic(const char * name,
1072
 
                          unsigned long long value,
1073
 
                          const char * arg) {
1074
 
  if (0 == strcmp(name,
1075
 
                  arg))
1076
 
    XPRINTF("%llu\n",
1077
 
           value);
1078
 
  return OK;
1079
 
}
1080
 
 
1081
 
/**
1082
 
 * Obtain statistics from a peer.
1083
 
 *
1084
 
 * @param argc number of arguments from the command line
1085
 
 * @param argv command line arguments
1086
 
 * @return 0 ok, 1 on error
1087
 
 */
1088
 
static int getStat(int argc, char ** argv) {
1089
 
  int res, peer, printProtocols;
1090
 
 
1091
 
  printProtocols = NO;
1092
 
  if (argc != 2) {
1093
 
    XPRINTF("Syntax: get-stat PEERID STATID\n");
1094
 
    return -1;
1095
 
  }
1096
 
  CHECK_PEER(peer, argv[0]);
1097
 
  res = requestStatistics(&nodes[peer].sock,
1098
 
                          (StatisticsProcessor) &printStatistic,
1099
 
                          argv[1]);
1100
 
  if (res == OK)
1101
 
    return 0;
1102
 
  else
1103
 
    return -1;
1104
 
}
1105
 
 
1106
 
/**
1107
 
 * Print statistics received.
1108
 
 *
1109
 
 * @param stream where to print the statistics
1110
 
 * @return OK on success, SYSERR on error
1111
 
 */
1112
 
static int printStatistics(const char * name,
1113
 
                           unsigned long long value,
1114
 
                           void * unused) {
1115
 
  XPRINTF("%-60s: %16llu\n",
1116
 
         name,
1117
 
         value);
1118
 
  return OK;
1119
 
}
1120
 
 
1121
 
static int lastIp2p;
1122
 
 
1123
 
static int printProtocols(unsigned short type,
1124
 
                          int isP2P,
1125
 
                          void * unused) {
1126
 
  const char *name = NULL;
1127
 
 
1128
 
  if (isP2P != lastIp2p) {
1129
 
    if (isP2P)
1130
 
      XPRINTF(_("Supported peer-to-peer messages:\n"));
1131
 
    else
1132
 
      XPRINTF(_("Supported client-server messages:\n"));
1133
 
    lastIp2p = isP2P;
1134
 
  }
1135
 
  if (isP2P)
1136
 
    name = p2pMessageName(type);
1137
 
  else
1138
 
    name = csMessageName(type);
1139
 
  if (name == NULL)
1140
 
    XPRINTF("\t%d\n",
1141
 
           type);
1142
 
  else
1143
 
    XPRINTF("\t%d\t(%s)\n",
1144
 
           type,
1145
 
           name);
1146
 
  return OK;
1147
 
}
1148
 
 
1149
 
/**
1150
 
 * Obtain statistics from a peer.
1151
 
 *
1152
 
 * @param argc number of arguments from the command line
1153
 
 * @param argv command line arguments
1154
 
 * @return 0 ok, 1 on error
1155
 
 */
1156
 
static int getStats(int argc, char ** argv) {
1157
 
  int res, peer, printProtocolsOpt;
1158
 
 
1159
 
  printProtocolsOpt = NO;
1160
 
  if (argc == 2) {
1161
 
    if (strcmp(argv[0], "-P")) {
1162
 
      XPRINTF("Syntax: get-stats [-P] PEERID\n");
1163
 
      return -1;
1164
 
    }
1165
 
    printProtocolsOpt = YES;
1166
 
    CHECK_PEER(peer, argv[1]);
1167
 
  } else if (argc != 1) {
1168
 
    XPRINTF("Syntax: get-stats [-P] PEERID\n");
1169
 
    return -1;
1170
 
  } else
1171
 
    CHECK_PEER(peer, argv[0]);
1172
 
  res = requestStatistics(&nodes[peer].sock,
1173
 
                          (StatisticsProcessor) &printStatistics,
1174
 
                          NULL);
1175
 
  if ( (printProtocolsOpt == YES) &&
1176
 
       (res == OK)) {
1177
 
 lastIp2p = 42; /* not YES or NO */
1178
 
    res = requestAvailableProtocols(&nodes[peer].sock,
1179
 
                                    (ProtocolProcessor) &printProtocols,
1180
 
                                    NULL);
1181
 
  }
1182
 
  if (res == OK)
1183
 
    return 0;
1184
 
  else
1185
 
    return -1;
1186
 
}
1187
 
 
1188
 
 
1189
 
/**
1190
 
 * Obtain option from a peer.
1191
 
 *
1192
 
 * @param argc number of arguments from the command line
1193
 
 * @param argv command line arguments
1194
 
 * @return 0 ok, 1 on error
1195
 
 */
1196
 
static int getOption(int argc, char ** argv) {
1197
 
  int peer;
1198
 
  char * opt;
1199
 
 
1200
 
  if (argc != 3) {
1201
 
    XPRINTF("Syntax: get-option PEERID SECTION OPTION\n");
1202
 
    return -1;
1203
 
  }
1204
 
  CHECK_PEER(peer, argv[0]);
1205
 
  opt = getConfigurationOptionValue(&nodes[peer].sock,
1206
 
                                    argv[1],
1207
 
                                    argv[2]);
1208
 
  if (opt == NULL) {
1209
 
    XPRINTF("Error sending request to peer %d\n",
1210
 
           peer);
1211
 
    return -1;
1212
 
  }
1213
 
  XPRINTF("%s\n",
1214
 
         opt);
1215
 
  FREE(opt);
1216
 
  return 0;
1217
 
}
1218
 
 
1219
 
 
1220
 
/**
1221
 
 * Upload a file to a peer.
1222
 
 */
1223
 
static int uploadFile(int argc,
1224
 
                      char *argv[]) {
1225
 
  int peer, nbytes, flen, ack;
1226
 
  char * buf;
1227
 
  FILE * infile;
1228
 
  TESTBED_UPLOAD_FILE_MESSAGE * msg;
1229
 
 
1230
 
  if (argc != 3) {
1231
 
    XPRINTF("Syntax: load-file PEERID LOCAL_FILENAME DEST_FILENAME\n");
1232
 
    return -1;
1233
 
  }
1234
 
  CHECK_PEER(peer, argv[0]);
1235
 
  infile = FOPEN(argv[1], "r");
1236
 
  if (infile == NULL) {
1237
 
    XPRINTF(" Could not open file %s\n",
1238
 
           argv[1]);
1239
 
    return -1;
1240
 
  }
1241
 
  flen = strlen(argv[2]) + 1; /* '\0' added in the flen */
1242
 
  if (flen > TESTBED_FILE_BLK_SIZE) {
1243
 
    XPRINTF(" destination file name too long (%d characters, limit %d).\n",
1244
 
           flen-1,
1245
 
           TESTBED_FILE_BLK_SIZE);
1246
 
    return -1;
1247
 
  }
1248
 
 
1249
 
  msg = MALLOC(sizeof(TESTBED_UPLOAD_FILE_MESSAGE) + TESTBED_FILE_BLK_SIZE);
1250
 
  msg->header.header.size
1251
 
    = htons(sizeof(TESTBED_UPLOAD_FILE_MESSAGE)+flen);
1252
 
  msg->header.header.type
1253
 
    = htons(CS_PROTO_testbed_REQUEST);
1254
 
  msg->header.msgType
1255
 
    = htonl(TESTBED_UPLOAD_FILE);
1256
 
  msg->type
1257
 
    = htonl(TESTBED_FILE_DELETE);
1258
 
  memcpy(((TESTBED_UPLOAD_FILE_MESSAGE_GENERIC*)msg)->buf, argv[2], flen);
1259
 
 
1260
 
  if (SYSERR == writeToSocket(&nodes[peer].sock,
1261
 
                              &msg->header.header)) {
1262
 
    fclose(infile);
1263
 
    FREE(msg);
1264
 
    XPRINTF(" Could not send message to peer %s.\n",
1265
 
           nodes[peer].ips);
1266
 
    return -1;
1267
 
  }
1268
 
  /* Read ack from the peer */
1269
 
  if (OK != readTCPResult(&nodes[peer].sock, &ack)) {
1270
 
    fclose(infile);
1271
 
    FREE(msg);
1272
 
    XPRINTF("Peer is not responding\n");
1273
 
    return -1;
1274
 
  }
1275
 
  if (ack != OK) {
1276
 
    fclose(infile);
1277
 
    FREE(msg);
1278
 
    XPRINTF(" Peer returned error (delete existing file).\n");
1279
 
    return -1;
1280
 
  }
1281
 
  msg->type = htonl(TESTBED_FILE_APPEND);
1282
 
  buf = ((TESTBED_UPLOAD_FILE_MESSAGE_GENERIC*)msg)->buf + flen;
1283
 
  while ((nbytes = GN_FREAD(buf, 1,
1284
 
                            (TESTBED_FILE_BLK_SIZE -
1285
 
                             sizeof(TESTBED_UPLOAD_FILE_MESSAGE) - flen),
1286
 
                            infile)) > 0) {
1287
 
    if (ferror(infile))
1288
 
      break;
1289
 
    msg->header.header.size = htons(sizeof(TESTBED_UPLOAD_FILE_MESSAGE) +
1290
 
                                    nbytes + flen);
1291
 
    if (SYSERR == writeToSocket(&nodes[peer].sock, &msg->header.header)) {
1292
 
      fclose(infile);
1293
 
      FREE(msg);
1294
 
      XPRINTF(" could not send file to node %s.\n",
1295
 
             nodes[peer].ips);
1296
 
      return -1;
1297
 
    }
1298
 
    if (OK != readResult(peer, &ack)) {
1299
 
      fclose(infile);
1300
 
      FREE(msg);
1301
 
      return -1;
1302
 
    }
1303
 
    if (ack != OK) {
1304
 
      fclose(infile);
1305
 
      FREE(msg);
1306
 
      XPRINTF(" peer returned error.\n");
1307
 
      return -1;
1308
 
    }
1309
 
  }
1310
 
  if (ferror(infile)) {
1311
 
    fclose(infile);
1312
 
    FREE(msg);
1313
 
    XPRINTF(" could not read source file. Transmission aborted.\n");
1314
 
    return -1;
1315
 
  }
1316
 
  fclose(infile);
1317
 
  FREE(msg);
1318
 
  XPRINTF("OK.\n");
1319
 
  return 0;
1320
 
}
1321
 
 
1322
 
/**
1323
 
 * Print the list of commands.
1324
 
 */
1325
 
static int printOnlineHelp(int argc,
1326
 
                           char * argv[]) {
1327
 
  int i;
1328
 
  i = 0;
1329
 
  while (commands[i].command != NULL) {
1330
 
    XPRINTF("%-30s%s\n",
1331
 
           commands[i].command,
1332
 
           commands[i].help);
1333
 
    i++;
1334
 
  }
1335
 
  return 0;
1336
 
}
1337
 
 
1338
 
static int processCommands(char * buffer,
1339
 
                           unsigned int * available) {
1340
 
  int ip[4];
1341
 
  int port;
1342
 
  unsigned int end;
1343
 
  unsigned int start;
1344
 
  char * up;
1345
 
  int err;
1346
 
 
1347
 
  err = 0;
1348
 
  end = 0;
1349
 
  start = 0;
1350
 
  while (end < *available) {
1351
 
    while ( (buffer[end] != '\n') &&
1352
 
            (end < *available) )
1353
 
      end++;
1354
 
    if (buffer[end] != '\n') {
1355
 
      if (start == 0) {
1356
 
        XPRINTF("Received invalid response from HTTP server!\n");
1357
 
        return -1;
1358
 
      } else {
1359
 
        memmove(buffer,
1360
 
                &buffer[start],
1361
 
                *available - start);
1362
 
        *available -= start;
1363
 
        return 0;
1364
 
      }
1365
 
    }
1366
 
    up = MALLOC(end-start+1);
1367
 
    memcpy(up,
1368
 
           &buffer[start],
1369
 
           end - start);
1370
 
    up[end-start] = '\0';
1371
 
    port = 2087; /* default port */
1372
 
    if (4 <= sscanf(up,
1373
 
                    "add-node %d %d %d %d %d",
1374
 
                    &ip[0],
1375
 
                    &ip[1],
1376
 
                    &ip[2],
1377
 
                    &ip[3],
1378
 
                    &port)) {
1379
 
      char ports[12];
1380
 
      char ips[128];
1381
 
      char * argv[2];
1382
 
      SNPRINTF(ports,
1383
 
               12,
1384
 
               "%d",
1385
 
               port);
1386
 
      SNPRINTF(ips,
1387
 
               128,
1388
 
               "%u.%u.%u.%u",
1389
 
               ip[0],
1390
 
               ip[1],
1391
 
               ip[2],
1392
 
               ip[3]);
1393
 
      argv[0] = ips;
1394
 
      argv[1] = ports;
1395
 
      if (0 != addNode(2, argv))
1396
 
        err = 2;
1397
 
    } else {
1398
 
      char * login;
1399
 
      login = MALLOC(64);
1400
 
      if (5 <= sscanf(up,
1401
 
                      "add-node %63s %d %d %d %d %d",
1402
 
                      login,
1403
 
                      &ip[0],
1404
 
                      &ip[1],
1405
 
                      &ip[2],
1406
 
                      &ip[3],
1407
 
                      &port)) {
1408
 
        char ports[12];
1409
 
        char ips[128];
1410
 
        char * argv[3];
1411
 
        SNPRINTF(ports,
1412
 
                 12,
1413
 
                 "%d",
1414
 
                 port);
1415
 
        SNPRINTF(ips,
1416
 
                 128,
1417
 
                 "%u.%u.%u.%u",
1418
 
                 ip[0],
1419
 
                 ip[1],
1420
 
                 ip[2],
1421
 
                 ip[3]);
1422
 
        argv[0] = login;
1423
 
        argv[1] = ips;
1424
 
        argv[2] = ports;
1425
 
        if (0 != addSshNode(3, argv))
1426
 
          err = 2;
1427
 
      }
1428
 
      FREE(login);
1429
 
    }
1430
 
    FREE(up);
1431
 
    end++;
1432
 
    start = end;
1433
 
  }
1434
 
  return err;
1435
 
}
1436
 
 
1437
 
 
1438
 
#define GET_COMMAND "GET %s/display.php3 HTTP/1.0\r\n\r\n"
1439
 
#define HTTP_URL "http://"
1440
 
 
1441
 
/**
1442
 
 * add-nodes that are listed as available at the
1443
 
 * TESTBED-HTTP registry.  Optional argument:
1444
 
 * URL of the registry (by default we use the
1445
 
 * value from the configuration file value).
1446
 
 */
1447
 
static int addAvailable(int argc,
1448
 
                        char * argv[]) {
1449
 
  char * reg = NULL;
1450
 
  long int port;
1451
 
  char * hostname;
1452
 
  unsigned int curpos;
1453
 
  struct sockaddr_in soaddr;
1454
 
  int sock;
1455
 
  size_t ret;
1456
 
  char * command;
1457
 
  cron_t start;
1458
 
  char c;
1459
 
  char * buffer;
1460
 
  int i;
1461
 
  int j;
1462
 
  int k;
1463
 
  struct sockaddr_in theProxy;
1464
 
  char *proxy, *proxyPort;
1465
 
  IPaddr ip;
1466
 
  size_t n;
1467
 
 
1468
 
  if (argc == 0) {
1469
 
    reg = getConfigurationString("GNUNET-TESTBED",
1470
 
                                 "REGISTERURL");
1471
 
    if (reg == NULL) {
1472
 
      XPRINTF(" no testbed registration URL given.\n");
1473
 
      return -1;
1474
 
    }
1475
 
  } else
1476
 
    reg = STRDUP(argv[0]);
1477
 
 
1478
 
 
1479
 
 
1480
 
  proxy = getConfigurationString("GNUNETD",
1481
 
                                 "HTTP-PROXY");
1482
 
  if (proxy != NULL) {
1483
 
    if (OK != GN_getHostByName(proxy,
1484
 
                               &ip)) {
1485
 
      XPRINTF(" Couldn't resolve name of HTTP proxy '%s'\n",
1486
 
              proxy);
1487
 
      theProxy.sin_addr.s_addr = 0;
1488
 
    } else {
1489
 
      memcpy(&theProxy.sin_addr.s_addr,
1490
 
             &ip,
1491
 
             sizeof(IPaddr));
1492
 
      proxyPort = getConfigurationString("GNUNETD",
1493
 
                                         "HTTP-PROXY-PORT");
1494
 
      if (proxyPort == NULL) {
1495
 
        theProxy.sin_port = htons(8080);
1496
 
      } else {
1497
 
        theProxy.sin_port = htons(atoi(proxyPort));
1498
 
        FREE(proxyPort);
1499
 
      }
1500
 
    }
1501
 
    FREE(proxy);
1502
 
  } else {
1503
 
    theProxy.sin_addr.s_addr = 0;
1504
 
  }
1505
 
 
1506
 
  if (0 != strncmp(HTTP_URL,
1507
 
                   reg,
1508
 
                   strlen(HTTP_URL)) ) {
1509
 
    XPRINTF(" invalid URL %s (must begin with %s)\n",
1510
 
           reg,
1511
 
           HTTP_URL);
1512
 
    return -1;
1513
 
  }
1514
 
  port = 80; /* default http port */
1515
 
 
1516
 
  hostname = STRDUP(&reg[strlen(HTTP_URL)]);
1517
 
  buffer = NULL;
1518
 
  j = -1;
1519
 
  k = -1;
1520
 
  for (i=0;i<strlen(hostname);i++) {
1521
 
    if (hostname[i] == ':')
1522
 
      j = i;
1523
 
    if (hostname[i] == '/') {
1524
 
      k = i;
1525
 
      if (j == -1)
1526
 
        j = i;
1527
 
      break;
1528
 
    }
1529
 
  }
1530
 
  if ( (j != -1) && (j < k) ) {
1531
 
    char * pstring;
1532
 
    if (k == -1) {
1533
 
      pstring = MALLOC(strlen(hostname)-j+1);
1534
 
      memcpy(pstring,
1535
 
             &hostname[j],
1536
 
             strlen(hostname)-j+1);
1537
 
      pstring[strlen(hostname)-j] = '\0';
1538
 
    } else {
1539
 
      pstring = MALLOC(k-j+1);
1540
 
      memcpy(pstring,
1541
 
             &hostname[j],
1542
 
             k-j);
1543
 
      pstring[k-j] = '\0';
1544
 
    }
1545
 
    port = strtol(pstring, &buffer, 10);
1546
 
    if ( (port < 0) || (port > 65536) ) {
1547
 
      XPRINTF(" malformed http URL: %s at %s.\n",
1548
 
             reg,
1549
 
             buffer);
1550
 
      FREE(hostname);
1551
 
      FREE(reg);
1552
 
      FREE(pstring);
1553
 
      return -1;
1554
 
    }
1555
 
    FREE(pstring);
1556
 
  }
1557
 
  hostname[k] = '\0';
1558
 
 
1559
 
#if DEBUG_TESTBED
1560
 
  LOG(LOG_INFO,
1561
 
      " Trying to download a hostlist from %s\n",
1562
 
      reg);
1563
 
#endif
1564
 
 
1565
 
 
1566
 
 
1567
 
  sock = SOCKET(PF_INET,
1568
 
                SOCK_STREAM,
1569
 
                0);
1570
 
  if (sock < 0) {
1571
 
    XPRINTF(" could not open socket for hostlist download (%s).\n",
1572
 
           STRERROR(errno));
1573
 
    FREE(hostname);
1574
 
    FREE(reg);
1575
 
    return -1;
1576
 
  }
1577
 
 
1578
 
  /* Do we need to connect through a proxy? */
1579
 
  if (theProxy.sin_addr.s_addr == 0) {
1580
 
    /* no proxy */
1581
 
    if (OK != GN_getHostByName(hostname,
1582
 
                               &ip)) {
1583
 
      XPRINTF(" could not download hostlist, host '%s' unknown\n",
1584
 
             hostname);
1585
 
      FREE(reg);
1586
 
      FREE(hostname);
1587
 
      return -1;
1588
 
    }
1589
 
    memcpy(&soaddr.sin_addr.s_addr,
1590
 
           &ip,
1591
 
           sizeof(IPaddr));
1592
 
    soaddr.sin_port
1593
 
      = htons((unsigned short)port);
1594
 
  } else {
1595
 
    /* proxy */
1596
 
    soaddr.sin_addr.s_addr
1597
 
      = theProxy.sin_addr.s_addr;
1598
 
    soaddr.sin_port
1599
 
      = theProxy.sin_port;
1600
 
  }
1601
 
  soaddr.sin_family = AF_INET;
1602
 
  if (CONNECT(sock,
1603
 
              (struct sockaddr*)&soaddr,
1604
 
              sizeof(soaddr)) < 0) {
1605
 
    XPRINTF(" failed to send HTTP request to host %s: %s\n",
1606
 
           hostname,
1607
 
           STRERROR(errno));
1608
 
    FREE(reg);
1609
 
    FREE(hostname);
1610
 
    closefile(sock);
1611
 
    return -1;
1612
 
  }
1613
 
 
1614
 
  n = strlen(GET_COMMAND) + strlen(reg);
1615
 
  command = MALLOC(n);
1616
 
  SNPRINTF(command,
1617
 
           n,
1618
 
           GET_COMMAND,
1619
 
           reg);
1620
 
  FREE(reg);
1621
 
  curpos = strlen(command)+1;
1622
 
  curpos = SEND_BLOCKING_ALL(sock,
1623
 
                             command,
1624
 
                             curpos);
1625
 
  if (SYSERR == (int)curpos) {
1626
 
    XPRINTF(" failed so send HTTP request %s to host %s (%u - %d) - %s\n",
1627
 
           command,
1628
 
           hostname,
1629
 
           curpos,
1630
 
           sock,
1631
 
           STRERROR(errno));
1632
 
    FREE(command);
1633
 
    FREE(hostname);
1634
 
    closefile(sock);
1635
 
    return -1;
1636
 
  }
1637
 
  FREE(command);
1638
 
  FREE(hostname);
1639
 
  cronTime(&start);
1640
 
 
1641
 
  /* we first have to read out the http_response*/
1642
 
  /* it ends with four line delimiters: "\r\n\r\n" */
1643
 
  curpos = 0;
1644
 
  while (curpos < 4) {
1645
 
    int success;
1646
 
 
1647
 
    if (start + 5 * cronMINUTES < cronTime(NULL))
1648
 
      break; /* exit after 5m */
1649
 
    success = RECV_NONBLOCKING(sock,
1650
 
                               &c,
1651
 
                               sizeof(c),
1652
 
                               &ret);
1653
 
    if ( success == NO ) {
1654
 
      gnunet_util_sleep(100 * cronMILLIS);
1655
 
      continue;
1656
 
    }
1657
 
    if ( (ret == 0) || (ret == (size_t)-1) )
1658
 
      break; /* end of transmission or error */
1659
 
    if ((c=='\r') || (c=='\n'))
1660
 
      curpos += ret;
1661
 
    else
1662
 
      curpos=0;
1663
 
  }
1664
 
  if (curpos < 4) { /* invalid response */
1665
 
    XPRINTF(" exit register (error: no http response read)\n");
1666
 
    closefile(sock);
1667
 
    return -1;
1668
 
  }
1669
 
 
1670
 
  /* now read peer list */
1671
 
  buffer = MALLOC(65536);
1672
 
 
1673
 
 
1674
 
  while (1) {
1675
 
    int success;
1676
 
 
1677
 
    if (start + 300 * cronSECONDS < cronTime(NULL))
1678
 
      break; /* exit after 300s */
1679
 
    curpos = 0;
1680
 
    while (curpos < 65536) {
1681
 
      if (start + 300 * cronSECONDS < cronTime(NULL))
1682
 
        break; /* exit after 300s */
1683
 
      success = RECV_NONBLOCKING(sock,
1684
 
                             &buffer[curpos],
1685
 
                             65536-curpos,
1686
 
                             &ret);
1687
 
      if ( success == NO ) {
1688
 
        gnunet_util_sleep(20);
1689
 
        continue;
1690
 
      }
1691
 
      if ( (ret == 0) || (ret == (size_t)-1) )
1692
 
        break; /* end of file or error*/
1693
 
      curpos += ret;
1694
 
 
1695
 
      if (0 != processCommands(buffer, &curpos)) {
1696
 
        FREE(buffer);
1697
 
        closefile(sock);
1698
 
        return -1;
1699
 
      }
1700
 
    }
1701
 
  }
1702
 
  if (0 != processCommands(buffer, &curpos)) {
1703
 
    FREE(buffer);
1704
 
    closefile(sock);
1705
 
    return -1;
1706
 
  }
1707
 
  FREE(buffer);
1708
 
  closefile(sock);
1709
 
  return 0;
1710
 
}
1711
 
 
1712
 
/**
1713
 
 * Print the list of available peers.
1714
 
 */
1715
 
static int listPeers(int argc, char * argv[]) {
1716
 
  int i;
1717
 
  for (i=0;i<nnodes;i++)
1718
 
    XPRINTF("%4d - %s:%d\n",
1719
 
           i,
1720
 
           nodes[i].ips,
1721
 
           nodes[i].port);
1722
 
  return 0;
1723
 
}
1724
 
 
1725
 
/**
1726
 
 * Exit gnunet-testbed shell.
1727
 
 */
1728
 
static int doExit(int argc, char * argv[]) {
1729
 
  do_quit = YES;
1730
 
  return 0;
1731
 
}
1732
 
 
1733
 
/* ****************** command set ****************** */
1734
 
 
1735
 
CMD_ENTRY commands[] = {
1736
 
  { "help",
1737
 
    "print this help text",
1738
 
    &printOnlineHelp },
1739
 
  { "get-trust",
1740
 
    "",
1741
 
    &getTrust },
1742
 
  { "set-bw",
1743
 
    "",
1744
 
    &setBW },
1745
 
  { "set-trust",
1746
 
    "",
1747
 
    &setTrust },
1748
 
  { "add-node",
1749
 
    "add node to testbed, arguments: IP PORT",
1750
 
    &addNode },
1751
 
  { "add-ssh-node",
1752
 
    "add node to testbed, arguments: LOGIN IP PORT",
1753
 
    &addSshNode },
1754
 
  { "connect",
1755
 
    "connect two peers",
1756
 
    &addConnection },
1757
 
  { "disconnect",
1758
 
    "disconnect two peers",
1759
 
    &delConnection },
1760
 
  { "disconnect-all",
1761
 
    "destroy all connections between peers",
1762
 
    &delAllConnections },
1763
 
  { "helo-disable",
1764
 
    "disable hello advertisements",
1765
 
    &disablehello },
1766
 
  { "helo-enable",
1767
 
    "enable hello advertisements",
1768
 
    &enablehello },
1769
 
  { "autoconnect-disable", "", &disableAUTOCONNECT },
1770
 
  { "autoconnect-enable", "", &enableAUTOCONNECT },
1771
 
  { "process-start",
1772
 
    "Start a process on a given peer.  Prints the process-ID on success.",
1773
 
    &startProcess },
1774
 
  { "process-signal",
1775
 
    "Send a signal to a process running at a peer.  Use signal 0 to test if the process is still running.  Use -1 to obtain the exit code of a process that terminated.",
1776
 
    &signalProcess },
1777
 
  { "process-output",
1778
 
    "Obtain the process output from a process at a peer.",
1779
 
    &dumpProcessOutput },
1780
 
  { "exit",
1781
 
    "exit the testbed shell",
1782
 
    &doExit },
1783
 
  { "list-peers", "", &listPeers},
1784
 
  { "set-loss", "", &setLoss} ,
1785
 
  { "get-stats",
1786
 
    "get all stats values from peer",
1787
 
    &getStats },
1788
 
  { "get-stat",
1789
 
    "get one specific stats value from peer",
1790
 
    &getStat },
1791
 
  { "get-option",
1792
 
    "Get configuration value from peer.",
1793
 
    &getOption },
1794
 
  { "load-module", "", &loadModule },
1795
 
  { "unload-module", "", &unloadModule },
1796
 
  { "add-available",
1797
 
    "Check http server for available testbed peers and add"
1798
 
    " all available nodes.  An optional argument can be"
1799
 
    " passed to specify the URL of the http server.",
1800
 
    &addAvailable },
1801
 
  { "upload",
1802
 
    "",
1803
 
    &uploadFile },
1804
 
  { "connect-deny", "", &denyConnect },
1805
 
  { "connect-allow", "", &allowConnect },
1806
 
  { NULL, NULL }, /* termination */
1807
 
};
1808
 
 
1809
 
 
1810
 
/* end of commands.c */