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

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

(trunk libT) API cleanup of the tr_address functions to make them more consistent.

This is loosely related to #2910, but only in the sense of laying the groundwork for #2910's fix...

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