⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbinethttpstream.cpp

📁 sloedgy open sip stack source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:

 /****************License************************************************
  *
  * Copyright 2000-2003.  ScanSoft, Inc.    
  *
  * Use of this software is subject to notices and obligations set forth 
  * in the SpeechWorks Public License - Software Version 1.2 which is 
  * included with this software. 
  *
  * ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech, 
  * SpeechWorks and the SpeechWorks logo are registered trademarks or 
  * trademarks of SpeechWorks International, Inc. in the United States 
  * and other countries.
  *
  ***********************************************************************/
 #include <vxibuildopts.h>
#if P_VXI

#ifndef _SB_USE_STD_NAMESPACE
 #define _SB_USE_STD_NAMESPACE
 #endif
 
 #ifdef WIN32
 
 #ifndef UNICODE
 #define UNICODE
 #endif
 #ifndef _UNICODE
 #define _UNICODE
 #endif
 
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
 #include <windows.h>
 #endif
 
 #include <sys/timeb.h>                  // for _ftime( )/ftime( )
 
 #include "vxi/VXIvalue.h"
 #include "vxi/VXIinet.h"
 #include "vxi/VXItrd.h"
 
 #include "SBinetLog.h"
 #include "SBinetURL.h"
 #include "SBinetHttpStream.hpp"
 #include "SBinetChannel.h"
 #include "SBinetHttpConnection.hpp"
 #include "SBinetValidator.h"
 #include "SBinetCookie.h"
 #include "SBinetUtils.hpp"
 #include "SWITimeWatch.hpp"
 
 #include "util_date.h"
 #include "ap_ctype.h"
 #include "HttpUtils.hpp"
 #include <vxi/SWIsocket.hpp>
 #include <vxi/SWIdataOutputStream.hpp>
 #include <vxi/SWIbufferedInputStream.hpp>
 #include <vxi/SWIbufferedOutputStream.hpp>

