+PeerConnectionBase::initialize(DownloadMain* download, PeerInfo* peerInfo, SocketFd fd, Bitfield* bitfield, std::auto_ptr encrypt, std::auto_ptr decrypt) { Consider passing just pointers, and then copy-by-value. Thus Handshake and PCB can have the member as a value rather than a pointer. if (length > m_encryptBuffer->size_end()) { length -= m_encryptBuffer->size_end(); WTF, need to look at this when i'm not tipsy. Does it fill the entire chunk into the buffer? - m_down->buffer()->move_end(read_stream_throws(m_down->buffer()->end(), read_size - m_down->buffer()->size_end())); + unsigned int read; + read = read_stream_throws(m_down->buffer()->end(), read_size - m_down->buffer()->size_end()); + if (is_encrypted()) + m_decrypt->crypt(m_down->buffer()->end(), read); + m_down->buffer()->move_end(read); Add an inline helper function for readning encrypted data. The handshake error messages should be similar to errno, with an strerror'ish func in ConnectionManager. + if ((h->encryption_options() & ConnectionManager::encryption_enable_retry) != 0 && h->get_retry_type() != Handshake::RETRY_NONE) { Store the retry options in Handshake, instead of using new enums. Just check if it is a valid retry flag.