Esempio n. 1
0
int command_check_hexstring(int argc, char **argv, int optind,
    int flags) {
  int ret = EXIT_SUCCESS;
  int i = optind-1;
  uint32_t strcrc, crc;
  long int cast;

  if(flags & CALC_PRINT_NUMERICAL)
    cast = (uint32_t) strtol(hexarg, NULL, 10);
  else
    cast = (uint32_t) strtol(hexarg, NULL, 16);
  if((cast == LONG_MIN || cast == LONG_MAX) &&
    errno == ERANGE)
    cast = 0;
  strcrc = (uint32_t) cast;

  while(argv[++i]) {
    if(check_access_flags_v(argv[i], F_OK | R_OK, 1) != 0) {
      log_failure(argv[i], "not accessible, not a file or doesn't exist");
      ret = EXIT_FAILURE;
      continue;
    }
    if((crc = compute_crc32(argv[i])) == strcrc)
      log_success(argv[i], "match");
    else 
      log_failure(argv[i], "mismatch: %08X is really %08X", strcrc, crc);
  }

  return ret;
}
Esempio n. 2
0
static int find_file () {
    struct parsed_cmd   *parsed_get;

        if (cmd_parse_failed ((parsed_get = cmd_parse (r->cmd, NULL))))
            return -1;

        /*
         *  Checking whether the arguments are valid.  If they are, retrieves the
         *  data (stored in the cache) about the file to be downloaded
         */
        if (parsed_get->argc == 1) {
            if (client_send (r->client,
                                " < get: you need to specify a key\n") < 0)
                log_failure (log_file, "cr_get: client_send () failed");
            goto error;
        }
        else {
            if (strlen (parsed_get->argv[1]) != FILE_KEY_SIZE) {
                if (client_send (r->client,
                                    " < get: hash size is not good, man\n") < 0)
                    log_failure (log_file, "cr_get: client_send () failed");
                goto error;
            }
            else {
                sem_wait (&file_cache_lock);
                file_to_dl = file_cache_get_by_key (file_cache, parsed_get->argv[1]);
                sem_post (&file_cache_lock);
                if (!file_to_dl) {
                    if (client_send (r->client,
                                    " < get: key not in cache, please list\n") < 0)
                        log_failure (log_file, "cr_get: client_send () failed");
                    goto error;
                }
                sprintf (answer,
                        "< get : seeder is %s:%d\n",
                        file_to_dl->seeders->ip,
                        file_to_dl->seeders->port);
                if (client_send (r->client, answer) < 0) {
                    log_failure (log_file, "cr_get: client_send () failed");
                    goto error;
                }
            }
        }
        
        cmd_parse_free (parsed_get);

        if (client_send (r->client, answer) < 0) {
            log_failure (log_file, "cr_get: client_send () failed");
            return -1;
        }

        return 0;

    error:
        if (parsed_get)
            cmd_parse_free (parsed_get);
        return -1;
    }
Esempio n. 3
0
int command_list_db(int argc, char **argv, int optind, int flags) {
  struct DBItem dbi = DBITEM_NULL;
  struct DBItem *e = NULL;
  char *p = NULL;
  int do_free_p = 0;
  int i = 0;

  for(i = optind; i < argc; ++i) {
    DBITEM_SET_NULL(dbi);
    e = NULL;
    if(access(argv[i], F_OK | R_OK) != 0 || DB_read(argv[i], &dbi) != 0) {
      log_failure(argv[i], "doesn't exist or isn't a valid database");
      continue;
    }
    if(dbi.kbuf == NULL) {
      log_info(argv[i], "is empty");
      continue;
    }
    e = &dbi;
    do {
      p = e->kbuf;
      if(flags & USE_REALPATH)
        p = get_realpath((const char*) e->kbuf, &do_free_p);
      log_success(argv[i], "%s -> %08X", p, e->crc);
      if(do_free_p == 1) {
        free(p);
        do_free_p = 0;
      }
    } while((e = e->next) != NULL);
    if(dbi.next != NULL)
      DB_item_free(dbi.next);
  }

  return EXIT_SUCCESS;
}
Esempio n. 4
0
int
daemon_send (struct daemon *d, const char *msg) {
    int     dest_sock;
    int     nb_sent;
    int     nb_sent_sum;
    int     send_size;
//    char    ending_char;

    // Log this (see ../util/logger.c to disactivate this)
    log_send (log_file, msg);

    dest_sock = d->socket;
    if (sem_wait (&d->socket_lock) < 0) {
        log_failure (log_file,
                    "failed to sem_wait socket_lock, error: %s",
                    strerror (errno));
        return -1;
    }

    // Now the socket is locked for us, let's send!
    send_size = strlen (msg);

    // Send the command
    nb_sent_sum = 0;
    while (nb_sent_sum < send_size) {
        nb_sent = send (dest_sock,
                        msg + nb_sent_sum,
                        send_size - nb_sent_sum,
                        0);
        if (nb_sent < 0) {
            log_failure (log_file,
                        "couldn't send to daemon socket, error: %s",
                        strerror (errno));
            return -1;
        }
        nb_sent_sum += nb_sent;
    }

    if (sem_post (&d->socket_lock) < 0) {
        log_failure (log_file,
                    "failed to sem_post socket_lock, error: %s",
                    strerror (errno));
    }

    return 0;
}
Esempio n. 5
0
/*
 * Creates a struct file_cache.
 */
