// =================================================================
//
// Copyright (C) 2001 Maciej Sobczak
// Copyright (C) 2003 Alex Vinokur - minor (cosmetic) changes
//
// For conditions of distribution and use, see
// copyright notice in common.h
//
// =================================================================
// #################################################################
//
// SOFTWARE : C++ Stream-Compatible TCP/IP Sockets Demo Application
// FILE : sockets2.h
//
// DESCRIPTION :
// The wrapper classes that can be used
// as a iostream-compatible TCP/IP sockets.
// Classes implementation (template methods)
//
// #################################################################
///////////////////////////
#ifndef INCLUDED_SOCKETS2_H
#define INCLUDED_SOCKETS2_H
///////////////////////////
// =================
#include "sockets.h"
// =================
// -------------------
// --- TCPStreamBuffer
// -------------------
// ------
// Constructor-1
template <class charT, class traits>
TCPStreamBuffer<charT, traits>::TCPStreamBuffer (
TCPSocketWrapper& sock,
bool takeowner,
streamsize bufsize
)
:
rsocket_(sock),
ownsocket_(takeowner),
inbuf_(NULL),
outbuf_(NULL),
bufsize_(bufsize),
remained_(0),
ownbuffers_(false)
{
SET_CTOR_TRACE;
}
// ------
// Destructor
template <class charT, class traits>
TCPStreamBuffer<charT, traits>::~TCPStreamBuffer()
{
SET_DTOR_TRACE;
if (
(rsocket_.state() == TCPSocketWrapper::CONNECTED)
||
(rsocket_.state() == TCPSocketWrapper::ACCEPTED)
)
{
_flush();
}
if (ownbuffers_)
{
delete [] inbuf_;
delete [] outbuf_;
}
if (ownsocket_) rsocket_.close();
}
// ------
template <class charT, class traits>
basic_streambuf<charT, traits>* TCPStreamBuffer<charT, traits>::setbuf (char_type *s, streamsize n)
{
SET_TRACE;
if (gptr() == NULL)
{
setg (s, s + n, s + n);
setp (s, s + n);
inbuf_ = s;
outbuf_ = s;
bufsize_ = n;
ownbuffers_ = false;
}
return this;
}
// ------
template <class charT, class traits>
void TCPStreamBuffer<charT, traits>::_flush()
{
SET_TRACE;
rsocket_.write(outbuf_, (pptr() - outbuf_) * sizeof(char_type));
}
// ------
template <class charT, class traits>
typename basic_streambuf<charT, traits>::int_type TCPStreamBuffer<charT, traits>::overflow(int_type c)
{
SET_TRACE;
// this method is supposed to flush the put area of the buffer
// to the I/O device
// if the buffer was not already allocated nor set by user,
// do it just now
if (pptr() == NULL)
{
outbuf_ = new char_type[bufsize_];
ownbuffers_ = true;
}
else
{
_flush();
}
setp(outbuf_, outbuf_ + bufsize_);
if (c != traits::eof())
{
sputc(traits::to_char_type(c));
}
return 0;
}
// ------
template <class charT, class traits>
int TCPStreamBuffer<charT, traits>::sync()
{
SET_TRACE;
// just flush the put area
_flush();
setp (outbuf_, outbuf_ + bufsize_);
return 0;
}
// ------
template <class charT, class traits>
typename basic_streambuf<charT, traits>::int_type TCPStreamBuffer<charT, traits>::underflow()
{
SET_TRACE;
// this method is supposed to read some bytes from the I/O device
// if the buffer was not already allocated nor set by user,
// do it just now
if (gptr() == NULL)
{
inbuf_ = new char_type[bufsize_];
ownbuffers_ = true;
}
if (remained_ != 0)
inbuf_[0] = remainedchar_;
size_t readn = rsocket_.read (
static_cast<char*>(inbuf_) + remained_,
bufsize_ * sizeof(char_type) - remained_
);
// if (readn == 0 && remained_ != 0)
// error - there is not enough bytes for completing
// the last character before the end of the stream
// - this can mean error on the remote end
if (readn == 0) return traits::eof();
size_t totalbytes = readn + remained_;
setg (inbuf_, inbuf_, inbuf_ + totalbytes / sizeof(char_type));
remained_ = totalbytes % sizeof(char_type);
if (remained_ != 0)
{
remainedchar_ = inbuf_[totalbytes / sizeof(char_type)];
}
return sgetc();
}
// --------------------
// --- TCPGenericStream
// --------------------
// ------
template <class charT, class traits>
TCPGenericStream<charT, traits>::TCPGenericStream (
TCPSocketWrapper& sock,
bool takeowner
)
:
TCPStreamBuffer<charT, traits>(sock, takeowner),
basic_iostream<charT, traits>(this)
{
SET_TRACE;
}
// --------------------------
// --- TCPGenericClientStream
// --------------------------
// ------
// Constructor-1
template <class charT, class traits>
TCPGenericClientStream<charT, traits>::TCPGenericClientStream (
const char* address,
int port
)
:
TCPGenericStream<charT, traits>(*this, false)
{
SET_CTOR_TRACE;
TCPSocketWrapper::connect(address, port);
}
// Destructor
template <class charT, class traits>
TCPGenericClientStream<charT, traits>::~TCPGenericClientStream ()
{
SET_DTOR_TRACE;
}
//////
#endif
//////