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

📄 httpclnt.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
    outMIME.SetAt(ConnectionTag, KeepAliveTag);

  for (PINDEX retry = 0; retry < 3; retry++) {
    if (!AssureConnect(url, outMIME))
      break;

    if (!WriteCommand(cmdName, url.AsString(PURL::URIOnly), outMIME, dataBody)) {
      lastResponseCode = -1;
      lastResponseInfo = GetErrorText(LastWriteError);
      break;
    }

    // If not persisting need to shut down write so other end stops reading
    if (!persist)
      Shutdown(ShutdownWrite);

    // Await a response, if all OK exit loop
    if (ReadResponse(replyMime))
      break;

    // If not persisting, we have no oppurtunity to write again, just error out
    if (!persist)
      break;

    // If have had a failure to read a response but there was no error then
    // we have a shutdown socket probably due to a lack of persistence so ...
    if (GetErrorCode(LastReadError) != NoError)
      break;

    // ... we close the channel and allow AssureConnet() to reopen it.
    Close();
  }

  return lastResponseCode;
}


BOOL PHTTPClient::WriteCommand(Commands cmd,
                               const PString & url,
                               PMIMEInfo & outMIME,
                               const PString & dataBody)
{
  return WriteCommand(commandNames[cmd], url, outMIME, dataBody);
}


BOOL PHTTPClient::WriteCommand(const PString & cmdName,
                               const PString & url,
                               PMIMEInfo & outMIME,
                               const PString & dataBody)
{
  ostream & this_stream = *this;
  PINDEX len = dataBody.GetSize()-1;
  if (!outMIME.Contains(ContentLengthTag))
    outMIME.SetInteger(ContentLengthTag, len);

  if (cmdName.IsEmpty())
    this_stream << "GET";
  else
    this_stream << cmdName;

  this_stream << ' ' << (url.IsEmpty() ? "/" :  (const char*) url) << " HTTP/1.1\r\n"
              << setfill('\r') << outMIME;

  return Write((const char *)dataBody, len);
}


BOOL PHTTPClient::ReadResponse(PMIMEInfo & replyMIME)
{
  PString http = ReadString(7);
  if (!http) {
    UnRead(http);

    if (http.Find("HTTP/") == P_MAX_INDEX) {
      lastResponseCode = PHTTP::RequestOK;
      lastResponseInfo = "HTTP/0.9";
      return TRUE;
    }

    if (http[0] == '\n')
      ReadString(1);
    else if (http[0] == '\r' &&  http[1] == '\n')
      ReadString(2);

    if (PHTTP::ReadResponse())
      if (replyMIME.Read(*this))
        return TRUE;
  }
 
  lastResponseCode = -1;
  if (GetErrorCode(LastReadError) != NoError)
    lastResponseInfo = GetErrorText(LastReadError);
  else {
    lastResponseInfo = "Premature shutdown";
    SetErrorValues(ProtocolFailure, 0, LastReadError);
  }

  return FALSE;
}


BOOL PHTTPClient::ReadContentBody(PMIMEInfo & replyMIME, PString & body)
{
  BOOL ok = InternalReadContentBody(replyMIME, body);
  body.SetSize(body.GetSize()+1);
  return ok;
}


BOOL PHTTPClient::ReadContentBody(PMIMEInfo & replyMIME, PBYTEArray & body)
{
  return InternalReadContentBody(replyMIME, body);
}


BOOL PHTTPClient::InternalReadContentBody(PMIMEInfo & replyMIME, PAbstractArray & body)
{
  PCaselessString encoding = replyMIME(TransferEncodingTag);

  if (encoding != ChunkedTag) {
    if (replyMIME.Contains(ContentLengthTag)) {
      PINDEX length = replyMIME.GetInteger(ContentLengthTag);
      body.SetSize(length);
      return ReadBlock(body.GetPointer(), length);
    }

    if (!(encoding.IsEmpty())) {
      lastResponseCode = -1;
      lastResponseInfo = "Unknown Transfer-Encoding extension";
      return FALSE;
    }

    // Must be raw, read to end file variety
    static const PINDEX ChunkSize = 2048;
    PINDEX bytesRead = 0;
    while (ReadBlock((char *)body.GetPointer(bytesRead+ChunkSize)+bytesRead, ChunkSize))
      bytesRead += GetLastReadCount();

    body.SetSize(bytesRead + GetLastReadCount());
    return GetErrorCode(LastReadError) == NoError;
  }

  // HTTP1.1 chunked format
  PINDEX bytesRead = 0;
  for (;;) {
    // Read chunk length line
    PString chunkLengthLine;
    if (!ReadLine(chunkLengthLine))
      return FALSE;

    // A zero length chunk is end of output
    PINDEX chunkLength = chunkLengthLine.AsUnsigned(16);
    if (chunkLength == 0)
      break;

    // Read the chunk
    if (!ReadBlock((char *)body.GetPointer(bytesRead+chunkLength)+bytesRead, chunkLength))
      return FALSE;
    bytesRead+= chunkLength;

    // Read the trailing CRLF
    if (!ReadLine(chunkLengthLine))
      return FALSE;
  }

  // Read the footer
  PString footer;
  do {
    if (!ReadLine(footer))
      return FALSE;
  } while (replyMIME.AddMIME(footer));

  return TRUE;
}


