HASH* hash_add(int type, char *text) { int address; HASH *node, *insertNode; node = (HASH*)calloc(1, sizeof(HASH)); node->type = type; node->text = text; // text já deve ter sido alocado fora da função node->dataType.identifierType = -1; node->dataType.valueType = -1; node->dataType.params = NULL; address = hash_address(text); insertNode = symbol_table[address]; // Insere somente se símbolo ainda não existe na tabela while (insertNode && (insertNode->type != type || strcmp(insertNode->text, text))) insertNode = insertNode->next; // Se insertNode é null, então não achou um simbolo igual na lista, pois percorreu até o fim if (!insertNode) { node->next = symbol_table[address]; symbol_table[address] = node; } return node; }
HASH_NODE *hash_find(char *text) { HASH_NODE *node; int address = hash_address(text); for(node = Table[address]; node != 0; node = node->next) if(!strcmp(text,node->text)) return node; return 0; }
HASH_NODE *hash_insert(char *text, int token) { HASH_NODE *node = 0; int address = 0; if(node = hash_find(text)) return node; address = hash_address(text); node = (HASH_NODE*) calloc (1,sizeof(HASH_NODE)); node->token = token; node->text = (char*) calloc (strlen(text)+1, sizeof(char)); strcpy(node->text,text); node->next = Table[address]; Table[address] = node; return node; }
bool ip_voter::cast_vote(address const& ip , int source_type, address const& source) { if (is_any(ip)) return false; if (is_local(ip)) return false; if (is_loopback(ip)) return false; // don't trust source that aren't connected to us // on a different address family than the external // IP they claim we have if (ip.is_v4() != source.is_v4()) return false; // this is the key to use for the bloom filters // it represents the identity of the voter sha1_hash k; hash_address(source, k); // do we already have an entry for this external IP? std::vector<external_ip_t>::iterator i = std::find_if(m_external_addresses.begin() , m_external_addresses.end(), boost::bind(&external_ip_t::addr, _1) == ip); if (i == m_external_addresses.end()) { // each IP only gets to add a new IP once if (m_external_address_voters.find(k)) return maybe_rotate(); if (m_external_addresses.size() > 40) { if (random() % 100 < 50) return maybe_rotate(); // use stable sort here to maintain the fifo-order // of the entries with the same number of votes // this will sort in ascending order, i.e. the lowest // votes first. Also, the oldest are first, so this // is a sort of weighted LRU. std::stable_sort(m_external_addresses.begin(), m_external_addresses.end()); // erase the last element, since it is one of the // ones with the fewest votes m_external_addresses.erase(m_external_addresses.end() - 1); } m_external_addresses.push_back(external_ip_t()); i = m_external_addresses.end() - 1; i->addr = ip; } // add one more vote to this external IP if (!i->add_vote(k, source_type)) return maybe_rotate(); ++m_total_votes; if (m_valid_external) return maybe_rotate(); i = std::min_element(m_external_addresses.begin(), m_external_addresses.end()); TORRENT_ASSERT(i != m_external_addresses.end()); if (i->addr == m_external_address) return maybe_rotate(); if (m_external_address != address_v4()) { // we have a temporary external address. As soon as we have // more than 25 votes, consider deciding which one to settle for return (m_total_votes >= 25) ? maybe_rotate() : false; } m_external_address = i->addr; return true; }
static uint32 unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) { return hash_address((sockaddr_un*)ourAddress) * 17 + hash_address((sockaddr_un*)peerAddress); }
/* sends a miniroute packet, automatically discovering the path if necessary. See description in the * .h file. */ int miniroute_send_pkt(network_address_t dest_address, int hdr_len, char* hdr, int data_len, char* data) { // This will store the route request struct, which is a structure related to the // search for a path to the host route_request_t route_request; // Store the routing header routing_header_t routing_header; // Store the route to the host, which is an array of addresses network_address_t* route; // Store the route data struct, which holds the route and some metadata route_data_t route_data; // Store my address network_address_t my_addr; // Used to synchronize access with structures the network handler touches interrupt_level_t prev_level; // This will store the combined routing + normal headers char* full_header; network_address_t dest_address2; // These will store data related to the routes int time_route_found; int route_len; int route_valid = 1; // Used to get data from the header containing the paht routing_header_t tmp_routing_header; // Used to just check the IP of senders; combats UDP port issues w/ simulated broadcasts unsigned int dest_address_ip = dest_address[0]; // Loop + tmp variables int current_req_id; int success = 0; int alarm_id; int x; int i; if (hdr_len == 0 || hdr == NULL || data_len == 0 || data == NULL) return -1; // Get the route item, which is a hashmap_item_t, from the hashmap for this addr semaphore_P(route_cache_sem); route_data = (route_data_t) hashmap_get(route_cache, hash_address(dest_address)); // If it's not NULL, extract the data from the item if (route_data != NULL) { time_route_found = route_data->time_found; route_len = route_data->route_len; // caveat: the cleanup thread may delete the route data, so we need to // save it in a separate variable, just incase. route = (network_address_t*) malloc(sizeof(network_address_t) * route_len); if (route == NULL) { semaphore_V(route_cache_sem); return -1; } memcpy(route, route_data->route, sizeof(network_address_t) * route_len); } else { route_valid = 0; } semaphore_V(route_cache_sem); // Check, if the route isn't NULL, if it's expired if (route_valid == 1 && (ticks - time_route_found) * PERIOD/MILLISECOND > 3000) { route_valid = 0; } // If the route is invalid (either not in the cache or expired)... if (route_valid == 0) { // We won't be needing that previous route variable if (route_data != NULL) { // But, just in case someone is still using it, use the route cache semaphore semaphore_P(route_cache_sem); free(route); semaphore_V(route_cache_sem); } // Check if someone else already initiated this route discovery request prev_level = set_interrupt_level(DISABLED); route_request = (route_request_t) hashmap_get(current_discovery_requests, dest_address_ip); set_interrupt_level(prev_level); // If so, we can just wait for their result if (route_request != NULL) { // Wait for the other thread to get the path // The threads waiting variable needs to be synchronized. We decided // to reuse the route cache sem, as there will not be much lock // contention semaphore_P(route_cache_sem); route_request->threads_waiting++; semaphore_V(route_cache_sem); semaphore_P(route_request->waiting_sem); // Get the route from the hashmap semaphore_P(route_cache_sem); route_data = (route_data_t) hashmap_get(route_cache, hash_address(dest_address)); // If the other thread didn't get the route, return an error if (route_data == NULL) { // Return failure... semaphore_V(route_cache_sem); return -1; } else { time_route_found = route_data->time_found; route_len = route_data->route_len; if ((ticks - time_route_found) * PERIOD/MILLISECOND > 3000) { // This could have been a left-over expired cache entry that we haven't // deleted yet. semaphore_V(route_cache_sem); return -1; } // Save the route in a separate variable in case the route gets cleaned up // while we're using it route = (network_address_t*) malloc(sizeof(network_address_t) * route_len); if (route == NULL) { semaphore_V(route_cache_sem); return -1; } memcpy(route, route_data->route, sizeof(network_address_t) * route_len); semaphore_V(route_cache_sem); } } else { // Otherwise, we have to do the route discovery process // Create a new route request struct route_request = create_route_request(); if (route_request == NULL) { return -1; } // Add the route request to the current discovery requests prev_level = set_interrupt_level(DISABLED); hashmap_insert(current_discovery_requests, dest_address_ip, route_request); set_interrupt_level(prev_level); // We'll try the route discovery process three times for (i = 0; i < 3; i++) { // Register an alarm to wake this thread up as it waits for a response alarm_id = register_alarm(12000, &alarm_wakeup_sem, (void*) route_request->initiator_sem); // Increment the request ID - must be synchronized, obviously semaphore_P(request_id_sem); current_req_id = route_request_id++; semaphore_V(request_id_sem); // We need to make a header for the discovery request, but the path // needs to have our address in it, so the reply can be forwarded back // to us network_get_my_address(my_addr); // Passing in the address of this local variable will suffice, as the // value is immediately copied into the header and then not used again // Create a routing header for the route discovery request routing_header = create_miniroute_header(ROUTING_ROUTE_DISCOVERY, dest_address, current_req_id, MAX_ROUTE_LENGTH, 1, &my_addr); if (routing_header == NULL) { return -1; } // Combine it with the given header full_header = merge_headers(routing_header, hdr, hdr_len); if (full_header == NULL) { free(routing_header); return -1; } // Send out the route discovery request network_bcast_pkt(sizeof(struct routing_header)+hdr_len, (char*) full_header, data_len, data); // Wait for a reply (which will be signalled by the network handler) prev_level = set_interrupt_level(DISABLED); semaphore_P(route_request->initiator_sem); set_interrupt_level(prev_level); // Check if we got a successful response if (route_request->interrupt_arg != NULL) { // Deregister the alarm before it tries to wake us up // Needs to be synchronized, as the IH touches it and we destroy it here prev_level = set_interrupt_level(alarm_id); deregister_alarm(alarm_id); set_interrupt_level(alarm_id); // Get the header tmp_routing_header = (routing_header_t) route_request->interrupt_arg->buffer; route_len = unpack_unsigned_int(tmp_routing_header->path_len); // Then the path, for our own use later in this function // We'll also create one copy and put it in the route data struct route = miniroute_reverse_raw_path(tmp_routing_header, route_len); if (route == NULL) { free(routing_header); free(full_header); return -1; } // Create a route data struct - with a different route (as it will be deleted by a diff thread) route_data = create_route_data(miniroute_reverse_raw_path(tmp_routing_header, route_len), route_len, ticks); if (route_data == NULL) { free(routing_header); free(full_header); return -1; } // add it to the cache hashmap semaphore_P(route_cache_sem); hashmap_insert(route_cache, hash_address(dest_address), route_data); semaphore_V(route_cache_sem); // Wake up the other threads waiting for (x = 0; x < route_request->threads_waiting; x++) { semaphore_V(route_request->waiting_sem); } // Clean up the route request struct, then delete it from the hashmap // DELETE ROUTE REQUEST WILL FREE THE NETWORK INTERRUPT ARG! prev_level = set_interrupt_level(DISABLED); delete_route_request(route_request); hashmap_delete(current_discovery_requests, dest_address_ip); set_interrupt_level(prev_level); // We don't need to actually get any of the routing stuff from the // route_ite, as this process also sent the data packet // Free the headers free(routing_header); free(full_header); // Return the total bytes sent, not including the routing header success = 1; break; } } // If we didn't get a successful response after 3 tries... if (success == 0) { // Wake up the other threads waiting so they can see we failed for (x = 0; x < route_request->threads_waiting; x++) { semaphore_V(route_request->waiting_sem); } // clean up the route request struct, then delete it from the hashmap prev_level = set_interrupt_level(DISABLED); delete_route_request(route_request); hashmap_delete(current_discovery_requests, dest_address_ip); set_interrupt_level(prev_level); // Free the headers free(routing_header); free(full_header); // Return failure... return -1; } } } // If we're here, we either found the route in the cache or waited for another // thread to finish getting the route (and it did so successfully) network_address_copy(route[route_len-1], dest_address2); // Need to update the dst address to deal with UDP port issues // This again is due to UDP port issues... pack_address(((mini_header_t) hdr)->destination_address, dest_address2); // Create a routing header for the data packet routing_header = create_miniroute_header(ROUTING_DATA, dest_address2, 0, MAX_ROUTE_LENGTH, route_len, route); if (routing_header == NULL) { return -1; } // Combine it with the given header full_header = merge_headers(routing_header, hdr, hdr_len); if (full_header == NULL) { free(routing_header); } // Set the right destination address network_address_copy(route[1], dest_address2); // Send the packet network_send_pkt(dest_address2, sizeof(struct routing_header) + hdr_len, full_header, data_len, data); // Free the route + headers free(route); free(routing_header); free(full_header); // Return the total data sent return hdr_len + data_len; }