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

Last change on this file since 12954 was 12954, checked in by jordan, 9 years ago

(trunk) #4490 "Transmission 2.40b1 fails to build: undefined references" -- fixed.

File size: 5.6 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
26#include <event2/event.h>
27
28#include "transmission.h"
29#include "net.h"
30#include "session.h"
31#include "crypto.h" /* tr_cryptoWeakRandInt() */
32#include "peer-mgr.h"
33#include "tr-utp.h"
34#include "utils.h"
35
36#define MY_NAME "UTP"
37
38#define dbgmsg( ... ) \
39    do { \
40        if( tr_deepLoggingIsActive( ) ) \
41            tr_deepLog( __FILE__, __LINE__, MY_NAME, __VA_ARGS__ ); \
42    } while( 0 )
43
44#ifndef WITH_UTP
45
46void
47UTP_Close(struct UTPSocket * socket)
48{
49    tr_nerr( MY_NAME, "UTP_Close(%p) was called.", socket );
50    dbgmsg( "UTP_Close(%p) was called.", socket );
51    assert( 0 ); /* FIXME: this is too much for the long term, but probably needed in the short term */
52}
53
54void
55UTP_RBDrained(struct UTPSocket *socket)
56{
57    tr_nerr( MY_NAME, "UTP_RBDrained(%p) was called.", socket );
58    dbgmsg( "UTP_RBDrained(%p) was called.", socket );
59    assert( 0 ); /* FIXME: this is too much for the long term, but probably needed in the short term */
60}
61
62bool
63UTP_Write(struct UTPSocket *socket, size_t count)
64{
65    tr_nerr( MY_NAME, "UTP_RBDrained(%p, %zu) was called.", socket, count );
66    dbgmsg( "UTP_RBDrained(%p, %zu) was called.", socket, count );
67    assert( 0 ); /* FIXME: this is too much for the long term, but probably needed in the short term */
68    return false;
69}
70
71int tr_utpPacket(const unsigned char *buf UNUSED, size_t buflen UNUSED,
72                 const struct sockaddr *from UNUSED, socklen_t fromlen UNUSED,
73                 tr_session *ss UNUSED) { return -1; }
74
75struct UTPSocket *UTP_Create(SendToProc *send_to_proc UNUSED,
76                             void *send_to_userdata UNUSED,
77                             const struct sockaddr *addr UNUSED,
78                             socklen_t addrlen UNUSED)
79{
80    errno = ENOSYS;
81    return NULL;
82}
83
84void tr_utpClose( tr_session * ss UNUSED ) { }
85
86void tr_utpSendTo(void *closure UNUSED,
87                  const unsigned char *buf UNUSED, size_t buflen UNUSED,
88                  const struct sockaddr *to UNUSED, socklen_t tolen UNUSED) { }
89
90#else
91
92/* Greg says 50ms works for them. */
93
94#define UTP_INTERVAL_US 50000
95
96static struct event *utp_timer = NULL;
97
98static void
99incoming(void *closure, struct UTPSocket *s)
100{
101    tr_session *ss = closure;
102    struct sockaddr_storage from_storage;
103    struct sockaddr *from = (struct sockaddr*)&from_storage;
104    socklen_t fromlen = sizeof(from_storage);
105    tr_address addr;
106    tr_port port;
107
108    if( !tr_sessionIsUTPEnabled(ss) ) {
109        UTP_Close(s);
110        return;
111    }
112
113    UTP_GetPeerName(s, from, &fromlen);
114    if( !tr_address_from_sockaddr_storage( &addr, &port, &from_storage ) )
115    {
116        tr_nerr("UTP", "Unknown socket family");
117        UTP_Close(s);
118        return;
119    }
120
121    tr_peerMgrAddIncoming(ss->peerMgr, &addr, port, -1, s);
122}
123
124void
125tr_utpSendTo(void *closure, const unsigned char *buf, size_t buflen,
126             const struct sockaddr *to, socklen_t tolen)
127{
128    tr_session *ss = closure;
129
130    if(to->sa_family == AF_INET && ss->udp_socket)
131        sendto(ss->udp_socket, buf, buflen, 0, to, tolen);
132    else if(to->sa_family == AF_INET6 && ss->udp_socket)
133        sendto(ss->udp6_socket, buf, buflen, 0, to, tolen);
134}
135
136static void
137reset_timer(tr_session *ss)
138{
139    int sec;
140    int usec;
141    if( tr_sessionIsUTPEnabled( ss ) ) {
142        sec = 0;
143        usec = UTP_INTERVAL_US / 2 + tr_cryptoWeakRandInt(UTP_INTERVAL_US);
144    } else {
145        /* If somebody has disabled uTP, then we still want to run
146           UTP_CheckTimeouts, in order to let closed sockets finish
147           gracefully and so on.  However, since we're not particularly
148           interested in that happening in a timely manner, we might as
149           well use a large timeout. */
150        sec = 2;
151        usec = tr_cryptoWeakRandInt( 1000000 );
152    }
153    tr_timerAdd( utp_timer, sec, usec );
154}
155
156static void
157timer_callback(int s UNUSED, short type UNUSED, void *closure)
158{
159    tr_session *ss = closure;
160    UTP_CheckTimeouts();
161    reset_timer( ss );
162}
163
164int
165tr_utpPacket(const unsigned char *buf, size_t buflen,
166             const struct sockaddr *from, socklen_t fromlen,
167             tr_session *ss)
168{
169    if( !ss->isClosed && !utp_timer )
170    {
171        utp_timer = evtimer_new( ss->event_base, timer_callback, ss );
172        if(utp_timer == NULL)
173            return -1;
174        reset_timer( ss );
175    }
176
177    return UTP_IsIncomingUTP(incoming, tr_utpSendTo, ss,
178                             buf, buflen, from, fromlen);
179}
180
181void
182tr_utpClose( tr_session * session UNUSED )
183{
184    if( utp_timer )
185    {
186        evtimer_del( utp_timer );
187        utp_timer = NULL;
188    }
189}
190
191#endif /* #ifndef WITH_UTP ... else */
Note: See TracBrowser for help on using the repository browser.