/Docs/Reference Code/Slurpie/client/src/context.c
C | 584 lines | 473 code | 58 blank | 53 comment | 88 complexity | 803f0a70d5986c3e6353492903d7396b MD5 | raw file
Possible License(s): BSD-3-Clause
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <time.h>
- #include "utils.h"
- #include "connection.h"
- #include "rem_slurpied.h"
- #include "protocol.h"
- #include "context.h"
- #include "leech_protocol.h"
- #include "leeches.h"
- #include "downloads.h"
- #include "dl.h"
- #include "hash_check.h"
- #include "version.h"
- // Local prototypes. aka helper functions
- static int parseSlurpieServer(context* c, const char* server_port);
- static int contextParseURL(context* c, const char* url);
- static int parseURLMD5SUM(context* c, const char* urlmd5sum);
- static int generateDestination(context* c);
- context* contextCreate() {
- context* c;
-
- // Allocate the structure
- c = (context*) malloc(sizeof(context));
- if (c == NULL)
- return NULL;
- memset(c, 0, sizeof(context));
- // Set some default values
- c->maxNumOfDownloads = DL_MAXDOWNLOADS;
- c->maxUpdateTreeLeaves = 100;
- c->maxNumOfNeighbors = MAXNUMNEIGHBORS;
- c->desiredNumOfNeighbors = DEFAULTNUMNEIGHBORS;
- c->desiredNumOfUpdates=DEFAULT_UPDATES_PER_ROUND;
- c->neighborChoice=0;
- c->URL= NULL;
- // leech server stuff
- c->maxNumOfLeeches = 10;
- c->numOfLeechThreads = 10;
- c->useMTLeechServ = 0;
- // Initialize the Block break rule
- c->blockRule = 0;
- c->blockSize = 256*1024; // by default, bs=256k
- c->blockingPriority = BLOCKSIZEPRIORITY; // by default, we fix
- // the blocksize, and then calculate the number of blocks
- // as a function of the size, by default
- c->fileSize = -1; // set later in init
- c->numberOfBlocks = -1;
- c->fd = 0;
- c->dlBitMap = NULL;
- c->dlq = NULL;
- c->ac = NULL;
- c->quiet = 0; // not quiet by default
- c->downloadType=DOWNLOADTYPE_ADAPTIVE; // download style
- c->phase2=0;
- c->magicTime=DEFAULT_MAGIC_TIME;
- c->pickTwo=0;
- c->randomSeed=-1;
- // Neighbor Manager: creation moved to contextJoin
- c->neighborMgr = NULL;
- // Hash stuff
- c->hashChecker = NULL;
- c->hash_enabled = 0;
- c->hash_maxRequestSize = DEFAULT_HASH_MAX_REQ_SIZE;
-
- c->backoffRule=BACKOFFRULE_GOOD;
- c->backoffBias=BACKOFFBIASDEFAULT;
- c->backOffCommitTime=DEFAULT_BACKOFF_TIME;
- c->backoffDidBackOff=0;
- c->peerBlocksDld=c-> sourceBlocksDld=0;
- // LeechesList
- //c->leeches = Q_Create();
- //c->leechLocalPort = LEECH_DEFAULT_PORT;
- // Update Tree
- // If you create something thing, don't forget to destroy
- // it at contextDestroy
- c->updateTree = updateTreeNew(c->maxUpdateTreeLeaves);
- c->updateThreadP=NULL;
- // Slurpie Server stuff
- c->slurpieServerAddress = (char*)(malloc(strlen(SLURPIED_DEFAULT_HOST)+1));
- strcpy(c->slurpieServerAddress, SLURPIED_DEFAULT_HOST);
- c->slurpieServerPort=SLURPIED_DEFAULT_PORT;
- c->localIp = getLocalHostIP();
- // Initialize the Synchronization Primitives
- c->lock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
- if (pthread_mutex_init(c->lock, NULL) != 0) {
- printf("contextCreate:pthread_mutex_init failed!\n");
- abort();
- }
- c->flock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
- if (pthread_mutex_init(c->flock, NULL) != 0) {
- printf("contextCreate:pthread_mutex_init failed!\n");
- abort();
- }
- // Default adaptive downloading parameters
- c->adl_maxBandwidth = DEFAULT_ADL_MAX_BANDWIDTH;;
- c->adl_timer = DEFAULT_ADL_TIMER;
- c->adl_timer_inc = DEFAULT_ADL_TIMER_INC;
- c->adl_maxConnections = DEFAULT_ADL_MAX_CONNECTIONS;
- c->adl_bandwidth_inc = DEFAULT_ADL_BANDWIDTH_INC;
- return c;
- }
- int contextParseParameters(context* c, int argc, char** argv) {
- int i;
- // Lock the mutex
- pthread_mutex_lock(c->lock);
- for(i=1;i<argc;i++){
- if(!strcmp(argv[i],"-q")){
- c->quiet=1;
- continue;
- }
- if(!strcmp(argv[i],"-p")){
- c->phase2=1;
- continue;
- }
- if((!strcmp(argv[i],"-s"))&&(i+1<argc)){
- i++;
- if(parseSlurpieServer(c,argv[i]))
- usage(argv[i],": bad server:port");
- continue;
- }
- if((!strcmp(argv[i],"-o"))&&(i+1<argc)){
- i++;
- c->destFileName = strdup(argv[i]);
- assert(c->destFileName!=NULL);
- continue;
- }
- if((!strcmp(argv[i],"-N"))&&(i+1<argc)){
- i++;
- c->maxNumOfNeighbors = atoi(argv[i]);
- assert(c->maxNumOfNeighbors>=0);
- continue;
- }
- if((!strcmp(argv[i],"-m"))&&(i+1<argc)){
- i++;
- c->magicTime = atoi(argv[i]);
- assert(c->magicTime>=0);
- continue;
- }
- if((!strcmp(argv[i],"-n"))&&(i+1<argc)){
- i++;
- c->numberOfBlocks = atoi(argv[i]);
- c->blockingPriority=NUMBLOCKSPRIORITY;
- assert(c->numberOfBlocks>=0);
- continue;
- }
- if((!strcmp(argv[i],"-b"))&&(i+1<argc)){
- i++;
- c->blockSize = atoi(argv[i]);
- c->blockingPriority=BLOCKSIZEPRIORITY;
- assert(c->blockSize>=0);
- continue;
- }
- if((!strcmp(argv[i],"-B"))&&(i+1<argc)){
- i++;
- c->backoffRule = atoi(argv[i]);
- continue;
- }
- if((!strcmp(argv[i],"-bt"))&&(i+1<argc)){
- i++;
- c->backoffTime = atoi(argv[i]);
- continue;
- }
- if((!strcmp(argv[i],"-bb"))&&(i+1<argc)){
- i++;
- c->backoffBias = atoi(argv[i]);
- continue;
- }
- if((!strcmp(argv[i],"-d"))&&(i+1<argc)){
- i++;
- DEBUGLEVEL = atoi(argv[i]);
- assert(DEBUGLEVEL>=0);
- continue;
- }
- if((!strcmp(argv[i],"-R"))&&(i+1<argc)){
- i++;
- c->randomSeed = atoi(argv[i]);
- continue;
- }
- if((!strcmp(argv[i],"-t"))&&(i+1<argc)){
- i++;
- c->maxNumOfDownloads = atoi(argv[i]);
- assert(c->maxNumOfDownloads>=0);
- continue;
- }
- if(!strncmp(argv[i],"ftp://",strlen("ftp://"))){
- if(contextParseURL(c,argv[i]))
- usage(argv[i],": bad URL");
- continue;
- }
- if(!strncmp(argv[i],"http://",strlen("http://"))){
- if(contextParseURL(c,argv[i]))
- usage(argv[i],": bad URL");
- continue;
- }
- if(!strcmp(argv[i],"-a")){
- c->downloadType=DOWNLOADTYPE_ADAPTIVE;
- continue;
- }
- if(!strcmp(argv[i],"-at")){
- i++;
- c->adl_timer=atoi(argv[i]);
- assert(c->adl_timer>=0);
- continue;
- }
- if(!strcmp(argv[i], "-P")) {
- c->pickTwo = 0;
- continue;
- }
- if(!strcmp(argv[i], "-L")) {
- c->neighborChoice = 1;
- continue;
- }
- if(!strcmp(argv[i], "-l")) {
- c->useMTLeechServ = 1;
- continue;
- }
- if(!strcmp(argv[i], "-S")) {
- c->hash_enabled = 1;
- continue;
- }
- if(!strcmp(argv[i], "-Ssize")) {
- // The value specified is in kilobytes, but store it in bytes for
- // easy comparison later
- i++;
- c->hash_maxRequestSize = 1024 * atoi(argv[i]);
- assert(c->hash_maxRequestSize > 0);
- continue;
- }
- usage(argv[i],": unknown argument");
- }
- pthread_mutex_unlock(c->lock);
- return 0;
- }
- void usage(char *s1, char *s2) {
- if(s1)
- fprintf(stderr,"%s ",s1);
- if(s2)
- fprintf(stderr,"%s ",s2);
- if(s1||s2)
- fprintf(stderr,"\n");
- fprintf(stderr,"Slurpie Client v%d.%d\n"
- "Usage:\n"
- "slurpie [options] <http://...|ftp://...>\n"
- "Options:\n"
- "\t-a - turns on adaptive downloads\n"
- "\t-s host[:port] - set slurpie server\n"
- "\t-t nThreads - number of concurrent downloads\n"
- "\t-o outfile - alternative name for outfile\n"
- "\t-b blocksize - sets the size of the blocks\n"
- "\t-B rule - sets the backoff rule [off]\n"
- "\t-bt secs - time in secs to backoff [%d]\n"
- "\t-bb k - goto the source with P(k/n) [%d]\n"
- "\t-m secs - the time to wait after downloads[%d]\n"
- "\t-n numberofblocks - sets the number of blocks (overrides blocksize)\n"
- "\t-N numofneighbors - sets the number of neighbors[%d]\n"
- "\t-l - use old (multithreaded) threaded leech sever\n"
- "\t-L - sets neighbors to O(ln(n))\n"
- "\t-p - disable phase1 of downloads\n"
- "\t-P - pick best block of 2\n"
- "\t-q - turns off all screen output\n"
- "\t-R seed - seed the PRNG with 'seed' \n"
- "\t-d level - sets the debug level[%d]\n"
- "\t-S - turns on secure mode (blocks verified)\n"
- "\t-------------- Adaptive Download Options -------------\n"
- "\t-at secs - initial timer value [%d] \n"
- "\t----------------- Secure Mode Options ----------------\n"
- "\t-Ssize kbytes - sets the maximum size of a hash request [1024]\n",
- SLURPIE_VERSION.major,
- SLURPIE_VERSION.minor,
- DEFAULT_BACKOFF_TIME,
- BACKOFFBIASDEFAULT,
- DEFAULT_MAGIC_TIME,
- DEFAULTNUMNEIGHBORS,
- DEFAULTDEBUGLEVEL,
- DEFAULT_ADL_TIMER
- );
- exit(1);
- }
- void contextDestroy(context* c) {
- Dprintf("contextDestroy ENTERED\n");
- // Free The user parameters
- if (c->slurpieServerAddress) free(c->slurpieServerAddress);
- if (c->URL) free(c->URL);
- if (c->URLMD5SUM) free(c->URLMD5SUM);
- if (c->destFileName) free(c->destFileName);
- // Destroy the NeighborManager
- if(c->neighborMgr)
- neighborManagerDestroy(c->neighborMgr);
- // Second the leeches list
- //while(!Q_empty(c->leeches)) {
- // leech_t* trash = (leech_t*)Q_Dequeue(c->leeches);
- // leechDestroy(trash);
- //}
- //Q_Destroy(c->leeches);
- // Destroy the Sync Primitives
- if (pthread_mutex_destroy(c->lock) != 0) {
- printf("contextDestroy: error destroying the mutex\n");
- abort();
- }
- // take out the updateTree
- pthread_cancel(*c->updateThreadP);
- if(c->updateTree)
- updateTreeFree(c->updateTree);
- close(c->fd);
- Dprintf("contextDestroy EXIT\n");
- }
- int contextJoin(context* c) {
- int rv = 0;
- char addr[30];
- connection_t* server;
- order_cmd* order;
- get_drinkers_cmd* get_drinkers;
- pthread_mutex_lock(c->lock);
-
- // moved from contextCreate: Rob
- c->neighborMgr= neighborManagerCreate((struct context *)c);
- server = connection_create(PROTO_SLURPIED, SLURPIE_VERSION);
- order = order_create(c->URL, neighborManagerGetAddr(c->neighborMgr, addr, 30), neighborManagerGetPort(c->neighborMgr));
- get_drinkers = get_drinkers_create(c->URL, c->neighborMgr->maxNumOfNeighbors);
- rv = server == NULL;
- rv = (rv) ? rv : connection_connect(server, c->slurpieServerAddress, c->slurpieServerPort);
- rv = (rv) ? rv : rem_slurpied_get_drinkers(server, &get_drinkers);
- rv = (rv) ? rv : rem_slurpied_order(server, order);
- if (server)
- connection_destroy(server);
- if (order)
- order_destroy(&order);
- if (get_drinkers) {
- int i;
- if (rv == 0) {
- if((get_drinkers->num_ip_ports)&&(!c->quiet)) printf("Neighbors:");
- for (i = 0; i < get_drinkers->num_ip_ports; i++) {
- char ipPortBuf[IP_PORT_BUF_LEN];
- if(!c->quiet) printf(" %s", ip_port_to_string(get_drinkers->ip_ports[i], ipPortBuf, IP_PORT_BUF_LEN));
- neighborManagerConnectToPeer(c->neighborMgr,
- get_drinkers->ip_ports[i]->ip,
- get_drinkers->ip_ports[i]->port);
- }
- if((get_drinkers->num_ip_ports)&&(!c->quiet)) printf("\n");
- }
- get_drinkers_destroy(&get_drinkers);
- }
- pthread_mutex_unlock(c->lock);
- return rv;
- }
- void contextCreateLeechServer(context* c) {
- if(c->useMTLeechServ)
- c->leechServerP = leech_server_create(c);
- else
- c->leechServerP = leech_server_new_create(c);
- assert(c->leechServerP);
- }
- void contextCreateHashCheck(context* c) {
- c->hashChecker = hash_check_create(c);
- }
- /* int contextFileOpen(context *c);
- * opens the dst file in the dst dir
- */
- int contextFileOpen(context *c){
- char buf[BUFLEN];
- int fd;
- snprintf(buf,BUFLEN,"%s",c->destFileName);
- fd= open(buf,O_RDWR|O_CREAT|O_TRUNC,0644);
- c->fd=fd;
- if(fd == -1){
- perror("contextFileOpen:open");
- abort();
- }
- return fd;
- }
- /* char *contextParseFileName(context *c)
- * sldkfslk
- */
- char * contextParseFileName(context *c){
- char * tmp;
- if(c->destFileName) // already set on command line
- return c->destFileName;
- tmp = rindex(c->URL,'/');
- tmp++;
- c->destFileName = strdup(tmp);
- return c->destFileName;
- }
- void do_context_tests() {
- context* c = contextCreate();
- // parseSlurpieServer test
- {
- const char* serverPort[] = {
- "envy.sodre.cx",
- "lust.sodre.cx:",
- "sloth.sodre.cx:33456",
- ":33457",
- ":",
- NULL
- };
- const char* expectedAddress[] = {
- "envy.sodre.cx",
- "lust.sodre.cx",
- "sloth.sodre.cx",
- SLURPIED_DEFAULT_HOST,
- SLURPIED_DEFAULT_HOST,
- NULL
- };
- const int expectedPort[] = {
- SLURPIED_DEFAULT_PORT,
- SLURPIED_DEFAULT_PORT,
- 33456,
- 33457,
- SLURPIED_DEFAULT_PORT,
- -1
- };
- const char** sp = serverPort;
- const char** ea = expectedAddress;
- const int* ep = expectedPort;
- for(; *sp != NULL; sp++, ea++, ep++) {
- assert(parseSlurpieServer(c, *sp) == 0);
- assert(strcmp(c->slurpieServerAddress, *ea) == 0);
- assert(c->slurpieServerPort == *ep);
- printf("%s -> %s:%d OK\n", *sp, *ea, *ep);
- free(c->slurpieServerAddress);
- }
- assert(parseSlurpieServer(c, *(--sp)) == 0);
- }
- // Test the contextParseURL
- {{{
- const char* url = "ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/debian-30r0-i386-1_NONUS.iso";
- assert(contextParseURL(c, url) == 0);
- assert(strcmp(c->URL, url) == 0);
- printf("%s == %s OK\n", url, c->URL);
- }}}
- // Test the parseURLMD5SUM
- {{{
- const char* url = "ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/MD5SUMS";
- assert(parseURLMD5SUM(c, url) == 0);
- assert(strcmp(c->URLMD5SUM, url) == 0);
- printf("%s == %s OK\n", url, c->URLMD5SUM);
- }}}
- // Test the generateDestinationFilename
- {{{
- const char* destFN = "debian-30r0-i386-1_NONUS.iso";
- assert(generateDestination(c) == 0);
- assert(strcmp(c->destFileName, destFN) == 0);
- printf("%s == %s OK\n", c->destFileName, destFN);
- }}}
- contextDestroy(c);
- return;
- }
- // Local Prototypes. aka helper functions {{{2
- static int parseSlurpieServer(context* c, const char* server_port) {{{
- int rv=0;
- int i=0;
- // Find a ':'
- while(i < strlen(server_port) && server_port[i] != ':')
- i++;
- // Copy the serverName
- if (i == 0) {
- const char* defaultServer = SLURPIED_DEFAULT_HOST;
- free(c->slurpieServerAddress);
- c->slurpieServerAddress = (char*)(malloc(strlen(defaultServer)+1));
- strcpy(c->slurpieServerAddress, defaultServer);
- }
- else {
- c->slurpieServerAddress = (char*)(malloc(i+1));
- strncpy(c->slurpieServerAddress, server_port, i);
- c->slurpieServerAddress[i] = '\0';
- }
- // Get the Port
- if ((i+1) >= strlen(server_port))
- c->slurpieServerPort = SLURPIED_DEFAULT_PORT;
- else {
- char* endPtr;
- c->slurpieServerPort = strtoul(&server_port[i+1], &endPtr, 10);
- if (*endPtr != '\0') {
- printf("contextParseSlurpieServer error: Invalid <[server]:[port]> %s\n", server_port);
- rv = -1;
- }
- }
- return rv;
- }}}
- static int contextParseURL(context* c, const char* url) {{{
- int rv = 0;
- // ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/debian-30r0-i386-1_NONUS.iso;
- c->URL = (char*)malloc(strlen(url)+1);
- if (c->URL)
- strcpy(c->URL, url);
- else
- rv = -1;
- return rv;
- }}}
- static int parseURLMD5SUM(context* c, const char* url) {{{
- // ftp://ftp2.it.debian.org/debian-cd/3.0_r0/i386/MD5SUMS;
- int rv = 0;
- c->URLMD5SUM = (char*)malloc(strlen(url)+1);
- if (c->URLMD5SUM)
- strcpy(c->URLMD5SUM, url);
- else
- rv = -1;
- return rv;
- }}}
- static int generateDestination(context* c) {{{
- int rv = 0;
- // Default value was
- // debian-30r0-i386-1_NONUS.iso;
- int i = strlen(c->URL);
- // Look for the url separator '/'
- do {
- i--;
- } while(i > 0 && c->URL[i] != '/');
- // copy the filename
- if (i > 0) {
- const char* destFN = &c->URL[i+1];
- c->destFileName = (char*)malloc(strlen(destFN)+1);
- if (c->destFileName)
- strcpy(c->destFileName, destFN);
- else
- rv = -1;
- }
- else
- rv = -1;
- return rv;
- }}}
- // 2}}}