// -*- c++ -*- //------------------------------------------------------------------------------ // xdrIOBuffer.cpp //------------------------------------------------------------------------------ // Copyright (C) 1997-2002,2005 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ // Created: 04/11/2000 //------------------------------------------------------------------------------ #include #include #include "assa/MemDump.h" #include "assa/xdrIOBuffer.h" #include "assa/XDRHack.h" namespace ASSA { Socket& operator>>(Socket& s_, xdrIOBuffer& b_) { trace_with_mask("Socket >> xdrIOBuffer", XDRBUFTRACE); DL((XDRBUFTRACE,"Buffer Initially:\n")); b_.dump (); if (b_.m_state != xdrIOBuffer::waiting) { EL((ASSAERR,"Wrong state: %s\n", b_.get_state ().c_str ())); return s_; } int expected = b_.m_sz - b_.size (); DL((XDRBUFTRACE,"Bytes expected: %d\n",expected)); DL((XDRBUFTRACE,"Bytes in Socket buffer(s): %d\n", s_.getBytesAvail ())); int ret; if ((ret = s_.read (b_.m_ptr, expected)) <= 0) { #if defined(WIN32) if (WSAGetLastError () != WSAEWOULDBLOCK) { WSASetLastError (0); EL((ASSAERR,"Socket::read() error!\n")); b_.m_state = xdrIOBuffer::error; } #else if (errno != EWOULDBLOCK) { EL((ASSAERR,"Socket::read() error!\n")); b_.m_state = xdrIOBuffer::error; } #endif else { EL((ASSAERR,"Socket::read() error! \n")); } return s_; } b_.m_ptr += ret; DL((XDRBUFTRACE,"Received %d bytes\n", ret)); b_.dump (); if (b_.m_sz == b_.size ()) { // at the end DL((XDRBUFTRACE,"Complete message is in the buffer!\n")); b_.m_state = xdrIOBuffer::xmitted; b_.m_ptr = b_.m_buf; // rewind m_ptr for parsing stage b_.dump (); } return s_; } } // end namespace ASSA using namespace ASSA; xdrIOBuffer:: xdrIOBuffer (u_int sz_) : m_sz (sz_), m_state (waiting) { trace_with_mask("xdrIOBuffer::xdrIOBuffer", XDRBUFTRACE); m_buf = new char[sz_]; m_ptr = m_buf; memset (m_buf, 0, m_sz); DL((XDRBUF,"Allocated xdrIOBuffer [%d]\n",m_sz)); dump (); } xdrIOBuffer:: ~xdrIOBuffer () { trace_with_mask("xdrIOBuffer::~xdrIOBuffer", XDRBUFTRACE); DL((XDRBUFTRACE,"xdrIOBuffer->this = 0x%x\n", long(this))); delete [] m_buf; } xdrIOBuffer& xdrIOBuffer::operator= (const xdrIOBuffer& rhs_) { trace_with_mask("xdrIOBuffer::operator=()", XDRBUFTRACE); delete [] m_buf; copy (rhs_); return *this; } void xdrIOBuffer:: copy (const xdrIOBuffer& rhs_) { trace_with_mask("xdrIOBuffer::copy", XDRBUFTRACE); m_sz = rhs_.m_sz; m_buf = new char[m_sz]; memcpy (m_buf, rhs_.m_buf, m_sz); m_ptr = m_buf + (rhs_.size ()); m_state = rhs_.m_state; } xdrIOBuffer& xdrIOBuffer:: operator>>(int& n_) { trace_with_mask("xdrIOBuffer::operator>>(int)", XDRBUFTRACE); if (m_state != xmitted) { EL((ASSAERR,"Wrong state: %s\n", get_state ().c_str () )); return *this; } int val; int unit_sz = sizeof (int); memcpy ((char*) &val, m_ptr, unit_sz); m_ptr += unit_sz; n_ = (int) ntohl (val); if (size () == m_sz) m_state = parsed; return *this; } xdrIOBuffer& xdrIOBuffer:: operator>>(std::string& s_) { trace_with_mask("xdrIOBuffer::operator>>(string)", XDRBUFTRACE); if (m_state != xmitted) { EL((ASSAERR,"Wrong state: %s\n", get_state ().c_str () )); return *this; } /** XDR format for STL string is described in Socket::operator<< comments. */ s_ = ""; u_long len = (u_long) *m_ptr; char* cptr = m_ptr + 4; while (len--) { s_ += *cptr++; } m_ptr += Socket::xdr_length (s_); if (size () == m_sz) { m_state = parsed; } return *this; } xdrIOBuffer& xdrIOBuffer:: operator>>(float& n_) { trace_with_mask("xdrIOBuffer::operator>>(float)", XDRBUFTRACE); if (m_state != xmitted) { EL((ASSAERR,"Wrong state: %s\n", get_state ().c_str () )); return *this; } float val; int unit_sz = sizeof (float); memcpy ((char*) &val, m_ptr, unit_sz); m_ptr += unit_sz; XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &val, unit_sz, XDR_DECODE); xdr_float (&xdrs, &n_); xdr_destroy (&xdrs); if (size () == m_sz) m_state = parsed; return *this; } void xdrIOBuffer::reset () { trace_with_mask("xdrIOBuffer::reset", XDRBUFTRACE); m_ptr = m_buf; memset (m_buf, 0, m_sz); m_state = waiting; } string xdrIOBuffer:: get_state () const { string msg; switch (m_state) { case xdrIOBuffer::waiting: msg = "waiting"; break; case xdrIOBuffer::xmitted: msg = "xmitted"; break; case xdrIOBuffer::parsed: msg = "parsed"; break; case xdrIOBuffer::error: msg = "error"; break; } return msg; } void xdrIOBuffer:: dump () const { trace_with_mask("xdrIOBuffer::dump", XDRBUFTRACE); DL((XDRBUFTRACE,"xdrIOBuffer->this = 0x%x\n", long(this) )); DL((XDRBUFTRACE,"\n\n" \ "\tm_buf ........: 0x%x \n" \ "\tm_sz .........: %d \n" \ "\tm_ptr ........: 0x%x \n" \ "\tbytes left ...: %d \n" \ "\tm_state ......: %s \n\n", long (m_buf), m_sz, long (m_ptr),(m_sz - size ()), get_state ().c_str ())); if (m_ptr != m_buf) { MemDump image (m_buf, size ()); DL((XDRBUFTRACE,"Bytes in buffer so far:\n\n%s\n\n", image.getMemDump () )); } else if (m_ptr == m_buf && m_state == xmitted) { MemDump image (m_buf, (m_sz)); DL((XDRBUFTRACE,"Complete buffer:\n\n%s\n\n", image.getMemDump () )); } else { DL((XDRBUFTRACE,"Empty buffer\n" )); } }