rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * $Id: push.c,v 1.3 2004/03/24 06:36:12 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 "msg_handler.h"
|
paulo@0
|
19
|
paulo@0
|
20 #include "gt_accept.h"
|
paulo@0
|
21 #include "gt_share_file.h"
|
paulo@0
|
22 #include "gt_share.h"
|
paulo@0
|
23
|
paulo@0
|
24 /*****************************************************************************/
|
paulo@0
|
25
|
paulo@0
|
26 typedef struct giv_connect
|
paulo@0
|
27 {
|
paulo@0
|
28 uint32_t index;
|
paulo@0
|
29 char *filename;
|
paulo@0
|
30 } giv_connect_t;
|
paulo@0
|
31
|
paulo@0
|
32 /*****************************************************************************/
|
paulo@0
|
33
|
paulo@0
|
34 static giv_connect_t *giv_connect_alloc (uint32_t index, const char *filename)
|
paulo@0
|
35 {
|
paulo@0
|
36 giv_connect_t *giv;
|
paulo@0
|
37
|
paulo@0
|
38 if (!(giv = malloc (sizeof(giv_connect_t))))
|
paulo@0
|
39 return NULL;
|
paulo@0
|
40
|
paulo@0
|
41 if (filename)
|
paulo@0
|
42 giv->filename = STRDUP (filename);
|
paulo@0
|
43 else
|
paulo@0
|
44 giv->filename = NULL;
|
paulo@0
|
45
|
paulo@0
|
46 giv->index = index;
|
paulo@0
|
47
|
paulo@0
|
48 return giv;
|
paulo@0
|
49 }
|
paulo@0
|
50
|
paulo@0
|
51 static void giv_connect_free (giv_connect_t *giv)
|
paulo@0
|
52 {
|
paulo@0
|
53 if (!giv)
|
paulo@0
|
54 return;
|
paulo@0
|
55
|
paulo@0
|
56 free (giv->filename);
|
paulo@0
|
57 free (giv);
|
paulo@0
|
58 }
|
paulo@0
|
59
|
paulo@0
|
60 static char *giv_connect_str (giv_connect_t *giv)
|
paulo@0
|
61 {
|
paulo@0
|
62 String *s;
|
paulo@0
|
63
|
paulo@0
|
64 if (!(s = string_new (NULL, 0, 0, TRUE)))
|
paulo@0
|
65 return NULL;
|
paulo@0
|
66
|
paulo@0
|
67 string_append (s, "GIV ");
|
paulo@0
|
68 string_appendf (s, "%u:", giv->index);
|
paulo@0
|
69 string_appendf (s, "%s/", gt_guid_str (GT_SELF_GUID));
|
paulo@0
|
70
|
paulo@0
|
71 if (giv->filename && !string_isempty (giv->filename))
|
paulo@0
|
72 string_append (s, giv->filename);
|
paulo@0
|
73
|
paulo@0
|
74 string_append (s, "\n\n");
|
paulo@0
|
75
|
paulo@0
|
76 return string_free_keep (s);
|
paulo@0
|
77 }
|
paulo@0
|
78
|
paulo@0
|
79 /*****************************************************************************/
|
paulo@0
|
80
|
paulo@0
|
81 static void handle_giv_connect (int fd, input_id id, TCPC *c,
|
paulo@0
|
82 giv_connect_t *giv)
|
paulo@0
|
83 {
|
paulo@0
|
84 char *str;
|
paulo@0
|
85 int ret;
|
paulo@0
|
86
|
paulo@0
|
87 if (MSG_DEBUG)
|
paulo@0
|
88 GT->DBGFN (GT, "entered");
|
paulo@0
|
89
|
paulo@0
|
90 if (net_sock_error (fd))
|
paulo@0
|
91 {
|
paulo@0
|
92 if (MSG_DEBUG)
|
paulo@0
|
93 GT->DBGFN (GT, "error connecting back: %s", GIFT_NETERROR ());
|
paulo@0
|
94
|
paulo@0
|
95 tcp_close (c);
|
paulo@0
|
96 return;
|
paulo@0
|
97 }
|
paulo@0
|
98
|
paulo@0
|
99 /* restore the index */
|
paulo@0
|
100 c->udata = NULL;
|
paulo@0
|
101 str = giv_connect_str (giv);
|
paulo@0
|
102
|
paulo@0
|
103 if (MSG_DEBUG)
|
paulo@0
|
104 GT->DBGSOCK (GT, c, "sending GIV response: %s", str);
|
paulo@0
|
105
|
paulo@0
|
106 ret = tcp_send (c, str, strlen (str));
|
paulo@0
|
107 free (str);
|
paulo@0
|
108
|
paulo@0
|
109 if (ret <= 0)
|
paulo@0
|
110 {
|
paulo@0
|
111 if (MSG_DEBUG)
|
paulo@0
|
112 GT->DBGFN (GT, "error sending: %s", GIFT_NETERROR ());
|
paulo@0
|
113
|
paulo@0
|
114 tcp_close (c);
|
paulo@0
|
115 return;
|
paulo@0
|
116 }
|
paulo@0
|
117
|
paulo@0
|
118 /* use this connection for something */
|
paulo@0
|
119 input_remove (id);
|
paulo@0
|
120 input_add (c->fd, c, INPUT_READ,
|
paulo@0
|
121 (InputCallback)gt_handshake_dispatch_incoming, TIMEOUT_DEF);
|
paulo@0
|
122 }
|
paulo@0
|
123
|
paulo@0
|
124 static void giv_connect (int fd, input_id id, TCPC *c)
|
paulo@0
|
125 {
|
paulo@0
|
126 giv_connect_t *giv;
|
paulo@0
|
127
|
paulo@0
|
128 giv = c->udata;
|
paulo@0
|
129 handle_giv_connect (fd, id, c, giv);
|
paulo@0
|
130
|
paulo@0
|
131 giv_connect_free (giv);
|
paulo@0
|
132 }
|
paulo@0
|
133
|
paulo@0
|
134 static void gt_giv_request (GtNode *src, uint32_t index, in_addr_t ip,
|
paulo@0
|
135 in_port_t port, uint8_t hops)
|
paulo@0
|
136 {
|
paulo@0
|
137 giv_connect_t *giv;
|
paulo@0
|
138 char *filename = NULL;
|
paulo@0
|
139 Share *share;
|
paulo@0
|
140 GtShare *gt_share;
|
paulo@0
|
141 TCPC *c;
|
paulo@0
|
142
|
paulo@0
|
143 if (MSG_DEBUG)
|
paulo@0
|
144 GT->DBGFN (GT, "entered");
|
paulo@0
|
145
|
paulo@0
|
146 /* if the pushed IP address is local, forget about it */
|
paulo@0
|
147 if (gt_is_local_ip (ip, src->ip))
|
paulo@0
|
148 return;
|
paulo@0
|
149
|
paulo@0
|
150 /* special case: if the node we got the giv from is local
|
paulo@0
|
151 * and the giv is from them (hops=0), don't connect to the
|
paulo@0
|
152 * external address but the internal */
|
paulo@0
|
153 if (hops == 0 && gt_is_local_ip (src->ip, ip))
|
paulo@0
|
154 ip = src->ip;
|
paulo@0
|
155
|
paulo@0
|
156 /*
|
paulo@0
|
157 * Look for the index in the local shared database, if it is found
|
paulo@0
|
158 * keep track of the filename.
|
paulo@0
|
159 */
|
paulo@0
|
160 if ((share = gt_share_local_lookup_by_index (index, NULL)) != NULL &&
|
paulo@0
|
161 (gt_share = share_get_udata (share, GT->name)) != NULL)
|
paulo@0
|
162 {
|
paulo@0
|
163 filename = gt_share->filename;
|
paulo@0
|
164 }
|
paulo@0
|
165
|
paulo@0
|
166 if (!(giv = giv_connect_alloc (index, filename)))
|
paulo@0
|
167 return;
|
paulo@0
|
168
|
paulo@0
|
169 if (!(c = tcp_open (ip, port, FALSE)))
|
paulo@0
|
170 {
|
paulo@0
|
171 giv_connect_free (giv);
|
paulo@0
|
172 return;
|
paulo@0
|
173 }
|
paulo@0
|
174
|
paulo@0
|
175 c->udata = giv;
|
paulo@0
|
176
|
paulo@0
|
177 input_add (c->fd, c, INPUT_WRITE,
|
paulo@0
|
178 (InputCallback)giv_connect, TIMEOUT_DEF);
|
paulo@0
|
179 }
|
paulo@0
|
180
|
paulo@0
|
181 GT_MSG_HANDLER(gt_msg_push)
|
paulo@0
|
182 {
|
paulo@0
|
183 gt_guid_t *client_guid;
|
paulo@0
|
184 uint32_t index;
|
paulo@0
|
185 uint32_t ip;
|
paulo@0
|
186 uint16_t port;
|
paulo@0
|
187 uint8_t hops;
|
paulo@0
|
188
|
paulo@0
|
189 if (MSG_DEBUG)
|
paulo@0
|
190 GT->DBGFN (GT, "entered");
|
paulo@0
|
191
|
paulo@0
|
192 client_guid = gt_packet_get_ustr (packet, 16);
|
paulo@0
|
193 index = gt_packet_get_uint32 (packet);
|
paulo@0
|
194 ip = gt_packet_get_ip (packet);
|
paulo@0
|
195 port = gt_packet_get_port (packet);
|
paulo@0
|
196
|
paulo@0
|
197 hops = gt_packet_hops (packet);
|
paulo@0
|
198
|
paulo@0
|
199 if (MSG_DEBUG)
|
paulo@0
|
200 {
|
paulo@0
|
201 GT->DBGSOCK (GT, c, "client_guid=%s index=%d ip=%s port=%hu",
|
paulo@0
|
202 gt_guid_str (client_guid), index, net_ip_str (ip), port);
|
paulo@0
|
203 }
|
paulo@0
|
204
|
paulo@0
|
205 if (gt_guid_cmp (client_guid, GT_SELF_GUID) == 0)
|
paulo@0
|
206 {
|
paulo@0
|
207 /* TODO: we should not respond if we get a lot of these */
|
paulo@0
|
208 gt_giv_request (GT_NODE(c), index, ip, port, hops);
|
paulo@0
|
209 return;
|
paulo@0
|
210 }
|
paulo@0
|
211
|
paulo@0
|
212 #if 0
|
paulo@0
|
213 if ((dst_c = push_cache_lookup (client->guid)))
|
paulo@0
|
214 gt_route_forward_packet (dst_c, packet);
|
paulo@0
|
215 #endif
|
paulo@0
|
216 }
|