#ifndef Buffer_hh #define Buffer_hh #include #include #include #include #include struct Buffer { explicit Buffer(unsigned int bufsize) : bufsize_(bufsize), vsize_(0), index_(0), recIndex_(0), minBytesAvailable_(0), bytesRemainingInMsg_(0) { if (bufsize_ > 0) { buf_ = new unsigned char[bufsize_]; } } ~Buffer() { if (bufsize_ > 0) { delete [] buf_; } } int PersistentWrite(const void* data, int len) { int rc; unsigned char* d2 = (unsigned char*) data; while ((rc = write(sock_, d2, len)) != len) { if (rc == -1) { ews_.SetErrorWords(errno, __FILE__, __LINE__); return 0; } len -= rc; d2 += rc; } return 1; } int PersistentRead(void* data, int len) { int rc; unsigned char* d2 = (unsigned char*) data; while ((rc = read(sock_, d2, len)) != len) { if (rc == -1) { ews_.SetErrorWords(errno, __FILE__, __LINE__); return 0; } else { if (rc == 0) { ews_.SetErrorWords(0, __FILE__, __LINE__); return 0; } len -= rc; d2 += rc; } } return 1; } int SendStoredData() { if (index_ > 0) { if (!PersistentWrite(buf_, index_)) { return 0; } index_ = 0; } return 1; } int Resize(unsigned int newsize) { if (newsize < index_) { if (!SendStoredData()) { ews_.SetErrorWords(0, __FILE__, __LINE__); return 0; } } unsigned char* tmp = new unsigned char[newsize]; memcpy(tmp, buf_, index_); delete [] buf_; buf_ = tmp; bufsize_ = newsize; return 1; } int Receive(const void* data, unsigned int dlen) { if (dlen > bufsize_ - index_) { if (!SendStoredData()) { return 0; } if (dlen > bufsize_) { if (!PersistentWrite(data, dlen)) { return 0; } return 1; } } memcpy(buf_ + index_, data, dlen); index_ += dlen; return 1; } int Give(void* address, unsigned int len) { using std::min; if (len > bytesRemainingInMsg_) { ews_.SetErrorWords(0, __FILE__, __LINE__); return 0; } char * addr = static_cast (address); if (vsize_ > recIndex_) { if (len <= (vsize_ - recIndex_)) { memcpy(addr, buf_ + recIndex_, len); recIndex_ += len; } else { memcpy(addr, buf_ + recIndex_, vsize_ - recIndex_); addr += (vsize_ - recIndex_); len -= (vsize_ - recIndex_); bytesRemainingInMsg_ -= (vsize_ - recIndex_); recIndex_ = vsize_; goto pull; } } else { pull: int rc = 0; if (minBytesAvailable_ < len) { if ((rc = ioctl(sock_, FIONREAD, &minBytesAvailable_)) == -1) { ews_.SetErrorWords(errno, __FILE__, __LINE__); return 0; } } if (len > bufsize_ || len > minBytesAvailable_) { if (!PersistentRead(addr, len)) { return 0; } minBytesAvailable_ = 0; } else { vsize_ = min(min(bufsize_, bytesRemainingInMsg_), minBytesAvailable_); minBytesAvailable_ -= vsize_; if ((rc = read(sock_, buf_, vsize_)) != vsize_) { ews_.SetErrorWords(errno, __FILE__, __LINE__); return 0; } memcpy(addr, buf_, len); recIndex_ = len; } } bytesRemainingInMsg_ -= len; return 1; } void Reset() { index_ = 0; recIndex_ = 0; vsize_ = 0; minBytesAvailable_ = 0; bytesRemainingInMsg_ = 0; return; } void SetMsgLength(unsigned int totLen) { bytesRemainingInMsg_ = totLen; } int Debug() { std::cout << "bufsize_ is " << bufsize_ << std::endl; std::cout << "vsize_ is " << vsize_ << std::endl; std::cout << "index_ is " << index_ << std::endl; std::cout << "recIndex_ is " << recIndex_ << std::endl; return 1; } int sock_; ErrorWordsShepherd ews_; private: unsigned int bufsize_; unsigned int vsize_; unsigned int index_; unsigned int recIndex_; unsigned int minBytesAvailable_; unsigned int bytesRemainingInMsg_; unsigned char* buf_; Buffer(Buffer const&); Buffer& operator=(Buffer const&); }; #endif