rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * $Id: vendor.c,v 1.6 2004/03/26 11:44:13 hipnod Exp $
|
paulo@0
|
3 *
|
paulo@0
|
4 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
|
paulo@0
|
5 *
|
paulo@0
|
6 * This program is free software; you can redistribute it and/or modify it
|
paulo@0
|
7 * under the terms of the GNU General Public License as published by the
|
paulo@0
|
8 * Free Software Foundation; either version 2, or (at your option) any
|
paulo@0
|
9 * later version.
|
paulo@0
|
10 *
|
paulo@0
|
11 * This program is distributed in the hope that it will be useful, but
|
paulo@0
|
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
|
paulo@0
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
paulo@0
|
14 * General Public License for more details.
|
paulo@0
|
15 */
|
paulo@0
|
16
|
paulo@0
|
17 #include "gt_gnutella.h"
|
paulo@0
|
18 #include "message/msg_handler.h"
|
paulo@0
|
19
|
paulo@0
|
20 #include "gt_connect.h" /* gt_connect_test */
|
paulo@0
|
21 #include "gt_bind.h"
|
paulo@0
|
22
|
paulo@0
|
23 #include "gt_utils.h" /* make_str */
|
paulo@0
|
24
|
paulo@0
|
25 #include "transfer/push_proxy.h"
|
paulo@0
|
26
|
paulo@0
|
27 /*****************************************************************************/
|
paulo@0
|
28
|
paulo@0
|
29 #define EMPTY_VENDOR { 0, 0, 0, 0 }
|
paulo@0
|
30
|
paulo@0
|
31 #define vmsg_name(name) \
|
paulo@0
|
32 name##_struct
|
paulo@0
|
33
|
paulo@0
|
34 #define declare_vmsg(name,vendor,id) \
|
paulo@0
|
35 const struct gt_vendor_msg vmsg_name(name) = { vendor, id }; \
|
paulo@0
|
36 const struct gt_vendor_msg *name = &name##_struct;
|
paulo@0
|
37
|
paulo@0
|
38 /* Globally visible vendor message structs */
|
paulo@0
|
39 declare_vmsg(GT_VMSG_MESSAGES_SUPP, EMPTY_VENDOR, 0);
|
paulo@0
|
40 declare_vmsg(GT_VMSG_HOPS_FLOW, "BEAR", 4);
|
paulo@0
|
41 declare_vmsg(GT_VMSG_TCP_CONNECT_BACK, "BEAR", 7);
|
paulo@0
|
42 declare_vmsg(GT_VMSG_PUSH_PROXY_REQ, "LIME", 21);
|
paulo@0
|
43 declare_vmsg(GT_VMSG_PUSH_PROXY_ACK, "LIME", 22);
|
paulo@0
|
44
|
paulo@0
|
45 /*****************************************************************************/
|
paulo@0
|
46
|
paulo@0
|
47 static GT_MSG_HANDLER(gt_msg_messages_supported);
|
paulo@0
|
48 static GT_MSG_HANDLER(gt_msg_hops_flow);
|
paulo@0
|
49 static GT_MSG_HANDLER(gt_msg_tcp_connect_back);
|
paulo@0
|
50 static GT_MSG_HANDLER(gt_msg_push_proxy_request);
|
paulo@0
|
51 static GT_MSG_HANDLER(gt_msg_push_proxy_acknowledgement);
|
paulo@0
|
52
|
paulo@0
|
53 /*****************************************************************************/
|
paulo@0
|
54
|
paulo@0
|
55 struct gt_vendor_table
|
paulo@0
|
56 {
|
paulo@0
|
57 const struct gt_vendor_msg *msg;
|
paulo@0
|
58 GtMessageHandler func;
|
paulo@0
|
59 uint16_t version;
|
paulo@0
|
60 BOOL in_msgs_supported; /* inside MessagesSupported */
|
paulo@0
|
61 };
|
paulo@0
|
62
|
paulo@0
|
63 static struct gt_vendor_table vendor_table[] =
|
paulo@0
|
64 {
|
paulo@0
|
65 { &vmsg_name(GT_VMSG_MESSAGES_SUPP), gt_msg_messages_supported,
|
paulo@0
|
66 1, FALSE },
|
paulo@0
|
67 { &vmsg_name(GT_VMSG_HOPS_FLOW), gt_msg_hops_flow,
|
paulo@0
|
68 1, FALSE /*TODO: support receving*/ },
|
paulo@0
|
69 { &vmsg_name(GT_VMSG_TCP_CONNECT_BACK), gt_msg_tcp_connect_back,
|
paulo@0
|
70 1, TRUE },
|
paulo@0
|
71 { &vmsg_name(GT_VMSG_PUSH_PROXY_REQ), gt_msg_push_proxy_request,
|
paulo@0
|
72 2, TRUE },
|
paulo@0
|
73 { &vmsg_name(GT_VMSG_PUSH_PROXY_ACK), gt_msg_push_proxy_acknowledgement,
|
paulo@0
|
74 2, FALSE },
|
paulo@0
|
75 };
|
paulo@0
|
76
|
paulo@0
|
77 static const size_t nr_vmsgs = sizeof(vendor_table) / sizeof(vendor_table[0]);
|
paulo@0
|
78
|
paulo@0
|
79 /*****************************************************************************/
|
paulo@0
|
80
|
paulo@0
|
81 static void vmsg_init (struct gt_vendor_msg *msg,
|
paulo@0
|
82 unsigned char *vendor_id, uint16_t id)
|
paulo@0
|
83 {
|
paulo@0
|
84 /* initialize to zero because of potential structure alignment issues */
|
paulo@0
|
85 memset (msg, 0, sizeof(struct gt_vendor_msg));
|
paulo@0
|
86
|
paulo@0
|
87 memcpy (&msg->vendor_id, vendor_id, 4);
|
paulo@0
|
88 msg->id = id;
|
paulo@0
|
89 }
|
paulo@0
|
90
|
paulo@0
|
91 static void append_vmsg (GtPacket *pkt, const struct gt_vendor_msg *msg,
|
paulo@0
|
92 uint16_t ver)
|
paulo@0
|
93 {
|
paulo@0
|
94 gt_packet_put_ustr (pkt, msg->vendor_id, 4);
|
paulo@0
|
95 gt_packet_put_uint16 (pkt, msg->id);
|
paulo@0
|
96 gt_packet_put_uint16 (pkt, ver);
|
paulo@0
|
97 }
|
paulo@0
|
98
|
paulo@0
|
99 void gt_vmsg_send_supported (GtNode *node)
|
paulo@0
|
100 {
|
paulo@0
|
101 GtPacket *pkt;
|
paulo@0
|
102 int i;
|
paulo@0
|
103 uint16_t vector_len = 0;
|
paulo@0
|
104
|
paulo@0
|
105 if (!dataset_lookupstr (node->hdr, "vendor-message"))
|
paulo@0
|
106 return;
|
paulo@0
|
107
|
paulo@0
|
108 if (!(pkt = gt_packet_vendor (GT_VMSG_MESSAGES_SUPP)))
|
paulo@0
|
109 return;
|
paulo@0
|
110
|
paulo@0
|
111 gt_packet_put_uint16 (pkt, 0);
|
paulo@0
|
112
|
paulo@0
|
113 for (i = 0; i < nr_vmsgs; i++)
|
paulo@0
|
114 {
|
paulo@0
|
115 if (vendor_table[i].in_msgs_supported)
|
paulo@0
|
116 {
|
paulo@0
|
117 vector_len++;
|
paulo@0
|
118 append_vmsg (pkt, vendor_table[i].msg, vendor_table[i].version);
|
paulo@0
|
119 }
|
paulo@0
|
120 }
|
paulo@0
|
121
|
paulo@0
|
122 /* XXX: packet put_xxx functions don't work with gt_packet_seek :( */
|
paulo@0
|
123 vector_len = htovl (vector_len);
|
paulo@0
|
124 memcpy (&pkt->data[GNUTELLA_HDR_LEN + VMSG_HDR_LEN], &vector_len, 2);
|
paulo@0
|
125
|
paulo@0
|
126 if (gt_packet_error (pkt))
|
paulo@0
|
127 {
|
paulo@0
|
128 gt_packet_free (pkt);
|
paulo@0
|
129 return;
|
paulo@0
|
130 }
|
paulo@0
|
131
|
paulo@0
|
132 GT->DBGSOCK (GT, GT_CONN(node), "sending MessagesSupported");
|
paulo@0
|
133
|
paulo@0
|
134 gt_packet_send (GT_CONN(node), pkt);
|
paulo@0
|
135 gt_packet_free (pkt);
|
paulo@0
|
136 }
|
paulo@0
|
137
|
paulo@0
|
138 /*****************************************************************************/
|
paulo@0
|
139
|
paulo@0
|
140 GT_MSG_HANDLER(gt_msg_vendor)
|
paulo@0
|
141 {
|
paulo@0
|
142 struct gt_vendor_msg vmsg;
|
paulo@0
|
143 unsigned char *vendor;
|
paulo@0
|
144 int i;
|
paulo@0
|
145 uint16_t id;
|
paulo@0
|
146 uint16_t version;
|
paulo@0
|
147
|
paulo@0
|
148 if (gt_packet_hops (packet) != 0 && gt_packet_ttl (packet) != 1)
|
paulo@0
|
149 return;
|
paulo@0
|
150
|
paulo@0
|
151 vendor = gt_packet_get_ustr (packet, 4);
|
paulo@0
|
152 id = gt_packet_get_uint16 (packet);
|
paulo@0
|
153 version = gt_packet_get_uint16 (packet);
|
paulo@0
|
154
|
paulo@0
|
155 /* initialize a copy for making a single call to memcmp */
|
paulo@0
|
156 vmsg_init (&vmsg, vendor, id);
|
paulo@0
|
157
|
paulo@0
|
158 if (gt_packet_error (packet))
|
paulo@0
|
159 {
|
paulo@0
|
160 if (MSG_DEBUG)
|
paulo@0
|
161 GT->DBGSOCK (GT, c, "Error parsing vendor message");
|
paulo@0
|
162
|
paulo@0
|
163 return;
|
paulo@0
|
164 }
|
paulo@0
|
165
|
paulo@0
|
166 for (i = 0; i < nr_vmsgs; i++)
|
paulo@0
|
167 {
|
paulo@0
|
168 if (memcmp (vendor_table[i].msg, &vmsg, sizeof(vmsg)) == 0 &&
|
paulo@0
|
169 version <= vendor_table[i].version)
|
paulo@0
|
170 {
|
paulo@0
|
171 vendor_table[i].func (MSG_HANDLER_ARG_NAMES);
|
paulo@0
|
172 return;
|
paulo@0
|
173 }
|
paulo@0
|
174 }
|
paulo@0
|
175
|
paulo@0
|
176 if (MSG_DEBUG)
|
paulo@0
|
177 {
|
paulo@0
|
178 GT->DBGSOCK (GT, c, "No handler for vendor message %s/%dv%d",
|
paulo@0
|
179 make_str (vendor, 4), id, version);
|
paulo@0
|
180 }
|
paulo@0
|
181 }
|
paulo@0
|
182
|
paulo@0
|
183 /*****************************************************************************/
|
paulo@0
|
184
|
paulo@0
|
185 static struct gt_vendor_table *find_in_vmsg_table (gt_vendor_msg_t *vmsg)
|
paulo@0
|
186 {
|
paulo@0
|
187 int i;
|
paulo@0
|
188
|
paulo@0
|
189 for (i = 0; i < nr_vmsgs; i++)
|
paulo@0
|
190 {
|
paulo@0
|
191 if (memcmp (vendor_table[i].msg, vmsg, sizeof(*vmsg)) == 0)
|
paulo@0
|
192 return &vendor_table[i];
|
paulo@0
|
193 }
|
paulo@0
|
194
|
paulo@0
|
195 return NULL;
|
paulo@0
|
196 }
|
paulo@0
|
197
|
paulo@0
|
198 static GT_MSG_HANDLER(gt_msg_messages_supported)
|
paulo@0
|
199 {
|
paulo@0
|
200 gt_vendor_msg_t vmsg;
|
paulo@0
|
201 unsigned char *vendor_id;
|
paulo@0
|
202 int i;
|
paulo@0
|
203 uint16_t id;
|
paulo@0
|
204 uint16_t version;
|
paulo@0
|
205 uint16_t vector_len;
|
paulo@0
|
206
|
paulo@0
|
207 vector_len = gt_packet_get_uint16 (packet);
|
paulo@0
|
208
|
paulo@0
|
209 if (gt_packet_error (packet))
|
paulo@0
|
210 return;
|
paulo@0
|
211
|
paulo@0
|
212 /*
|
paulo@0
|
213 * Track the supported messages in a dataset on this node.
|
paulo@0
|
214 */
|
paulo@0
|
215 for (i = 0; i < vector_len; i++)
|
paulo@0
|
216 {
|
paulo@0
|
217 struct gt_vendor_table *entry;
|
paulo@0
|
218
|
paulo@0
|
219 vendor_id = gt_packet_get_ustr (packet, 4);
|
paulo@0
|
220 id = gt_packet_get_uint16 (packet);
|
paulo@0
|
221 version = gt_packet_get_uint16 (packet);
|
paulo@0
|
222
|
paulo@0
|
223 if (gt_packet_error (packet))
|
paulo@0
|
224 break;
|
paulo@0
|
225
|
paulo@0
|
226 vmsg_init (&vmsg, vendor_id, id);
|
paulo@0
|
227
|
paulo@0
|
228 if (!(entry = find_in_vmsg_table (&vmsg)))
|
paulo@0
|
229 continue;
|
paulo@0
|
230
|
paulo@0
|
231 /* only send the minimum supported by both ends to this node */
|
paulo@0
|
232 version = MIN (version, entry->version);
|
paulo@0
|
233
|
paulo@0
|
234 /* track support for this vendor message */
|
paulo@0
|
235 dataset_insert (&node->vmsgs_supported, &vmsg, sizeof(vmsg),
|
paulo@0
|
236 &version, sizeof(version));
|
paulo@0
|
237 }
|
paulo@0
|
238
|
paulo@0
|
239 /* send our batch of vendor messages now */
|
paulo@0
|
240 gt_bind_completed_connection (node);
|
paulo@0
|
241 }
|
paulo@0
|
242
|
paulo@0
|
243 /*****************************************************************************/
|
paulo@0
|
244
|
paulo@0
|
245 static GT_MSG_HANDLER(gt_msg_hops_flow)
|
paulo@0
|
246 {
|
paulo@0
|
247 }
|
paulo@0
|
248
|
paulo@0
|
249 /*****************************************************************************/
|
paulo@0
|
250
|
paulo@0
|
251 static GT_MSG_HANDLER(gt_msg_tcp_connect_back)
|
paulo@0
|
252 {
|
paulo@0
|
253 in_port_t port;
|
paulo@0
|
254
|
paulo@0
|
255 port = gt_packet_get_port (packet);
|
paulo@0
|
256
|
paulo@0
|
257 if (!port)
|
paulo@0
|
258 return;
|
paulo@0
|
259
|
paulo@0
|
260 gt_connect_test (node, port);
|
paulo@0
|
261 }
|
paulo@0
|
262
|
paulo@0
|
263 /*****************************************************************************/
|
paulo@0
|
264
|
paulo@0
|
265 static GT_MSG_HANDLER(gt_msg_push_proxy_request)
|
paulo@0
|
266 {
|
paulo@0
|
267 return;
|
paulo@0
|
268 }
|
paulo@0
|
269
|
paulo@0
|
270 static GT_MSG_HANDLER(gt_msg_push_proxy_acknowledgement)
|
paulo@0
|
271 {
|
paulo@0
|
272 in_addr_t ip;
|
paulo@0
|
273 in_port_t port;
|
paulo@0
|
274
|
paulo@0
|
275 ip = gt_packet_get_ip (packet);
|
paulo@0
|
276 port = gt_packet_get_port (packet);
|
paulo@0
|
277
|
paulo@0
|
278 if (gt_packet_error (packet))
|
paulo@0
|
279 return;
|
paulo@0
|
280
|
paulo@0
|
281 gt_push_proxy_del (node);
|
paulo@0
|
282 gt_push_proxy_add (node, ip, port);
|
paulo@0
|
283 }
|