📄 gnutella.c
字号:
}/* * This routine is the sock->idle_func callback for each gnutella * connection. We will regularly search for specific files. */intnut_idle_searching (svz_socket_t *sock){ nut_config_t *cfg = sock->cfg; nut_packet_t *pkt; nut_header_t hdr; nut_query_t query; svz_uint8_t *header, *search; char *text; /* search strings given ? */ if (cfg->search && svz_array_size (cfg->search) > 0) { /* get next search string */ if (svz_array_size (cfg->search) > (unsigned long) cfg->search_index) { text = svz_array_get (cfg->search, cfg->search_index); cfg->search_index++; } else { cfg->search_index = 0; text = svz_array_get (cfg->search, 0); } /* create new gnutella packet */ nut_calc_guid (hdr.id); hdr.function = NUT_SEARCH_REQ; hdr.ttl = (svz_uint8_t) cfg->ttl; hdr.hop = 0; hdr.length = SIZEOF_NUT_QUERY + strlen (text) + 1; query.speed = (unsigned short) cfg->min_speed; header = nut_put_header (&hdr); search = nut_put_query (&query); /* try sending this packet to this connection */ if (svz_sock_write (sock, (char *) header, SIZEOF_NUT_HEADER) == -1 || svz_sock_write (sock, (char *) search, SIZEOF_NUT_QUERY) == -1 || svz_sock_write (sock, text, strlen (text) + 1) == -1) { return -1; } /* save this packet for later routing */ pkt = svz_malloc (sizeof (nut_packet_t)); pkt->sock = sock; pkt->sent = time (NULL); svz_hash_put (cfg->packet, (char *) hdr.id, pkt); } /* wake up in a certain time */ sock->idle_counter = NUT_SEARCH_INTERVAL; return 0;}/* * Gnutella server info callback. */char *nut_info_server (svz_server_t *server){ nut_config_t *cfg = server->cfg; static char info[80 * 19]; char *e, *ext = NULL; int n; /* create file extension list */ if (cfg->extensions) { svz_array_foreach (cfg->extensions, e, n) { if (!ext) { ext = svz_malloc (strlen (e) + 2); strcpy (ext, e); } else { ext = svz_realloc (ext, strlen (ext) + strlen (e) + 2); strcat (ext, e); } strcat (ext, ";"); } ext[strlen (ext) - 1] = '\0'; } sprintf (info, " tcp bindings : %s\r\n" " force ip : %s\r\n" " force port : %s\r\n" " maximum ttl : %u\r\n" " default ttl : %u\r\n" " speed : %u KBit/s\r\n" " clientID128 : %s\r\n" " download path : %s\r\n" " share path : %s\r\n" " search pattern : %s\r\n" " file extensions : %s\r\n" " routing table : %u entries\r\n" " connected hosts : %u/%u\r\n" " sent packets : %u\r\n" " routing errors : %u\r\n" " hosts : %u gnutella clients seen\r\n" " data pool : %u MB in %u files on %u hosts\r\n" " database : %u MB in %u files\r\n" " downloads : %u/%u\r\n" " uploads : %u/%u\r\n" " recent queries : %u", svz_server_bindings (server), cfg->ip ? svz_inet_ntoa (cfg->ip) : "no specified", cfg->port ? svz_itoa (ntohs (cfg->port)) : "no specified", cfg->max_ttl, cfg->ttl, cfg->speed, nut_print_guid (cfg->guid), cfg->save_path, cfg->share_path, cfg->search && svz_array_size (cfg->search) > 0 ? (unsigned long) cfg->search_index < svz_array_size (cfg->search) ? (char *) svz_array_get (cfg->search, cfg->search_index) : (char *) svz_array_get (cfg->search, 0) : "none given", ext ? ext : "no extensions", svz_hash_size (cfg->route), svz_hash_size (cfg->conn), cfg->connections, svz_hash_size (cfg->packet), cfg->errors, svz_hash_size (cfg->net), cfg->size / 1024, cfg->files, cfg->nodes, cfg->db_size / 1024 / 1024, cfg->db_files, cfg->dnloads, cfg->max_dnloads, cfg->uploads, cfg->max_uploads, svz_hash_size (cfg->query)); svz_free (ext); return info;}/* * Gnutella client info callback. */char *nut_info_client (svz_server_t *server, svz_socket_t *sock){ static char info[80 * 3]; static char text[128]; nut_transfer_t *transfer = sock->data; nut_client_t *client = sock->data; unsigned current, all, elapsed; sprintf (info, "This is a gnutella spider client.\r\n\r\n"); /* normal gnutella host */ if (sock->userflags & NUT_FLAG_CLIENT) { sprintf (text, " * usual gnutella host\r\n" " * dropped packets : %u/%u\r\n" " * invalid packets : %u\r\n", client->dropped, client->packets, client->invalid); strcat (info, text); sprintf (text, " * data pool : %u MB in %u files on %u hosts\r\n", client->size / 1024, client->files, client->nodes); strcat (info, text); } /* file upload and download */ if (sock->userflags & (NUT_FLAG_UPLOAD | NUT_FLAG_DNLOAD)) { current = transfer->original_size - transfer->size; all = transfer->original_size; elapsed = time (NULL) - transfer->start; if (!all) all++; if (!elapsed) elapsed++; sprintf (text, " * file : %s\r\n", transfer->file); strcat (info, text); sprintf (text, " * %s progress : %u/%u - %u.%u%% - %u.%u kb/sec\r\n", sock->userflags & NUT_FLAG_DNLOAD ? "download" : "upload", current, all, current * 100 / all, (current * 1000 / all) % 10, current / 1024 / elapsed, (current * 10 / 1024 / elapsed) % 10); strcat (info, text); } /* http header received ? */ if (sock->userflags & NUT_FLAG_HDR) { strcat (info, " * header received\r\n"); } /* host list */ if (sock->userflags & NUT_FLAG_HOSTS) { strcat (info, " * sending host catcher list\r\n"); } return info;}/* * This is the protocol detection routine for self connected gnutella * hosts. It is used for normal gnutella network connections and * push requests (download). */intnut_detect_connect (svz_socket_t *sock){ nut_config_t *cfg = sock->cfg; int len = strlen (NUT_OK); /* check for self connected response of normal gnutella host */ if (sock->recv_buffer_fill >= len && !memcmp (sock->recv_buffer, NUT_OK, len)) { sock->userflags |= (NUT_FLAG_CLIENT | NUT_FLAG_SELF); svz_log (LOG_NOTICE, "nut: host %s:%u connected\n", svz_inet_ntoa (sock->remote_addr), ntohs (sock->remote_port)); svz_sock_reduce_recv (sock, len); if (nut_connect_socket (svz_server_find (cfg), sock) == -1) return -1; return sock->check_request (sock); } return 0;}/* * Incoming connections will be protocol checked. */int nut_detect_proto (svz_server_t *server, svz_socket_t *sock){ nut_config_t *cfg = server->cfg; int len = strlen (NUT_CONNECT); /* detect normal connect */ len = strlen (NUT_CONNECT); if (sock->recv_buffer_fill >= len && !memcmp (sock->recv_buffer, NUT_CONNECT, len)) { sock->userflags |= NUT_FLAG_CLIENT; svz_log (LOG_NOTICE, "gnutella protocol detected (client)\n"); svz_sock_reduce_recv (sock, len); return -1; } /* detect upload request */ len = strlen (NUT_GET); if (sock->recv_buffer_fill >= len && !memcmp (sock->recv_buffer, NUT_GET, len)) { sock->userflags |= NUT_FLAG_UPLOAD; svz_log (LOG_NOTICE, "gnutella protocol detected (upload)\n"); return -1; } /* detect host catcher request */ len = strlen (cfg->net_detect); if (sock->recv_buffer_fill >= len && !memcmp (sock->recv_buffer, cfg->net_detect, len)) { sock->userflags |= NUT_FLAG_HOSTS; svz_log (LOG_NOTICE, "gnutella protocol detected (host list)\n"); svz_sock_reduce_recv (sock, len); return -1; } /* check for push request reply */ len = strlen (NUT_GIVE); if (sock->recv_buffer_fill >= len && !memcmp (sock->recv_buffer, NUT_GIVE, len)) { sock->userflags |= NUT_FLAG_GIVEN; svz_log (LOG_NOTICE, "gnutella protocol detected (giving)\n"); return -1; } return 0;}/* * This routine will be called when the detection routine return * success. */int nut_connect_socket (svz_server_t *server, svz_socket_t *sock){ nut_config_t *cfg = server->cfg; /* assign download callbacks */ if (sock->userflags & NUT_FLAG_GIVEN) { sock->check_request = nut_check_given; return 0; } /* assign host catcher request routines */ if (sock->userflags & NUT_FLAG_HOSTS) { sock->check_request = nut_hosts_check; sock->write_socket = nut_hosts_write; svz_sock_resize_buffers (sock, NUT_SEND_BUFSIZE, sock->recv_buffer_size); return 0; } /* assign upload request routines */ if (sock->userflags & NUT_FLAG_UPLOAD) { if (cfg->uploads <= cfg->max_uploads) { sock->check_request = nut_check_upload; return 0; } return -1; } /* assign normal gnutella request routines */ if (sock->userflags & NUT_FLAG_CLIENT) { /* check if we got enough clients already */ if (svz_hash_size (cfg->conn) > cfg->connections) return -1; /* send the first reply if necessary */ if (!(sock->userflags & NUT_FLAG_SELF)) if (svz_sock_printf (sock, NUT_OK) == -1) return -1; /* assign gnutella specific callbacks */ sock->flags |= SOCK_FLAG_NOFLOOD; sock->disconnected_socket = nut_disconnect; sock->check_request = nut_check_request; sock->idle_func = nut_idle_searching; sock->idle_counter = NUT_SEARCH_INTERVAL; sock->data = nut_create_client (); /* send initial ping */ if (nut_init_ping (sock) == -1) return -1; /* put this client to the current connection hash */ svz_hash_put (cfg->conn, nut_client_key (sock->remote_addr, sock->remote_port), sock); return 0; } return -1;}int have_gnutella = 1;#else /* ENABLE_GNUTELLA */int have_gnutella = 0; /* Shut compiler warnings up, remember for runtime */#endif /* not ENABLE_GNUTELLA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -