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