~ubuntu-branches/ubuntu/karmic/gtk-gnutella/karmic

« back to all changes in this revision

Viewing changes to src/core/udp.c

  • Committer: Bazaar Package Importer
  • Author(s): Anand Kumria
  • Date: 2005-08-04 11:32:05 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050804113205-q746i4lgo3rtlegn
Tags: 0.95.4-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: udp.c,v 1.23 2005/06/25 01:37:41 daichik Exp $
 
3
 *
 
4
 * Copyright (c) 2004, Raphael Manfredi
 
5
 *
 
6
 *----------------------------------------------------------------------
 
7
 * This file is part of gtk-gnutella.
 
8
 *
 
9
 *  gtk-gnutella is free software; you can redistribute it and/or modify
 
10
 *  it under the terms of the GNU General Public License as published by
 
11
 *  the Free Software Foundation; either version 2 of the License, or
 
12
 *  (at your option) any later version.
 
13
 *
 
14
 *  gtk-gnutella is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 *  GNU General Public License for more details.
 
18
 *
 
19
 *  You should have received a copy of the GNU General Public License
 
20
 *  along with gtk-gnutella; if not, write to the Free Software
 
21
 *  Foundation, Inc.:
 
22
 *      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 *----------------------------------------------------------------------
 
24
 */
 
25
 
 
26
/**
 
27
 * @ingroup core
 
28
 * @file
 
29
 *
 
30
 * Handling UDP datagrams.
 
31
 *
 
32
 * @author Raphael Manfredi
 
33
 * @date 2004
 
34
 */
 
35
 
 
36
#include "common.h"
 
37
 
 
38
RCSID("$Id: udp.c,v 1.23 2005/06/25 01:37:41 daichik Exp $");
 
39
 
 
40
#include "udp.h"
 
41
#include "gmsg.h"
 
42
#include "inet.h"
 
43
#include "nodes.h"
 
44
#include "sockets.h"
 
45
#include "bsched.h"
 
46
#include "gnet_stats.h"
 
47
#include "gnutella.h"
 
48
#include "mq_udp.h"
 
49
#include "routing.h"
 
50
#include "pcache.h"
 
51
#include "ntp.h"
 
52
#include "bogons.h"
 
53
 
 
54
#include "if/gnet_property_priv.h"
 
55
 
 
56
#include "lib/endian.h"
 
57
#include "lib/misc.h"
 
58
#include "lib/override.h"               /* Must be the last header included */
 
59
 
 
60
/**
 
61
 * Look whether the datagram we received is a valid Gnutella packet.
 
62
 */
 
63
static gboolean
 
64
udp_is_valid_gnet(struct gnutella_socket *s)
 
65
{
 
66
        struct gnutella_node *n = node_udp_get_ip_port(s->ip, s->port);
 
67
        struct gnutella_header *head;
 
68
        gchar *msg;
 
69
        guint32 size;                           /**< Payload size, from the Gnutella message */
 
70
 
 
71
        if (s->pos < GTA_HEADER_SIZE) {
 
72
                msg = "Too short";
 
73
                goto not;
 
74
        }
 
75
 
 
76
        head = (struct gnutella_header *) s->buffer;
 
77
        READ_GUINT32_LE(head->size, size);
 
78
 
 
79
        n->header = *head;                                              /* Struct copy */
 
80
        n->size = s->pos - GTA_HEADER_SIZE;             /* Payload size if Gnutella msg */
 
81
 
 
82
        gnet_stats_count_received_header(n);
 
83
        gnet_stats_count_received_payload(n);
 
84
 
 
85
        if (size + GTA_HEADER_SIZE != s->pos) {
 
86
                msg = "Size mismatch";
 
87
                goto not;
 
88
        }
 
89
 
 
90
        /*
 
91
         * We only support a subset of Gnutella message from UDP.  In particular,
 
92
         * messages like HSEP data, BYE or QRP are not expected!
 
93
         */
 
94
 
 
95
        switch (head->function) {
 
96
        case GTA_MSG_INIT:
 
97
        case GTA_MSG_INIT_RESPONSE:
 
98
        case GTA_MSG_VENDOR:
 
99
        case GTA_MSG_STANDARD:
 
100
        case GTA_MSG_PUSH_REQUEST:
 
101
        case GTA_MSG_SEARCH_RESULTS:
 
102
                break;
 
103
        case GTA_MSG_SEARCH:
 
104
                msg = "Queries not yet processed from UDP";
 
105
                goto drop;                      /* XXX don't handle GUESS queries for now */
 
106
        default:
 
107
                msg = "Gnutella message not processed from UDP";
 
108
                goto drop;
 
109
        }
 
110
 
 
111
        return TRUE;
 
112
 
 
113
drop:
 
114
        gnet_stats_count_dropped(n, MSG_DROP_UNEXPECTED);
 
115
        gnet_stats_count_general(GNR_UDP_UNPROCESSED_MESSAGE, 1);
 
116
        goto log;
 
117
 
 
118
not:
 
119
        gnet_stats_count_general(GNR_UDP_ALIEN_MESSAGE, 1);
 
120
        /* FALL THROUGH */
 
121
 
 
122
log:
 
123
        if (udp_debug) {
 
124
                g_warning("got invalid Gnutella packet from UDP (%s): %s",
 
125
                        ip_port_to_gchar(s->ip, s->port), msg);
 
126
                if (s->pos)
 
127
                        dump_hex(stderr, "UDP datagram", s->buffer, s->pos);
 
128
        }
 
129
 
 
130
        return FALSE;
 
131
}
 
