wxString CTransferSocket::SetupActiveTransfer(const wxString& ip) { ResetSocket(); m_pSocketServer = CreateSocketServer(); if (!m_pSocketServer) { m_pControlSocket->LogMessage(::Debug_Warning, _T("CreateSocketServer failed")); return _T(""); } int error; int port = m_pSocketServer->GetLocalPort(error); if (port == -1) { ResetSocket(); m_pControlSocket->LogMessage(::Debug_Warning, _T("GetLocalPort failed: %s"), CSocket::GetErrorDescription(error).c_str()); return _T(""); } wxString portArguments; if (m_pSocketServer->GetAddressFamily() == CSocket::ipv6) { portArguments = wxString::Format(_T("|2|%s|%d|"), ip.c_str(), port); } else { portArguments = ip; portArguments += wxString::Format(_T(",%d,%d"), port / 256, port % 256); portArguments.Replace(_T("."), _T(",")); } return portArguments; }
/*virtual*/ void OpScopeNetwork::Reset() { ResetSTP(); if (GetConnectionState() != STATE_CLOSED) ResetSocket(); }
OpScopeNetworkServer::~OpScopeNetworkServer() { State state = GetListenerState(); ResetSocket(); if (state == STATE_LISTENING) NotifyListenerClosed(this); }
/* virtual */ void OpScopeNetworkServer::OnSocketClosed(OpSocket* closing_socket) { if (closing_socket != listening_socket) return; ResetSocket(); NotifyListenerClosed(this); }
void OpScopeNetworkServer::Disconnect() { BOOL was_listening = GetListenerState() == STATE_LISTENING; ResetSocket(); if (was_listening) NotifyListenerClosed(this); }
OP_STATUS OpScopeNetworkServer::SetupListener() { if (is_listening) ResetSocket(); RETURN_IF_ERROR(SocketWrapper::CreateTCPSocket(&listening_socket, this, SocketWrapper::NO_WRAPPERS)); RETURN_IF_ERROR(OpSocketAddress::Create(&sockaddr)); OP_STATUS status; is_listening = TRUE; if (listen_port == 0) { sockaddr->FromString(listen_address.CStr()); int port = 49152; // Dynamic/private ports: 49152-65535 <http://www.iana.org/assignments/port-numbers> do { port++; sockaddr->SetPort(port); listen_port = port; // See OnSocketListenError is_address_in_use = FALSE; status = listening_socket->Listen(sockaddr, 1); } while (is_address_in_use && port < 65535); } else { if (!listen_address.IsEmpty()) RETURN_IF_ERROR(sockaddr->FromString(listen_address.CStr())); sockaddr->SetPort(listen_port); status = listening_socket->Listen(sockaddr, 1); } if (!is_listening) ResetSocket(); if (OpStatus::IsError(status) || !is_listening) NotifyListeningFailure(this); else NotifyListeningSuccess(this); return status; }
void CTransferSocket::TransferEnd(TransferEndReason reason) { controlSocket_.LogMessage(MessageType::Debug_Verbose, _T("CTransferSocket::TransferEnd(%d)"), reason); if (m_transferEndReason != TransferEndReason::none) return; m_transferEndReason = reason; ResetSocket(); engine_.send_event<CFileZillaEngineEvent>(engineTransferEnd); }
void CTransferSocket::TransferEnd(enum TransferEndReason reason) { m_pControlSocket->LogMessage(::Debug_Verbose, _T("CTransferSocket::TransferEnd(%d)"), reason); if (m_transferEndReason != none) return; m_transferEndReason = reason; ResetSocket(); m_pEngine->SendEvent(engineTransferEnd); }
bool CTransferSocket::SetupPassiveTransfer(wxString host, int port) { ResetSocket(); m_pSocket = new CSocket(this); if (m_pControlSocket->m_pProxyBackend) { m_pProxyBackend = new CProxySocket(this, m_pSocket, m_pControlSocket); int res = m_pProxyBackend->Handshake(m_pControlSocket->m_pProxyBackend->GetProxyType(), host, port, m_pControlSocket->m_pProxyBackend->GetUser(), m_pControlSocket->m_pProxyBackend->GetPass()); if (res != EINPROGRESS) { ResetSocket(); return false; } int error; host = m_pControlSocket->m_pSocket->GetPeerIP(); port = m_pControlSocket->m_pSocket->GetRemotePort(error); if( host.empty() || port < 1 ) { m_pControlSocket->LogMessage(::Debug_Warning, _T("Could not get peer address of control connection.")); ResetSocket(); return false; } } SetSocketBufferSizes(m_pSocket); int res = m_pSocket->Connect(host, port); if (res && res != EINPROGRESS) { ResetSocket(); return false; } return true; }
std::wstring CTransferSocket::SetupActiveTransfer(std::string const& ip) { ResetSocket(); m_pSocketServer = CreateSocketServer(); if (!m_pSocketServer) { controlSocket_.LogMessage(MessageType::Debug_Warning, _T("CreateSocketServer failed")); return std::wstring(); } int error; int port = m_pSocketServer->GetLocalPort(error); if (port == -1) { ResetSocket(); controlSocket_.LogMessage(MessageType::Debug_Warning, _T("GetLocalPort failed: %s"), CSocket::GetErrorDescription(error)); return std::wstring(); } if (engine_.GetOptions().GetOptionVal(OPTION_LIMITPORTS)) { port += static_cast<int>(engine_.GetOptions().GetOptionVal(OPTION_LIMITPORTS_OFFSET)); if (port <= 0 || port >= 65536) { controlSocket_.LogMessage(MessageType::Debug_Warning, _T("Port outside valid range")); return std::wstring(); } } std::wstring portArguments; if (m_pSocketServer->GetAddressFamily() == CSocket::ipv6) { portArguments = fz::sprintf(L"|2|%s|%d|", ip, port); } else { portArguments = fz::to_wstring(ip); fz::replace_substrings(portArguments, L".", L","); portArguments += fz::sprintf(L",%d,%d", port / 256, port % 256); } return portArguments; }
OpScopeNetwork::~OpScopeNetwork() { ConnectionState constate = GetConnectionState(); in_destruct = TRUE; g_main_message_handler->UnsetCallBack(this, MSG_SCOPE_PROCESS_MESSAGE); ResetSTP(); if (constate != STATE_CLOSED) ResetSocket(); if (constate == STATE_CONNECTED) NotifyConnectionClosed(this); }
CTransferSocket::~CTransferSocket() { remove_handler(); if (m_transferEndReason == TransferEndReason::none) { m_transferEndReason = TransferEndReason::successful; } ResetSocket(); if (m_transferMode == TransferMode::upload || m_transferMode == TransferMode::download) { if (ioThread_) { if (m_transferMode == TransferMode::download) { FinalizeWrite(); } ioThread_->SetEventHandler(0); } } }
CTransferSocket::~CTransferSocket() { if (m_transferEndReason == none) m_transferEndReason = successful; ResetSocket(); if (m_pControlSocket) { if (m_transferMode == upload || m_transferMode == download) { CFtpFileTransferOpData *pData = static_cast<CFtpFileTransferOpData *>(static_cast<CRawTransferOpData *>(m_pControlSocket->m_pCurOpData)->pOldData); if (pData && pData->pIOThread) { if (m_transferMode == download) FinalizeWrite(); pData->pIOThread->SetEventHandler(0); } } } }
int CHttpControlSocket::ResetOperation(int nErrorCode) { if (m_pCurOpData && m_pCurOpData->opId == cmd_transfer) { CHttpFileTransferOpData *pData = static_cast<CHttpFileTransferOpData *>(m_pCurOpData); delete pData->pFile; pData->pFile = 0; } if (!m_pCurOpData || !m_pCurOpData->pNextOpData) { if (m_pBackend) { if (nErrorCode == FZ_REPLY_OK) LogMessage(Status, _("Disconnected from server")); else LogMessage(::Error, _("Disconnected from server")); } ResetSocket(); m_pHttpOpData = 0; } return CControlSocket::ResetOperation(nErrorCode); }
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; }
bool CTransferSocket::SetupPassiveTransfer(std::wstring const& host, int port) { std::string ip; ResetSocket(); m_pSocket = new CSocket(engine_.GetThreadPool(), this); if (controlSocket_.m_pProxyBackend) { m_pProxyBackend = new CProxySocket(this, m_pSocket, &controlSocket_); int res = m_pProxyBackend->Handshake(controlSocket_.m_pProxyBackend->GetProxyType(), host, port, controlSocket_.m_pProxyBackend->GetUser(), controlSocket_.m_pProxyBackend->GetPass()); if (res != EINPROGRESS) { ResetSocket(); return false; } int error; ip = controlSocket_.m_pSocket->GetPeerIP(); port = controlSocket_.m_pSocket->GetRemotePort(error); if (ip.empty() || port < 1) { controlSocket_.LogMessage(MessageType::Debug_Warning, _T("Could not get peer address of control connection.")); ResetSocket(); return false; } } else { ip = fz::to_utf8(host); } SetSocketBufferSizes(m_pSocket); // Try to bind the source IP of the data connection to the same IP as the control connection. // We can do so either if // 1) the destination IP of the data connection matches peer IP of the control connection or // 2) we are using a proxy. // // In case destination IPs of control and data connection are different, do not bind to the // same source. std::string bindAddress; if (m_pProxyBackend) { bindAddress = controlSocket_.m_pSocket->GetLocalIP(); controlSocket_.LogMessage(MessageType::Debug_Info, _T("Binding data connection source IP to control connection source IP %s"), bindAddress); } else { if (controlSocket_.m_pSocket->GetPeerIP(true) == ip || controlSocket_.m_pSocket->GetPeerIP(false) == ip) { bindAddress = controlSocket_.m_pSocket->GetLocalIP(); controlSocket_.LogMessage(MessageType::Debug_Info, _T("Binding data connection source IP to control connection source IP %s"), bindAddress); } else { controlSocket_.LogMessage(MessageType::Debug_Warning, _T("Destination IP of data connection does not match peer IP of control connection. Not binding source address of data connection.")); } } int res = m_pSocket->Connect(fz::to_native(ip), port, CSocket::unspec, bindAddress); if (res && res != EINPROGRESS) { ResetSocket(); return false; } return true; }
int CRealControlSocket::DoClose(int nErrorCode /*=FZ_REPLY_DISCONNECTED*/) { ResetSocket(); return CControlSocket::DoClose(nErrorCode); }