int CRealControlSocket::ContinueConnect() { wxString host; unsigned int port = 0; const int proxy_type = m_pEngine->GetOptions()->GetOptionVal(OPTION_PROXY_TYPE); if (proxy_type > CProxySocket::unknown && proxy_type < CProxySocket::proxytype_count && !m_pCurrentServer->GetBypassProxy()) { LogMessage(::Status, _("Connecting to %s through proxy"), m_pCurrentServer->FormatHost().c_str()); host = m_pEngine->GetOptions()->GetOption(OPTION_PROXY_HOST); port = m_pEngine->GetOptions()->GetOptionVal(OPTION_PROXY_PORT); delete m_pBackend; m_pProxyBackend = new CProxySocket(this, m_pSocket, this); m_pBackend = m_pProxyBackend; int res = m_pProxyBackend->Handshake((enum CProxySocket::ProxyType)proxy_type, m_pCurrentServer->GetHost(), m_pCurrentServer->GetPort(), m_pEngine->GetOptions()->GetOption(OPTION_PROXY_USER), m_pEngine->GetOptions()->GetOption(OPTION_PROXY_PASS)); if (res != EINPROGRESS) { LogMessage(::Error, _("Could not start proxy handshake: %s"), CSocket::GetErrorDescription(res).c_str()); DoClose(); return FZ_REPLY_ERROR; } } else { if (m_pCurOpData && m_pCurOpData->opId == cmd_connect) { CConnectOpData* pData = (CConnectOpData*)m_pCurOpData; host = ConvertDomainName(pData->host); port = pData->port; } if (host == _T("")) { host = m_pCurrentServer->GetHost(); port = m_pCurrentServer->GetPort(); } } if (!IsIpAddress(host)) LogMessage(Status, _("Resolving address of %s"), host.c_str()); int res = m_pSocket->Connect(host, port); // Treat success same as EINPROGRESS, we wait for connect notification in any case if (res && res != EINPROGRESS) { LogMessage(::Error, _("Could not connect to server: %s"), CSocket::GetErrorDescription(res).c_str()); DoClose(); return FZ_REPLY_ERROR; } return FZ_REPLY_WOULDBLOCK; }
int CRealControlSocket::ContinueConnect() { wxString host; unsigned int port = 0; const int proxy_type = engine_.GetOptions().GetOptionVal(OPTION_PROXY_TYPE); if (proxy_type > CProxySocket::unknown && proxy_type < CProxySocket::proxytype_count && !m_pCurrentServer->GetBypassProxy()) { LogMessage(MessageType::Status, _("Connecting to %s through %s proxy"), m_pCurrentServer->FormatHost(), CProxySocket::Name(static_cast<CProxySocket::ProxyType>(proxy_type))); host = engine_.GetOptions().GetOption(OPTION_PROXY_HOST); port = engine_.GetOptions().GetOptionVal(OPTION_PROXY_PORT); delete m_pBackend; m_pProxyBackend = new CProxySocket(this, m_pSocket, this); m_pBackend = m_pProxyBackend; int res = m_pProxyBackend->Handshake((enum CProxySocket::ProxyType)proxy_type, m_pCurrentServer->GetHost(), m_pCurrentServer->GetPort(), engine_.GetOptions().GetOption(OPTION_PROXY_USER), engine_.GetOptions().GetOption(OPTION_PROXY_PASS)); if (res != EINPROGRESS) { LogMessage(MessageType::Error, _("Could not start proxy handshake: %s"), CSocket::GetErrorDescription(res)); DoClose(); return FZ_REPLY_ERROR; } } else { if (m_pCurOpData && m_pCurOpData->opId == Command::connect) { CConnectOpData* pData(static_cast<CConnectOpData*>(m_pCurOpData)); host = ConvertDomainName(pData->host); port = pData->port; } if (host.empty()) { host = m_pCurrentServer->GetHost(); port = m_pCurrentServer->GetPort(); } } if (fz::get_address_type(host.ToStdWstring()) == fz::address_type::unknown) { LogMessage(MessageType::Status, _("Resolving address of %s"), host); } int res = m_pSocket->Connect(fz::to_native(host), port); // Treat success same as EINPROGRESS, we wait for connect notification in any case if (res && res != EINPROGRESS) { LogMessage(MessageType::Error, _("Could not connect to server: %s"), CSocket::GetErrorDescription(res)); DoClose(); return FZ_REPLY_ERROR; } return FZ_REPLY_WOULDBLOCK; }
int CRealControlSocket::Connect(const CServer &server) { SetWait(true); if (server.GetEncodingType() == ENCODING_CUSTOM) m_pCSConv = new wxCSConv(server.GetCustomEncoding()); if (m_pCurrentServer) delete m_pCurrentServer; m_pCurrentServer = new CServer(server); // International domain names m_pCurrentServer->SetHost(ConvertDomainName(server.GetHost()), server.GetPort()); return ContinueConnect(); }
int CRealControlSocket::Connect(const CServer &server) { SetWait(true); if (server.GetEncodingType() == ENCODING_CUSTOM) { LogMessage(MessageType::Debug_Info, _T("Using custom encoding: %s"), server.GetCustomEncoding()); m_pCSConv = new wxCSConv(server.GetCustomEncoding()); } delete m_pCurrentServer; m_pCurrentServer = new CServer(server); // International domain names m_pCurrentServer->SetHost(ConvertDomainName(server.GetHost()), server.GetPort()); return ContinueConnect(); }
BOOL CControlSocket::Connect(CString hostAddress, UINT nHostPort) { hostAddress = ConvertDomainName(hostAddress); //Don't resolve host asynchronously when using proxies if (m_pProxyLayer) { //If using proxies, we can't use ident -> won't be reachable from outside return CAsyncSocketEx::Connect(hostAddress, nHostPort); } BOOL res = CAsyncSocketEx::Connect(hostAddress, nHostPort); int nLastError = WSAGetLastError(); if (res || nLastError==WSAEWOULDBLOCK) { #ifndef MPEXT_NO_IDENT if (COptions::GetOptionVal(OPTION_IDENT)) m_pIdentControl = new CIdentServerControl(this); #endif WSASetLastError(nLastError); } return res; }
int CRealControlSocket::Connect(const CServer &server) { SetWait(true); if (server.GetEncodingType() == ENCODING_CUSTOM) m_pCSConv = new wxCSConv(server.GetCustomEncoding()); if (m_pCurrentServer) delete m_pCurrentServer; m_pCurrentServer = new CServer(server); CConnectOpData* pData; if (!m_pCurOpData || m_pCurOpData->opId != cmd_connect) pData = 0; else pData = static_cast<CConnectOpData *>(m_pCurOpData); const wxString& host = pData ? pData->host : server.GetHost(); if (!IsIpAddress(host)) { LogMessage(Status, _("Resolving IP-Address for %s"), host.c_str()); CAsyncHostResolver *resolver = new CAsyncHostResolver(m_pEngine, ConvertDomainName(host)); m_pEngine->AddNewAsyncHostResolver(resolver); resolver->Create(); resolver->Run(); } else { wxIPV4address addr; addr.Hostname(host); return ContinueConnect(&addr); } return FZ_REPLY_WOULDBLOCK; }
int CHttpControlSocket::ParseHeader(CHttpOpData* pData) { // Parse the HTTP header. // We do just the neccessary parsing and silently ignore most header fields // Redirects are supported though if the server sends the Location field. for (;;) { // Find line ending unsigned int i = 0; for (i = 0; (i + 1) < m_recvBufferPos; i++) { if (m_pRecvBuffer[i] == '\r') { if (m_pRecvBuffer[i + 1] != '\n') { LogMessage(::Error, _("Malformed reply, server not sending proper line endings")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } break; } } if ((i + 1) >= m_recvBufferPos) { if (m_recvBufferPos == m_recvBufferLen) { // We don't support header lines larger than 4096 LogMessage(::Error, _("Too long header line")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } return FZ_REPLY_WOULDBLOCK; } m_pRecvBuffer[i] = 0; const wxString& line = wxString(m_pRecvBuffer, wxConvLocal); if (line != _T("")) LogMessageRaw(Response, line); if (pData->m_responseCode == -1) { pData->m_responseString = line; if (m_recvBufferPos < 16 || memcmp(m_pRecvBuffer, "HTTP/1.", 7)) { // Invalid HTTP Status-Line LogMessage(::Error, _("Invalid HTTP Response")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } if (m_pRecvBuffer[9] < '1' || m_pRecvBuffer[9] > '5' || m_pRecvBuffer[10] < '0' || m_pRecvBuffer[10] > '9' || m_pRecvBuffer[11] < '0' || m_pRecvBuffer[11] > '9') { // Invalid response code LogMessage(::Error, _("Invalid response code")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } pData->m_responseCode = (m_pRecvBuffer[9] - '0') * 100 + (m_pRecvBuffer[10] - '0') * 10 + m_pRecvBuffer[11] - '0'; if (pData->m_responseCode >= 400) { // Failed request ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } if (pData->m_responseCode == 305) { // Unsupported redirect LogMessage(::Error, _("Unsupported redirect")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } } else { if (!i) { // End of header, data from now on // Redirect if neccessary if (pData->m_responseCode >= 300) { if (pData->m_redirectionCount++ == 5) { LogMessage(::Error, _("Too many redirects")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } ResetSocket(); ResetHttpData(pData); wxString host; enum ServerProtocol protocol; int pos; if ((pos = pData->m_newLocation.Find(_T("://"))) != -1) { protocol = CServer::GetProtocolFromPrefix(pData->m_newLocation.Left(pos)); host = pData->m_newLocation.Mid(pos + 3); } else { protocol = HTTP; host = pData->m_newLocation; } if ((pos = host.Find(_T("/"))) != -1) host = host.Left(pos); unsigned long port; if ((pos = host.Find(':', true)) != -1) { wxString strport = host.Mid(pos + 1); if (!strport.ToULong(&port) || port < 1 || port > 65535) { if (protocol == HTTPS) port = 443; else port = 80; } host = host.Left(pos); } else { if (protocol == HTTPS) port = 443; else port = 80; } if (host == _T("")) { // Unsupported redirect LogMessage(::Error, _("Redirection to invalid address")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } pData->m_newHostWithPort = wxString::Format(_T("%s:%d"), host.c_str(), (int)port); // International domain names host = ConvertDomainName(host); int res = InternalConnect(host, port, protocol == HTTPS); if (res == FZ_REPLY_WOULDBLOCK) res |= FZ_REPLY_REDIRECTED; return res; } pData->m_gotHeader = true; memmove(m_pRecvBuffer, m_pRecvBuffer + 2, m_recvBufferPos - 2); m_recvBufferPos -= 2; if (m_recvBufferPos) { int res; if (pData->m_transferEncoding == pData->chunked) res = OnChunkedData(pData); else { pData->m_receivedData += m_recvBufferPos; res = ProcessData(m_pRecvBuffer, m_recvBufferPos); m_recvBufferPos = 0; } return res; } return FZ_REPLY_WOULDBLOCK; } if (m_recvBufferPos > 12 && !memcmp(m_pRecvBuffer, "Location: ", 10)) { pData->m_newLocation = wxString(m_pRecvBuffer + 10, wxConvLocal); } else if (m_recvBufferPos > 21 && !memcmp(m_pRecvBuffer, "Transfer-Encoding: ", 19)) { if (!strcmp(m_pRecvBuffer + 19, "chunked")) pData->m_transferEncoding = CHttpOpData::chunked; else if (!strcmp(m_pRecvBuffer + 19, "identity")) pData->m_transferEncoding = CHttpOpData::identity; else pData->m_transferEncoding = CHttpOpData::unknown; } else if (i > 16 && !memcmp(m_pRecvBuffer, "Content-Length: ", 16)) { pData->m_totalSize = 0; char* p = m_pRecvBuffer + 16; while (*p) { if (*p < '0' || *p > '9') { LogMessage(::Error, _("Malformed header: %s"), _("Invalid Content-Length")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } pData->m_totalSize = pData->m_totalSize * 10 + *p++ - '0'; } } } memmove(m_pRecvBuffer, m_pRecvBuffer + i + 2, m_recvBufferPos - i - 2); m_recvBufferPos -= i + 2; if (!m_recvBufferPos) break; } return FZ_REPLY_WOULDBLOCK; }