long sockbuf::howmanyc () // return how many chars are available for reading in the input buffer // and the recvbuf of the socket. { std::streamsize theShowMany = showmanyc(); assert (theShowMany < INT_MAX); return (long)theShowMany + nread (); }
streamsize mem_streambuf::xsgetn( char_type *buf, std::streamsize size ) { streamsize const remaining = showmanyc(); if ( size > remaining ) size = remaining; ::memcpy( buf, gptr(), static_cast<size_t>( size ) ); gbump( static_cast<int>(size) ); return size; }
streamsize streambuf::in_avail() { #if defined(OS_INCLUDE_STREAMBUF_BUFFERS) if (mgend != 0 && mgnext != 0) { return mgend - mgnext; } #endif return showmanyc(); }
std::streamsize sockbuf::xsgetn (char_type* s, std::streamsize n) { std::streamsize rval = showmanyc (); if (rval >= n) { memcpy (s, gptr (), (size_t)(n * sizeof (char_type))); gbump ((int)n); return n; } memcpy (s, gptr (), (size_t)(rval * sizeof (char_type))); gbump ((int)rval); if (underflow () != eof) return rval + xsgetn (s + rval, n - rval); return rval; }
std::streamsize ProcReader::xsgetn(char_type* ptr, std::streamsize num) { std::streamsize howMany = showmanyc(); if (num < howMany) { memcpy(ptr, gptr(), num * sizeof(char_type)); gbump(num); return num; } memcpy(ptr, gptr(), howMany * sizeof(char_type)); gbump(howMany); if (traits_type::eof() == underflow()) return howMany; return howMany + xsgetn(ptr + howMany, num - howMany); }
std::streamsize filedescriptor_streambuf::xsgetn( char *target, std::streamsize count) { std::streamsize available = showmanyc(); if(count <= available) { memcpy(target, gptr(), count * sizeof(char_type)); gbump(count); return count; } memcpy(target, gptr(), available * sizeof(char_type)); gbump(available); if(traits_type::eof() == underflow()) return available; return (available + xsgetn(target+available, count-available)); }
std::streamsize Socket::showmanyc() { #ifdef WIN32 unsigned long result = 0; if(ioctlsocket(handle, FIONREAD, &result)) { #else int result = 0; if(ioctl(handle, FIONREAD, &result)) { #endif disconnect(); throw Exception(Exception::ERROR_IOCTL); }else return result; } std::streamsize Socket::advanceInputBuffer() { if(inputIntermediateSize == 0) //No input buffer return 0; std::streamsize inAvail; if(type == UDP_PEER) inAvail = 0; else{ inAvail = egptr()-gptr(); memmove(eback(), gptr(), inAvail); } try { inAvail += receive(eback()+inAvail, inputIntermediateSize-inAvail); } catch(Exception err) { } setg(eback(), eback(), eback()+inAvail); return inAvail; } std::streamsize Socket::receive(char_type* buffer, std::streamsize size) { if(type == TCP_SERVER) throw Exception(Exception::BAD_TYPE); if(status != Socket::Status::READY && status != Socket::Status::BUSY) return 0; size = std::min(size, showmanyc()); if(size == 0) return 0; switch(type) { case UDP_PEER: { struct sockaddr_storage remoteAddr; #ifdef WIN32 int addrSize = sizeof(remoteAddr); #else unsigned int addrSize = sizeof(remoteAddr); #endif int result = recvfrom(handle, (char*)buffer, size, 0, reinterpret_cast<struct sockaddr*>(&remoteAddr), &addrSize); if(result <= 0) { portRemote = 0; hostRemote = ""; throw Exception(Exception::ERROR_READ); }else readSockaddr(&remoteAddr, hostRemote, portRemote); return result; } case TCP_CLIENT: case TCP_SERVERS_CLIENT: { int result = recv(handle, (char*)buffer, size, 0); if(result <= 0) throw Exception(Exception::ERROR_READ); return result; } default: case NONE: case TCP_SERVER: throw Exception(Exception::BAD_TYPE); } } std::streamsize Socket::send(const char_type* buffer, std::streamsize size) { if(type == TCP_SERVER) throw Exception(Exception::BAD_TYPE); if(status != Socket::Status::READY || size == 0) return 0; switch(type) { case UDP_PEER: { AddrinfoContainer info = getSocketInfoFor(hostRemote.c_str(), portRemote, false); size_t sentBytes = 0; while(sentBytes < (size_t)size) { int result = ::sendto(handle, (const char*)buffer + sentBytes, size - sentBytes, 0, info->ai_addr, info->ai_addrlen); if(result <= 0) { status = BUSY; throw Exception(Exception::ERROR_SEND); } sentBytes += result; } return sentBytes; } case TCP_CLIENT: case TCP_SERVERS_CLIENT: { size_t sentBytes = 0; while(sentBytes < (size_t)size) { int result = ::send(handle, (const char*)buffer + sentBytes, size - sentBytes, 0); if(result <= 0) { status = BUSY; throw Exception(Exception::ERROR_SEND); } sentBytes += result; } return sentBytes; } default: case NONE: case TCP_SERVER: throw Exception(Exception::BAD_TYPE); } } std::streamsize Socket::redirect(const std::vector<std::shared_ptr<Socket>>& destinations) { if(type == TCP_SERVER) throw Exception(Exception::BAD_TYPE); std::streamsize size = 0; while(in_avail()) { auto length = egptr()-gptr(); for(const auto& destination : destinations) if(destination->sputn(gptr(), length) < length) throw Exception(Exception::ERROR_SEND); gbump(length); size += length; advanceInputBuffer(); } return size; } std::streamsize Socket::getInputBufferSize() { return inputIntermediateSize; } std::streamsize Socket::getOutputBufferSize() { return epptr()-pbase(); } void Socket::setInputBufferSize(std::streamsize n) { if(eback()) { delete[] eback(); setg(NULL, NULL, NULL); } if(n == 0) return; if(type == TCP_SERVER) throw Exception(Exception::BAD_TYPE); char_type* readBuffer = new char_type[n]; setg(readBuffer, readBuffer, readBuffer); inputIntermediateSize = n; } void Socket::setOutputBufferSize(std::streamsize n) { if(pbase()) { delete[] pbase(); setp(NULL, NULL); } if(n == 0) return; if(type == TCP_SERVER) throw Exception(Exception::BAD_TYPE); char_type* writeBuffer = new char_type[n]; setp(writeBuffer, writeBuffer+n); } void Socket::setBlockingMode(bool blocking) { #ifdef WIN32 unsigned long flag = !blocking; if(ioctlsocket(handle, FIONBIO, &flag) != 0) #else int flags = fcntl(handle, F_GETFL); if(blocking) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; if(fcntl(handle, F_SETFL, flags) == -1) #endif throw Exception(Exception::ERROR_IOCTL); }
std::streamsize Socket::showmanyc() { #ifdef WIN32 unsigned long result = -1; if(ioctlsocket(handle, FIONREAD, &result)) { #else int result = -1; if(ioctl(handle, FIONREAD, &result)) { #endif disconnect(); throw Exception(Exception::ERROR_IOCTL); }else return result; } std::streamsize Socket::advanceInputBuffer() { if(inputIntermediateSize == 0) //No input buffer return 0; std::streamsize inAvail; if(type == UDP_PEER) inAvail = 0; else{ inAvail = egptr()-gptr(); memmove(eback(), gptr(), inAvail); } try { inAvail += receive(eback()+inAvail, inputIntermediateSize-inAvail); } catch(Exception err) { } setg(eback(), eback(), eback()+inAvail); return inAvail; } std::streamsize Socket::receive(char_type* buffer, std::streamsize size) { size = std::min(size, showmanyc()); if(size == 0) return 0; switch(type) { case UDP_PEER: { struct sockaddr_storage remoteAddr; #ifdef WIN32 int addrSize = sizeof(remoteAddr); #else unsigned int addrSize = sizeof(remoteAddr); #endif int result = recvfrom(handle, (char*)buffer, size, 0, reinterpret_cast<struct sockaddr*>(&remoteAddr), &addrSize); if(result == -1) { portRemote = 0; hostRemote = ""; throw Exception(Exception::ERROR_READ); }else readSockaddr(&remoteAddr, hostRemote, portRemote); return result; } case TCP_CLIENT: case TCP_SERVERS_CLIENT: { int result = recv(handle, (char*)buffer, size, 0); if(result == -1) throw Exception(Exception::ERROR_READ); return result; } default: case NONE: case TCP_SERVER: throw Exception(Exception::BAD_TYPE); } }