PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/Src/Symphony/slurpie_client/context.cpp

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