1 /***************************************************************************
3 * Copyright (C) 2006 David Brodsky *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation and appearing *
8 * in the file LICENSE.GPL included in the packaging of this file. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 * General Public License for more details. *
15 ***************************************************************************/
17 #include <arpa/inet.h>
19 #include <tairon/core/log.h>
20 #include <tairon/core/thread.h>
21 #include <tairon/net/ireader.h>
22 #include <tairon/net/limiter.h>
23 #include <tairon/net/socket.h>
24 #include <tairon/net/swriter.h>
25 #include <tairon/net/timer.h>
27 #include "connection.h"
29 #include "core/bencode.h"
30 #include "core/bitfield.h"
31 #include "ratemeasurer.h"
33 #include "torrentclient.h"
34 #include "torrentmanager.h"
35 #include "torrentserver.h"
43 const unsigned int handshakeLength
= 48; // without peer id
44 const char *protocolName
= "BitTorrent protocol";
46 Tairon::Net::Limiter
*rlimiter
= 0;
47 Tairon::Net::Limiter
*wlimiter
= 0;
49 /* {{{ Connection::Connection(int) */
50 Connection::Connection(int fd
) : bitfield(0), choked(true), client(0), commandReader(0), deleteReader(true), interested(false), lastPieceTime(0), lengthReader(0), peerChoked(true), peerInterested(false), pieceReaders(0), pieceWriters(0), reader(0)
52 socket
= new Tairon::Net::Socket(fd
);
55 incomingRate
= new RateMeasurer(10);
56 outgoingRate
= new RateMeasurer(10);
60 /* {{{ Connection::Connection(const String &, uint16_t, const String &, TorrentClient *) */
61 Connection::Connection(const String
&ip
, uint16_t port
, const String
&pID
, TorrentClient
*c
) : bitfield(0), choked(true), client(c
), commandReader(0), deleteReader(true), interested(false), lastPieceTime(0), lengthReader(0), peerChoked(true), peerID(pID
), peerInterested(false), pieceReaders(0), pieceWriters(0), reader(0)
63 Tairon::Core::Thread
*current
= Tairon::Core::Thread::current();
65 socket
= new Tairon::Net::Socket(Tairon::Net::Socket::Stream
);
66 socket
->connectedSignal
.connect(Tairon::Core::threadMethodDFunctor(current
, this, &Connection::socketConnected
));
67 socket
->errorSignal
.connect(Tairon::Core::threadMethodDFunctor(current
, this, &Connection::connectingError
));
69 incomingRate
= new RateMeasurer(10);
70 outgoingRate
= new RateMeasurer(10);
72 socket
->connect(ip
, port
);
76 /* {{{ Connection::~Connection() */
77 Connection::~Connection()
89 for (std::list
<Tairon::Net::Writer
*>::const_iterator it
= commandQueue
.begin(); it
!= commandQueue
.end(); ++it
)
94 /* {{{ Connection::readBitField(Tairon::Net::Reader *) */
95 void Connection::readBitField(Tairon::Net::Reader
*)
97 DEBUG("bitfield read");
98 bitfield
= new Tairent::Core::BitField(reader
->getBuffer(), client
->getMetaInfo()["info"]["pieces"].asString().length() / 20);
100 reader
= lengthReader
;
101 deleteReader
= false;
103 client
->gotBitField(this);
107 /* {{{ Connection::readCancel(Tairon::Net::Reader *) */
108 void Connection::readCancel(Tairon::Net::Reader
*)
110 uint32_t index
= htonl(*(uint32_t *) reader
->getBuffer());
111 uint32_t start
= htonl(*(uint32_t *) (reader
->getBuffer() + 4));
113 for (std::list
<PieceRequestStruct
>::iterator it
= peersRequests
.begin(); it
!= peersRequests
.end(); ++it
)
114 if ((it
->index
== index
) && (it
->start
== start
)) {
115 peersRequests
.erase(it
);
120 reader
= lengthReader
;
121 deleteReader
= false;
125 /* {{{ Connection::readCommand(Tairon::Net::Reader *) */
126 void Connection::readCommand(Tairon::Net::Reader
*)
128 commandReader
->reset();
129 switch (*reader
->getBuffer()) {
132 reader
= lengthReader
;
133 if (choked
) // we're already choked
136 client
->gotChoke(this);
140 reader
= lengthReader
;
141 if (!choked
) // we're already unchoked
144 client
->gotUnchoke(this);
148 reader
= lengthReader
;
149 peerInterested
= true;
150 client
->gotInterestedChange(this);
153 DEBUG("not interested");
154 reader
= lengthReader
;
155 peerInterested
= false;
156 client
->gotInterestedChange(this);
160 reader
= new Tairon::Net::IReader(4, socket
, rlimiter
);
161 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readHave
));
162 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
168 closedSignal
.emit(this);
172 reader
= new Tairon::Net::IReader(12, socket
, rlimiter
);
173 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readRequest
));
174 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
179 reader
= new Tairon::Net::IReader(8, socket
, rlimiter
);
180 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readPiece
));
181 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
182 lastPieceTime
= Tairon::Net::Timer::currentTime();
187 reader
= new Tairon::Net::IReader(8, socket
, rlimiter
);
188 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readCancel
));
189 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
193 DEBUG((const char *) String("unknown message" + String::number(*reader
->getBuffer())));
195 closedSignal
.emit(this);
200 /* {{{ Connection::readFirstCommand(Tairon::Net::Reader *) */
201 void Connection::readFirstCommand(Tairon::Net::Reader
*)
203 commandReader
->bufferFullSignal
.clear();
204 commandReader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readCommand
));
205 commandReader
->reset();
207 if (*reader
->getBuffer() == 5) { // bitfield
210 // check if the peer isn't sending fake data
211 uint32_t len
= client
->getMetaInfo()["info"]["pieces"].asString().length() / 20;
212 if ((commandLength
- 1) != (len
/ 8 + (len
% 8 ? 1 : 0))) {
213 ERROR("Peer sent an invalid bitfield length");
215 closedSignal
.emit(this);
219 reader
= new Tairon::Net::IReader(commandLength
- 1, socket
, rlimiter
);
220 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readBitField
));
221 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
225 bitfield
= new Tairent::Core::BitField(client
->getMetaInfo()["info"]["pieces"].asString().length() / 20);
231 /* {{{ Connection::readHandshake(Tairon::Net::Reader *) */
232 void Connection::readHandshake(Tairon::Net::Reader
*)
234 DEBUG("got handshake 1");
236 const char *buffer
= reader
->getBuffer();
238 // check the protocol length (in the case that reader emitted
239 // bufferFullSignal instead of dataReadSignal.
241 WARNING("Invalid protocol length");
243 closedSignal
.emit(this);
247 if (strstr(buffer
+ 1, protocolName
) != (buffer
+ 1)) { // invalid protocol name
248 WARNING("Invalid protocol name");
250 closedSignal
.emit(this);
254 DEBUG("Protocol ok");
257 String
infoHash(buffer
+ 28, 20);
258 DEBUG("sending handshake");
259 client
= TorrentManager::self()->getClient(infoHash
);
261 WARNING("Got unknown infohash");
263 closedSignal
.emit(this);
266 sendHandshake(infoHash
);
271 reader
= new Tairon::Net::IReader(20, socket
, rlimiter
);
272 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readPeerID
));
273 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
277 /* {{{ Connection::readHave(Tairon::Net::Reader *) */
278 void Connection::readHave(Tairon::Net::Reader
*)
280 uint32_t index
= htonl(*(uint32_t *) reader
->getBuffer());
282 if (index
> bitfield
->getLength()) {
283 WARNING("Peer sent invalid have index");
285 closedSignal
.emit(this);
290 reader
= lengthReader
;
291 deleteReader
= false;
293 bitfield
->setBit(index
);
294 client
->gotHave(index
, this);
298 /* {{{ Connection::readLength(Tairon::Net::Reader *) */
299 void Connection::readLength(Tairon::Net::Reader
*)
301 commandLength
= ntohl(*(uint32_t *) lengthReader
->getBuffer());
302 DEBUG((const char *) String("Got message of length " + String::number(commandLength
)));
304 lengthReader
->reset();
307 reader
= commandReader
;
312 /* {{{ Connection::readPeerID(Tairon::Net::Reader *) */
313 void Connection::readPeerID(Tairon::Net::Reader
*)
315 DEBUG("got peer id");
316 String
pID(reader
->getBuffer(), 20);
318 if (peerID
.length() && (peerID
!= pID
)) { // we are connecting to a peer and it's ID doesn't match
319 WARNING("Peer's ID doesn't match");
321 closedSignal
.emit(this);
327 lengthReader
= new Tairon::Net::IReader(4, socket
, rlimiter
);
328 lengthReader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readLength
));
329 lengthReader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
331 commandReader
= new Tairon::Net::IReader(1, socket
, rlimiter
);
332 commandReader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readFirstCommand
));
333 commandReader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
335 reader
= lengthReader
;
336 deleteReader
= false;
338 TorrentServer::self()->connectionCompleted(this);
339 client
->newConnection(this);
343 /* {{{ Connection::readPiece(Tairon::Net::Reader *) */
344 void Connection::readPiece(Tairon::Net::Reader
*)
346 pieceIndex
= ntohl(*(uint32_t *) reader
->getBuffer());
347 pieceStart
= ntohl(*(uint32_t *) (reader
->getBuffer() + 4));
350 std::set
<uint32_t> &r
= requests
[pieceIndex
];
353 requests
.erase(pieceIndex
);
355 deleteReader
= false;
356 client
->gotPiece(pieceIndex
, pieceStart
, this);
360 /* {{{ Connection::readProtocolLength(Tairon::Net::Reader *, size_t) */
361 void Connection::readProtocolLength(Tairon::Net::Reader
*, size_t)
363 if (*reader
->getBuffer() != 19) { // length of the protocol name
364 WARNING("Invalid protocol length");
366 closedSignal
.emit(this);
370 reader
->dataReadSignal
.clear();
374 /* {{{ Connection::readRequest(Tairon::Net::Reader *) */
375 void Connection::readRequest(Tairon::Net::Reader
*)
377 if (peerChoked
) // don't send anything to the choked peer
380 PieceRequestStruct rs
;
381 rs
.index
= htonl(*(uint32_t *) reader
->getBuffer());
382 rs
.start
= htonl(*(uint32_t *) (reader
->getBuffer() + 4));
383 rs
.length
= htonl(*(uint32_t *) (reader
->getBuffer() + 8));
385 if (rs
.length
> 16384) {
386 WARNING((const char *) String("Client requested too big chunk: " + String::number(rs
.length
)));
388 closedSignal
.emit(this);
393 reader
= lengthReader
;
394 deleteReader
= false;
396 if (pieceWriters
|| commandQueue
.size()) // we are sending something
397 peersRequests
.push_back(rs
);
399 client
->getStorage()->gotRequest(rs
.index
, rs
.start
, rs
.length
, this);
403 /* {{{ Connection::readyRead(Tairon::Net::Socket *) */
404 void Connection::readyRead(Tairon::Net::Socket
*)
408 } catch (const Tairon::Net::SocketException
&) { // connection closed or other error
410 closedSignal
.emit(this);
415 /* {{{ Connection::readyWrite(Tairon::Net::Socket *) */
416 void Connection::readyWrite(Tairon::Net::Socket
*)
419 pieceWriters
->writers
.front()->write();
421 commandQueue
.front()->write();
425 /* {{{ Connection::addCommandWriter(Tairon::Net::Writer *) */
426 void Connection::addCommandWriter(Tairon::Net::Writer
*writer
)
428 commandQueue
.push_back(writer
);
429 if ((commandQueue
.size() == 1) && !pieceWriters
) // don't send anything if we are sending something
434 /* {{{ Connection::connectingError(Tairon::Net::Socket *, int) */
435 void Connection::connectingError(Tairon::Net::Socket
*, int)
438 client
->connectingFailed(this);
442 /* {{{ Connection::close() */
443 void Connection::close()
449 /* {{{ Connection::clearRequested() */
450 void Connection::clearRequested()
456 /* {{{ Connection::dataWritten(Tairon::Net::Writer *) */
457 void Connection::dataWritten(Tairon::Net::Writer
*writer
)
459 DEBUG("dataWritten");
461 Tairon::Net::Writer
*w
= commandQueue
.front();
462 if (w
== writer
) // is this writer in the queue?
463 commandQueue
.pop_front(); // remove it
466 if (commandQueue
.size()) // are there some commands to send?
467 commandQueue
.front()->write();
468 else if (peersRequests
.size()) { // let's try to send some piece
469 PieceRequestStruct rs
= peersRequests
.front();
470 peersRequests
.pop_front();
471 client
->getStorage()->gotRequest(rs
.index
, rs
.start
, rs
.length
, this);
476 /* {{{ Connection::destroyPieceReaders() */
477 void Connection::destroyPieceReaders()
482 for (std::list
<Tairon::Net::Reader
*>::iterator it
= pieceReaders
->readers
.begin(); it
!= pieceReaders
->readers
.end(); ++it
)
489 /* {{{ Connection::destroyPieceWriters() */
490 void Connection::destroyPieceWriters()
495 for (std::list
<Tairon::Net::Writer
*>::iterator it
= pieceWriters
->writers
.begin(); it
!= pieceWriters
->writers
.end(); ++it
)
502 /* {{{ Connection::getIncomingRate() */
503 double Connection::getIncomingRate()
505 return incomingRate
->getRate();
509 /* {{{ Connection::getOutgoingRate() */
510 double Connection::getOutgoingRate()
512 return outgoingRate
->getRate();
516 /* {{{ Connection::getPieceLength() */
517 uint32_t Connection::getPieceLength()
519 // 1 byte message type, 4 bytes index, 4 bytes start
520 return commandLength
- 9;
524 /* {{{ Connection::getReadingLimiter() */
525 Tairon::Net::Limiter
*Connection::getReadingLimiter()
531 /* {{{ Connection::getRequestsCount() */
532 unsigned int Connection::getRequestsCount()
534 unsigned int ret
= 0;
535 for (std::map
<uint32_t, std::set
<uint32_t> >::const_iterator it
= requests
.begin(); it
!= requests
.end(); ++it
)
536 ret
+= it
->second
.size();
541 /* {{{ Connection::getWritingLimiter() */
542 Tairon::Net::Limiter
*Connection::getWritingLimiter()
548 /* {{{ Connection::init() */
549 void Connection::init()
551 Tairon::Core::Thread
*current
= Tairon::Core::Thread::current();
553 socket
->errorSignal
.connect(Tairon::Core::threadMethodDFunctor(current
, this, &Connection::socketError
));
554 socket
->readyReadSignal
.connect(Tairon::Core::threadMethodDFunctor(current
, this, &Connection::readyRead
));
555 socket
->readyWriteSignal
.connect(Tairon::Core::threadMethodDFunctor(current
, this, &Connection::readyWrite
));
558 reader
= new Tairon::Net::IReader(handshakeLength
, socket
, rlimiter
);
559 reader
->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readHandshake
));
560 // it is safe to do this, we just want to check the first byte
561 reader
->dataReadSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readProtocolLength
));
562 reader
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
566 /* {{{ Connection::isSnubbed() */
567 bool Connection::isSnubbed()
569 return Tairon::Net::Timer::currentTime() - lastPieceTime
> 10000; // 10 seconds, should be configurable
573 /* {{{ Connection::pieceDataWritten(Tairon::Net::Writer *) */
574 void Connection::pieceDataWritten(Tairon::Net::Writer
*writer
)
576 pieceWriters
->writers
.pop_front();
578 if (pieceWriters
->writers
.size()) { // there is still something to send from the piece
579 delete writer
; // delete the current writer
580 pieceWriters
->writers
.front()->write();
581 } else { // whole piece has been sent
582 outgoingRate
->update(pieceWriters
->length
);
583 client
->pieceSent(pieceWriters
->index
, pieceWriters
->length
, this);
584 // the last piece's writer will be deleted in dataWritten() method
593 /* {{{ Connection::readerError(Tairon::Net::Reader *, Tairon::Net::Socket *) */
594 void Connection::readerError(Tairon::Net::Reader
*, Tairon::Net::Socket
*)
596 closedSignal
.emit(this);
600 /* {{{ Connection::sendChoke() */
601 void Connection::sendChoke()
603 DEBUG("sending choke");
608 peersRequests
.clear();
611 Tairon::Net::SWriter
*writer
= new Tairon::Net::SWriter(String("\x00\x00\x00\x01\x00", 5), socket
, wlimiter
);
612 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
613 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
615 addCommandWriter(writer
);
619 /* {{{ Connection::sendHandshake(const String &) */
620 void Connection::sendHandshake(const String
&infoHash
)
623 handshake
[0] = (char) 19;
624 memcpy(handshake
+ 1, protocolName
, 19);
625 memset(handshake
+ 20, 0, 8);
626 memcpy(handshake
+ 28, infoHash
.data(), 20);
627 memcpy(handshake
+ 48, TorrentManager::self()->getClientID().data(), 20);
629 String
h(handshake
, 68);
631 Tairon::Net::Writer
*writer
= new Tairon::Net::SWriter(h
, socket
, wlimiter
);
632 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
633 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
635 addCommandWriter(writer
);
637 if (client
->getStorage()->hasSomething()) { // we have already downloaded some piece, send bitfield as well
638 DEBUG("sending bitfield");
639 // count length of the bitfield
640 size_t length
= client
->getStorage()->getBitField()->getLength();
641 length
= length
/ 8 + (length
% 8 ? 1 : 0);
643 char *bf
= new char[5 + length
];
645 uint32_t l
= htonl(1 + length
); // 1 byte message type, rest is bitfield
646 memcpy(bf
, (const char *) (&l
), 4);
647 bf
[4] = 5; // bitfield message
648 memcpy(bf
+ 5, client
->getStorage()->getBitField()->getData(), length
);
650 String
b(bf
, 5 + length
);
651 writer
= new Tairon::Net::SWriter(b
, socket
, wlimiter
);
652 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
653 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
655 addCommandWriter(writer
);
662 /* {{{ Connection::sendHave(uint32_t) */
663 void Connection::sendHave(uint32_t index
)
665 DEBUG("sending have");
667 uint32_t i
= htonl(index
);
668 Tairon::Net::SWriter
*writer
= new Tairon::Net::SWriter(String("\x00\x00\x00\x05\x04", 5) + String((const char *) (&i
), 4), socket
, wlimiter
);
669 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
670 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
672 addCommandWriter(writer
);
676 /* {{{ Connection::sendInterested() */
677 void Connection::sendInterested()
679 DEBUG("sending interested");
685 Tairon::Net::SWriter
*writer
= new Tairon::Net::SWriter(String("\x00\x00\x00\x01\x02", 5), socket
, wlimiter
);
686 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
687 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
689 addCommandWriter(writer
);
693 /* {{{ Connection::sendNotInterested() */
694 void Connection::sendNotInterested()
696 DEBUG("sending not interested");
702 Tairon::Net::SWriter
*writer
= new Tairon::Net::SWriter(String("\x00\x00\x00\x01\x03", 5), socket
, wlimiter
);
703 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
704 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
706 addCommandWriter(writer
);
710 /* {{{ Connection::sendRequest(uint32_t, uint32_t, uint32_t) */
711 void Connection::sendRequest(uint32_t index
, uint32_t start
, uint32_t length
)
713 requests
[index
].insert(start
);
716 memcpy(msg
, "\x00\x00\x00\x0d\x06", 5);
717 *(uint32_t *) (msg
+ 5) = htonl(index
);
718 *(uint32_t *) (msg
+ 9) = htonl(start
);
719 *(uint32_t *) (msg
+ 13) = htonl(length
);
721 Tairon::Net::SWriter
*writer
= new Tairon::Net::SWriter(String(msg
, 17), socket
, wlimiter
);
722 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
723 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
725 addCommandWriter(writer
);
729 /* {{{ Connection::sendUnchoke(int) */
730 void Connection::sendUnchoke(int time
)
732 DEBUG("sending unchoke");
740 Tairon::Net::SWriter
*writer
= new Tairon::Net::SWriter(String("\x00\x00\x00\x01\x01", 5), socket
, wlimiter
);
741 writer
->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::dataWritten
));
742 writer
->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
744 addCommandWriter(writer
);
748 /* {{{ Connection::setNextReader(Tairon::Net::Reader *) */
749 void Connection::setNextReader(Tairon::Net::Reader
*)
751 delete pieceReaders
->readers
.front();
752 pieceReaders
->readers
.pop_front();
754 if (pieceReaders
->readers
.size()) {
755 DEBUG("Setting next piece reader");
756 reader
= pieceReaders
->readers
.front();
758 DEBUG("Piece downloaded");
760 incomingRate
->update(pieceReaders
->length
);
762 bool fake
= pieceReaders
->fake
;
765 reader
= lengthReader
;
766 deleteReader
= false;
768 client
->pieceDownloaded(pieceIndex
, pieceStart
, this);
773 /* {{{ Connection::setReaders(PieceReadersStruct *) */
774 void Connection::setReaders(PieceReadersStruct
*readers
)
776 for (std::list
<Tairon::Net::Reader
*>::iterator it
= readers
->readers
.begin(); it
!= readers
->readers
.end(); ++it
) {
777 (*it
)->bufferFullSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::setNextReader
));
778 (*it
)->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::readerError
));
780 pieceReaders
= readers
;
781 reader
= pieceReaders
->readers
.front();
785 /* {{{ Connection::setWriters(PieceWritersStruct *) */
786 void Connection::setWriters(PieceWritersStruct
*writers
)
788 for (std::list
<Tairon::Net::Writer
*>::iterator it
= writers
->writers
.begin(); it
!= writers
->writers
.end(); ++it
) {
789 (*it
)->dataWrittenSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::pieceDataWritten
));
790 (*it
)->errorSignal
.connect(Tairon::Core::methodFunctor(this, &Connection::writerError
));
793 pieceWriters
= writers
;
794 writers
->writers
.front()->write();
798 /* {{{ Connection::socketConnected(Tairon::Net::Socket *) */
799 void Connection::socketConnected(Tairon::Net::Socket
*)
801 socket
->connectedSignal
.clear();
802 socket
->errorSignal
.clear();
806 sendHandshake(client
->getInfoHash());
810 /* {{{ Connection::socketError(Tairon::Net::Socket *, int) */
811 void Connection::socketError(Tairon::Net::Socket
*, int)
814 closedSignal
.emit(this);
818 /* {{{ Connection::writerError(Tairon::Net::Writer *, Tairon::Net::Socket *) */
819 void Connection::writerError(Tairon::Net::Writer
*, Tairon::Net::Socket
*)
821 closedSignal
.emit(this);
827 }; // namespace Tairent
829 // vim: ai sw=4 ts=4 noet fdm=marker