comparison src/message/vendor.c @ 0:d39e1d0d75b6

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