132
 
 
133
/**
 
134
 * Notification from the socket layer that we got a new datagram.
 
135
 */
 
136
void
 
137
udp_received(struct gnutella_socket *s)
 
138
{
 
139
        gboolean bogus = FALSE;
 
140
 
 
141
        /*
 
142
         * If reply comes from the NTP port, notify that they're running NTP.
 
143
         */
 
144
 
 
145
        if (s->ip == 0x7f000001 && s->port == NTP_PORT) {       /* from 127.0.0.1:123 */
 
146
                ntp_got_reply(s);
 
147
                return;
 
148
        }
 
149
 
 
150
        /*
 
151
         * This must be regular Gnutella traffic then.
 
152
         */
 
153
 
 
154
        inet_udp_got_incoming(s->ip);
 
155
        bws_udp_count_read(s->pos);
 
156
 
 
157
        /*
 
158
         * If we get traffic from a bogus IP (unroutable), warn, for now.
 
159
         */
 
160
 
 
161
        if (bogons_check(s->ip)) {
 
162
                bogus = TRUE;
 
163
 
 
164
                if (udp_debug) {
 
165
                        g_warning("UDP datagram (%d byte%s) received from bogus IP %s",
 
166
                                (gint) s->pos, s->pos == 1 ? "" : "s", ip_to_gchar(s->ip));
 
167
                }
 
168
                gnet_stats_count_general(GNR_UDP_BOGUS_SOURCE_IP, 1);
 
169
        }
 
170
 
 
171
        if (!udp_is_valid_gnet(s))
 
172
                return;
 
173
 
 
174
        /*
 
175
         * Process message as if it had been received from regular Gnet by
 
176
         * another node, only we'll use a special "pseudo UDP node" as origin.
 
177
         */
 
178
 
 
179
        if (udp_debug > 19)
 
180
                printf("UDP got %s from %s%s\n", gmsg_infostr_full(s->buffer),
 
181
                        bogus ? "BOGUS " : "", ip_port_to_gchar(s->ip, s->port));
 
182
 
 
183
        node_udp_process(s);
 
184
}
 
185
 
 
186
/**
 
187
 * Send a datagram to the specified node, made of `len' bytes from `buf',
 
188
 * forming a valid Gnutella message.
 
189
 */
 
190
void udp_send_msg(gnutella_node_t *n, gpointer buf, gint len)
 
191
{
 
192
        g_assert(NODE_IS_UDP(n));
 
193
 
 
194
        mq_udp_node_putq(n->outq, gmsg_to_pmsg(buf, len), n);
 
195
}
 
196
 
 
197
/**
 
198
 * Send a Gnutella ping to the specified host via UDP, using the
 
199
 * specified MUID.
 
200
 */
 
201
void
 
202
udp_connect_back(guint32 ip, guint16 port, const gchar *muid)
 
203
{
 
204
        struct gnutella_msg_init *m;
 
205
        struct gnutella_node *n = node_udp_get_ip_port(ip, port);
 
206
        guint32 size;
 
207
 
 
208
        if (!udp_active())
 
209
                return;
 
210
 
 
211
        m = build_ping_msg(muid, 1, FALSE, &size);
 
212
 
 
213
        mq_udp_node_putq(n->outq, gmsg_to_pmsg(m, size), n);
 
214
 
 
215
        if (udp_debug > 19)
 
216
                printf("UDP queued connect-back PING %s (%u bytes) to %s\n",
 
217
                        guid_hex_str(muid), size, ip_port_to_gchar(ip, port));
 
218
}
 
219
 
 
220
/**
 
221
 * Send a Gnutella ping to the specified host.
 
222
 */
 
223
void
 
224
udp_send_ping(guint32 ip, guint16 port)
 
225
{
 
226
        struct gnutella_msg_init *m;
 
227
        struct gnutella_node *n = node_udp_get_ip_port(ip, port);
 
228
        guint32 size;
 
229
 
 
230
        if (!udp_active())
 
231
                return;
 
232
 
 
233
        m = build_ping_msg(NULL, 1, FALSE, &size);
 
234
        udp_send_msg(n, m, size);
 
235
}
 
236
 
 
237
/* vi: set ts=4 sw=4 cindent: */