view 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
line source
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 */
17 #include "gt_gnutella.h"
18 #include "message/msg_handler.h"
20 #include "gt_connect.h" /* gt_connect_test */
21 #include "gt_bind.h"
23 #include "gt_utils.h" /* make_str */
25 #include "transfer/push_proxy.h"
27 /*****************************************************************************/
29 #define EMPTY_VENDOR { 0, 0, 0, 0 }
31 #define vmsg_name(name) \
32 name##_struct
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;
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);
45 /*****************************************************************************/
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);
53 /*****************************************************************************/
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 };
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 };
77 static const size_t nr_vmsgs = sizeof(vendor_table) / sizeof(vendor_table[0]);
79 /*****************************************************************************/
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));
87 memcpy (&msg->vendor_id, vendor_id, 4);
88 msg->id = id;
89 }
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 }
99 void gt_vmsg_send_supported (GtNode *node)
100 {
101 GtPacket *pkt;
102 int i;
103 uint16_t vector_len = 0;
105 if (!dataset_lookupstr (node->hdr, "vendor-message"))
106 return;
108 if (!(pkt = gt_packet_vendor (GT_VMSG_MESSAGES_SUPP)))
109 return;
111 gt_packet_put_uint16 (pkt, 0);
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 }
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);
126 if (gt_packet_error (pkt))
127 {
128 gt_packet_free (pkt);
129 return;
130 }
132 GT->DBGSOCK (GT, GT_CONN(node), "sending MessagesSupported");
134 gt_packet_send (GT_CONN(node), pkt);
135 gt_packet_free (pkt);
136 }
138 /*****************************************************************************/
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;
148 if (gt_packet_hops (packet) != 0 && gt_packet_ttl (packet) != 1)
149 return;
151 vendor = gt_packet_get_ustr (packet, 4);
152 id = gt_packet_get_uint16 (packet);
153 version = gt_packet_get_uint16 (packet);
155 /* initialize a copy for making a single call to memcmp */
156 vmsg_init (&vmsg, vendor, id);
158 if (gt_packet_error (packet))
159 {
160 if (MSG_DEBUG)
161 GT->DBGSOCK (GT, c, "Error parsing vendor message");
163 return;
164 }
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 }
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 }
183 /*****************************************************************************/
185 static struct gt_vendor_table *find_in_vmsg_table (gt_vendor_msg_t *vmsg)
186 {
187 int i;
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 }
195 return NULL;
196 }
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;
207 vector_len = gt_packet_get_uint16 (packet);
209 if (gt_packet_error (packet))
210 return;
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;
219 vendor_id = gt_packet_get_ustr (packet, 4);
220 id = gt_packet_get_uint16 (packet);
221 version = gt_packet_get_uint16 (packet);
223 if (gt_packet_error (packet))
224 break;
226 vmsg_init (&vmsg, vendor_id, id);
228 if (!(entry = find_in_vmsg_table (&vmsg)))
229 continue;
231 /* only send the minimum supported by both ends to this node */
232 version = MIN (version, entry->version);
234 /* track support for this vendor message */
235 dataset_insert (&node->vmsgs_supported, &vmsg, sizeof(vmsg),
236 &version, sizeof(version));
237 }
239 /* send our batch of vendor messages now */
240 gt_bind_completed_connection (node);
241 }
243 /*****************************************************************************/
245 static GT_MSG_HANDLER(gt_msg_hops_flow)
246 {
247 }
249 /*****************************************************************************/
251 static GT_MSG_HANDLER(gt_msg_tcp_connect_back)
252 {
253 in_port_t port;
255 port = gt_packet_get_port (packet);
257 if (!port)
258 return;
260 gt_connect_test (node, port);
261 }
263 /*****************************************************************************/
265 static GT_MSG_HANDLER(gt_msg_push_proxy_request)
266 {
267 return;
268 }
270 static GT_MSG_HANDLER(gt_msg_push_proxy_acknowledgement)
271 {
272 in_addr_t ip;
273 in_port_t port;
275 ip = gt_packet_get_ip (packet);
276 port = gt_packet_get_port (packet);
278 if (gt_packet_error (packet))
279 return;
281 gt_push_proxy_del (node);
282 gt_push_proxy_add (node, ip, port);
283 }