Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
comparison src/message/gt_message.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:65a09b76bcd4 |
---|---|
1 /* | |
2 * $Id: gt_message.c,v 1.6 2004/01/07 07:24:43 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 "msg_handler.h" | |
19 | |
20 #include "gt_netorg.h" | |
21 #include "gt_connect.h" | |
22 | |
23 #include "gt_utils.h" | |
24 | |
25 #include "io/rx_stack.h" /* gt_rx_stack_new */ | |
26 #include "io/tx_stack.h" /* gt_tx_stack_new */ | |
27 | |
28 #include "gt_message.h" | |
29 | |
30 /*****************************************************************************/ | |
31 | |
32 extern void gt_vmsg_send_supported (GtNode *node); /* vendor.c */ | |
33 | |
34 /*****************************************************************************/ | |
35 | |
36 extern GT_MSG_HANDLER(gt_msg_ping); | |
37 extern GT_MSG_HANDLER(gt_msg_ping_reply); | |
38 extern GT_MSG_HANDLER(gt_msg_bye); | |
39 extern GT_MSG_HANDLER(gt_msg_push); | |
40 extern GT_MSG_HANDLER(gt_msg_query_route); | |
41 extern GT_MSG_HANDLER(gt_msg_query); | |
42 extern GT_MSG_HANDLER(gt_msg_query_reply); | |
43 extern GT_MSG_HANDLER(gt_msg_vendor); | |
44 | |
45 static struct msg_handler | |
46 { | |
47 uint8_t command; | |
48 GtMessageHandler func; | |
49 } | |
50 msg_handler_table[] = | |
51 { | |
52 /* table listed not in numerical order, but by frequency of messages */ | |
53 { GT_MSG_QUERY, gt_msg_query }, | |
54 { GT_MSG_QUERY_REPLY, gt_msg_query_reply }, | |
55 { GT_MSG_PING_REPLY, gt_msg_ping_reply }, | |
56 { GT_MSG_PING, gt_msg_ping }, | |
57 { GT_MSG_PUSH, gt_msg_push }, | |
58 { GT_MSG_QUERY_ROUTE, gt_msg_query_route }, | |
59 { GT_MSG_VENDOR, gt_msg_vendor }, | |
60 { GT_MSG_VENDOR_STD, gt_msg_vendor }, /* same as non-standard */ | |
61 { GT_MSG_BYE, gt_msg_bye }, | |
62 { 0x00, NULL } | |
63 }; | |
64 | |
65 /*****************************************************************************/ | |
66 | |
67 static BOOL handle_message (TCPC *c, GtPacket *packet) | |
68 { | |
69 struct msg_handler *handler; | |
70 uint8_t command; | |
71 | |
72 if (!packet) | |
73 return FALSE; | |
74 | |
75 command = gt_packet_command (packet); | |
76 | |
77 /* locate the handler */ | |
78 for (handler = msg_handler_table; handler->func; handler++) | |
79 { | |
80 if (command == handler->command) | |
81 { | |
82 handler->func (GT_NODE(c), c, packet); | |
83 return TRUE; | |
84 } | |
85 } | |
86 | |
87 GIFT_ERROR (("[%s] found no handler for cmd %hx, payload %hx", | |
88 net_ip_str (GT_NODE(c)->ip), command, | |
89 gt_packet_payload_len (packet))); | |
90 | |
91 return FALSE; | |
92 } | |
93 | |
94 static void cleanup_node_rx (GtNode *node) | |
95 { | |
96 TCPC *c = GT_CONN(node); | |
97 | |
98 assert (GT_NODE(c) == node); | |
99 gt_node_disconnect (c); | |
100 } | |
101 | |
102 /* TODO: make this the same type as cleanup_node_rx */ | |
103 static void cleanup_node_tx (GtTxStack *stack, GtNode *node) | |
104 { | |
105 TCPC *c = GT_CONN(node); | |
106 | |
107 assert (GT_NODE(c) == node); | |
108 gt_node_disconnect (c); | |
109 } | |
110 | |
111 static void recv_packet (GtNode *node, GtPacket *packet) | |
112 { | |
113 assert (packet != NULL); | |
114 | |
115 gt_packet_log (packet, GT_CONN(node), FALSE); | |
116 (void)handle_message (node->c, packet); | |
117 } | |
118 | |
119 /* Find out what our IP is */ | |
120 static in_addr_t get_self_ip (TCPC *c) | |
121 { | |
122 in_addr_t our_ip; | |
123 char *ip_str; | |
124 | |
125 if ((ip_str = dataset_lookupstr (GT_NODE(c)->hdr, "remote-ip"))) | |
126 { | |
127 /* | |
128 * Since we may be firewalled, we may not know what our ip is. So set | |
129 * the ip from what the other node thinks it is. | |
130 * | |
131 * Doing this allows you to setup port forwarding on a firewall | |
132 * and accept incoming connections. | |
133 */ | |
134 our_ip = net_ip (ip_str); | |
135 } | |
136 else | |
137 { | |
138 struct sockaddr_in saddr; | |
139 int len = sizeof (saddr); | |
140 | |
141 if (getsockname (c->fd, (struct sockaddr *)&saddr, &len) == 0) | |
142 our_ip = saddr.sin_addr.s_addr; | |
143 else | |
144 our_ip = net_ip ("127.0.0.1"); | |
145 } | |
146 | |
147 return our_ip; | |
148 } | |
149 | |
150 /* | |
151 * Begin a node connection with the peer on the specified TCPC. | |
152 * | |
153 * We arrive here from either an incoming or outgoing connection. | |
154 * This is the entrance point to the main packet-reading loop. | |
155 * | |
156 * After setting up the connection, we send the node a ping. | |
157 * If it doesn't respond after a timeout, we will destroy the | |
158 * connection. | |
159 */ | |
160 void gnutella_start_connection (int fd, input_id id, TCPC *c) | |
161 { | |
162 GtPacket *ping; | |
163 GtNode *node; | |
164 | |
165 node = GT_NODE(c); | |
166 assert (GT_CONN(node) == c); | |
167 | |
168 /* remove the old input handler first -- need to before sending data */ | |
169 input_remove (id); | |
170 | |
171 if (net_sock_error (c->fd)) | |
172 { | |
173 if (HANDSHAKE_DEBUG) | |
174 gt_node_error (c, NULL); | |
175 | |
176 gt_node_disconnect (c); | |
177 return; | |
178 } | |
179 | |
180 /* if this is the crawler, disconnect */ | |
181 if (dataset_lookupstr (GT_NODE(c)->hdr, "crawler")) | |
182 { | |
183 if (HANDSHAKE_DEBUG) | |
184 GT->DBGSOCK (GT, c, "closing crawler connection"); | |
185 | |
186 gt_node_disconnect (c); | |
187 return; | |
188 } | |
189 | |
190 if (!(node->rx_stack = gt_rx_stack_new (node, c, node->rx_inflated))) | |
191 { | |
192 if (HANDSHAKE_DEBUG) | |
193 GT->DBGSOCK (GT, c, "error allocating rx_stack"); | |
194 | |
195 gt_node_disconnect (c); | |
196 return; | |
197 } | |
198 | |
199 if (!(node->tx_stack = gt_tx_stack_new (c, node->tx_deflated))) | |
200 { | |
201 if (HANDSHAKE_DEBUG) | |
202 GT->DBGSOCK (GT, c, "error allocating tx stack"); | |
203 | |
204 gt_node_disconnect (c); | |
205 return; | |
206 } | |
207 | |
208 /* determine the other node's opinion of our IP address */ | |
209 node->my_ip = get_self_ip (c); | |
210 | |
211 /* determine the other ends port */ | |
212 peer_addr (c->fd, NULL, &node->peer_port); | |
213 | |
214 if (HANDSHAKE_DEBUG) | |
215 { | |
216 GT->DBGSOCK (GT, c, "self IP=[%s]", net_ip_str (node->my_ip)); | |
217 GT->DBGSOCK (GT, c, "peer port=%hu", node->peer_port); | |
218 } | |
219 | |
220 if (!(ping = gt_packet_new (GT_MSG_PING, 1, NULL))) | |
221 { | |
222 gt_node_disconnect (c); | |
223 return; | |
224 } | |
225 | |
226 /* set the state as intermediately connecting and mark the node connected | |
227 * only when it replies to our ping */ | |
228 gt_node_state_set (node, GT_NODE_CONNECTING_2); | |
229 | |
230 /* give the connection some more time */ | |
231 gnutella_set_handshake_timeout (c, TIMEOUT_3 * SECONDS); | |
232 | |
233 /* | |
234 * Setup our packet handlers, for both receiving and sending packets. | |
235 */ | |
236 gt_rx_stack_set_handler (node->rx_stack, | |
237 (GtRxStackHandler)recv_packet, | |
238 (GtRxStackCleanup)cleanup_node_rx, | |
239 node); | |
240 | |
241 gt_tx_stack_set_handler (node->tx_stack, | |
242 (GtTxStackCleanup)cleanup_node_tx, | |
243 node); | |
244 | |
245 /* send first ping */ | |
246 gt_packet_send (c, ping); | |
247 gt_packet_free (ping); | |
248 | |
249 /* send MessagesSupported Vendor message, if this node supports it */ | |
250 gt_vmsg_send_supported (node); | |
251 } |