source: branches/encryption/libtransmission/peer-connection.c @ 2936

Last change on this file since 2936 was 2936, checked in by charles, 15 years ago

not ready for use yet -- this is a periodic checkin so I don't lose my changes. Outgoing connections work for plaintext, encrypted, and encrypted connections that prefer plaintext. Incoming connections don't work yet. Handshakes aren't wired in to the rest of the peer code yet.

  • Property svn:keywords set to Date Rev Author Id
File size: 7.2 KB
Line 
1/*
2 * This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id:$
11 */
12
13#include <assert.h>
14#include <string.h>
15#include <stdio.h>
16#include <unistd.h>
17#include <arpa/inet.h>
18#include <event.h>
19#include "transmission.h"
20#include "encryption.h"
21#include "net.h"
22#include "peer-connection.h"
23#include "trevent.h"
24#include "utils.h"
25
26/**
27***
28**/
29
30struct tr_peerConnection
31{
32    struct tr_handle * handle;
33    struct tr_torrent * torrent;
34
35    struct in_addr in_addr;
36    int port;
37    int socket;
38    int extensions;
39    struct bufferevent * bufev;
40    uint8_t peerId[20];
41
42    unsigned int isEncrypted : 1;
43    unsigned int isIncoming : 1;
44    unsigned int peerIdIsSet : 1;
45
46    tr_can_read_cb     canRead;
47    tr_did_write_cb    didWrite;
48    tr_net_error_cb    gotError;
49    void             * userData;
50
51    tr_encryption * encryption;
52};
53
54/**
55***
56**/
57
58static void
59didWriteWrapper( struct bufferevent * e, void * userData )
60{
61    tr_peerConnection * c = (tr_peerConnection *) userData;
62    assert( c->didWrite != NULL );
63    (*c->didWrite)( e, c->userData );
64}
65
66static void
67canReadWrapper( struct bufferevent * e, void * userData )
68{
69    tr_peerConnection * c = (tr_peerConnection *) userData;
70
71    assert( c->canRead != NULL );
72
73    for( ;; ) {
74        const int ret = (*c->canRead)( e, c->userData );
75        switch( ret ) {
76            case READ_DONE: return;
77            case READ_AGAIN: continue;
78            case READ_MORE: tr_peerConnectionSetIOMode( c, EV_READ ); return;
79        }
80    }
81}
82
83static void
84gotErrorWrapper( struct bufferevent * e, short what, void * userData )
85{
86    tr_peerConnection * c = (tr_peerConnection *) userData;
87    assert( c->gotError != NULL );
88    (*c->gotError)( e, what, c->userData );
89}
90
91/**
92***
93**/
94
95static tr_peerConnection*
96tr_peerConnectionNew( struct tr_handle  * handle,
97                      struct in_addr    * in_addr,
98                      struct tr_torrent * torrent,
99                      int                 isIncoming,
100                      int                 socket )
101{
102    tr_peerConnection * c;
103    c = tr_new0( tr_peerConnection, 1 );
104    c->torrent = torrent;
105    c->encryption = tr_encryptionNew( torrent ? torrent->info.hash : NULL, isIncoming );
106    c->handle = handle;
107    c->in_addr = *in_addr;
108    c->socket = socket;
109    c->bufev = bufferevent_new( c->socket,
110                                canReadWrapper,
111                                didWriteWrapper,
112                                gotErrorWrapper,
113                                c );
114    return c;
115}
116
117tr_peerConnection*
118tr_peerConnectionNewIncoming( struct tr_handle  * handle,
119                              struct in_addr    * in_addr,
120                              int                 socket )
121{
122    tr_peerConnection * c =
123        tr_peerConnectionNew( handle, in_addr, NULL, 1, socket );
124    c->port = -1;
125    return c;
126}
127
128tr_peerConnection*
129tr_peerConnectionNewOutgoing( struct tr_handle  * handle,
130                              struct in_addr    * in_addr,
131                              int                 port,
132                              struct tr_torrent * torrent )
133{
134    tr_peerConnection * c;
135
136    assert( handle != NULL );
137    assert( in_addr != NULL );
138    assert( port >= 0 );
139    assert( torrent != NULL );
140
141    c = tr_peerConnectionNew( handle, in_addr, torrent, 0,
142                              tr_netOpenTCP( in_addr, port, 0 ) );
143    c->port = port;
144    return c;
145}
146
147void
148tr_peerConnectionFree( tr_peerConnection * c )
149{
150    bufferevent_free( c->bufev );
151    tr_netClose( c->socket );
152    tr_encryptionFree( c->encryption );
153    tr_free( c );
154}
155
156void 
157tr_peerConnectionSetIOFuncs( tr_peerConnection  * connection,
158                             tr_can_read_cb       readcb,
159                             tr_did_write_cb      writecb,
160                             tr_net_error_cb      errcb,
161                             void               * userData )
162{
163    connection->canRead = readcb;
164    connection->didWrite = writecb;
165    connection->gotError = errcb;
166    connection->userData = userData;
167}
168
169void
170tr_peerConnectionSetIOMode( tr_peerConnection * c, short mode )
171{
172    tr_setBufferEventMode( c->handle, c->bufev, mode );
173}
174
175void
176tr_peerConnectionReadOrWait( tr_peerConnection * c )
177{
178    if( EVBUFFER_LENGTH( c->bufev->input ) )
179        canReadWrapper( c->bufev, c );
180    else
181        tr_peerConnectionSetIOMode( c, EV_READ );
182}
183
184int
185tr_peerConnectionIsIncoming( const tr_peerConnection * c )
186{
187    return c->isIncoming;
188}
189
190int
191tr_peerConnectionReconnect( tr_peerConnection * connection )
192{
193    assert( !tr_peerConnectionIsIncoming( connection ) );
194
195    if( connection->socket >= 0 )
196        tr_netClose( connection->socket );
197
198    connection->socket = tr_netOpenTCP( &connection->in_addr,
199                                        connection->port, 0 );
200
201    return connection->socket >= 0 ? 0 : -1;
202}
203
204
205tr_encryption* 
206tr_peerConnectionGetEncryption( tr_peerConnection * c )
207{
208    return c->encryption;
209}
210
211/**
212***
213**/
214
215void
216tr_peerConnectionWrite( tr_peerConnection   * connection,
217                        const void          * writeme,
218                        int                   writeme_len )
219{
220    tr_bufferevent_write( connection->handle,
221                          connection->bufev,
222                          writeme,
223                          writeme_len );
224}
225
226void
227tr_peerConnectionWriteBuf  ( tr_peerConnection   * connection,
228                             struct evbuffer     * buf )
229{
230    tr_peerConnectionWrite( connection,
231                            EVBUFFER_DATA(buf),
232                            EVBUFFER_LENGTH(buf) );
233}
234
235/**
236***
237**/
238
239void
240tr_peerConnectionSetTorrent( tr_peerConnection  * connection,
241                             struct tr_torrent  * torrent )
242{
243    connection->torrent = torrent;
244
245    tr_encryptionSetTorrentHash( connection->encryption, torrent->info.hash );
246}
247
248struct tr_torrent*
249tr_peerConnectionGetTorrent( tr_peerConnection * connection )
250{
251    return connection->torrent;
252}
253
254/**
255***
256**/
257
258void
259tr_peerConnectionSetPeersId( tr_peerConnection * connection,
260                             const uint8_t     * peer_id )
261{
262    assert( connection != NULL );
263
264    if(( connection->peerIdIsSet = peer_id != NULL ))
265        memcpy( connection->peerId, peer_id, 20 );
266    else
267        memset( connection->peerId, 0, 20 );
268}
269
270const uint8_t* 
271tr_peerConnectionGetPeersId( const tr_peerConnection * connection )
272{
273    assert( connection != NULL );
274    assert( connection->peerIdIsSet );
275
276    return connection->peerId;
277}
278
279/**
280***
281**/
282
283void
284tr_peerConnectionSetExtension( tr_peerConnection * connection,
285                               int                 extensions )
286{
287    assert( connection != NULL );
288    assert( ( extensions == LT_EXTENSIONS_NONE )
289         || ( extensions == LT_EXTENSIONS_LTEP )
290         || ( extensions == LT_EXTENSIONS_AZMP ) );
291
292    connection->extensions = extensions;
293}
294
295int
296tr_peerConnectionGetExtension( const tr_peerConnection * connection )
297{
298    assert( connection != NULL );
299
300    return connection->extensions;
301}
Note: See TracBrowser for help on using the repository browser.