/* */ #include "PeerConnection.h" #include "message.h" #include "DlAbortEx.h" #include "LogFactory.h" #include "Logger.h" #include "BtHandshakeMessage.h" #include "Socket.h" #include "a2netcompat.h" #include namespace aria2 { PeerConnection::PeerConnection(int32_t cuid, const SocketHandle& socket, const Option* op) :cuid(cuid), socket(socket), option(op), logger(LogFactory::getInstance()), resbufLength(0), currentPayloadLength(0), lenbufLength(0) {} PeerConnection::~PeerConnection() {} int32_t PeerConnection::sendMessage(const unsigned char* data, int32_t dataLength) { int32_t writtenLength = 0; if(socket->isWritable(0)) { // TODO fix this socket->writeData((const char*)data, dataLength); writtenLength += dataLength; } return writtenLength; } bool PeerConnection::receiveMessage(unsigned char* data, int32_t& dataLength) { if(resbufLength == 0 && 4 > lenbufLength) { if(!socket->isReadable(0)) { return false; } // read payload size, 32bit unsigned integer int32_t remaining = 4-lenbufLength; int32_t temp = remaining; socket->readData(lenbuf+lenbufLength, remaining); if(remaining == 0) { // we got EOF logger->debug("CUID#%d - In PeerConnection::receiveMessage(), remain=%d", cuid, temp); throw new DlAbortEx(EX_EOF_FROM_PEER); } lenbufLength += remaining; if(4 > lenbufLength) { // still 4-lenbufLength bytes to go return false; } uint32_t payloadLength = ntohl(*(reinterpret_cast(lenbuf))); if(payloadLength > MAX_PAYLOAD_LEN) { throw new DlAbortEx(EX_TOO_LONG_PAYLOAD, payloadLength); } currentPayloadLength = payloadLength; } if(!socket->isReadable(0)) { return false; } // we have currentPayloadLen-resbufLen bytes to read int32_t remaining = currentPayloadLength-resbufLength; int32_t temp = remaining; if(remaining > 0) { socket->readData(resbuf+resbufLength, remaining); if(remaining == 0) { // we got EOF logger->debug("CUID#%d - In PeerConnection::receiveMessage(), payloadlen=%d, remaining=%d", cuid, currentPayloadLength, temp); throw new DlAbortEx(EX_EOF_FROM_PEER); } resbufLength += remaining; if(currentPayloadLength > resbufLength) { return false; } } // we got whole payload. resbufLength = 0; lenbufLength = 0; memcpy(data, resbuf, currentPayloadLength); dataLength = currentPayloadLength; return true; } bool PeerConnection::receiveHandshake(unsigned char* data, int32_t& dataLength, bool peek) { int32_t remaining = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength; if(remaining > 0 && !socket->isReadable(0)) { dataLength = 0; return false; } bool retval = true; if(remaining > 0) { int32_t temp = remaining; socket->readData(resbuf+resbufLength, remaining); if(remaining == 0) { // we got EOF logger->debug("CUID#%d - In PeerConnection::receiveHandshake(), remain=%d", cuid, temp); throw new DlAbortEx(EX_EOF_FROM_PEER); } resbufLength += remaining; if(BtHandshakeMessage::MESSAGE_LENGTH > resbufLength) { retval = false; } } int32_t writeLength = resbufLength > dataLength ? dataLength : resbufLength; memcpy(data, resbuf, writeLength); dataLength = writeLength; if(retval && !peek) { resbufLength = 0; } return retval; } } // namespace aria2