📄 gnutella.c
字号:
/*-*-linux-c-*-*//* * gnewtellium - Newtella for Unix * Copyright (C) 2001 Elias Athanasopoulos * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* These includes are needed in the specified order by the BSD family. It maybe better to add an #ifdef BSD or something here...*/#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <string.h>#include "newtella.h"#include "guid.h"#include "connection.h"#include "gnutella.h"#include "global.h"#include "file.h"#include "hosts.h"#include "uploads.h"gint gnutella_send_ping(struct newtella_connection *con, gint wake_up){ struct gnutella_header *header = newtella_malloc(sizeof *header); gchar *data; guidget(header->guid); header->f = GNUTELLA_INIT; if (wake_up) header->ttl = 1; else header->ttl = GNUTELLA_PING_TTL; header->hops = 0; header->length = 0; data = newtella_malloc(GN_HEADER_SIZE); GNUTELLA_HDR_ATTACH(data, header) con_send_packet(con, data, GN_HEADER_SIZE, 0); newtella_free(header); newtella_free(data); return 1;}gint gnutella_send_pong(struct newtella_connection *con, gchar *guid, guint8 ttl){ struct gnutella_header *header; struct gnutella_pong_header *gpong; guint32 pack_size = 0; gchar *data; header = newtella_malloc(sizeof *header); gpong = newtella_malloc(sizeof *gpong); guidcpy(header->guid, guid); header->f = GNUTELLA_INITRESPONSE; header->hops = 0; header->ttl = ttl; header->length = GN_PONG_SIZE; gpong->host_ip = g_htonl(gl_my_host_info->ip); gpong->host_port = gl_my_host_info->port; gpong->file_count = gl_my_host_info->file_count; gpong->files_total_size = gl_my_host_info->files_total_size; pack_size = GN_HEADER_SIZE + header->length; data = newtella_malloc(pack_size); GNUTELLA_HDR_ATTACH(data, header) data += GN_HEADER_SIZE; memcpy(data, &(gpong->host_port), 2); memcpy(data+2, &(gpong->host_ip), 4); memcpy(data+6, &(gpong->file_count), 4); memcpy(data+10, &(gpong->files_total_size), 4); data -= GN_HEADER_SIZE; con_send_packet(con, data, pack_size, 1); newtella_free(header); newtella_free(gpong); newtella_free(data); return 1;}gint gnutella_send_cached_host(struct newtella_connection *con, struct host_info *host){ struct gnutella_header *header; struct gnutella_pong_header *gpong; gchar *data; header = newtella_malloc(sizeof *header); gpong = newtella_malloc(sizeof *gpong); guidget(header->guid); header->f = GNUTELLA_INITRESPONSE; header->hops = 0; header->ttl = 1; header->length = GN_PONG_SIZE; gpong->host_ip = g_htonl(host->ip); gpong->host_port = host->port; gpong->file_count = host->file_count; gpong->files_total_size = host->files_total_size; data = newtella_malloc(GN_HEADER_SIZE + header->length); GNUTELLA_HDR_ATTACH(data, header) data += GN_HEADER_SIZE; memcpy(data, &(gpong->host_port), 2); memcpy(data+2, &(gpong->host_ip), 4); memcpy(data+6, &(gpong->file_count), 4); memcpy(data+10, &(gpong->files_total_size), 4); data -= GN_HEADER_SIZE; con_send_packet(con, data, GN_HEADER_SIZE + header->length, 0); newtella_free(header); newtella_free(gpong); newtella_free(data); return 1;}gint gnutella_send_query(struct squery *query, struct newtella_connection *con, gint broadcast){ struct gnutella_header *header; struct gnutella_query_header *query_header; guint32 pack_size = 0; gchar *data; query_header = newtella_malloc(sizeof *query_header); query_header->min_speed = 0; header = newtella_malloc(sizeof *header); guidcpy(header->guid, query->guid); header->f = GNUTELLA_SEARCH; header->ttl = GNUTELLA_SEARCH_TTL; header->hops = 0; header->length = GN_QUERY_SIZE + strlen(query->keyword) + 1; pack_size = GN_HEADER_SIZE + header->length; data = newtella_malloc(pack_size); GNUTELLA_HDR_ATTACH(data, header) data += GN_HEADER_SIZE; memcpy(data, &(query_header->name), GN_QUERY_SIZE); data += GN_QUERY_SIZE; strcpy(data, query->keyword); data -= GN_HEADER_SIZE + GN_QUERY_SIZE; if (broadcast) con_send_to_all(data, pack_size, 0); else con_send_packet(con, data, pack_size, 0); newtella_free(header); newtella_free(query_header); newtella_free(data); return 1;}gint gnutella_send_query_response(struct newtella_connection *con, GList *found_hits, gchar *guid){ GList *iter; struct gnutella_hits *ghits = newtella_malloc(sizeof *ghits); struct gnutella_header *header = newtella_malloc(sizeof *header); struct file_entry *fe; gchar *data, *p; gchar open_data_byte = 0; gint i = 0, str_offs = 0, packet_size = 0; ghits->n = g_list_length(found_hits); ghits->port = gl_my_host_info->port; if (host_is_private(gl_my_host_info->ip, gl_my_host_info->port)) ghits->ip = g_htonl(gl_options->local_ip); else ghits->ip = g_htonl(gl_my_host_info->ip); ghits->speed = gl_options->con_speed; guidcpy(header->guid, guid); header->f = GNUTELLA_SEARCHRESPONSE; header->ttl = GNUTELLA_SEARCH_TTL; header->hops = 0; /* find out the size of the packet * we have to add: * - gnutella header * - hits header * - (hit header) x number of hits * - size of each returned file name + 2 for \0\0 * - extended QHD: 1 length byte + 2 status bytes + 4 bytes for the vendor code * - our guid (last 16 bytes) */ packet_size = GN_HEADER_SIZE + GN_HITS_SIZE + ghits->n*GN_HIT_SIZE + GN_EXTENDED_QHD_SIZE + 16; iter = g_list_first(found_hits); while (iter) { fe = (struct file_entry*)iter->data; /* add size of the file name to packet size */ packet_size += (strlen(fe->name) + 2); iter = g_list_next(iter); } /* now we know exactly how many bytes are needed for the new packet */ data = newtella_malloc(packet_size); /* copy standard header */ GNUTELLA_HDR_ATTACH(data, header) /* copy standard gnutella hits header */ GNUTELLA_HITS_ATTACH((data+GN_HEADER_SIZE), ghits) /* copy each hit */ iter = g_list_first(found_hits); while (iter) { fe = (struct file_entry*)iter->data; p = data+str_offs+GN_HEADER_SIZE+GN_HITS_SIZE+GN_HIT_SIZE*i; memcpy(p, &(fe->index), 4); memcpy(p+4, &(fe->size), 4); memcpy(p+8, fe->name, strlen(fe->name)); memcpy(p+8+strlen(fe->name), "\0\0", 2); i++; str_offs += (strlen(fe->name)+2); iter = g_list_next(iter); } /* attach the QHD data */ p = data+packet_size - 16 - GN_EXTENDED_QHD_SIZE; i = upload_active_con(); if (i == gl_options->max_uploads) /* busy */ open_data_byte |= QHD_BUSY_BIT_MASK; if (host_is_private(gl_my_host_info->ip, gl_my_host_info->port)) /* push */ open_data_byte |= QHD_PUSH_BIT_MASK; /* vendor */ memcpy(p, "GNEW", 4); i = QHD_OD_SIZE; memcpy(p+4, &i, 1); memcpy(p+5, &open_data_byte, 1); memcpy(p+6, &open_data_byte, 1); /* copy guid to the last 16 bytes */ guidcpy(data+packet_size-16, gl_options->gl_guid); header->length = packet_size - GN_HEADER_SIZE; /* adjust header length */ memcpy(data+19, &(header->length), 4); con_send_packet(con, data, header->length+GN_HEADER_SIZE, 1); newtella_free(header); newtella_free(ghits); newtella_free(data); return 1;}gint gnutella_send_push(struct newtella_connection *dcon){ struct gnutella_header *header = newtella_malloc(sizeof *header); struct gnutella_push *gpush = newtella_malloc(sizeof *gpush); char *data; guidget(header->guid); header->f = GNUTELLA_PUSHREQUEST; header->ttl = GNUTELLA_SEARCH_TTL; header->hops = 0; header->length = GN_PUSH_SIZE; guidcpy(gpush->guid, dcon->fi->guid); gpush->index = dcon->fi->index; gpush->ip = g_htonl(gl_options->local_ip); gpush->port = dcon->port; data = newtella_malloc(GN_HEADER_SIZE+GN_PUSH_SIZE); GNUTELLA_HDR_ATTACH(data, header) data += GN_HEADER_SIZE; memcpy(data, &(gpush->guid), 16); memcpy(data+16, &(gpush->index), 4); memcpy(data+20, &(gpush->ip), 4); memcpy(data+24, &(gpush->port), 2); data -= GN_HEADER_SIZE; con_send_to_all(data, GN_HEADER_SIZE+GN_PUSH_SIZE, 0); newtella_free(header); newtella_free(gpush); newtella_free(data); return 1;}/* various help functions */gchar *translate_vendor_id(gchar *vid){ if (!strncmp(vid, "GNEW", 4)) return "Gnewtellium"; if (!strncmp(vid, "BEAR", 4)) return "BearShare"; if (!strncmp(vid, "LIME", 4)) return "LimeWire"; if (!strncmp(vid, "TOAD", 4)) return "ToadNode"; if (!strncmp(vid, "GNOT", 4)) return "Gnotella"; if (!strncmp(vid, "MACT", 4)) return "Mactella"; if (!strncmp(vid, "GNUC", 4)) return "Gnucleus"; if (!strncmp(vid, "GNUT", 4)) return "Gnut"; if (!strncmp(vid, "GTKG", 4)) return "Gtk-Gnutella"; if (!strncmp(vid, "NAPS", 4)) return "NapShare"; if (!strncmp(vid, "OCFG", 4)) return "OpenCola"; if (!strncmp(vid, "HSLG", 4)) return "Hagelslag"; if (!strncmp(vid, "CULT", 4)) return "Cultiv8r"; if (!strncmp(vid, "PHEX", 4)) return "Phex"; if (!strncmp(vid, "XOLO", 4)) return "Xolox"; if (!strncmp(vid, "MNAP", 4)) return "MyNapster"; if (!strncmp(vid, "SNUT", 4)) return "SwapNut"; if (!strncmp(vid, "QTEL", 4)) return "QTella"; else// return vid; return "Unknown"; }gint rate_result_set(gint rs, gchar *open_data_byte, gchar *vendor){ struct file_found *found; GList *iter; gint busy; gint push; if (((open_data_byte[1] & 4) == 4) && ((open_data_byte[2] & 4) == 4)) busy = 1; else busy = 0; if (((open_data_byte[1] & 1) == 1) && ((open_data_byte[2] & 1) == 1)) push = 1; else push = 0; iter = g_list_nth(gl_results, rs); while (iter) { found = iter->data; found->busy = busy; if (!found->push && push) found->push = push; memcpy(found->servent, vendor, 4); iter = g_list_next(iter); } return 1;}/* debug */void gnutella_hdr_dump(struct gnutella_header *hdr){ guiddump(hdr->guid); g_print("f: %d ttl: %d hops %d len: %d\n", hdr->f, hdr->ttl, hdr->hops, hdr->length);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -