Rewritten SocketBuffer::BufEntry and SocketBuffer::send()

pull/1/head
Tatsuhiro Tsujikawa 2011-03-18 17:20:37 +09:00
parent 18d51a3e20
commit 3d2fa5954e
2 changed files with 77 additions and 62 deletions

View File

@ -44,57 +44,77 @@
namespace aria2 {
SocketBuffer::ByteArrayBufEntry::ByteArrayBufEntry
(unsigned char* bytes, size_t length)
: bytes_(bytes), length_(length)
{}
SocketBuffer::ByteArrayBufEntry::~ByteArrayBufEntry()
{
delete [] bytes_;
}
ssize_t SocketBuffer::ByteArrayBufEntry::send
(const SharedHandle<SocketCore>& socket, size_t offset)
{
return socket->writeData(bytes_+offset, length_-offset);
}
bool SocketBuffer::ByteArrayBufEntry::final(size_t offset) const
{
return length_ <= offset;
}
SocketBuffer::StringBufEntry::StringBufEntry(const std::string& s)
: str_(s)
{}
ssize_t SocketBuffer::StringBufEntry::send
(const SharedHandle<SocketCore>& socket, size_t offset)
{
return socket->writeData(str_.data()+offset, str_.size()-offset);
}
bool SocketBuffer::StringBufEntry::final(size_t offset) const
{
return str_.size() <= offset;
}
SocketBuffer::SocketBuffer(const SharedHandle<SocketCore>& socket):
socket_(socket), offset_(0) {}
SocketBuffer::~SocketBuffer()
{
std::for_each(bufq_.begin(), bufq_.end(),
std::mem_fun_ref(&BufEntry::deleteBuf));
}
SocketBuffer::~SocketBuffer() {}
void SocketBuffer::pushBytes(unsigned char* bytes, size_t len)
{
bufq_.push_back(BufEntry(bytes, len));
if(len > 0) {
bufq_.push_back(SharedHandle<BufEntry>(new ByteArrayBufEntry(bytes, len)));
}
}
void SocketBuffer::pushStr(const std::string& data)
{
bufq_.push_back(BufEntry(data));
if(data.size() > 0) {
bufq_.push_back(SharedHandle<BufEntry>(new StringBufEntry(data)));
}
}
ssize_t SocketBuffer::send()
{
size_t totalslen = 0;
while(!bufq_.empty()) {
BufEntry& buf = bufq_[0];
if(buf.size() == 0) {
buf.deleteBuf();
bufq_.pop_front();
continue;
}
const char* data;
ssize_t r;
if(buf.type == TYPE_BYTES) {
data = reinterpret_cast<const char*>(buf.bytes);
r = buf.bytesLen-offset_;
} else {
const std::string& str = *buf.str;
data = str.data();
r = str.size()-offset_;
}
ssize_t slen = socket_->writeData(data+offset_, r);
const SharedHandle<BufEntry>& buf = bufq_[0];
ssize_t slen = buf->send(socket_, offset_);
if(slen == 0 && !socket_->wantRead() && !socket_->wantWrite()) {
throw DL_ABORT_EX(fmt(EX_SOCKET_SEND, "Connection closed."));
}
totalslen += slen;
if(slen < r) {
offset_ += slen;
break;
} else {
offset_ = 0;
buf.deleteBuf();
offset_ += slen;
if(buf->final(offset_)) {
bufq_.pop_front();
offset_ = 0;
} else {
break;
}
}
return totalslen;

View File

@ -48,44 +48,39 @@ class SocketCore;
class SocketBuffer {
private:
enum BUF_TYPE {
TYPE_BYTES,
TYPE_STR
class BufEntry {
public:
virtual ~BufEntry() {}
virtual ssize_t send
(const SharedHandle<SocketCore>& socket, size_t offset) = 0;
virtual bool final(size_t offset) const = 0;
};
struct BufEntry {
BUF_TYPE type;
unsigned char* bytes;
size_t bytesLen;
std::string* str;
void deleteBuf()
{
if(type == TYPE_BYTES) {
delete [] bytes;
} else if(type == TYPE_STR) {
delete str;
}
}
class ByteArrayBufEntry:public BufEntry {
public:
ByteArrayBufEntry(unsigned char* bytes, size_t length);
virtual ~ByteArrayBufEntry();
virtual ssize_t send
(const SharedHandle<SocketCore>& socket, size_t offset);
virtual bool final(size_t offset) const;
private:
unsigned char* bytes_;
size_t length_;
};
size_t size() const
{
if(type == TYPE_BYTES) {
return bytesLen;
} else {
return str->size();
}
}
BufEntry(unsigned char* bytes, size_t len):
type(TYPE_BYTES), bytes(bytes), bytesLen(len) {}
BufEntry(const std::string& str):
type(TYPE_STR), str(new std::string(str)) {}
class StringBufEntry:public BufEntry {
public:
StringBufEntry(const std::string& s);
virtual ssize_t send
(const SharedHandle<SocketCore>& socket, size_t offset);
virtual bool final(size_t offset) const;
private:
std::string str_;
};
SharedHandle<SocketCore> socket_;
std::deque<BufEntry> bufq_;
std::deque<SharedHandle<BufEntry> > bufq_;
// Offset of data in bufq_[0]. SocketBuffer tries to send bufq_[0],
// but it cannot always send whole data. In this case, offset points
@ -100,7 +95,7 @@ public:
SocketBuffer(const SocketBuffer&);
SocketBuffer& operator=(const SocketBuffer&);
// Feeds data pointered by bytes with length len. into queue. This
// Feeds data pointered by bytes with length len into queue. This
// object gets ownership of bytes, so caller must not delete or
// later bytes after this call. This function doesn't send data.
void pushBytes(unsigned char* bytes, size_t len);