//sends is file table to a particular peer/tracker depending on that peers socket ID int fileTable_Send(int sockfd) { if (sendfunc(sockfd, (void *) &file_table_size, sizeof(file_table_size)) < 0) { printf("Error Sending File Table Count\n"); return -1; } filenode* temp = file_table; while (temp != NULL) { if (sendfunc(sockfd, (void *) temp, sizeof(filenode)) < 0) { printf("Error Sending File Table\n"); return -1; } temp = temp->next; } return 1; }
// download data from the remote peer void *P2PDownload(void *arg) { peer_peer_t *p = (peer_peer_t *) arg; // send the required name and range if (sendfunc(p->sockfd, p->filename, sizeof(p->filename)) < 0) { printf("%s p2p download failed @filename!\n", peer_trace); pthread_exit((void *) p); } if (sendfunc(p->sockfd, &p->start, sizeof(p->start)) < 0) { printf("%s p2p download failed @start!\n", peer_trace); pthread_exit((void *) p); } if (sendfunc(p->sockfd, &p->end, sizeof(p->end)) < 0) { printf("%s p2p download failed @end!\n", peer_trace); pthread_exit((void *) p); } int s = 0; int e = p->end - p->start; // read file from peer //FILE *f; //f = fopen(p->filename, "r+"); //assert(f != NULL); //fseek(f, p->start, SEEK_SET); //char buf[MAX_DATA_LEN]; // recv and gather while (s != e) { int l = MIN(e - s, MAX_DATA_LEN); int n = recvfunc(p->sockfd, p->addr + s, l); if (n < 0) { printf("%s p2p download from %s failed!\n", peer_trace, p->IP); pthread_exit((void *) p); } //printf("%s p2p download %d bytes from %s!\n", peer_trace, n, p->IP); s += l; } //fclose(f); printf("%s Downloading from %s range (%d - %d) finished!\n", peer_trace, p->IP, p->start, p->end); pthread_exit(NULL); }
//upload data to the remote peer void *P2PUpload(void *arg) { int conn = *(int *) arg; char filename[FILE_NAME_LEN]; int start; int end; // recv the required name and range while (recvfunc(conn, filename, sizeof(filename)) > 0) { if (recvfunc(conn, &start, sizeof(start)) < 0) { printf("%s p2p upload failed @start!\n", peer_trace); return NULL; } if (recvfunc(conn, &end, sizeof(end)) < 0) { printf("%s p2p upload failed @end!\n", peer_trace); return NULL; } FILE *f; f = fopen(filename, "r"); if (f == NULL) { printf("%s p2p upload file doesn't exist!\n", peer_trace); return NULL; } fseek(f, start, SEEK_SET); char buf[MAX_DATA_LEN]; // divide and send while (start != end) { int l = MIN(end - start, MAX_DATA_LEN); fread(buf, l, 1, f); int n = sendfunc(conn, &buf, l); if (n < 0) { printf("%s p2p upload failed!\n", peer_trace); return NULL; } //printf("%s p2p upload %d bytes!\n", peer_trace, n); start += l; } fclose(f); } close(conn); return NULL; }
/* * Parses data buffer to a query, finds the correct answer * and calls the given function for every packet to send. */ void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count, enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*), void* userdata, FILE* verbose_out) { ldns_status status; ldns_pkt *query_pkt = NULL; ldns_pkt *answer_pkt = NULL; struct reply_packet *p; ldns_rr *query_rr = NULL; uint8_t *outbuf = NULL; size_t answer_size = 0; struct entry* entry = NULL; ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop."); status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen); if (status != LDNS_STATUS_OK) { verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); ldns_rdf_free(stop_command); return; } query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), (transport==transport_tcp)?"TCP":"UDP", (int)inlen); if(verbose_out) ldns_rr_print(verbose_out, query_rr); if(verbose_out) ldns_pkt_print(verbose_out, query_pkt); if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT && ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH && ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) { exit(0); } /* fill up answer packet */ entry = find_match(entries, query_pkt, transport); if(!entry || !entry->reply_list) { verbose(1, "no answer packet for this query, no reply.\n"); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } for(p = entry->reply_list; p; p = p->next) { verbose(3, "Answer pkt:\n"); if (p->reply_from_hex) { /* try to parse the hex packet, if it can be * parsed, we can use adjust rules. if not, * send packet literally */ status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex); if (status == LDNS_STATUS_OK) { adjust_packet(entry, answer_pkt, query_pkt); if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); if (status != LDNS_STATUS_OK) { verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } ldns_pkt_free(answer_pkt); answer_pkt = NULL; } else { verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status)); /* still try to adjust ID */ answer_size = ldns_buffer_capacity(p->reply_from_hex); outbuf = LDNS_XMALLOC(uint8_t, answer_size); memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size); if(entry->copy_id) { ldns_write_uint16(outbuf, ldns_pkt_id(query_pkt)); } } } else { answer_pkt = ldns_pkt_clone(p->reply); adjust_packet(entry, answer_pkt, query_pkt); if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); if (status != LDNS_STATUS_OK) { verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } ldns_pkt_free(answer_pkt); answer_pkt = NULL; } if(p->packet_sleep) { verbose(3, "sleeping for next packet %d secs\n", p->packet_sleep); #ifdef HAVE_SLEEP sleep(p->packet_sleep); #else Sleep(p->packet_sleep * 1000); #endif verbose(3, "wakeup for next packet " "(slept %d secs)\n", p->packet_sleep); } sendfunc(outbuf, answer_size, userdata); LDNS_FREE(outbuf); outbuf = NULL; answer_size = 0; } ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); }