static struct file_cache *
file_cache_new (const char *filename,
                const char *key,
                file_size_t size,
                const char *ip,
                int port) {
    struct file_cache *file_cache;

    file_cache = (struct file_cache *)malloc (sizeof (struct file_cache));

    if (strlen (filename) > FILE_NAME_SIZE) {
        log_failure (log_file, "file_cache_new (): Too long filename");
        free (file_cache);
        return NULL;
    }
    strncpy (file_cache->filename, filename, FILE_NAME_SIZE + 1);

    if (strlen (key) != FILE_KEY_SIZE) {
        log_failure (log_file, "file_cache_new (): Wrong key size");
        free (file_cache);
        return NULL;
    }
    strncpy (file_cache->key, key, FILE_KEY_SIZE + 1);

    file_cache->size = size;

    file_cache->seeders = (struct seeder *)malloc (sizeof (struct seeder));
    strncpy (file_cache->seeders->ip, ip, FILE_IP_SIZE + 1);
    file_cache->seeders->port = port;
    file_cache->seeders->next = NULL;

    if (sem_init (&file_cache->seeders_lock, 0, 1) < 0) {
        log_failure (log_file, "file_cache_new (): Unable to sem_init");
        free (file_cache->seeders);
        free (file_cache);
        return NULL;
    }

    file_cache->left = NULL;
    file_cache->right = NULL;

    return file_cache;
}
Esempio n. 6
0
/*
 * We silently ignore options/arguments, according to the protocol.
 */