BOOL PHTTPClient::GetTextDocument(const PURL & url,
                                  PString & document,
                                  BOOL persist)
{
  PMIMEInfo outMIME, replyMIME;
  if (!GetDocument(url, outMIME, replyMIME, persist))
    return FALSE;

  return ReadContentBody(replyMIME, document);
}


BOOL PHTTPClient::GetDocument(const PURL & _url,
                              PMIMEInfo & _outMIME,
                              PMIMEInfo & replyMIME,
                              BOOL persist)
{
  int count = 0;
  static const char locationTag[] = "Location";
  PURL url = _url;
  for (;;) {
    PMIMEInfo outMIME = _outMIME;
    replyMIME.RemoveAll();
    PString u = url.AsString();
    int code = ExecuteCommand(GET, url, outMIME, PString(), replyMIME, persist);
    switch (code) {
      case RequestOK:
        return TRUE;
      case MovedPermanently:
      case MovedTemporarily:
        {
          if (count > 10)
            return FALSE;
          PString str = replyMIME(locationTag);
          if (str.IsEmpty())
            return FALSE;
          PString doc;
          if (!ReadContentBody(replyMIME, doc))
            return FALSE;
          url = str;
          count++;
        }
        break;
      default:
        return FALSE;
    }
  }
}


BOOL PHTTPClient::GetHeader(const PURL & url,
                            PMIMEInfo & outMIME,
                            PMIMEInfo & replyMIME,
                            BOOL persist)
{
  return ExecuteCommand(HEAD, url, outMIME, PString(), replyMIME, persist) == RequestOK;
}


BOOL PHTTPClient::PostData(const PURL & url,
                           PMIMEInfo & outMIME,
                           const PString & data,
                           PMIMEInfo & replyMIME,
                           BOOL persist)
{
  PString dataBody = data;
  if (!outMIME.Contains(ContentTypeTag)) {
    outMIME.SetAt(ContentTypeTag, "application/x-www-form-urlencoded");
    dataBody += "\r\n"; // Add CRLF for compatibility with some CGI servers.
  }

  return ExecuteCommand(POST, url, outMIME, data, replyMIME, persist) == RequestOK;
}


BOOL PHTTPClient::PostData(const PURL & url,
                           PMIMEInfo & outMIME,
                           const PString & data,
                           PMIMEInfo & replyMIME,
                           PString & body,
                           BOOL persist)
{
  if (!PostData(url, outMIME, data, replyMIME, persist))
    return FALSE;

  return ReadContentBody(replyMIME, body);
}


BOOL PHTTPClient::AssureConnect(const PURL & url, PMIMEInfo & outMIME)
{
  PString host = url.GetHostName();

  // Is not open or other end shut down, restablish connection
  if (!IsOpen()) {
    if (host.IsEmpty()) {
      lastResponseCode = BadRequest;
      lastResponseInfo = "No host specified";
      return SetErrorValues(ProtocolFailure, 0, LastReadError);
    }

#if P_SSL
    if (url.GetScheme() == "https") {
      PTCPSocket * tcp = new PTCPSocket(url.GetPort());
      tcp->SetReadTimeout(readTimeout);
      if (!tcp->Connect(host)) {
        lastResponseCode = -2;
        lastResponseInfo = tcp->GetErrorText();
        delete tcp;
        return FALSE;
      }

      PSSLChannel * ssl = new PSSLChannel;
      if (!ssl->Connect(tcp)) {
        lastResponseCode = -2;
        lastResponseInfo = ssl->GetErrorText();
        delete ssl;
        return FALSE;
      }

      if (!Open(ssl)) {
        lastResponseCode = -2;
        lastResponseInfo = GetErrorText();
        return FALSE;
      }
    }
    else
#endif

    if (!Connect(host, url.GetPort())) {
      lastResponseCode = -2;
      lastResponseInfo = GetErrorText();
      return FALSE;
    }
  }

  // Have connection, so fill in the required MIME fields
  static char HostTag[] = "Host";
  if (!outMIME.Contains(HostTag)) {
    if (!host)
      outMIME.SetAt(HostTag, host);
    else {
      PIPSocket * sock = GetSocket();
      if (sock != NULL)
        outMIME.SetAt(HostTag, sock->GetHostName());
    }
  }

  return TRUE;
}


// End Of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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