annotate 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
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 }