annotate src/message/push.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: 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 }