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

Last change on this file since 12094 was 12094, checked in by jordan, 12 years ago

(trunk libT) new function: tr_ssToAddr()

This handles converting the data in a sockaddr_storage to a tr_address + port, and removes redundant code from fdlimit.c and tr-udp.c that previously did this work.

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