void *
client_request_download (void *arg) {
    struct client_request    *r;
    struct dl_file           *tmp;
    struct stat              stat_buf;
    char answer[512];
   
    r = (struct client_request *) arg; 
    if (!r)
        return NULL;

    sem_wait (&downloads_lock);
    if (!downloads) {
        sprintf (answer, 
                 "No files are currently being downloaded.\n");
        if (client_send (r->client, answer) < 0) {
            log_failure (log_file,
                        "client_request_download () : client_send () failed");
        }
        sem_post (&downloads_lock);
        goto out;
    }
    
    for (tmp = downloads; tmp; tmp = tmp->next) {
        stat (tmp->path, &stat_buf);
        sprintf (answer, 
                "Downloading file %s %.2f %c %d %d \n", 
                tmp->path,
                (float) stat_buf.st_size/ (float)tmp->total_size * 100,        
               '%',
                (int) stat_buf.st_size,
                (int) tmp->total_size);
        if (client_send (r->client, answer) < 0) {
            log_failure (log_file,
                        "client_request_download () : client_send () failed");
        }
    }
    sem_post (&downloads_lock);

out:
    return NULL;
}
Esempio n. 7
0
int command_check(int argc, char **argv, int optind, int flags) {
  int ret = EXIT_SUCCESS;
  int i = optind-1;
  int  ci, ti;
  uint32_t compcrc, matchcrc;
  char *string;
  char results[9];
  regmatch_t rmatch;
  regex_t regex;

  while(argv[++i]) {
    if(check_access_flags_v(argv[i], F_OK | R_OK, 1) != 0) {
      log_info(argv[i], "Inaccessbile file, skipping.");
      continue;
    }
    string = get_basename((char*)argv[i]);
    compile_regex(&regex, crcregex, REG_ICASE);
    switch(regexec((const regex_t*) &regex, string, 1, &rmatch, 0)) {
      case 0:
        for(ci = rmatch.rm_so, ti = 0; ci < rmatch.rm_eo; ++ci)
            results[ti++] = string[ci];
        results[ti] = '\0';
        break;
      case REG_NOMATCH:
        log_info(argv[i], "Does not contain a hexstring, ignoring.");
        continue;
    }
    regfree(&regex);
    compcrc = compute_crc32(argv[i]);
    matchcrc = (uint32_t) strtol(results, NULL, 16);
    if(compcrc == matchcrc)
      log_success(argv[i], "OK");
    else {
      log_failure(argv[i], "Mismatch: %08X is really %08X", matchcrc, compcrc);
      ret = EXIT_FAILURE;
    }
  } /* while */

  return ret;
}
Esempio n. 8
0
int command_merge(int argc, char **argv, int optind, int cmdflags) {
  char *dbsources[argc-optind+1];
  int i, j;
  int do_truncate = 1;

  if(cmdflags & APPEND_TO_DB)
    do_truncate = 0;

  for(i = optind, j = 0; i < argc; ++i) {
    dbsources[j++] = argv[i];
  }
  dbsources[j] = NULL;

  if(DB_merge(dbiofile, (const char**) dbsources, do_truncate) != 0)
    return EXIT_FAILURE;

  if(cmdflags & USE_REALPATH)
    if(DB_make_paths_absolute(dbiofile) != 0)
      log_failure(dbiofile, "couldn't make file paths absolute");

  return EXIT_SUCCESS;
}
Esempio n. 9
0
/* Assume that reported resolution is constant */
static void clock_getres_verify(struct ctx *ctx)
{
	struct timespec sanity;

	clock_getres_syscall_nofail(CLOCK_ID, &sanity);

	ctx_start_timer(ctx);

	while (!test_should_stop(ctx)) {
		struct timespec kres;
		struct timespec vres;

		clock_getres_syscall_nofail(CLOCK_ID, &kres);

		/* Check assumptions */
		if (!timespecs_equal(&kres, &sanity)) {
			error(EXIT_FAILURE, 0,
			      "clock resolution reported by kernel changed: "
			      "from [%ld, %ld] to [%ld, %ld]",
			      sanity.tv_sec, sanity.tv_nsec,
			      kres.tv_sec, kres.tv_nsec);
		}

		if (!vdso_has_clock_getres())
			continue;

		clock_getres_vdso_nofail(CLOCK_ID, &vres);
		if (!timespecs_equal(&kres, &vres)) {
			log_failure(ctx, "clock resolutions differ:\n"
				    "\t[%ld, %ld] (kernel)\n"
				    "\t[%ld, %ld] (vDSO)\n",
				    kres.tv_sec, kres.tv_nsec,
				    vres.tv_sec, vres.tv_nsec);
		}
	}

	ctx_cleanup_timer(ctx);
}
Esempio n. 10
0
int command_remove_tag(int argc, char **argv, int optind, int flags) {
  const char *filename = argv[argc-1];
  char *str, *nstr, *p, *q;
  const char *d;
  int i;

  for(i = optind; i < argc; ++i) {
    check_access_flags(argv[i], F_OK | R_OK | W_OK, 1);
    str = get_basename((char*)argv[i]);
    if((nstr = strip_tag((const char*) str, crcregex_stripper)) == NULL) {
      log_failure(argv[i], "no hexstring found");
      return EXIT_FAILURE;
    }
    d = (const char*) dirname((char*)argv[i]);
    p = pathcat(d, (const char*)str);
    q = pathcat(d, (const char*)nstr);
    if(rename((const char*) p, (const char*) q) != 0)
      LERROR(EXIT_FAILURE, errno, "rename() failed");
    free(p);
    free(q);
    free(nstr);
  }
  return EXIT_SUCCESS;
}
Esempio n. 11
0
static void
server_stop (int sig) {
    struct client   *c;
    struct daemon   *d;

    pool_destroy (slow_pool);
    pool_destroy (fast_pool);
    pool_destroy (clients_pool);
    pool_destroy (daemons_pool);

    (void) sig;
    log_failure (log_file, "Ok, received a signal");
    sleep (2);

    sem_destroy (&clients_lock);
    sem_destroy (&daemons_lock);
    sem_destroy (&file_cache_lock);
    sem_destroy (&downloads_lock);

    if (clients) {
        while (clients) {
            c = clients->next;
            client_free (clients);
            clients = c;
        }
        log_success (log_file,
                     "%s : all clients have been freed",
                     __func__);
    }

    if (daemons) {
        while (daemons) {
            d = daemons->next;
            daemon_send (daemons, "quit\n");
            daemon_free (daemons);
            daemons = d;
        }
        log_success (log_file,
                     "%s : all daemons have been freed",
                     __func__);
    }

    if (file_cache) {
        file_cache_free (file_cache);
        log_success (log_file,
                     "%s : file cache has been freed",
                     __func__);
    }

    if (unlink (prefs->lock_file) < 0)
        if (log_file)
            log_failure (log_file, "Could not destroy the lock file");
    if (prefs) {
        conf_free (prefs);
        log_success (log_file,
                     "%s : Preferences have been freed.",
                     __func__);
    }

    if (log_file) {
        log_success (log_file, "Stopping server, waiting for SIGKILL");
        fclose (log_file);
    }

    exit (EXIT_SUCCESS);
}
Esempio n. 12
0
void*
client_request_get (void *arg) {
    r = (struct client_request *) arg;
    struct daemon_list  *d_list;
    struct daemon_list  *list_item_to_delete;
    struct daemon       *next_d;
    int                 seeder_count;
    
    if (!r)
        return NULL;


    /* First we find the file in the cache */
    
    if (find_file () < 0)
        return NULL;
    /* file_to_dl should now be the good one */


    /* Find the daemons owning the file by checking its IP */
    if ((d_list = find_daemons ()) != NULL) {
        if (client_send (r->client,
            " < no seeder for the requested file. Former seeders must have been disconnected.\n") < 0)
            log_failure (log_file, "cr_get: client_send () failed");
        return NULL;
    }

    
    /* about handling multi-seeders and block-by-block download */
    
    // we know the number of seeders
    seeder_count = d_list->id;
    
    /* FIXME : calculate smartly the blocks to consider,
     * given :
     * - number of seeders
     * - size of file to dl
     * - a max_size for a block ? Not implemented
     */
     
    /* loop where we have to post a job for each seeder
     */
    next_d = d_list->daemon;
    while (next_d != NULL) {
        // FIXME : act !!!! do something !!!
        
        list_item_to_delete = d_list;
        d_list = d_list->next;
        free (list_item_to_delete);
    }



    /* Sending the "get key begin end" message */
    sprintf (answer,
             "get %s %d %ld\n",
             file_to_dl->key,
             0,
             file_to_dl->size);
    if (daemon_send (d, answer) < 0) {
        log_failure (log_file, "cr_get: could not send the get command");
        return NULL;
    }
    
    
/* FIXME */
#if 0
    sem_wait (&downloads_lock);
    char *full_path;
    struct dl_file *f;

    full_path = malloc (strlen (prefs->shared_folder)
                        + strlen (file_to_dl->filename) + 2);
    if (!full_path) {
        log_failure (log_file, "OMG NO MALLOC IS POSSIBLE");
        return NULL;
    }
    else {
        sprintf (full_path, "%s/%s",
                        prefs->shared_folder, file_to_dl->filename);
    }
    f = dl_file_new (full_path);
    if (!f) {
        log_failure (log_file, "SHARED FOLDER : %S", prefs->shared_folder);
        log_failure (log_file, "f was NULL %s", full_path);
    }
    downloads = dl_file_add (downloads, f);
    if (!downloads)
        log_failure (log_file, "downlaods was NULL");
    else
        log_failure (log_file, "downloads->path : %s", downloads->path);
    sem_post (&downloads_lock);
#endif

    return NULL;
}
Esempio n. 13
0
void*
daemon_request_list (void *arg) {
    struct daemon_request   *r;
    char                    answer[512];
    DIR                     *dir;
    struct dirent           *entry;
    char                    entry_full_path[256];
    struct stat             entry_stat;
    char                    *key;

    /* OKAY, let's say all options/args are silently ignored */

    r = (struct daemon_request *)arg;
    if (!r)
        return NULL;

    dir = opendir (prefs->shared_folder);
    if (dir == NULL) {
        log_failure (log_file,
                    "daemon_request_list (): Unable to opendir %s",
                    prefs->shared_folder);
        return NULL;
    }
    // Browsing my own files
    for (entry = readdir (dir); entry != NULL; entry = readdir (dir)) {
        // Listing all regular files
        if (entry->d_type == DT_REG) {
            sprintf (entry_full_path,
                    "%s/%s",
                    prefs->shared_folder,
                    entry->d_name);
            if (stat (entry_full_path, &entry_stat) < 0) {
                log_failure (log_file,
                            "daemon_request_list (): can't stat file %s",
                            entry_full_path);
                continue;
            }

            key = get_md5 (entry_full_path);
            if (!key)
                continue;

            sprintf (answer, "file %s %s %d %s:%d\n",
                    entry->d_name,
                    key,
                    (int) entry_stat.st_size,
                    my_ip,
                    prefs->daemon_port);

            if (daemon_send (r->daemon, answer) < 0) {
                log_failure (log_file,
                    "daemon_request_list (): failed to send data to daemon");
            }

            free (key);
            key = NULL;
        }
    }

    if (closedir (dir) < 0) {
        log_failure (log_file,
                    "daemon_request_list () : can't close shared directory");
        return NULL;
    }

    return NULL;
}
Esempio n. 14
0
struct file_cache *
file_cache_add (struct file_cache *tree,
                const char *filename,
                const char *key,
                file_size_t size,
                const char *ip,
                int port) {
    /* bias determines if we go left or right in the binary tree */
    int                 bias = 0;
    struct seeder       *s;

    // If the tree is empty, we create it
    if (!tree) {
        tree = file_cache_new (filename, key, size, ip, port);
        if (!tree) {
            log_failure (log_file,
                        "file_cache_add (): Unable to file_cache_new ()");
            return NULL;
        }
    }
    // If the tree isn't empty, recursive call to find the right place
    else {
        bias = strcmp (key, tree->key);
        if (bias < 0) {
            tree->left = file_cache_add (tree->left,
                                            filename,
                                            key,
                                            size,
                                            ip,
                                            port);
        }
        else if (bias > 0) {
            tree->right = file_cache_add (tree->right,
                                            filename,
                                            key,
                                            size,
                                            ip, port);
        }
        /* If a node with the same key already exists */
        else {
            /* Search if the seeder is already registered, if he is, leave */
            sem_wait (&tree->seeders_lock);
            for (s = tree->seeders; s; s = s->next)
                if (strcmp (s->ip, ip) == 0 && s->port == port)
                    return tree;
            sem_post (&tree->seeders_lock);

            /* If the seeder isn't registered, we must add him */
            s = (struct seeder *)malloc (sizeof (struct seeder));
            if (!s) {
                log_failure (log_file,
                            "file_cache_add (): Unable to allocate seeder");
                return tree;
            }
            strcpy (s->ip, ip);
            s->port = port;
            sem_wait (&tree->seeders_lock);
            s->next = tree->seeders;
            tree->seeders = s;
            sem_post (&tree->seeders_lock);
        }
    }
    return tree;
}
Esempio n. 15
0
void*
daemon_request_ready (void* arg) {
    struct daemon_request   *r;
    // Parse elements
    char                    *key, *delay, *ip, *port, *proto, *begin, *end;
/* cmd version: */
    int                     argc;
    char                    **argv;
    int                     dl_sock;
    struct sockaddr_in      dl_addr;
    struct file_cache       *file;
    int                     local_file;
    int                     nb_received;
    file_size_t             nb_received_sum;
    char                    buffer[BUFFSIZE];
    int                     nb_written;
    char                    *full_path;
    char                    error_buffer[BUFFSIZE];

    r = (struct daemon_request *) arg;
    if (!r)
        return NULL;

    /*
     * cmd is supposedly:
     * ready KEY DELAY IP PORT PROTOCOL BEGINNING END
     */
    argv = cmd_to_argc_argv (r->cmd, &argc);
    if (argc < 8) {
        cmd_free (argv);
        sprintf (error_buffer, 
                 "error %s: Invalid number of arguments",
                 __FUNCTION__);
        daemon_send (r->daemon, error_buffer);
        return NULL;
    }
    key = argv[1];
    delay = argv[2];
    ip = argv[3];
    port = argv[4];
    proto = argv[5];
    begin = argv[6];
    end = argv[7];

    /* TODO&FIXME: We should use all above arguments */
    if ((dl_sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
        log_failure (log_file, "daemon_request_ready (): socket () failed");
        return NULL;
    }

    dl_addr.sin_family = AF_INET;
    if (inet_pton (AF_INET, ip, &dl_addr.sin_addr) < 1) {
        log_failure (log_file, "dr_ready: inet_pton () failed");
        return NULL;
    }
    // TODO: Verifications on port
    dl_addr.sin_port = htons (atoi (port));

    file = file_cache_get_by_key (file_cache, key);
    if (!file) {
        log_failure (log_file, "dr_ready: file_cache_get_by_key () failed");
        return NULL;
    }

    // TODO: Check if we actually asked for that file

    // TODO: Check if file already exists

    /* + 2 for '/' and '\0' */
    full_path = (char *)malloc ((strlen (prefs->shared_folder)
                                + strlen (file->filename)
                                + 2) * sizeof (char));
    sprintf (full_path, "%s/%s", prefs->shared_folder, file->filename);
    // FIXME: We should not truncate the file when downloading it by blocks
    local_file = open (full_path,
                        O_WRONLY | O_TRUNC | O_CREAT,
                        (mode_t)0644);
    //free (full_path);
    if (local_file < 0) {
        log_failure (log_file,
                    "dr_ready: open () failed, error: %s",
                    strerror (errno));
        return NULL;
    }

    if (connect (dl_sock, (struct sockaddr *)&dl_addr, sizeof (dl_addr)) < 0) {
        log_failure (log_file,
                    "dr_ready: connect () failed, error: %s",
                    strerror (errno));
        return NULL;
    }

    /*
     * Downloading the file
     */

    /* Let's upload the download queue */
    struct dl_file *f;
    
    f = dl_file_new (full_path, file->size);
    if (!f) {
        log_failure (log_file, "struct dl_file is NULL :(");
        goto out;
    }

    sem_wait (&downloads_lock);
    downloads = dl_file_add (downloads, f);
    if (!downloads) {
        log_failure (log_file, 
                    "Could not add the file to the download queue\n");
        goto out;
    }
    sem_post (&downloads_lock);

    nb_received_sum = 0;
    // FIXME: nb_received_sum should be compared to end - begin
    sleep (2);
    while (nb_received_sum < file->size) {
        log_failure (log_file,
                     "DBG %d %d",
                     nb_received_sum,
                     file->size);
                     
        nb_received = recv (dl_sock, buffer, BUFFSIZE, 0);
        if (nb_received < 0) {
            log_failure (log_file,
                        "dr_ready: recv () failed");
            return NULL;
        }
        nb_received_sum += nb_received;
        while (nb_received) {
            nb_written = write (local_file, buffer, nb_received);
            if (nb_written < 0) {
                log_failure (log_file,
                            "dr_ready: write () failed");
                return NULL;
            }
            nb_received -= nb_written;
        }
    }

    /* 
     * Releasing the file from the download queue 
     */
    sem_wait (&downloads_lock);
    downloads = dl_file_remove (downloads, f);
    dl_file_free (f);
    sem_post (&downloads_lock);

    log_success (log_file, 
                "dr_ready: Received block completely %s",
                full_path);

    close (dl_sock);
    close (local_file);


out:
    if (full_path)
        free (full_path);
    if (argv)
        cmd_free (argv);
    return NULL;
}
Esempio n. 16
0
void daemonize (void) {
    int lock;
    char str[10];

    switch (fork ()) {
        case -1:
            exit (1);
        case 0:
            fclose (log_file);
            if (prefs)
                conf_free (prefs);
            exit (0);
            break;
        default:
            break;
    }

    setsid ();
    log_success (log_file, "setsid ok");

    close (STDIN_FILENO);
    close (STDOUT_FILENO);
    close (STDERR_FILENO);

    log_success (log_file, "Closed stdin, stdout, stderr.");

    umask (027);
    log_success (log_file, "Set file permissions to 750.");

    lock = open (prefs->lock_file, O_RDWR | O_CREAT, 0640);
    if (lock < 0) {
        log_failure (log_file,
                     "Failed to open lock file (%s).",
                     prefs->lock_file);
    }
    else
        log_success (log_file, "Opened lock file (%s).", prefs->lock_file);

    if (lockf (lock, F_TLOCK, 0) < 0) {
        log_failure (log_file, "Could not lock %s", prefs->lock_file);
    }

    sprintf (str, "%d\n", getpid ());
    write (lock, str, strlen (str));
    if (close (lock) < 0) {
        log_failure (log_file,
                     "Failed to close LOCK_FILE (%s).",
                    prefs->lock_file);
    }
    else
        log_success (log_file, "Created lock file (%s)", prefs->lock_file);

    sigset_t mask;
    sigemptyset (&mask);
    sigaddset (&mask, SIGCHLD);
    sigaddset (&mask, SIGTSTP);
    sigaddset (&mask, SIGTTOU);
    sigaddset (&mask, SIGTTIN);
    sigprocmask (SIG_BLOCK, &mask, NULL);

    struct sigaction    on_signal;
    sigemptyset (&on_signal.sa_mask);
    on_signal.sa_flags = 0;
    on_signal.sa_handler = signal_handler;
    sigaction (SIGHUP, &on_signal, NULL);
    on_signal.sa_handler = server_stop;
    sigaction (SIGINT, &on_signal, NULL);
    sigaction (SIGTERM, &on_signal, NULL);

    log_success (log_file, "Signals deferred or handled.");

}
Esempio n. 17
0
static void
start_server (void) {
    int                 client_sd;
    int                 daemon_sd;
    int                 connected_sd;
    struct sockaddr_in  client_sa;
    struct sockaddr_in  daemon_sa;
    struct sockaddr_in  connected_sa;
    socklen_t           size;
    fd_set              socket_set;
    int                 nfds;
    struct ifreq        if_info;
    struct sockaddr_in  *if_addr;
    char                addr[INET_ADDRSTRLEN];
    struct client       *c;
    struct daemon       *d;
    struct parsed_cmd   *pcmd = NULL;
    char                *ident_msg;
    int                 port;
    char                *colon;


    /* Prepare all the threads */
    slow_pool = NULL;
    fast_pool = NULL;
    clients_pool = NULL;
    daemons_pool = NULL;

    ABORT_IF (!(slow_pool = pool_create (prefs->nb_proc)),
        "Unable to create slow_pool")

    ABORT_IF (!(fast_pool = pool_create (prefs->nb_proc)),
        "Unable to create fast_pool")

    ABORT_IF (!(clients_pool = pool_create (prefs->max_clients)),
        "Unable to create clients_pool")

    ABORT_IF (!(daemons_pool = pool_create (prefs->max_daemons)),
        "Unable to create daemons_pool")

    /* Create the shared directory if it does not exist already */
    ABORT_IF (create_dir (prefs->shared_folder, (mode_t)0755) < 0,
                "Unable to create shared directory")

    /* Initialize global pointers and their semaphores */
    clients = NULL;
    ABORT_IF (sem_init (&clients_lock, 0, 1) < 0,
        "Unable to sem_init clients_lock")

    daemons = NULL;
    ABORT_IF (sem_init (&daemons_lock, 0, 1) < 0,
        "Unable to sem_init daemons_lock")

    file_cache = NULL;
    ABORT_IF (sem_init (&file_cache_lock, 0, 1) < 0,
        "Unable to sem_init file_cache_lock")

    list_client = NULL;
    ABORT_IF (sem_init (&list_lock, 0, 1) < 0,
        "Unable to sem_init list_lock")

    downloads = NULL;
    ABORT_IF (sem_init (&downloads_lock, 0, 1) < 0,
        "Unable to sem_init download_queue_lock")

    client_sa.sin_family        = AF_INET;
    client_sa.sin_addr.s_addr   = INADDR_ANY;
    client_sa.sin_port          = htons (prefs->client_port);
    client_sd = socket_init (&client_sa);
    ABORT_IF (client_sd < 0,
        "Unable to socket_init client_sd")

    daemon_sa.sin_family        = AF_INET;
    daemon_sa.sin_addr.s_addr   = INADDR_ANY;
    daemon_sa.sin_port          = htons (prefs->daemon_port);
    daemon_sd = socket_init (&daemon_sa);
    ABORT_IF (daemon_sd < 0,
        "Unable to socket_init daemon_sd")

#if 1
    /* We get our ip */
    memcpy (if_info.ifr_name, prefs->interface, strlen (prefs->interface) + 1);
    if (ioctl (daemon_sd, SIOCGIFADDR, &if_info) == -1) {
        log_failure (log_file, "Can't get my ip from interface");
        log_failure (log_file, "LOL ERRNO : %s\n", strerror (errno));
        goto abort;
    }
    if_addr = (struct sockaddr_in *)&if_info.ifr_addr;
    inet_ntop (AF_INET, &if_addr->sin_addr, my_ip, INET_ADDRSTRLEN);
    log_success (log_file, "Found my IP : %s", my_ip);
#endif

    /* socket_set contains both client_sd and daemon_sd */
    FD_ZERO (&socket_set);
    size = sizeof (connected_sa);
    nfds = NFDS (client_sd, daemon_sd);
    for (;;) {
        /*
         * It is VERY important to FD_SET at each loop, because select
         * will FD_UNSET the socket descriptors
         */
        FD_SET (client_sd, &socket_set);
        FD_SET (daemon_sd, &socket_set);

        /* Block until a socket is ready to accept */
        if (select (nfds, &socket_set, NULL, NULL, NULL) < 0) {
            log_failure (log_file, "main () : select failed");
        }

        if (FD_ISSET (client_sd, &socket_set)) {
            if ((connected_sd = (accept (client_sd,
                                        (struct sockaddr *) &connected_sa,
                                        &size))) < 0) {
                log_failure (log_file, "Failed to accept incoming connection.");
                break;
            }

            /* Can we handle this client? */
            if (client_count () > prefs->max_clients) {
                socket_sendline (connected_sd, " < Too many clients\n");
                goto close_socket;
            }

            /* Then, let's handle him */
            if (!inet_ntop (AF_INET, &connected_sa.sin_addr,
                            addr, INET_ADDRSTRLEN)) {
                socket_sendline (connected_sd, " < Oops\n");
                goto close_socket;
            }
            if (!(c = client_new (connected_sd, addr))) {
                socket_sendline (connected_sd, " < Sorry pal :(\n");
            }

            pool_queue (clients_pool, handle_client, c);
        }
        else if (FD_ISSET (daemon_sd, &socket_set)) {
            if ((connected_sd = (accept (daemon_sd,
                                        (struct sockaddr *) &connected_sa,
                                        &size))) < 0) {
                log_failure (log_file, "Failed to accept incoming connection.");
                break;
            }

            /* Can we handle this daemon? */
            if (daemon_count () > prefs->max_daemons) {
                socket_sendline (connected_sd, " < Too many daemons\n");
                goto close_socket;
            }

            /* Let's identify him first */
            ident_msg = socket_try_getline (connected_sd,
                                            IDENTIFICATION_TIMEOUT);
            if (!ident_msg) {
                socket_sendline (connected_sd,
                                "error: identification timed out\n");
                goto close_socket;
            }
            if (cmd_parse_failed ((pcmd = cmd_parse (ident_msg, NULL)))) {
                pcmd = NULL;
                goto close_socket;
            }
            if (pcmd->argc < 2)
                goto close_socket;
            if (strcmp (pcmd->argv[0], "neighbour") != 0)
                goto close_socket;
            if (!(colon = strchr (pcmd->argv[1], ':')))
                goto close_socket;
            port = atoi (colon + 1);

            free (ident_msg);
            cmd_parse_free (pcmd);
            pcmd = NULL;

            if (!inet_ntop (AF_INET, &connected_sa.sin_addr,
                            addr, INET_ADDRSTRLEN)) {
                socket_sendline (connected_sd, " < Oops\n");
                goto close_socket;
            }

            /* Now we've got his port, let him go in */
            if (!(d = daemon_new (connected_sd, addr, port))) {
                socket_sendline (connected_sd, " < Sorry pal :(\n");
                goto close_socket;
            }

            pool_queue (daemons_pool, handle_daemon, d);
        }
        else {
            /* This should never happen : neither client nor daemon!? */
            log_failure (log_file, "Unknown connection");
        }

        continue;

close_socket:
        if (pcmd) {
            cmd_parse_free (pcmd);
            pcmd = NULL;
        }
        close (connected_sd);
    }

abort:
    if (slow_pool)
        pool_destroy (slow_pool);
    if (fast_pool)
        pool_destroy (fast_pool);
    if (clients_pool)
        pool_destroy (clients_pool);
    if (daemons_pool)
        pool_destroy (daemons_pool);
    conf_free (prefs);
    exit (EXIT_FAILURE);
}