danicoin/src/System/TcpStream.cpp
2016-01-18 15:33:29 +00:00

94 lines
2.2 KiB
C++

// Copyright (c) 2011-2016 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "TcpStream.h"
#include <System/TcpConnection.h>
namespace System {
TcpStreambuf::TcpStreambuf(TcpConnection& connection) : connection(connection) {
setg(&readBuf.front(), &readBuf.front(), &readBuf.front());
setp(reinterpret_cast<char*>(&writeBuf.front()), reinterpret_cast<char *>(&writeBuf.front() + writeBuf.max_size()));
}
TcpStreambuf::~TcpStreambuf() {
dumpBuffer(true);
}
std::streambuf::int_type TcpStreambuf::overflow(std::streambuf::int_type ch) {
if (ch == traits_type::eof()) {
return traits_type::eof();
}
if (pptr() == epptr()) {
if (!dumpBuffer(false)) {
return traits_type::eof();
}
}
*pptr() = static_cast<char>(ch);
pbump(1);
return ch;
}
int TcpStreambuf::sync() {
return dumpBuffer(true) ? 0 : -1;
}
std::streambuf::int_type TcpStreambuf::underflow() {
if (gptr() < egptr()) {
return traits_type::to_int_type(*gptr());
}
size_t bytesRead;
try {
bytesRead = connection.read(reinterpret_cast<uint8_t*>(&readBuf.front()), readBuf.max_size());
} catch (std::exception&) {
return traits_type::eof();
}
if (bytesRead == 0) {
return traits_type::eof();
}
setg(&readBuf.front(), &readBuf.front(), &readBuf.front() + bytesRead);
return traits_type::to_int_type(*gptr());
}
bool TcpStreambuf::dumpBuffer(bool finalize) {
try {
size_t count = pptr() - pbase();
if(count == 0) {
return true;
}
size_t transferred = connection.write(&writeBuf.front(), count);
if(transferred == count) {
pbump(-static_cast<int>(count));
} else {
if(!finalize) {
size_t front = 0;
for (size_t pos = transferred; pos < count; ++pos, ++front) {
writeBuf[front] = writeBuf[pos];
}
pbump(-static_cast<int>(transferred));
} else {
size_t offset = transferred;
while( offset != count) {
offset += connection.write(&writeBuf.front() + offset, count - offset);
}
pbump(-static_cast<int>(count));
}
}
} catch (std::exception&) {
return false;
}
return true;
}
}