mirror of https://github.com/aria2/aria2
Rewritten SocketBuffer::BufEntry and SocketBuffer::send()
parent
18d51a3e20
commit
3d2fa5954e
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue