OW_HTTPChunkedIStream.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00036 #include "OW_config.h"
00037 #include "OW_HTTPChunkedIStream.hpp"
00038 #include "OW_HTTPUtils.hpp"
00039 #include "OW_HTTPException.hpp"
00040 #include "OW_CIMException.hpp"
00041 #include "OW_CIMErrorException.hpp"
00042 
00043 namespace OW_NAMESPACE
00044 {
00045 
00046 using std::istream;
00048 HTTPChunkedIStreamBuffer::HTTPChunkedIStreamBuffer(istream& istr,
00049    HTTPChunkedIStream* chunker)
00050    : BaseStreamBuffer(HTTP_BUF_SIZE, "in"), m_istr(istr),
00051    m_inLen(0), m_inPos(0), m_isEOF(false), m_pChunker(chunker)
00052 {
00053 }
00055 HTTPChunkedIStreamBuffer::~HTTPChunkedIStreamBuffer()
00056 {
00057 }
00059 int
00060 HTTPChunkedIStreamBuffer::buffer_from_device(char* c, int n)
00061 {
00062    if (m_isEOF || n < 0)
00063    {
00064       return -1;
00065    }
00066    unsigned int un = n; 
00067    unsigned int tmpInLen = 0;
00068    unsigned int offset = 0;
00069    unsigned int lastRead = 0;
00070    while (offset < un && m_istr.good())
00071    {
00072       if (m_inLen == 0)
00073       {
00074          m_istr >> std::hex >> m_inLen >> std::dec;
00075          if (m_istr.fail() || m_istr.bad())
00076          {
00077             return -1;
00078          }
00079             //OW_THROW(HTTPChunkException, "Invalid length in chunk header");
00080                // skip past the trailing \r\n
00081          while (m_istr.get() != '\n' && m_istr.good())
00082          {
00083             // do nothing
00084          }
00085 
00086          m_inPos = 0;
00087          if (m_inLen == 0)
00088          {
00089             // reset the state
00090             m_isEOF = true;
00091             m_pChunker->buildTrailerMap(); // build the trailer map
00092             return offset;
00093          }
00094       }
00095       // min of (n - offset) and (m_inLen - m_inPos)
00096       tmpInLen = ((un - offset) < (m_inLen - m_inPos)) ? (un - offset)
00097          : (m_inLen - m_inPos);
00098       m_istr.read(c + offset, tmpInLen);
00099       lastRead = m_istr.gcount(); 
00100       offset += lastRead;
00101       m_inPos += lastRead;
00102       if (m_inPos == m_inLen)
00103       {
00104          m_inLen = 0; 
00105          m_inPos = 0;
00106          // don't need to skip trailing \r\n, because formatted input will
00107          // skip it.
00108       }
00109       if (lastRead < tmpInLen) // eof from other side
00110       {
00111          break;
00112       }
00113    }
00114    return offset; // should be equal to n if we reached this.
00115 }
00117 void
00118 HTTPChunkedIStreamBuffer::resetInput()
00119 {
00120    initGetBuffer();
00121    m_inLen = 0; 
00122    m_inPos = 0;
00123    m_isEOF = false;
00124 }
00127 HTTPChunkedIStream::HTTPChunkedIStream(istream& istr)
00128    : HTTPChunkedIStreamBase(istr, this)
00129    , CIMProtocolIStreamIFC(&m_strbuf)
00130    , m_istr(istr)
00131    , m_trailerMap()
00132 {
00133 }
00135 HTTPChunkedIStream::~HTTPChunkedIStream()
00136 {
00137 }
00139 void
00140 HTTPChunkedIStream::resetInput()
00141 {
00142    clear();
00143    m_strbuf.resetInput();
00144 }
00146 void
00147 HTTPChunkedIStream::buildTrailerMap()
00148 {
00149    if (!HTTPUtils::parseHeader(m_trailerMap, m_istr))
00150    {
00151       m_trailerMap.clear();
00152       OW_THROW(HTTPException, "Error parsing trailers");
00153    }
00154 }
00156 String
00157 HTTPChunkedIStream::getTrailer(const String& key) const
00158 {
00159    for (Map<String, String>::const_iterator iter = m_trailerMap.begin();
00160         iter != m_trailerMap.end(); ++iter)
00161    {
00162       if (iter->first.substring(3).equalsIgnoreCase(key))
00163       {
00164          return iter->second;
00165       }
00166    }
00167    return String();
00168 }
00170 // TODO: Move all this knowledge about CIM and specific trailers into HTTPClient
00171 void HTTPChunkedIStream::checkForError() const
00172 {
00173    String errorStr;
00174    errorStr = getTrailer("CIMError");
00175    if (!errorStr.empty())
00176    {
00177       OW_THROW(CIMErrorException, errorStr.c_str());
00178    }
00179    errorStr = getTrailer("CIMStatusCode");
00180    if (errorStr.empty())
00181    {
00182       // try the old OW 2.0.x pre-standard way
00183       errorStr = getTrailer("CIMErrorCode");
00184    }
00185    if (!errorStr.empty())
00186    {
00187       String descr;
00188       descr = getTrailer("CIMStatusDescription");
00189       if (descr.empty())
00190       {
00191          // try the old OW 2.0.x pre-standard way
00192          descr = getTrailer("CIMErrorDescription");
00193       }
00194       if (!descr.empty())
00195       {
00196          OW_THROWCIMMSG(CIMException::ErrNoType(errorStr.toInt32()),
00197             descr.c_str());
00198       }
00199       else
00200       {
00201          OW_THROWCIM(CIMException::ErrNoType(errorStr.toInt32()));
00202       }
00203    }
00204 }
00206 
00207 } // end namespace OW_NAMESPACE
00208 

Generated on Thu Feb 9 08:47:59 2006 for openwbem by  doxygen 1.4.6