📄 gnutella.c
字号:
return -1; } p = cfg->save_path + strlen (cfg->save_path) - 1; if (*p == '/' || *p == '\\') *p = '\0'; p = cfg->share_path + strlen (cfg->share_path) - 1; if (*p == '/' || *p == '\\') *p = '\0'; /* check for existence and create them if necessary */ if (cfg->save_path[0]) { if (stat (cfg->save_path, &buf) == -1) { /* create the download directory */ if (mkdir (cfg->save_path, 0755) == -1) { svz_log (LOG_ERROR, "nut: mkdir: %s\n", SYS_ERROR); return -1; } } /* check if the given path is a directory already */ else if (!S_ISDIR (buf.st_mode)) { svz_log (LOG_ERROR, "nut: %s is not a directory\n", cfg->save_path); return -1; } } /* read shared files */ nut_read_database (cfg, cfg->share_path[0] ? cfg->share_path : "/"); svz_log (LOG_NOTICE, "nut: %d files in database\n", cfg->db_files); /* calculate forced local ip and port if necessary */ if (cfg->force_ip) { cfg->ip = inet_addr (cfg->force_ip); } cfg->port = htons ((unsigned short) cfg->force_port); /* create and modify packet hash */ cfg->packet = svz_hash_create (4); cfg->packet->code = nut_hash_code; cfg->packet->equals = nut_hash_equals; cfg->packet->keylen = nut_hash_keylen; /* create and modify reply hash */ cfg->reply = svz_hash_create (4); cfg->reply->code = nut_hash_code; cfg->reply->equals = nut_hash_equals; cfg->reply->keylen = nut_hash_keylen; /* create current connection hash */ cfg->conn = svz_hash_create (4); /* create host catcher hash */ cfg->net = svz_hash_create (4); /* create recent query hash */ cfg->query = svz_hash_create (4); /* create push request hash */ cfg->push = svz_hash_create (4); /* create and modify the routing table hash */ cfg->route = svz_hash_create (4); cfg->route->code = nut_hash_code; cfg->route->equals = nut_hash_equals; cfg->route->keylen = nut_hash_keylen; /* calculate this server instance's GUID */ nut_calc_guid (cfg->guid); /* create detection string for gnutella host list */ cfg->net_detect = svz_malloc (strlen (NUT_HOSTS) + strlen (cfg->net_url) + 1); sprintf (cfg->net_detect, NUT_HOSTS, cfg->net_url); /* go through all given hosts and try to connect to them */ svz_array_foreach (cfg->hosts, p, n) nut_connect_host (cfg, p); /* bind listening server to configurable port address FIXME: how can we disable bindings ? if (!cfg->disable) server_bind (server, cfg->netport);*/ return 0;}/* * Instance finalizer. */intnut_finalize (svz_server_t *server){ nut_config_t *cfg = server->cfg; nut_host_t **client; nut_packet_t **pkt; nut_transfer_t **transfer; int n; /* destroy sharing files */ nut_destroy_database (cfg); svz_hash_destroy (cfg->conn); svz_hash_destroy (cfg->route); svz_hash_destroy (cfg->query); svz_hash_destroy (cfg->reply); /* destroy sent packet hash */ if ((pkt = (nut_packet_t **) svz_hash_values (cfg->packet)) != NULL) { for (n = 0; n < svz_hash_size (cfg->packet); n++) { svz_free (pkt[n]); } svz_hash_xfree (pkt); } svz_hash_destroy (cfg->packet); /* destroy host catcher hash */ if ((client = (nut_host_t **) svz_hash_values (cfg->net)) != NULL) { for (n = 0; n < svz_hash_size (cfg->net); n++) { svz_free (client[n]); } svz_hash_xfree (client); } svz_hash_destroy (cfg->net); /* destroy push request hash */ if ((transfer = (nut_transfer_t **) svz_hash_values (cfg->push)) != NULL) { for (n = 0; n < svz_hash_size (cfg->push); n++) { svz_free (transfer[n]->file); svz_free (transfer[n]); } svz_hash_xfree (transfer); } svz_hash_destroy (cfg->push); /* free detection string */ svz_free (cfg->net_detect); return 0;}/* * Global gnutella finalizer. */intnut_global_finalize (svz_servertype_t *server){#ifdef __MINGW32__ if (oleHandle) FreeLibrary (oleHandle);#endif /* __MINGW32__ */ /* destroy confguration defaults */ svz_config_strarray_destroy (nut_config.search); return 0;}/* * This is the sock->disconnected_socket callback for gnutella * connections. */intnut_disconnect (svz_socket_t *sock){ nut_config_t *cfg = sock->cfg; nut_host_t *host; svz_uint8_t *id; char *key, **keys; int size, n; nut_packet_t *pkt; nut_client_t *client = sock->data; /* delete all push request routing information for this connection */ while ((id = (svz_uint8_t *) svz_hash_contains (cfg->reply, sock)) != NULL) svz_hash_delete (cfg->reply, (char *) id); /* delete all routing information for this connection */ while ((id = (svz_uint8_t *) svz_hash_contains (cfg->route, sock)) != NULL) svz_hash_delete (cfg->route, (char *) id); /* drop all packet information for this connection */ if ((keys = (char **) svz_hash_keys (cfg->packet)) != NULL) { size = svz_hash_size (cfg->packet); for (n = 0; n < size; n++) { pkt = (nut_packet_t *) svz_hash_get (cfg->packet, keys[n]); if (pkt->sock == sock) { svz_hash_delete (cfg->packet, keys[n]); svz_free (pkt); } } svz_hash_xfree (keys); } /* remove this socket from the current connection hash */ key = nut_client_key (sock->remote_addr, sock->remote_port); svz_hash_delete (cfg->conn, key); /* remove the connection from the host catcher */ if ((host = svz_hash_delete (cfg->net, key)) != NULL) svz_free (host); /* free client structure */ if (client) { cfg->nodes -= client->nodes; cfg->files -= client->files; cfg->size -= client->size; svz_free (client); sock->data = NULL; } return 0;}/* * This callback is regularly called in the `server_periodic_tasks' * routine. Here we try connecting to more gnutella hosts. */intnut_server_notify (svz_server_t *server){ nut_config_t *cfg = server->cfg; static int count = NUT_CONNECT_INTERVAL; char **keys; nut_packet_t *pkt; int n, size, connect; time_t t, received; /* go sleep if we still do not want to do something */ if (count-- > 0) return 0; /* do we have enough connections ? */ connect = cfg->connections - svz_hash_size (cfg->conn); if (connect > 0) { /* are there hosts in the host catcher hash ? */ if ((keys = (char **) svz_hash_keys (cfg->net)) != NULL) { /* go through all caught hosts */ for (n = 0; n < svz_hash_size (cfg->net) && connect; n++) { /* check if we are not already connected */ if (svz_hash_get (cfg->conn, keys[n]) == NULL) { if (nut_connect_host (cfg, keys[n]) != -1) connect--; } } svz_hash_xfree (keys); } } /* go through the sent packet hash and drop old entries */ if ((keys = (char **) svz_hash_keys (cfg->packet)) != NULL) { t = time (NULL); size = svz_hash_size (cfg->packet); for (n = 0; n < size; n++) { pkt = (nut_packet_t *) svz_hash_get (cfg->packet, keys[n]); if (t - pkt->sent > NUT_ENTRY_AGE) { svz_hash_delete (cfg->packet, keys[n]); svz_free (pkt); } } svz_hash_xfree (keys); } /* drop older entries from the recent query hash */ if ((keys = (char **) svz_hash_keys (cfg->query)) != NULL) { t = time (NULL); size = svz_hash_size (cfg->query); for (n = 0; n < size; n++) { received = (time_t) (long) svz_hash_get (cfg->query, keys[n]); if (t - received > NUT_ENTRY_AGE) { svz_hash_delete (cfg->query, keys[n]); } } svz_hash_xfree (keys); } /* wake up in a certain time */ count = NUT_CONNECT_INTERVAL; return 0;}/* * Whenever there is data arriving for this socket we call this * routine. */intnut_check_request (svz_socket_t *sock){ nut_client_t *client = sock->data; nut_header_t *hdr; svz_uint8_t *packet; int len = strlen (NUT_OK); unsigned fill = sock->recv_buffer_fill; /* go through all packets in the receive queue */ while ((fill = sock->recv_buffer_fill) >= SIZEOF_NUT_HEADER) { hdr = nut_get_header ((svz_uint8_t *) sock->recv_buffer); /* is there enough data to fulfill a complete packet ? */ if (fill >= SIZEOF_NUT_HEADER + hdr->length) { len = SIZEOF_NUT_HEADER + hdr->length; packet = (svz_uint8_t *) sock->recv_buffer + SIZEOF_NUT_HEADER; client->packets++;#if 0 svz_hexdump (stdout, "gnutella packet", sock->sock_desc, sock->recv_buffer, len, 0);#endif /* try to route the packet */ if (nut_route (sock, hdr, packet) == 0) { /* handle the packet */ switch (hdr->function) { case NUT_PING_REQ: nut_ping (sock, hdr, NULL); break; case NUT_PING_ACK: nut_pong (sock, hdr, packet); break; case NUT_PUSH_REQ: nut_push_request (sock, hdr, packet); break; case NUT_SEARCH_REQ: nut_query (sock, hdr, packet); break; case NUT_SEARCH_ACK: nut_reply (sock, hdr, packet); break; } } else if (!(sock->flags & SOCK_FLAG_KILLED)) { client->dropped++; } /* return if this client connection has been killed */ if (sock->flags & SOCK_FLAG_KILLED) return -1; /* cut this packet from the send buffer queue */ svz_sock_reduce_recv (sock, len); } else break; } return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -