PageRenderTime 135ms CodeModel.GetById 35ms app.highlight 66ms RepoModel.GetById 2ms app.codeStats 0ms

/Docs/Reference Code/Slurpie/client/src/context.c

https://bitbucket.org/jurgen_kluft/symphony
C | 584 lines | 473 code | 58 blank | 53 comment | 88 complexity | 803f0a70d5986c3e6353492903d7396b MD5 | raw file
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4#include <assert.h>
  5#include <sys/socket.h>
  6#include <arpa/inet.h>
  7#include <sys/socket.h>
  8#include <sys/types.h>
  9#include <sys/stat.h>
 10#include <fcntl.h>
 11#include <time.h>
 12
 13#include "utils.h"
 14#include "connection.h"
 15#include "rem_slurpied.h"
 16#include "protocol.h"
 17#include "context.h"
 18#include "leech_protocol.h"
 19#include "leeches.h"
 20#include "downloads.h"
 21#include "dl.h"
 22#include "hash_check.h"
 23#include "version.h"
 24
 25// Local prototypes. aka helper functions
 26static int parseSlurpieServer(context* c, const char* server_port);
 27static int contextParseURL(context* c, const char* url);
 28static int parseURLMD5SUM(context* c, const char* urlmd5sum);
 29static int generateDestination(context* c);
 30
 31context* contextCreate() {
 32
 33  context* c;
 34		
 35  // Allocate the structure
 36  c = (context*) malloc(sizeof(context));
 37  if (c == NULL)
 38    return NULL;
 39  memset(c, 0, sizeof(context));
 40
 41  // Set some default values
 42  c->maxNumOfDownloads = DL_MAXDOWNLOADS;
 43  c->maxUpdateTreeLeaves = 100;
 44  c->maxNumOfNeighbors = MAXNUMNEIGHBORS;
 45  c->desiredNumOfNeighbors = DEFAULTNUMNEIGHBORS;
 46  c->desiredNumOfUpdates=DEFAULT_UPDATES_PER_ROUND;
 47  c->neighborChoice=0;
 48
 49  c->URL= NULL;
 50
 51  // leech server stuff
 52  c->maxNumOfLeeches = 10;
 53  c->numOfLeechThreads = 10;
 54  c->useMTLeechServ = 0;
 55
 56  // Initialize the Block break rule
 57  c->blockRule = 0;
 58  c->blockSize = 256*1024;			// by default, bs=256k
 59  c->blockingPriority = BLOCKSIZEPRIORITY;	// by default, we fix
 60  			// the blocksize, and then calculate the number of blocks
 61  			// as a function of the size, by default
 62  c->fileSize = -1;	// set later in init
 63  c->numberOfBlocks = -1;
 64  c->fd = 0;
 65  c->dlBitMap = NULL;
 66  c->dlq = NULL;
 67  c->ac = NULL;
 68  c->quiet = 0;		// not quiet by default
 69  c->downloadType=DOWNLOADTYPE_ADAPTIVE;	// download style
 70  c->phase2=0;
 71  c->magicTime=DEFAULT_MAGIC_TIME;
 72  c->pickTwo=0;
 73  c->randomSeed=-1;
 74
 75  // Neighbor Manager: creation moved to contextJoin
 76  c->neighborMgr = NULL;
 77
 78  // Hash stuff
 79  c->hashChecker = NULL;
 80  c->hash_enabled = 0;
 81  c->hash_maxRequestSize = DEFAULT_HASH_MAX_REQ_SIZE;
 82  
 83  c->backoffRule=BACKOFFRULE_GOOD;
 84  c->backoffBias=BACKOFFBIASDEFAULT;
 85  c->backOffCommitTime=DEFAULT_BACKOFF_TIME;
 86  c->backoffDidBackOff=0;
 87
 88  c->peerBlocksDld=c-> sourceBlocksDld=0;
 89
 90  // LeechesList
 91  //c->leeches = Q_Create();
 92  //c->leechLocalPort = LEECH_DEFAULT_PORT;
 93
 94  // Update Tree
 95  // If you create something thing, don't forget to destroy
 96  // it at contextDestroy
 97  c->updateTree = updateTreeNew(c->maxUpdateTreeLeaves);
 98  c->updateThreadP=NULL;
 99
100  // Slurpie Server stuff
101  c->slurpieServerAddress = (char*)(malloc(strlen(SLURPIED_DEFAULT_HOST)+1));
102  strcpy(c->slurpieServerAddress, SLURPIED_DEFAULT_HOST);
103  c->slurpieServerPort=SLURPIED_DEFAULT_PORT;
104
105  c->localIp = getLocalHostIP();
106
107  // Initialize the Synchronization Primitives
108  c->lock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
109  if (pthread_mutex_init(c->lock, NULL) != 0) {
110    printf("contextCreate:pthread_mutex_init failed!\n");
111    abort();
112  }
113  c->flock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
114  if (pthread_mutex_init(c->flock, NULL) != 0) {
115    printf("contextCreate:pthread_mutex_init failed!\n");
116    abort();
117  }
118  // Default adaptive downloading parameters
119	c->adl_maxBandwidth = DEFAULT_ADL_MAX_BANDWIDTH;;
120	c->adl_timer =	DEFAULT_ADL_TIMER;
121	c->adl_timer_inc =	DEFAULT_ADL_TIMER_INC;
122	c->adl_maxConnections =	DEFAULT_ADL_MAX_CONNECTIONS;
123	c->adl_bandwidth_inc =	DEFAULT_ADL_BANDWIDTH_INC;
124
125  return c;
126}
127
128int contextParseParameters(context* c, int argc, char** argv) {
129  int i;
130  // Lock the mutex
131
132  pthread_mutex_lock(c->lock);
133  for(i=1;i<argc;i++){
134    if(!strcmp(argv[i],"-q")){
135	    c->quiet=1;
136      continue;
137    }
138    if(!strcmp(argv[i],"-p")){
139	    c->phase2=1;
140      continue;
141    }
142    if((!strcmp(argv[i],"-s"))&&(i+1<argc)){
143      i++;
144      if(parseSlurpieServer(c,argv[i]))
145	usage(argv[i],": bad server:port");
146      continue;
147    }
148    if((!strcmp(argv[i],"-o"))&&(i+1<argc)){
149      i++;
150      c->destFileName = strdup(argv[i]);
151      assert(c->destFileName!=NULL);
152      continue;
153    }
154    if((!strcmp(argv[i],"-N"))&&(i+1<argc)){
155      i++;
156      c->maxNumOfNeighbors = atoi(argv[i]);
157      assert(c->maxNumOfNeighbors>=0);
158      continue;
159    }
160    if((!strcmp(argv[i],"-m"))&&(i+1<argc)){
161      i++;
162      c->magicTime = atoi(argv[i]);
163      assert(c->magicTime>=0);
164      continue;
165    }
166    if((!strcmp(argv[i],"-n"))&&(i+1<argc)){
167      i++;
168      c->numberOfBlocks = atoi(argv[i]);
169      c->blockingPriority=NUMBLOCKSPRIORITY;
170      assert(c->numberOfBlocks>=0);
171      continue;
172    }
173    if((!strcmp(argv[i],"-b"))&&(i+1<argc)){
174      i++;
175      c->blockSize = atoi(argv[i]);
176      c->blockingPriority=BLOCKSIZEPRIORITY;
177      assert(c->blockSize>=0);
178      continue;
179    }
180    if((!strcmp(argv[i],"-B"))&&(i+1<argc)){
181      i++;
182      c->backoffRule = atoi(argv[i]);
183      continue;
184    }
185    if((!strcmp(argv[i],"-bt"))&&(i+1<argc)){
186      i++;
187      c->backoffTime = atoi(argv[i]);
188      continue;
189    }
190    if((!strcmp(argv[i],"-bb"))&&(i+1<argc)){
191      i++;
192      c->backoffBias = atoi(argv[i]);
193      continue;
194    }
195    if((!strcmp(argv[i],"-d"))&&(i+1<argc)){
196      i++;
197      DEBUGLEVEL = atoi(argv[i]);
198      assert(DEBUGLEVEL>=0);
199      continue;
200    }
201    if((!strcmp(argv[i],"-R"))&&(i+1<argc)){
202      i++;
203      c->randomSeed = atoi(argv[i]);
204      continue;
205    }
206    if((!strcmp(argv[i],"-t"))&&(i+1<argc)){
207      i++;
208      c->maxNumOfDownloads = atoi(argv[i]);
209      assert(c->maxNumOfDownloads>=0);
210      continue;
211    }
212    if(!strncmp(argv[i],"ftp://",strlen("ftp://"))){
213      if(contextParseURL(c,argv[i]))
214	usage(argv[i],": bad URL");
215      continue;
216    }
217    if(!strncmp(argv[i],"http://",strlen("http://"))){
218      if(contextParseURL(c,argv[i]))
219	usage(argv[i],": bad URL");
220      continue;
221    }
222    if(!strcmp(argv[i],"-a")){
223	    c->downloadType=DOWNLOADTYPE_ADAPTIVE;
224      continue;
225    }
226    if(!strcmp(argv[i],"-at")){
227      i++;
228      c->adl_timer=atoi(argv[i]);
229      assert(c->adl_timer>=0);
230      continue;
231    }
232    if(!strcmp(argv[i], "-P")) {
233      c->pickTwo = 0;
234      continue;
235    }
236    if(!strcmp(argv[i], "-L")) {
237      c->neighborChoice = 1;
238      continue;
239    }
240    if(!strcmp(argv[i], "-l")) {
241      c->useMTLeechServ = 1;
242      continue;
243    }
244    if(!strcmp(argv[i], "-S")) {
245      c->hash_enabled = 1;
246      continue;
247    }
248    if(!strcmp(argv[i], "-Ssize")) {
249      // The value specified is in kilobytes, but store it in bytes for
250      // easy comparison later
251      i++;
252      c->hash_maxRequestSize = 1024 * atoi(argv[i]);
253      assert(c->hash_maxRequestSize > 0);
254      continue;
255    }
256    usage(argv[i],": unknown argument");
257  }
258
259  pthread_mutex_unlock(c->lock);
260  return 0;
261}
262
263void usage(char *s1, char *s2) {
264  if(s1)
265    fprintf(stderr,"%s ",s1);
266  if(s2)
267    fprintf(stderr,"%s ",s2);
268  if(s1||s2)
269    fprintf(stderr,"\n");
270
271
272  fprintf(stderr,"Slurpie Client v%d.%d\n"
273	  "Usage:\n"
274	  "slurpie [options] <http://...|ftp://...>\n"
275	  "Options:\n"
276	  "\t-a                 - turns on adaptive downloads\n"
277	  "\t-s host[:port]     - set slurpie server\n"
278	  "\t-t nThreads        - number of concurrent downloads\n"
279	  "\t-o outfile         - alternative name for outfile\n"
280	  "\t-b blocksize       - sets the size of the blocks\n"
281	  "\t-B rule       	- sets the backoff rule [off]\n"
282	  "\t-bt secs		- time in secs to backoff [%d]\n"
283	  "\t-bb k		- goto the source with P(k/n) [%d]\n"
284	  "\t-m secs		- the time to wait after downloads[%d]\n"
285	  "\t-n numberofblocks  - sets the number of blocks (overrides blocksize)\n"
286	  "\t-N numofneighbors  - sets the number of neighbors[%d]\n"
287	  "\t-l                 - use old (multithreaded) threaded leech sever\n"
288	  "\t-L                 - sets neighbors to O(ln(n))\n"
289	  "\t-p			- disable phase1 of downloads\n"
290	  "\t-P			- pick best block of 2\n"
291	  "\t-q                 - turns off all screen output\n"
292	  "\t-R seed		- seed the PRNG with 'seed' \n"
293	  "\t-d level           - sets the debug level[%d]\n"
294	  "\t-S                 - turns on secure mode (blocks verified)\n"
295	  "\t-------------- Adaptive Download Options -------------\n"
296	  "\t-at secs           - initial timer value [%d] \n"
297	  "\t----------------- Secure Mode Options ----------------\n"
298	  "\t-Ssize kbytes      - sets the maximum size of a hash request [1024]\n",
299  	SLURPIE_VERSION.major,
300	SLURPIE_VERSION.minor,
301  	  DEFAULT_BACKOFF_TIME,
302  	  BACKOFFBIASDEFAULT,
303  	  DEFAULT_MAGIC_TIME,
304	  DEFAULTNUMNEIGHBORS,
305	  DEFAULTDEBUGLEVEL,
306	  DEFAULT_ADL_TIMER
307	  );
308  exit(1);
309}
310
311void contextDestroy(context* c) {
312  Dprintf("contextDestroy ENTERED\n");
313  // Free The user parameters
314  if (c->slurpieServerAddress) free(c->slurpieServerAddress);
315  if (c->URL) free(c->URL);
316  if (c->URLMD5SUM) free(c->URLMD5SUM);
317  if (c->destFileName) free(c->destFileName);
318
319  // Destroy the NeighborManager
320  if(c->neighborMgr)
321    neighborManagerDestroy(c->neighborMgr);
322
323  // Second the leeches list
324  //while(!Q_empty(c->leeches)) {
325  //  leech_t* trash = (leech_t*)Q_Dequeue(c->leeches);
326  //  leechDestroy(trash);
327  //}
328  //Q_Destroy(c->leeches);
329
330  // Destroy the Sync Primitives
331  if (pthread_mutex_destroy(c->lock) != 0) {
332    printf("contextDestroy: error destroying the mutex\n");
333    abort();
334  }
335  // take out the updateTree
336  pthread_cancel(*c->updateThreadP);
337  if(c->updateTree)
338    updateTreeFree(c->updateTree);
339
340  close(c->fd);
341
342  Dprintf("contextDestroy EXIT\n");
343}
344
345int contextJoin(context* c) {
346  int rv = 0;
347  char addr[30];
348  connection_t* server;
349  order_cmd* order;
350  get_drinkers_cmd* get_drinkers;
351
352  pthread_mutex_lock(c->lock);
353	
354  // moved from contextCreate: Rob
355  c->neighborMgr= neighborManagerCreate((struct context *)c);
356
357  server = connection_create(PROTO_SLURPIED, SLURPIE_VERSION);
358  order = order_create(c->URL, neighborManagerGetAddr(c->neighborMgr, addr, 30), neighborManagerGetPort(c->neighborMgr));
359  get_drinkers = get_drinkers_create(c->URL, c->neighborMgr->maxNumOfNeighbors);
360
361  rv = server == NULL;
362  rv = (rv) ? rv : connection_connect(server, c->slurpieServerAddress, c->slurpieServerPort);
363  rv = (rv) ? rv : rem_slurpied_get_drinkers(server, &get_drinkers);
364  rv = (rv) ? rv : rem_slurpied_order(server, order);
365
366  if (server)
367    connection_destroy(server);
368  if (order) 
369    order_destroy(&order);
370  if (get_drinkers) {
371    int i;
372    if (rv == 0) {
373      if((get_drinkers->num_ip_ports)&&(!c->quiet)) printf("Neighbors:");
374      for (i = 0; i < get_drinkers->num_ip_ports; i++) {
375	char ipPortBuf[IP_PORT_BUF_LEN];
376	if(!c->quiet) printf(" %s", ip_port_to_string(get_drinkers->ip_ports[i], ipPortBuf, IP_PORT_BUF_LEN));
377	neighborManagerConnectToPeer(c->neighborMgr,
378				     get_drinkers->ip_ports[i]->ip,
379				     get_drinkers->ip_ports[i]->port);
380      }
381      if((get_drinkers->num_ip_ports)&&(!c->quiet)) printf("\n");
382    }
383
384    get_drinkers_destroy(&get_drinkers);
385  }
386  pthread_mutex_unlock(c->lock);
387  return rv;
388}
389
390void contextCreateLeechServer(context* c) {
391  if(c->useMTLeechServ)
392    c->leechServerP = leech_server_create(c);
393  else
394    c->leechServerP = leech_server_new_create(c);
395  assert(c->leechServerP);
396}
397
398void contextCreateHashCheck(context* c) {
399  c->hashChecker = hash_check_create(c);
400}
401
402/* int contextFileOpen(context *c);
403 * 	opens the dst file in the dst dir
404 */
405
406int contextFileOpen(context *c){
407  char buf[BUFLEN];
408  int fd;
409
410  snprintf(buf,BUFLEN,"%s",c->destFileName);
411  fd= open(buf,O_RDWR|O_CREAT|O_TRUNC,0644);
412  c->fd=fd;
413  if(fd == -1){
414    perror("contextFileOpen:open");
415    abort();
416  }
417  return fd;
418}
419
420/* char *contextParseFileName(context *c)
421 * 	sldkfslk
422 */
423
424char * contextParseFileName(context *c){
425  char * tmp;
426  if(c->destFileName)	// already set on command line
427    return c->destFileName;	
428  tmp = rindex(c->URL,'/');
429  tmp++;
430  c->destFileName = strdup(tmp);
431  return c->destFileName;
432}
433
434
435void do_context_tests() {
436  context* c = contextCreate();
437
438  // parseSlurpieServer test
439  {
440    const char* serverPort[] = { 
441      "envy.sodre.cx", 
442      "lust.sodre.cx:", 
443      "sloth.sodre.cx:33456",
444      ":33457", 
445      ":", 
446      NULL
447    };
448    const char* expectedAddress[] = {
449      "envy.sodre.cx",
450      "lust.sodre.cx",
451      "sloth.sodre.cx",
452      SLURPIED_DEFAULT_HOST,
453      SLURPIED_DEFAULT_HOST,
454      NULL
455    };
456    const int expectedPort[] = {
457      SLURPIED_DEFAULT_PORT,
458      SLURPIED_DEFAULT_PORT,
459      33456,
460      33457,
461      SLURPIED_DEFAULT_PORT,
462      -1
463    };
464    const char** sp = serverPort;
465    const char** ea = expectedAddress;
466    const int* ep = expectedPort;
467    for(; *sp != NULL; sp++, ea++, ep++) {
468      assert(parseSlurpieServer(c, *sp) == 0);
469      assert(strcmp(c->slurpieServerAddress, *ea) == 0);
470      assert(c->slurpieServerPort == *ep);
471      printf("%s -> %s:%d OK\n", *sp, *ea, *ep);
472      free(c->slurpieServerAddress);
473    }
474
475    assert(parseSlurpieServer(c, *(--sp)) == 0);
476  }
477
478  // Test the contextParseURL
479  {{{
480    const char* url = "ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/debian-30r0-i386-1_NONUS.iso";
481    assert(contextParseURL(c, url) == 0);
482    assert(strcmp(c->URL, url) == 0);
483    printf("%s == %s OK\n", url, c->URL);
484  }}}
485
486  // Test the parseURLMD5SUM
487  {{{
488    const char* url = "ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/MD5SUMS";
489    assert(parseURLMD5SUM(c, url) == 0);
490    assert(strcmp(c->URLMD5SUM, url) == 0);
491    printf("%s == %s OK\n", url, c->URLMD5SUM);
492  }}}
493
494  // Test the generateDestinationFilename
495  {{{
496    const char* destFN = "debian-30r0-i386-1_NONUS.iso";
497    assert(generateDestination(c) == 0);
498    assert(strcmp(c->destFileName, destFN) == 0);
499    printf("%s == %s OK\n", c->destFileName, destFN);
500  }}}
501
502  contextDestroy(c);
503  return;
504}
505
506// Local Prototypes. aka helper functions {{{2
507static int parseSlurpieServer(context* c, const char* server_port) {{{
508  int rv=0;
509  int i=0;
510  // Find a ':'
511  while(i < strlen(server_port) && server_port[i] != ':')
512    i++;
513
514  // Copy the serverName
515  if (i == 0) {
516    const char* defaultServer = SLURPIED_DEFAULT_HOST;
517    free(c->slurpieServerAddress);
518    c->slurpieServerAddress = (char*)(malloc(strlen(defaultServer)+1));
519    strcpy(c->slurpieServerAddress, defaultServer);
520  }
521  else {
522    c->slurpieServerAddress = (char*)(malloc(i+1));
523    strncpy(c->slurpieServerAddress, server_port, i);
524    c->slurpieServerAddress[i] = '\0';
525  }
526  // Get the Port
527  if ((i+1) >= strlen(server_port)) 
528    c->slurpieServerPort = SLURPIED_DEFAULT_PORT;
529  else {
530    char* endPtr;
531    c->slurpieServerPort = strtoul(&server_port[i+1], &endPtr, 10);
532    if (*endPtr != '\0') {
533      printf("contextParseSlurpieServer error: Invalid <[server]:[port]> %s\n", server_port);
534      rv = -1;
535    }
536  }
537
538  return rv;
539}}}
540static int contextParseURL(context* c, const char* url) {{{
541  int rv = 0;
542  // ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/debian-30r0-i386-1_NONUS.iso;
543  c->URL = (char*)malloc(strlen(url)+1);
544  if (c->URL) 
545    strcpy(c->URL, url);
546  else 
547    rv = -1;
548  return rv;
549}}}
550static int parseURLMD5SUM(context* c, const char* url) {{{
551  // ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/MD5SUMS;
552  int rv = 0;
553  c->URLMD5SUM = (char*)malloc(strlen(url)+1);
554  if (c->URLMD5SUM)
555    strcpy(c->URLMD5SUM, url);
556  else
557    rv = -1;
558  return rv;
559}}}
560static int generateDestination(context* c) {{{
561  int rv = 0;
562  // Default value was 
563  // debian-30r0-i386-1_NONUS.iso;
564  int i = strlen(c->URL);
565
566  // Look for the url separator '/'
567  do {
568    i--;
569  } while(i > 0 && c->URL[i] != '/');
570
571  // copy the filename
572  if (i > 0) {
573    const char* destFN = &c->URL[i+1];
574    c->destFileName = (char*)malloc(strlen(destFN)+1);
575    if (c->destFileName) 
576      strcpy(c->destFileName, destFN);
577    else 
578      rv = -1;
579  }
580  else 
581    rv = -1;
582  return rv;
583}}}
584// 2}}}