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

📄 sbinethttpstream.cpp

📁 sloedgy open sip stack source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
 
 VXIinetResult
 SBinetHttpStream::Open(VXIint32                  flags,
 		       const VXIMap             *properties,
 		       VXIMap                   *streamInfo)
 {
   VXIinetResult rc;
 
   // Make a copy in case of redirect.
   SBinetString initialUrl = _url->getAbsolute();
 
   const int maxRedirect = 5;
   int nbRedirect = 0;
   time_t requestTime = (time_t) -1;
 
   for (;;)
   {
     // Set up request
     rc = VXIinet_RESULT_NON_FATAL_ERROR;
     _HttpStatus = HTTP_UNDEFINED;
     requestTime = time(NULL);
     _chunked = false;
     _leftToRead = (unsigned)~0;
     _closeConnection = !SBinetChannel::getUsePersistentConnections();
     _connectionAborted = FALSE;
 
     if (_method == GET_METHOD)
       rc = doGet(flags, properties, streamInfo);
     else if (_method == POST_METHOD)
       rc = doPost(flags, properties, streamInfo);
 
     if (rc != VXIinet_RESULT_SUCCESS)
     {
       _closeConnection = TRUE;
       break;
     }
     else if ((rc = getHeaderInfo(streamInfo)) != VXIinet_RESULT_SUCCESS)
     {
       if (_connectionAborted)
       {
         _closeConnection = TRUE;
         Close();
 
         // Clear the streamInfo map so that previous fetch attributes do not
         // remain in the map.
         if (streamInfo != NULL)
           clearMap(streamInfo);
 
         continue;
       }
       else
       {
         _closeConnection = TRUE;
         break;
       }
     }
 
     // Avoid race condition on 100-Continue time-out.  If we got a CONTINUE
     // from previous call to getHeaderInfo, we need to get it again.
     if (_HttpStatus == SBinetHttpUtils::HTTP_CONTINUE &&
         (rc = getHeaderInfo(streamInfo)) != VXIinet_RESULT_SUCCESS)
     {
       _closeConnection = TRUE;
       break;
     }
 
     if (_HttpStatus >= 300 && _HttpStatus <= 399 &&
         handleRedirect(streamInfo))
     {
       // perform a reset on the stream.
       Close();
       if (++nbRedirect > maxRedirect)
       {
         Error(229, L"%s%s", L"URL", initialUrl.c_str());
         return VXIinet_RESULT_FETCH_ERROR;
       }
       // Clear the streamInfo map to avoid previous fetch attribute to remain
       // in the map.
       if (streamInfo != NULL)
         clearMap(streamInfo);
     }
     else
       break;
   }
 
   if (streamInfo != NULL && _HttpStatus >= 100 && _HttpStatus <= 999)
   {
     VXIMapSetProperty(streamInfo, INET_INFO_HTTP_STATUS,
                       (VXIValue*) VXIIntegerCreate(_HttpStatus));
   }
 
   switch (_HttpStatus)
   {
    case SBinetHttpUtils::HTTP_OK:
      if (streamInfo != NULL)
      {
        processHeaderInfo(streamInfo);
        setValidatorInfo(streamInfo, requestTime);
      }
      rc = VXIinet_RESULT_SUCCESS;
      break;
    case SBinetHttpUtils::HTTP_NOT_MODIFIED:
      if (streamInfo != NULL) setValidatorInfo(streamInfo, requestTime);
      Close();
      rc = VXIinet_RESULT_NOT_MODIFIED;
      break;
    default:
      Close();
 
      // Map the HTTP error code
      if (_HttpStatus != HTTP_UNDEFINED)
      {
        const VXIchar *errorDesc;
        rc = MapError(_HttpStatus, &errorDesc);
        Error(219, L"%s%s%s%s%s%d%s%s", L"URL", initialUrl.c_str(),
              L"Method", (_method == GET_METHOD) ? L"GET" : L"POST",
              L"HTTPStatus", _HttpStatus, L"HTTPStatusDescription", errorDesc);
      }
      else
      {
        Error(217, L"%s%s", L"URL", initialUrl.c_str());
        rc = VXIinet_RESULT_NON_FATAL_ERROR;
      }
      break;
   }
 
   return rc;
 }
 
 
 VXIinetResult SBinetHttpStream::Close()
 {
   if (_connection != NULL)
   {
     if (_closeConnection)
       delete _connection;
     else
     {
       // First make sure there is nothing left in the body.
       VXIinetResult rc = skipBody();
       if (rc == VXIinet_RESULT_SUCCESS)
         _channel->putHttpConnection(_connection);
       else
         delete _connection;
     }
 
     _connection = NULL;
     _inputStream = NULL;
     _outputStream = NULL;
   }
 
   return(VXIinet_RESULT_SUCCESS);
 }
 
 
 VXIinetResult SBinetHttpStream::skipBody()
 {
   // These HTTP status code do not allow for a body.
   if (_HttpStatus == SBinetHttpUtils::HTTP_NOT_MODIFIED ||
       _HttpStatus == SBinetHttpUtils::HTTP_NO_DATA  ||
       (_HttpStatus >= 100 && _HttpStatus <= 199))
     return VXIinet_RESULT_SUCCESS;
 
   VXIinetResult rc;
   VXIbyte buffer[1024];
 
   while ((rc = Read(buffer, sizeof(buffer), NULL)) == VXIinet_RESULT_SUCCESS);
   if (rc == VXIinet_RESULT_END_OF_STREAM)
     rc = VXIinet_RESULT_SUCCESS;
 
   return rc;
 }
 
 SBinetHttpStream::EncodingType SBinetHttpStream::getEncodingType(const VXIMap *properties)
 {
   SBinetHttpStream::EncodingType encodingType = TYPE_URL_ENCODED;
 
   // Get the submit MIME type from the properties, if defined
   const VXIchar *strType =
     SBinetUtils::getString(properties, INET_SUBMIT_MIME_TYPE);
 
   if (strType && *strType)
   {
     // If DEFAULT ever changes, this code will need to be updated
     if (::wcscmp(strType, INET_SUBMIT_MIME_TYPE_DEFAULT) == 0)
       encodingType = TYPE_URL_ENCODED;
     else if (::wcscmp(strType, L"multipart/form-data") == 0)
       encodingType = TYPE_MULTIPART;
     else
       Error(304, L"%s%s%s%s%s%s", L"URL", _url->getAbsolute(),
             L"EncodingType", strType,
             L"DefaultType", INET_SUBMIT_MIME_TYPE_DEFAULT);
   }
 
   return encodingType;
 }
 
 VXIinetResult SBinetHttpStream::getStatus()
 {
   _HttpStatus = HTTP_UNDEFINED;
 
   VXIinetResult rc = waitStreamReady();
   if (rc != VXIinet_RESULT_SUCCESS)
     return rc;
 
   writeDebugTimeStamp();
 
   // The HTTP status line should have the following syntax:
   // HTTP/x.x yyy msg CRLF
   //
   // This is buggy if we ever see an HTTP/1.xx in the future
   SWIdataOutputStream line;
   const char *c_line = NULL;
 
   SWIstream::Result src = _channel->readLine(_inputStream, &line);
   if (src >= 0)
   {
     if (ap_checkmask(c_line = line.getString(), "HTTP/#.# ###*"))
     {
       _HttpStatus = atoi(&c_line[9]);
       int version = (c_line[5] - '0') * 10 + (c_line[7] - '0');
       if (version < 11) _closeConnection = TRUE;
     }
     else
     {
       Error(249, L"%s%s", L"URL", _url->getAbsolute());
     }
   }
   // A return value of END_OF_FILE means the connection was gracefully closed.
   // A return value of CONNECTION_ABORTED means the connection was aborted
   // because of a time out or some other problem.
   else if ((src == SWIstream::CONNECTION_ABORTED) || (src == SWIstream::END_OF_FILE))
   {
     // Return immediately and do not check the _HttpStatus since
     // we don't want to print errors for nothing.
     _connectionAborted = true;
     return VXIinet_RESULT_NON_FATAL_ERROR;
   }
   else
   {
     Error(249, L"%s%s", L"URL", _url->getAbsolute());
   }
 
   if (_HttpStatus < 100 || _HttpStatus > 999)
   {
     if (_HttpStatus != HTTP_UNDEFINED)
     {
       Error(219, L"%s%s%s%s%s%d",
             L"URL", _url->getAbsolute(),
             L"Method", _method == GET_METHOD ? L"GET" : L"POST",
             L"HTTPStatus", _HttpStatus);
     }
     else
     {
       Error(221, L"%s%s", L"URL", _url->getAbsolute());
     }
     rc = VXIinet_RESULT_NON_FATAL_ERROR;
   }
 
   return rc;
 }
 
 enum HandlerValueType
 {
   HANDLER_INT = 0x01,
   HANDLER_DATE = 0x02,
   HANDLER_STRING = 0x04,
   HANDLER_CONTENT = 0x08,
   HANDLER_LIST = 0x10
 };
 
 
 // Currently doing a linear search because of case-insenstivity of
 // comparisons.  If the number of entries in this array increases, we should
 // consider using a hash implementation instead.
 SBinetHttpStream::HeaderInfo SBinetHttpStream::headerInfoMap[] =
 {
   { "Age", NULL, HANDLER_INT, NULL },
   { "Cache-Control", NULL, HANDLER_STRING | HANDLER_LIST, NULL },
   { "Content-Length", INET_INFO_SIZE_BYTES, HANDLER_INT, contentLengthHandler },
   { "Content-Type", INET_INFO_MIME_TYPE, HANDLER_STRING, NULL },
   { "Connection", NULL, HANDLER_STRING, connectionHandler },
   { "Date", NULL, HANDLER_DATE, NULL },
   { "ETag", NULL, HANDLER_STRING, NULL },
   { "Expires", NULL, HANDLER_DATE, NULL },
   { "Last-Modified", NULL, HANDLER_DATE, NULL },
   { "Location", NULL, HANDLER_STRING, NULL },
   { "Pragma", NULL, HANDLER_STRING, NULL },
   { "Set-Cookie", NULL, HANDLER_STRING, setCookieHandler },
   { "Set-Cookie2", NULL, HANDLER_STRING, setCookie2Handler },
   { "Transfer-Encoding", NULL, HANDLER_STRING, transferEncodingHandler},
   { NULL, NULL, 0, NULL }
 };
 
 void SBinetHttpStream::setCookieHandler(HeaderInfo *headerInfo,
                                         const char *value,
                                         SBinetHttpStream *httpStream,
                                         VXIMap *streamInfo)
 {
   if (!httpStream->_channel->cookiesEnabled())
     return;
 
   const char *p = value;
 
   while (p != NULL && *p)
   {
     SBinetCookie *cookie = SBinetCookie::parse(httpStream->_url, p, httpStream);
     if (cookie != NULL)
     {
       httpStream->_channel->updateCookie(cookie);
     }
   }
   httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
                    L"SBinetHttpStream::setCookieHandler",
                    L"Set-Cookie: %S", value);
 }
 
 void SBinetHttpStream::setCookie2Handler(HeaderInfo *headerInfo,
                                          const char *value,
                                          SBinetHttpStream *httpStream,
                                          VXIMap *streamInfo)
 {
   if (!httpStream->_channel->cookiesEnabled())
     return;
 
   httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
                    L"SBinetHttpStream::setCookie2Handler",
                    L"Not Supported: \"Set-Cookie2: %S\"", value);
 }
 
 void SBinetHttpStream::contentLengthHandler(HeaderInfo *headerInfo,
                                             const char *value,
                                             SBinetHttpStream *httpStream,
                                             VXIMap *streamInfo)
 {
   // Ignore content-length is stream is chunked.
   if (!httpStream->_chunked)
   {
     httpStream->_leftToRead = atoi(value);
   }
 }
 
 void SBinetHttpStream::connectionHandler(HeaderInfo *headerInfo,
                                          const char *value,
                                          SBinetHttpStream *httpStream,
                                          VXIMap *streamInfo)
 {
   SBinetNString attrib;
 
   for (;;)
   {
     if ((value = SBinetHttpUtils::getValue(value, attrib)) == NULL)
     {
       httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
                        L"SBinetHttpStream::connectionHandler",
                        L"Could not get attribute.");
       break;
     }
 
     if ((value = SBinetHttpUtils::expectChar(value, ",")) == NULL)
     {
       httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
                        L"SBinetHttpStream::connectionHandler",
                        L"Expecting ','.");
       break;
     }
 
     if (::strcasecmp(attrib.c_str(), "close") == 0)
     {
       httpStream->_closeConnection = TRUE;
     }
 
     // Skip comma, or if at end of string, stop parsing.
     if (*value)
       value++;
     else
       break;
   }
 }
 
 void SBinetHttpStream::transferEncodingHandler(HeaderInfo *headerInfo,
                                                const char *value,
                                                SBinetHttpStream *httpStream,
                                                VXIMap *streamInfo)
 {
   SBinetNString encoding;
 
   for (;;)
   {
     if ((value = SBinetHttpUtils::getValue(value, encoding)) == NULL)
     {
       httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
                        L"SBinetHttpStream::transferEncodingHandler",
                        L"Could not get encoding.");
       break;
     }
 
     if ((value = SBinetHttpUtils::expectChar(value, ",")) == NULL)
     {
       httpStream->Diag(MODULE_SBINET_STREAM_TAGID,
                        L"SBinetHttpStream::transferEncodingHandler",
                        L"Expecting ','.");
       break;
     }
 
     if (::strcasecmp(encoding.c_str(), "chunked") == 0)
     {
       httpStream->_chunked = true;
       httpStream->_leftToRead = 0;
     }

⌨️ 快捷键说明

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