Example #1
0
void a_mapcache_add ( GdkPixbuf *pixbuf, mapcache_extra_t extra, gint x, gint y, gint z, guint16 type, gint zoom, guint8 alpha, gdouble xshrinkfactor, gdouble yshrinkfactor, const gchar* name )
{
  guint nn = name ? g_str_hash ( name ) : 0;
  gchar *key = g_strdup_printf ( HASHKEY_FORMAT_STRING, type, x, y, z, zoom, nn, alpha, xshrinkfactor, yshrinkfactor );

  g_mutex_lock(mc_mutex);
  cache_add(key, pixbuf, extra);

  // TODO: that should be done on preference change only...
  max_cache_size = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "mapcache_size")->u * 1024 * 1024;

  if ( cache_size > max_cache_size ) {
    if ( queue_tail ) {
      gchar *oldkey = list_shift_add_entry ( key );
      cache_remove(oldkey);

      while ( cache_size > max_cache_size &&
             (queue_tail->next != queue_tail) ) { /* make sure there's more than one thing to delete */
        oldkey = list_shift ();
        cache_remove(oldkey);
      }
    }
    /* chop off 'start' etc */
  } else {
    list_add_entry ( key );
    /* business as usual */
  }
  g_mutex_unlock(mc_mutex);

  static int tmp = 0;
  if ( (++tmp == 100 )) { g_debug("DEBUG: cache count=%d size=%u list count=%d\n", g_hash_table_size(cache), cache_size, queue_count ); tmp=0; }
}
Example #2
0
void a_mapcache_add ( GdkPixbuf *pixbuf, gint x, gint y, gint z, guint8 type, guint zoom, guint8 alpha, gdouble xshrinkfactor, gdouble yshrinkfactor )
{
  gchar *key = g_strdup_printf ( HASHKEY_FORMAT_STRING, x, y, z, type, zoom, alpha, xshrinkfactor, yshrinkfactor );
  static int tmp = 0;

  g_mutex_lock(mc_mutex);
  cache_add(key, pixbuf);

  // TODO: that should be done on preference change only...
  max_queue_size = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "mapcache_size")->u * 1024 * 1024;

  if ( queue_size > max_queue_size ) {
    gchar *oldkey = list_shift_add_entry ( key );
    cache_remove(oldkey);

    while ( queue_size > max_queue_size &&
        (queue_tail->next != queue_tail) ) { /* make sure there's more than one thing to delete */
      oldkey = list_shift ();
      cache_remove(oldkey);
    }

    /* chop off 'start' etc */
  } else {
    list_add_entry ( key );
    /* business as usual */
  }
  g_mutex_unlock(mc_mutex);

  if ( (++tmp == 100 ))  { g_print("DEBUG: queue count=%d size=%u\n", queue_count, queue_size ); tmp=0; }
}
Example #3
0
bool
mule_file_add_source(
                    MULE_FILE* mf,
                    uint8_t type,
                    UINT128* id,
                    uint32_t ip4_no,
                    uint16_t tcp_port_no,
                    uint16_t udp_port_no,
                    uint8_t cipher_opts
                   )
{
  bool result = false;
  MULE_SOURCE* msc = NULL;

  do {

    // [TODO] one file source can be attached to multiple kad files.

    if (!mf) break;

    if (!mule_source_create(type, id, ip4_no, tcp_port_no, udp_port_no, cipher_opts, &msc)){

      LOG_ERROR("Failed to create mule source.");

      break;

    }

    mule_source_add_type(msc, MULE_SOURCE_FLAG_FILE_BOUND);

    if(!list_add_entry(&mf->sources, (void*)msc)){

      LOG_ERROR("Failed to add source to sources list.");

      break;

    }

    result = true;

  } while (false);

  if (!result && msc) mule_source_destroy(msc);

  return result;
}
Example #4
0
bool
mule_file_part_get_block_to_download(
                                     MULE_FILE_PART* mfp,
                                     uint32_t pref_blk_len,
                                     uint64_t* block_start_out,
                                     uint64_t* block_len_out
                                    )
{
  bool result = false;
  MULE_FILE_PART_BLOCK* mfpb = NULL;
  uint64_t offset_from_start = 0;
  uint64_t part_start = 0;
  uint64_t block_start = 0;
  uint64_t block_len = 0;
  bool found = false;

  do {

    if (!mfp || !block_start_out || !block_len_out) break;

    part_start = mfp->start;

    LOG_DEBUG("part_start = %.8x", (uint32_t)part_start);

    LIST_EACH_ENTRY_WITH_DATA_BEGIN(mfp->blocks, e, mfpb);

      LOG_DEBUG("block_start = %.8x, block_len = %.8x, block_recvd = %.8x, block_state = %.8x",
                (uint32_t)(part_start + offset_from_start),
                (uint32_t)mfpb->len,
                (uint32_t)mfpb->recvd,
                (uint32_t)mfpb->state
               );

      if (mfpb->state == MULE_FILE_BLOCK_STATE_ALLOCATED){

        // Block state remain allocated in case of this part being not available on remote source.
        // Can also be allocated when download was canceled and block was not fully downloaded.
        
        block_start = part_start + offset_from_start;

        block_len = mfpb->len;

        mfpb->state = MULE_FILE_BLOCK_STATE_DOWNLOADING;

        LOG_DEBUG("Already allocated block %.8x:%.8x", (uint32_t)block_start, (uint32_t)block_len);

        found = true;

        break;

      }

      offset_from_start += mfpb->len;

    LIST_EACH_ENTRY_WITH_DATA_END(e);

    if (!found){

      LOG_DEBUG("offset_from_start = %.8x", offset_from_start);

      block_start = part_start + offset_from_start;

      block_len = ((mfp->length - offset_from_start) < pref_blk_len)?(mfp->length - offset_from_start):pref_blk_len;

      LOG_DEBUG("Next allocated block: %.8x:%.8x", (uint32_t)block_start, (uint32_t)block_len);

      if (!block_len) break; // In original source DebugBreak() used instead of break, probably for catching errors.

      mfpb = (MULE_FILE_PART_BLOCK*)mem_alloc(sizeof(MULE_FILE_PART_BLOCK) - 1 + (uint32_t)block_len);

      if (!mfpb){

        LOG_ERROR("Failed to allocate memory for kad file part block.");

        break;

      }

      mfpb->state = MULE_FILE_BLOCK_STATE_DOWNLOADING;

      mfpb->len = (uint32_t) block_len;

      list_add_entry(&mfp->blocks, (void*)mfpb);

    }

    *block_start_out = block_start;

    *block_len_out = block_len;

    result = true;

  } while (false);

  return result;
}
Example #5
0
bool
mule_file_init_parts(
                     MULE_FILE* kf,
                     uint64_t size,
                     bool full
                    )
{
  bool result = false;
  MULE_FILE_PART* part = NULL;
  uint32_t rem_file_size = 0;

  do {

    kf->part_size = MULE_FILE_PART_SIZE;

    // Real parts count
    
    kf->part_count = (uint32_t) ((size + MULE_FILE_PART_SIZE - 1) / MULE_FILE_PART_SIZE);

    kf->part_hashes_needed = kf->part_count > 1;

    // Parts for OP_FILESTATUS
    
    kf->e2k_part_count = (uint32_t)(size / MULE_FILE_PART_SIZE + 1);

    // Parts for OP_HASHSETANSWER;

    kf->e2k_part_hash_count = (uint32_t)(size / MULE_FILE_PART_SIZE);

    if (kf->e2k_part_hash_count) kf->e2k_part_hash_count++;

    LOG_DEBUG("size = %.8x%.8x, parts_size = %.8x, part_count = %.8x, e2k_part_count = %.8x, e2k_part_hash_count = %.8x",
              (uint32_t)(size >> 32),
              (uint32_t)size,
              kf->part_size,
              kf->part_count,
              kf->e2k_part_count,
              kf->e2k_part_hash_count
              );

    rem_file_size = (uint32_t)size;

    for (uint32_t i = 0; i < kf->part_count; i++){

      part = (MULE_FILE_PART*)mem_alloc(sizeof(MULE_FILE_PART) - 1 + kf->part_size);

      if (!part) {

        LOG_ERROR("Failed to allocate memory or part structure.");

        break;

      }

      // Initialize part entry
      
      part->status = full?MULE_FILE_PART_STATUS_ON_DISK:MULE_FILE_PART_STATUS_DOWNLOADING;

      // [LOCK] part lock initialization
      
      part->start = i * kf->part_size;

      part->idx = (uint16_t)i;

      part->length = (rem_file_size > kf->part_size)?kf->part_size:rem_file_size;

      list_add_entry(&kf->parts, (void*)part);

      rem_file_size -= (rem_file_size > kf->part_size)?kf->part_size:rem_file_size;

    }

    result = true;

  } while (false);

  if (!result) list_destroy(kf->parts, true);

  return result;
}
Example #6
0
File: kad.c Project: mzhel/libkad
bool
kad_session_init(
                 uint16_t tcp_port,
                 uint16_t udp_port,
                 char* nodes_file_path,
                 KAD_SESSION** ks_out
                 )
{
  bool result = false;
  KAD_SESSION* ks = NULL;
  char host_name[HOST_NAME_MAX + 1];
  struct hostent* he = NULL;
  UINT128 zone_idx;
  uint32_t now = 0;

  do {

    LOG_PREFIX("[libkad] ");

    LOG_LEVEL_DEBUG;

    LOG_FILE_NAME("libkad.log");

    LOG_OUTPUT_CONSOLE_AND_FILE;
    
    if (!ks_out) break;

    ks = (KAD_SESSION*)mem_alloc(sizeof(KAD_SESSION));

    if (!ks){

      LOG_ERROR("Failed to allocate memory for kad session.");

      break;

    }

    ks->version = KADEMLIA_VERSION;

    random_init(ticks_now_ms());

    gethostname(host_name, HOST_NAME_MAX);

    LOG_DEBUG("Host name: %s", host_name);

    he = gethostbyname(host_name);

    ks->loc_ip4_no = *(uint32_t*)he->h_addr;

    kad_fw_set_status(&ks->fw, true);

    kad_fw_set_status_udp(&ks->fw, true);

    uint128_generate(&ks->kad_id);

    LOG_DEBUG_UINT128("kad_id: ", ((UINT128*)&ks->kad_id));

    for (uint32_t i = 0; i < sizeof(ks->user_hash); i++){

      ks->user_hash[i] = random_uint8();

    }

    ks->user_hash[5] = 14;

    ks->user_hash[14] = 111;

    kadhlp_gen_udp_key(&ks->udp_key);

    LOG_DEBUG("udp_key: %.8x", ks->udp_key);

    ks->udp_port = udp_port;

    ks->tcp_port = tcp_port;

    LOG_DEBUG("udp_port = %d", udp_port);

    LOG_DEBUG("tcp_port = %d", tcp_port);

    uint128_init(&zone_idx, 0);

    routing_create_zone(NULL, 0, &zone_idx, &ks->root_zone);

    list_add_entry(&ks->active_zones, ks->root_zone);

    now = ticks_now_ms();

    ks->timers.self_lookup = now + MIN2MS(3);

    ks->timers.udp_port_lookup = now;

    ks->timers.nodes_count_check = now + SEC2MS(10);

    ks->opts.use_extrn_udp_port = true;

    queue_create(CONTROL_PACKET_QUEUE_LENGTH, &ks->queue_in_udp);

    queue_create(CONTROL_PACKET_QUEUE_LENGTH, &ks->queue_out_udp);

    if (nodes_file_path) kadhlp_add_nodes_from_file(ks, nodes_file_path);

    kadusr_init(ks);
  
    *ks_out = ks;

    result = true;

  } while (false);

  return result;
}
Example #7
0
bool
kadhlp_parse_nodes_dat(
                       KAD_SESSION* ks,
                       char* file_path,
                       LIST** kn_lst_out
                       )
{
  bool result = false;
  KAD_FILE* kf = NULL;
  uint32_t file_len = 0;
  uint32_t ver = 0;
  uint32_t kn_cnt = 0;
  UINT128 id;
  UINT128 dist;
  uint32_t ip4;
  uint16_t udp_port;
  uint16_t tcp_port;
  uint8_t type;
  uint8_t contact_ver;
  uint32_t udp_key_ip4;
  uint32_t udp_key;
  uint8_t verified;
  KAD_NODE* kn;
  LIST* kn_lst = NULL;

  do {

    if (!kadfile_open_read(file_path, &file_len, &kf)){

      LOG_ERROR("Failed to open file %s", file_path);
      
      break;

    }

    LOG_DEBUG("Nodes file length %.8x(%d)", file_len, file_len);

    if (!file_len) break;

    // Skip zero counter for older versions.

    kadfile_read_uint32(kf, NULL);

    file_len -= 4;

    if (file_len < 8) break;

    // nodes file version.

    kadfile_read_uint32(kf, &ver);

    file_len -= 4;

    if (ver != 2) {

      LOG_ERROR("Wrong nodes file version.");
      
      break;

    }

    // nodes count in file.

    kadfile_read_uint32(kf, &kn_cnt);

    LOG_DEBUG("%d nodes in file.", kn_cnt);

    file_len -= 4;

    if (kn_cnt && file_len < kn_cnt * 25) break;

    while (kn_cnt--){

      // node id
      
      kadfile_read_uint128(kf, &id);

      file_len -= sizeof(UINT128);

      // node ip address

      kadfile_read_uint32(kf, &ip4);

      file_len -= sizeof(uint32_t);

      // node udp port
      
      kadfile_read_uint16(kf, &udp_port);

      file_len -= sizeof(uint16_t);

      // node tcp port
      
      kadfile_read_uint16(kf, &tcp_port);

      file_len -= sizeof(uint16_t);

      // contact version

      kadfile_read_uint8(kf, &contact_ver);

      file_len -= sizeof(uint8_t);

      // udp key data

      kadfile_read_uint32(kf, &udp_key);

      file_len -= sizeof(uint32_t);

      kadfile_read_uint32(kf, &udp_key_ip4);

      file_len -= sizeof(uint32_t);
      
      // node verification status
      
      kadfile_read_uint8(kf, &verified);

      file_len -= sizeof(uint8_t);

      uint128_xor(&ks->kad_id, &id, &dist);

      if (!node_create(
                       &id,
                       htonl(udp_key_ip4),
                       htonl(ip4),
                       htons(tcp_port),
                       htons(udp_port),
                       contact_ver,
                       udp_key,
                       verified > 0,
                       &dist,
                       &kn 
                       )
      ) continue;

      list_add_entry(kn_lst_out, kn);

    }

    LOG_DEBUG("Remained file length %.8x", file_len);

    result = true;

  } while (false);

  if (kf) kadfile_close(kf);

  return result;
}
Example #8
0
bool
routing_get_bootstrap_contacts(
                              ROUTING_ZONE* rz,
                              // [LOCK]
                              uint32_t max_required,
                              LIST** kn_lst_out,
                              bool top_level_call
                              )
{
  bool result = false;
  LIST* kn_lst = NULL;
  LIST* entry = NULL;
  uint32_t ent_cnt = 0;
  void* data = NULL;
  uint32_t copy_cnt = 0;

  do {

    // [LOCK] lock active zones.

    if (!rz || !kn_lst_out) break;

    if (!routing_get_top_depth_entries(rz, LOG_BASE_EXPONENT, &kn_lst, false)){

      LOG_ERROR("Failed to get top entries.");

      break;

    }
    
    list_entries_count(kn_lst, &ent_cnt);

    entry = kn_lst;

    if (ent_cnt){

      copy_cnt = ent_cnt > max_required? max_required : ent_cnt;

      while (copy_cnt--) {

        if (!entry) break;

        list_get_entry_data(entry, &data);

        list_add_entry(kn_lst_out, data);

        list_next_entry(entry, &entry);

      }

    }

    result = true;

  } while (false);

  if (kn_lst) list_destroy(kn_lst, true);

  // [LOCK] unlock active zones.

  return result;
}
Example #9
0
bool
routing_add_node(
                 LIST** active_zones_ptr,
                 // [LOCK] Here should be zone lock.
                 ROUTING_ZONE* rz,
                 KAD_NODE* kn,
                 uint32_t self_pub_ip4_no,
                 bool update_existing,
                 bool* existing_updated_out,
                 bool top_level_call
                )
{
  bool result = false;
  uint32_t idx = 0;
  KAD_NODE* found_kn = NULL;
  uint32_t check_udp_key = 0;

  do {

    if (!active_zones_ptr || !rz || !kn) break;

    // [LOCK] here should be active zones lock if call is top level.
    
    if (existing_updated_out) *existing_updated_out = false;

    // If zone bucket is empty then zone have sub zones.
    // Add node to one of zone sub zones.

    if (!rz->kb){

      idx = uint128_get_bit_value_reverse(&kn->dist, rz->level);

      result = routing_add_node(
                                active_zones_ptr, 
                                //[LOCK] here should be zone lock 
                                rz->sub_zones[idx], 
                                kn, 
                                self_pub_ip4_no, 
                                update_existing, 
                                existing_updated_out, 
                                false
                                );

      break;

    }

    if (kbucket_node_by_id(rz->kb, &kn->id, &found_kn)){

      // Node already added to zone bucket.
      
      if (update_existing){

        check_udp_key = node_get_udp_key_by_ip(found_kn, self_pub_ip4_no);

        if (check_udp_key && check_udp_key != node_get_udp_key_by_ip(kn, self_pub_ip4_no)) {

          // Nodes keys do not match.
          
          LOG_ERROR("Udp keys do not match, old = %.8x, new = %.8x", check_udp_key, node_get_udp_key_by_ip(kn, self_pub_ip4_no));       

          break;

        }

        if (kn->version < found_kn->version){

          // New node version in lesser than old.

          break;

        }

        // Update node information.

        // [TODO] Legacy kad2 contacts.
        // [TODO] Checks when changing ip of exisitng node.
        
        found_kn->ip4_no = kn->ip4_no;

        found_kn->udp_port_no = kn->udp_port_no;

        found_kn->tcp_port_no = kn->tcp_port_no;

        found_kn->version = kn->version;

        if (kn->hello_received) found_kn->hello_received = true;

        found_kn->status = kn->status;

        found_kn->next_check_time = kn->next_check_time;

        node_set_udp_key_with_ip(found_kn, kn->udp_key, self_pub_ip4_no);

        if (!found_kn->ip_verified) found_kn->ip_verified = kn->ip_verified;

        if (existing_updated_out) *existing_updated_out = true;

        // All information copied to existing node
        // so we destroy the original.

        node_destroy(kn);

        result = true;

      } else {

        // Node found but we do not update it.

        result = false;

      }

    } else if (rz->kb->nodes_count < K) {

      // Have space in current zone bucket.
      
      result = kbucket_add_node(rz->kb, kn);

    } else if (routing_zone_can_be_split(rz)){

      // Zone bucket is full, zone split required.
      
      if (!routing_split_zone(rz)){

        LOG_ERROR("Failed to split zone.");

        break;

      }

      list_add_entry(active_zones_ptr, rz->sub_zones[0]);

      list_add_entry(active_zones_ptr, rz->sub_zones[1]);

      idx = uint128_get_bit_value_reverse(&kn->dist, rz->level);

      result = routing_add_node(
                                active_zones_ptr,
                                // [LOCK] lock
                                rz->sub_zones[idx],
                                kn,
                                self_pub_ip4_no,
                                update_existing,
                                existing_updated_out,
                                false
                               );

    }


  } while (false);

  // [LOCK] if (top_level_call) unlock active zones

  return result;
}