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