Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
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 } |