#if defined(_MSC_VER)
#pragma warning(disable:4061)
#endif
 
 #define HTTP_UNDEFINED -1234  /* No HTTP error code yet */
 
 #define READ_CHUNK_SIZE 128 * 1024 // Read from socket in 128 Kb chunks
 
 SBinetHttpStream::SBinetHttpStream(SBinetURL* url,
                                    SubmitMethod method,
                                    SBinetChannel* ch,
                                    VXIlogInterface *log,
                                    VXIunsigned diagLogBase):
   SBinetStoppableStream(url, log, diagLogBase),
   _HttpStatus(HTTP_UNDEFINED), _leftToRead((unsigned)~0), _chunked(false),
   _method(method), _channel(ch), _connection(NULL),
   _inputStream(NULL), _outputStream(NULL),
   _closeConnection(TRUE), _validator(NULL), _connectionAborted(FALSE)
 {}
 
 SBinetHttpStream::~SBinetHttpStream()
 {
   delete _validator;
   Close();
 }
 
 VXIinetResult SBinetHttpStream::initSocket(SubmitMethod method,
                                            const VXIMap *properties,
                                            VXIMap *streamInfo)
 {
   _connection = _channel->getHttpConnection(_url, properties);
 
   if (_connection == NULL)
   {
     Error(262, L"%s%s", L"URL", _url->getAbsolute());
     return VXIinet_RESULT_FETCH_ERROR;
   }
 
   SWITimeWatch timeWatch;
   timeWatch.start();
 
   switch (_connection->connect(getDelay()))
   {
    case SWIstream::TIMED_OUT:
      Error(241, NULL);
      return VXIinet_RESULT_FETCH_TIMEOUT;
      break;
    case SWIstream::SUCCESS:
      break;
    default:
      Error(244, L"%s%s", L"URL", _url->getAbsolute());
      return VXIinet_RESULT_FETCH_ERROR;
   }
 
   _inputStream = _connection->getInputStream();
   _outputStream = _connection->getOutputStream();
 
   Diag(MODULE_SBINET_TIMING_TAGID, L"SBinetHttpStream::initSocket",
        L"%i msecs, Connect to socket", timeWatch.getElapsed());
 
   writeDebugTimeStamp();
 
   if (method == SBinetHttpStream::GET_METHOD)
     _channel->writeString(_outputStream, "GET ");
   else
     _channel->writeString(_outputStream, "POST ");
 
   if (_connection->usesProxy())
     _channel->writeString(_outputStream, _url->getNAbsolute());
   else
     _channel->writeString(_outputStream, _url->getNPath());
 
   _channel->writeString(_outputStream, " HTTP/1.1" CRLF);
   _channel->writeString(_outputStream, "Accept: */*" CRLF);
 
   // Write HOST header.
   _channel->writeString(_outputStream, "Host: ");
   _channel->writeString(_outputStream, _url->getNHost());
   int defaultPort = _url->getProtocol() == SBinetURL::HTTP_PROTOCOL ? 80 : 443;
   int port = _url->getPort();
 
   if (port != defaultPort)
   {
     _channel->writeString(_outputStream, ":");
     _channel->writeInt(_outputStream, port);
   }
   _channel->writeString(_outputStream, CRLF);
 
   // Write USER-AGENT header.
   _channel->writeString(_outputStream, "User-Agent: ");
   _channel->writeString(_outputStream, _channel->getUserAgent());
   _channel->writeString(_outputStream, CRLF);
 
   // Write REFERER header.
   SBinetNString baseUrl = _url->getNBase();
   if (baseUrl.length() > 0)
   {
     // Cut query arguments, if present
     VXIunsigned queryArgsSeparator = baseUrl.find('?');
     if (queryArgsSeparator < baseUrl.length())
       baseUrl.resize(queryArgsSeparator);
 
     if (baseUrl.length() > 0)
     {
       _channel->writeString(_outputStream, "Referer: ");
       _channel->writeString(_outputStream, baseUrl.c_str());
       _channel->writeString(_outputStream, CRLF);
     }
   }
 
   SBinetUtils::getInteger(properties, INET_CLOSE_CONNECTION, _closeConnection);
 
   if (_closeConnection)
   {
     _channel->writeString(_outputStream, "Connection: close" CRLF);
   }
 
   VXIint32 maxAge = -1;
   VXIint32 maxStale = -1;
 
   getCacheInfo(properties, maxAge, maxStale);
 
   if (maxAge != -1)
   {
     _channel->writeString(_outputStream, "Cache-Control: max-age=");
     _channel->writeInt(_outputStream, maxAge);
     _channel->writeString(_outputStream, CRLF);
   }
 
   if (maxStale != -1)
   {
     _channel->writeString(_outputStream, "Cache-Control: max-stale=");
     _channel->writeInt(_outputStream, maxStale);
     _channel->writeString(_outputStream, CRLF);
   }
 
   time_t lastModified = (time_t) -1;
   SBinetNString etag;
 
   getModInfo(properties, lastModified, etag);
 
   if (method == SBinetHttpStream::GET_METHOD && lastModified != (time_t) -1)
   {
     char lastModStr[32];
     ap_gm_timestr_822(lastModStr, lastModified);
     _channel->writeString(_outputStream, "If-Modified-Since: ");
     _channel->writeString(_outputStream, lastModStr);
     _channel->writeString(_outputStream, CRLF);
   }
 
   if (etag[0])
   {
     _channel->writeString(_outputStream, "If-None-Match: ");
     _channel->writeString(_outputStream, etag.c_str());
     _channel->writeString(_outputStream, CRLF);
   }
 
   if (_channel->cookiesEnabled())
   {
     _channel->collectCookies(_outputStream, _url->getNHost(), _url->getNPath());
   }
 
   return VXIinet_RESULT_SUCCESS;
 }
 
 VXIinetResult SBinetHttpStream::doGet(VXIint32 flags,
                                       const VXIMap *properties,
                                       VXIMap *streamInfo)
 
 {
   VXIinetResult rc = initSocket(GET_METHOD, properties, streamInfo);
   if (rc != VXIinet_RESULT_SUCCESS)
     return rc;
 
   _channel->writeString(_outputStream, CRLF);
 
   if (_outputStream->flush() != SWIstream::SUCCESS)
     rc = VXIinet_RESULT_IO_ERROR;
 
   return rc;
 }
 
 /*
  * POST simple form data. Don't know how to combine Form data and audio in multipart POST
  */
 VXIinetResult SBinetHttpStream::doPost(VXIint32 flags,
                                        const VXIMap *properties,
                                        VXIMap *streamInfo)
 {
   const VXIMap *queryArgs =
     (const VXIMap *)VXIMapGetProperty(properties, INET_URL_QUERY_ARGS);
 
   SBinetNString queryArgsStr;
   VXIint argsLen;
 
   EncodingType encodingType = getEncodingType(properties);
   const char *encodingStr;
 
   if (encodingType == TYPE_MULTIPART)
   {
     encodingStr = SB_MULTIPART;
     queryArgsStr = _url->queryArgsToMultipart(queryArgs);
     argsLen = queryArgsStr.length();
     Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetHttpStream::doPost",
          L"Performing multipart POST, data size %i", argsLen);
   }
   else
   {
     encodingStr = SB_URLENCODED;
     queryArgsStr = _url->queryArgsToNString(queryArgs);
     argsLen = queryArgsStr.length();
     Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetHttpStream::doPost",
          L"Performing URL-encoded POST, data size %i", argsLen);
   }
 
   VXIinetResult rc = initSocket(POST_METHOD, properties, streamInfo);
 
   if (rc != VXIinet_RESULT_SUCCESS)
     return rc;
 
   _channel->writeString(_outputStream, "Expect: 100-continue" CRLF);
 
   _channel->writeString(_outputStream, "Content-Length: ");
   _channel->writeInt(_outputStream, argsLen);
   _channel->writeString(_outputStream, CRLF);
 
   _channel->writeString(_outputStream, "Content-Type: ");
   _channel->writeString(_outputStream, encodingStr);
   _channel->writeString(_outputStream, CRLF CRLF);
 
   if (_outputStream->flush() != SWIstream::SUCCESS)
   {
     return VXIinet_RESULT_IO_ERROR;
   }
 
   // Wait for input stream to be ready.  If time-out, just send data anyway.
   // If we don't time out, we should be able to get an HTTP_CONTINUE.
   VXIint32 continueTimeout = SBinetChannel::getPostContinueTimeout();
   int maxDelay = getDelay();
   if (continueTimeout < 0 ||
       (maxDelay >=0 && continueTimeout > maxDelay))
     continueTimeout = maxDelay;
 
   switch (_inputStream->waitReady(continueTimeout))
   {
    case SWIstream::SUCCESS:
      // Read the HTTP_CONTINUE header
      if ((rc = getHeaderInfo(streamInfo)) != VXIinet_RESULT_SUCCESS)
        return rc;
 
      if (_HttpStatus != SBinetHttpUtils::HTTP_CONTINUE)
        return VXIinet_RESULT_FETCH_ERROR;
 
      break;
    case SWIstream::TIMED_OUT:
      // We still have to send the body of the message.  This is done
      // after the switch anyway so we do nothing.
      break;
    default:
      // I/O error on the stream.  Just return an error.
      return VXIinet_RESULT_FETCH_ERROR;
   }
 
   if (encodingType == TYPE_MULTIPART)
   {
     _channel->writeData(_outputStream, queryArgsStr.data(), argsLen);
   }
   else
   {
     _channel->writeString(_outputStream, queryArgsStr.c_str());
   }
 
   if (_outputStream->flush() != SWIstream::SUCCESS)
     rc = VXIinet_RESULT_IO_ERROR;
 
   return rc;
 }
 
 bool SBinetHttpStream::handleRedirect(VXIMap *streamInfo)
 {
   const VXIchar *location;
 
   switch (_HttpStatus)
   {
     case SBinetHttpUtils::HTTP_SEE_OTHER:
      // This return code implies that we change a POST into a GET.
      _method = GET_METHOD;
      // no break: intentional
 
    case SBinetHttpUtils::HTTP_MULTIPLE_CHOICES:
    case SBinetHttpUtils::HTTP_PERM_REDIRECT:
    case SBinetHttpUtils::HTTP_FOUND:
    case SBinetHttpUtils::HTTP_TEMP_REDIRECT:
      location = SBinetUtils::getString(streamInfo, L"Location");
      if (location == NULL || !*location)
      {
        Error(247, L"%s%s", L"URL", _url->getAbsolute());
        return false;
      }
 
      if (_url->parse(location, _url->getAbsolute()) != VXIinet_RESULT_SUCCESS)
      {
        Error(248, L"%s%s%s%s", L"URL", _url->getAbsolute(),
              L"Location", location);
        return false;
      }
 
      return true;
      break;
    default:
      return false;
   }
 }
 
 // stupid function required because the people who designed VXIMap, in their
 // great wisdom, did not include a VXIMapClear function or the ability for the
 // iterator to delete the current entry.
 static void clearMap(VXIMap *streamInfo)
 {
   VXIunsigned n = VXIMapNumProperties(streamInfo);
   const VXIchar **keys = new const VXIchar *[n];
   const VXIchar *key;
   const VXIValue *value;
 
   int i = 0;
 
   VXIMapIterator *mapIterator = VXIMapGetFirstProperty(streamInfo,
                                                        &key,
                                                        &value );
   do
   {
     if (key != NULL)
     {
       keys[i++] = key;
     }
   }
   while (VXIMapGetNextProperty(mapIterator, &key, &value) == VXIvalue_RESULT_SUCCESS);
 
   VXIMapIteratorDestroy(&mapIterator);
   i--;
 
   while (--i >= 0)
   {
     VXIMapDeleteProperty(streamInfo, keys[i]);
   }
 
   delete [] keys;
 }
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -