Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web


// =================================================================
//
//  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
//////