source: trunk/libtransmission/tr-utp.c @ 11961

Last change on this file since 11961 was 11961, checked in by jordan, 11 years ago

(trunk libT) add a stub for UTP_Close() s.t. peer-mgr.c doesn't need the #ifdefs from r11960

File size: 5.1 KB
Line 
1/*
2Copyright (c) 2010 by Juliusz Chroboczek
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.
21
22*/
23
24#include <assert.h>
25#include <unistd.h>
26
27#include <event.h>
28#include <libutp/utp.h>
29
30#include "transmission.h"
31#include "net.h"
32#include "session.h"
33#include "crypto.h"
34#include "peer-io.h"
35#include "peer-mgr.h"
36#include "tr-utp.h"
37#include "utils.h"
38
39#define MY_NAME "UTP"
40
41#define dbgmsg( ... ) \
42    do { \
43        if( tr_deepLoggingIsActive( ) ) \
44            tr_deepLog( __FILE__, __LINE__, MY_NAME, __VA_ARGS__ ); \
45    } while( 0 )
46
47#ifndef WITH_UTP
48
49void
50UTP_Close(struct UTPSocket * socket )
51{
52    tr_nerr( MY_NAME, "UTP_Close(%p) was called.", socket );
53    dbgmsg( "UTP_Close(%p) was called.", socket );
54    assert( 0 ); /* FIXME: this is too much for the long term, but probably needed in the short term */
55}
56
57int tr_utpPacket(const unsigned char *buf UNUSED, size_t buflen UNUSED,
58                 const struct sockaddr *from UNUSED, socklen_t fromlen UNUSED,
59                 tr_session *ss UNUSED) { return -1; }
60
61void tr_utpClose( tr_session * ss UNUSED ) { }
62
63void tr_utpSendTo(void *closure UNUSED,
64                  const unsigned char *buf UNUSED, size_t buflen UNUSED,
65                  const struct sockaddr *to UNUSED, socklen_t tolen UNUSED) { }
66
67#else
68
69/* Greg says 50ms works for them. */
70
71#define UTP_INTERVAL_US 50000
72
73static struct event *utp_timer = NULL;
74
75static void
76incoming(void *closure, struct UTPSocket *s)
77{
78    tr_session *ss = (tr_session*)closure;
79    struct sockaddr_storage from_storage;
80    struct sockaddr *from = (struct sockaddr*)&from_storage;
81    socklen_t fromlen = sizeof(from_storage);
82    tr_address addr;
83    tr_port port;
84
85    if( !tr_sessionIsUTPEnabled(ss) ) {
86        UTP_Close(s);
87        return;
88    }
89   
90    UTP_GetPeerName(s, from, &fromlen);
91    if(from->sa_family == AF_INET) {
92        struct sockaddr_in *sin = (struct sockaddr_in*)from;
93        addr.type = TR_AF_INET;
94        addr.addr.addr4.s_addr = sin->sin_addr.s_addr;
95        port = sin->sin_port;
96    } else if(from->sa_family == AF_INET6) {
97        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)from;
98        addr.type = TR_AF_INET6;
99        addr.addr.addr6 = sin6->sin6_addr;
100        port = sin6->sin6_port;
101    } else {
102        tr_nerr("UTP", "Unknown socket family");
103        UTP_Close(s);
104        return;
105    }
106
107    tr_peerMgrAddIncoming(ss->peerMgr, &addr, port, -1, s);
108}
109
110void
111tr_utpSendTo(void *closure, const unsigned char *buf, size_t buflen,
112             const struct sockaddr *to, socklen_t tolen)
113{
114    tr_session *ss = (tr_session*)closure;
115
116    if(to->sa_family == AF_INET && ss->udp_socket)
117        sendto(ss->udp_socket, buf, buflen, 0, to, tolen);
118    else if(to->sa_family == AF_INET6 && ss->udp_socket)
119        sendto(ss->udp6_socket, buf, buflen, 0, to, tolen);
120}
121
122static void
123reset_timer(tr_session *ss)
124{
125    int sec;
126    int usec;
127    if( tr_sessionIsUTPEnabled( ss ) ) {
128        sec = 0;
129        usec = UTP_INTERVAL_US / 2 + tr_cryptoWeakRandInt(UTP_INTERVAL_US);
130    } else {
131        /* If somebody has disabled uTP, then we still want to run
132           UTP_CheckTimeouts, in order to let closed sockets finish
133           gracefully and so on.  However, since we're not particularly
134           interested in that happening in a timely manner, we might as
135           well use a large timeout. */
136        sec = 2;
137        usec = tr_cryptoWeakRandInt( 1000000 );
138    }
139    tr_timerAdd( utp_timer, sec, usec );
140}
141
142static void
143timer_callback(int s UNUSED, short type UNUSED, void *closure)
144{
145    tr_session *ss = closure;
146    UTP_CheckTimeouts();
147    reset_timer( ss );
148}
149
150int
151tr_utpPacket(const unsigned char *buf, size_t buflen,
152             const struct sockaddr *from, socklen_t fromlen,
153             tr_session *ss)
154{
155    if(utp_timer == NULL)
156    {
157        utp_timer = evtimer_new( ss->event_base, timer_callback, ss );
158        if(utp_timer == NULL)
159            return -1;
160        reset_timer( ss );
161    }
162
163    return UTP_IsIncomingUTP(incoming, tr_utpSendTo, ss,
164                             buf, buflen, from, fromlen);
165}
166
167void
168tr_utpClose( tr_session * session UNUSED )
169{
170    if( utp_timer )
171    {
172        evtimer_del( utp_timer );
173        utp_timer = NULL;
174    }
175}
176
177#endif /* #ifndef WITH_UTP ... else */
Note: See TracBrowser for help on using the repository browser.