1 /* 2 * gnutella.h - gnutella protocol header file 3 * 4 * Copyright (C) 2011-2013 Thien-Thi Nguyen 5 * Copyright (C) 2000 Stefan Jahn <stefan@lkcc.org> 6 * 7 * This is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3, or (at your option) 10 * any later version. 11 * 12 * This software is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this package. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef __GNUTELLA_H__ 22 #define __GNUTELLA_H__ 1 23 24 /* general defines */ 25 #define NUT_VERSION "0.48" 26 #define NUT_CONNECT "GNUTELLA CONNECT/0.4\n\n" 27 #define NUT_OK "GNUTELLA OK\n\n" 28 #define NUT_HOSTS "GET /%s HTTP/1." 29 #define NUT_GIVE "GIV " 30 31 /* default values */ 32 #define NUT_PORT 6346 /* gnutella default tcp port */ 33 #define NUT_GUID {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 34 #define NUT_GUID_SIZE 16 /* GUID length in bytes */ 35 #define NUT_SEARCH_INTERVAL 10 /* send search queries */ 36 #define NUT_TTL 5 /* default packet TTL */ 37 #define NUT_MAX_TTL 5 /* default maximum packet TTL */ 38 #define NUT_CONNECT_INTERVAL 2 /* reconnect to gnutella hosts */ 39 #define NUT_SEND_BUFSIZE (1024 * 100) /* host list buffer size */ 40 #define NUT_CONNECT_TIMEOUT 20 /* close connection then */ 41 #define NUT_ENTRY_AGE (60 * 3) /* maximum hash entry age */ 42 43 /* function IDs */ 44 #define NUT_PING_REQ 0x00 /* ping */ 45 #define NUT_PING_ACK 0x01 /* ping response */ 46 #define NUT_PUSH_REQ 0x40 /* client push request */ 47 #define NUT_SEARCH_REQ 0x80 /* search request */ 48 #define NUT_SEARCH_ACK 0x81 /* search response */ 49 50 /* protocol flags */ 51 #define NUT_FLAG_DNLOAD 0x0001 /* downloading a file */ 52 #define NUT_FLAG_HDR 0x0002 /* http header received? */ 53 #define NUT_FLAG_HOSTS 0x0004 /* sending host catcher list (http proto) */ 54 #define NUT_FLAG_CLIENT 0x0008 /* normal gnutella host */ 55 #define NUT_FLAG_UPLOAD 0x0010 /* uploading a file */ 56 #define NUT_FLAG_SELF 0x0020 /* connecting to a gnutella host */ 57 #define NUT_FLAG_GIVEN 0x0040 /* push request reply (GIV) */ 58 59 /* guid: 60 * The header contains a Microsoft GUID (Globally Unique Identifier for 61 * you nonWinblows people) which is the message identifer. My crystal ball 62 * reports that "the GUIDs only have to be unique on the client", which 63 * means that you can really put anything here, as long as you keep track 64 * of it (a client won't respond to you if it sees the same message id 65 * again). If you're responding to a message, be sure you haven't seen the 66 * message id (from that host) before, copy their message ID into your 67 * response and send it on it's way. 68 */ 69 70 /* 71 * The Gnutella packets are all in little endian byte order except 72 * ip adresses which are in network byte order (big endian). So they 73 * need to be converted to host byte order if necessary. 74 */ 75 76 /* gnutella header */ 77 typedef struct 78 { 79 uint8_t id[NUT_GUID_SIZE]; /* message ID */ 80 uint8_t function; /* function ID */ 81 uint8_t ttl; /* remaining TTL */ 82 uint8_t hop; /* hop count */ 83 unsigned int length; /* data length */ 84 } 85 nut_header_t; 86 #define SIZEOF_NUT_HEADER (NUT_GUID_SIZE + 7) 87 88 /* ping response structure */ 89 typedef struct 90 { 91 in_port_t port; /* port number of the listening host */ 92 in_addr_t ip; /* address of the listening host, network byte order */ 93 unsigned int files; /* number of files shared by the host */ 94 unsigned int size; /* total size of files shared by the host, in KB */ 95 } 96 nut_pong_t; 97 #define SIZEOF_NUT_PONG (14) 98 99 /* search query header */ 100 typedef struct 101 { 102 uint16_t speed; /* minimum speed (in kbps) */ 103 char search[1]; /* search request (NULL terminated) */ 104 } 105 nut_query_t; 106 #define SIZEOF_NUT_QUERY (2) 107 108 /* search record structure */ 109 typedef struct 110 { 111 unsigned int index; /* file index */ 112 unsigned int size; /* file size */ 113 char file[1]; /* file name (double-NULL terminated) */ 114 } 115 nut_record_t; 116 #define SIZEOF_NUT_RECORD (8) 117 118 /* search reply header */ 119 typedef struct 120 { 121 uint8_t records; /* number of records which follow this header */ 122 in_port_t port; /* listening port number of the host */ 123 in_addr_t ip; /* ip address of the host, network byte order */ 124 uint16_t speed; /* speed of the host which found the results */ 125 uint16_t pad; /* dunno */ 126 nut_record_t record[1]; /* array of records */ 127 uint8_t id[NUT_GUID_SIZE]; /* clientID128 sending the reply */ 128 } 129 nut_reply_t; 130 #define SIZEOF_NUT_REPLY (11) 131 132 /* client push request structure */ 133 typedef struct 134 { 135 /* servers GUID the client wishes the push from */ 136 uint8_t id[NUT_GUID_SIZE]; 137 unsigned int index; /* index of file requested */ 138 in_addr_t ip; /* ip address of the host requesting the push */ 139 in_port_t port; /* port number of the host requesting the push */ 140 } 141 nut_push_t; 142 #define SIZEOF_NUT_PUSH (26) 143 144 /* gnutella host structure */ 145 typedef struct 146 { 147 uint8_t id[NUT_GUID_SIZE]; /* clientID128 GUID */ 148 in_addr_t ip; /* IP address */ 149 in_port_t port; /* TCP port */ 150 time_t last_reply; /* last packet received */ 151 } 152 nut_host_t; 153 154 /* each gnutella host connection gets such a structure */ 155 typedef struct 156 { 157 unsigned dropped; /* number of dropped packets */ 158 unsigned packets; /* number of received packets */ 159 unsigned invalid; /* number of invalid packet types */ 160 unsigned queries; /* number of queries */ 161 unsigned files; /* files at this connection */ 162 unsigned size; /* file size (in KB) here */ 163 unsigned nodes; /* number of hosts at this connection */ 164 } 165 nut_client_t; 166 167 /* sent packet structure */ 168 typedef struct 169 { 170 time_t sent; /* when was this packet sent */ 171 svz_socket_t *sock; /* sent to this socket */ 172 } 173 nut_packet_t; 174 175 /* reply structure */ 176 typedef struct 177 { 178 svz_socket_t *sock; /* routing information */ 179 unsigned int index; /* file index to push */ 180 } 181 nut_push_reply_t; 182 183 /* files in the sharing directory */ 184 typedef struct 185 { 186 off_t size; /* file size */ 187 unsigned index; /* database index */ 188 char *file; /* filename */ 189 char *path; /* path to file */ 190 void *next; /* pointer to next file entry */ 191 } 192 nut_file_t; 193 194 /* 195 * Protocol server specific configuration. 196 */ 197 typedef struct 198 { 199 int disable; /* if set we do not listen on any port cfg */ 200 int max_ttl; /* maximum ttl for a gnutella packet */ 201 int ttl; /* initial ttl for a gnutella packet */ 202 svz_array_t *hosts; /* array of initial hosts */ 203 uint8_t guid[NUT_GUID_SIZE]; /* this servers GUID */ 204 svz_hash_t *route; /* routing table */ 205 svz_hash_t *conn; /* connected hosts hash */ 206 svz_array_t *search; /* search pattern array */ 207 size_t search_index; /* current search pattern index */ 208 int search_limit; /* limit amount of search reply records */ 209 svz_hash_t *packet; /* this servers created packets */ 210 unsigned errors; /* routing errors */ 211 unsigned files; /* files within connected network */ 212 unsigned size; /* file size (in KB) */ 213 unsigned nodes; /* hosts within the connected network */ 214 char *save_path; /* where to store downloaded files */ 215 char *share_path; /* local search database path */ 216 int dnloads; /* concurrent downloads */ 217 int max_dnloads; /* maximum concurrent downloads */ 218 int speed; /* connection speed (KBit/s) */ 219 int min_speed; /* minimum connection speed for searching */ 220 svz_array_t *extensions; /* file extensions */ 221 svz_hash_t *net; /* host catcher */ 222 size_t connections; /* number of connections to keep up */ 223 char *force_ip; /* force the local ip to this value */ 224 in_addr_t ip; /* calculated from `force_ip' */ 225 int force_port; /* force the local port to this value */ 226 in_port_t port; /* calculated from `force_port' */ 227 svz_hash_t *query; /* recent query hash */ 228 svz_hash_t *reply; /* reply hash for routing push requests */ 229 svz_hash_t *push; /* push request hash */ 230 nut_file_t *database; /* shared file array */ 231 unsigned db_files; /* number of database files */ 232 unsigned db_size; /* size of database in bytes */ 233 int uploads; /* current number of uploads */ 234 int max_uploads; /* maximum number of uploads */ 235 char *net_url; /* configurable gnutella net url */ 236 char *net_detect; /* detection string for the above value */ 237 } 238 nut_config_t; 239 240 /* 241 * Basic server callback definitions. 242 */ 243 244 /* detection routines */ 245 int nut_detect_proto (svz_server_t *server, svz_socket_t *sock); 246 int nut_detect_connect (svz_socket_t *sock); 247 248 /* connection routine */ 249 int nut_connect_socket (svz_server_t *server, svz_socket_t *sock); 250 251 /* check request routine */ 252 int nut_check_request (svz_socket_t *sock); 253 254 /* disconnection routine */ 255 int nut_disconnect (svz_socket_t *sock); 256 257 /* idle routines */ 258 int nut_idle_searching (svz_socket_t *sock); 259 int nut_connect_timeout (svz_socket_t *sock); 260 261 /* server functions */ 262 int nut_init (svz_server_t *server); 263 int nut_global_init (svz_servertype_t *server); 264 int nut_finalize (svz_server_t *server); 265 int nut_global_finalize (svz_servertype_t *server); 266 int nut_server_notify (svz_server_t *server); 267 char *nut_info_server (svz_server_t *server); 268 char *nut_info_client (svz_server_t *server, svz_socket_t *sock); 269 270 /* 271 * This server's definition. 272 */ 273 extern svz_servertype_t nut_server_definition; 274 275 #endif /* __GNUTELLA_H__ */ 276