/* This file is part of Mitsuba, a physically based rendering system. Copyright (c) 2007-2011 by Wenzel Jakob and others. Mitsuba is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. Mitsuba is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #if !defined(WIN32) #include #endif #include MTS_NAMESPACE_BEGIN SSHStream::SSHStream(const std::string &userName, const std::string &hostName, const std::vector &cmdLine, int port, int timeout) : m_userName(userName), m_hostName(hostName), m_port(port), m_timeout(timeout), m_received(0), m_sent(0) { setByteOrder(ENetworkByteOrder); Log(EInfo, "Establishing a SSH connection to \"%s@%s\"", userName.c_str(), hostName.c_str()); #if defined(WIN32) /* Inherit pipe handles */ SECURITY_ATTRIBUTES sAttr; sAttr.nLength = sizeof(SECURITY_ATTRIBUTES); sAttr.bInheritHandle = TRUE; sAttr.lpSecurityDescriptor = NULL; /* Create stdout pipe */ if (!CreatePipe(&m_childOutRd, &m_childOutWr, &sAttr, 0)) Log(EError, "Error in CreatePipe(): %s", lastErrorText().c_str()); /* Create stdin pipe */ if (!CreatePipe(&m_childInRd, &m_childInWr, &sAttr, 0)) Log(EError, "Error in CreatePipe(): %s", lastErrorText().c_str()); /* Only inherit one side of the pipes */ if (!SetHandleInformation(m_childOutRd, HANDLE_FLAG_INHERIT, 0)) Log(EError, "Error in SetHandleInformation(): %s", lastErrorText().c_str()); if (!SetHandleInformation(m_childInWr, HANDLE_FLAG_INHERIT, 0)) Log(EError, "Error in SetHandleInformation(): %s", lastErrorText().c_str()); /* Start the plink process */ PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.hStdError = m_childOutWr; si.hStdOutput = m_childOutWr; si.hStdInput = m_childInRd; si.dwFlags |= STARTF_USESTDHANDLES; std::string params = formatString("-batch -P %i -T %s@%s", m_port, m_userName.c_str(), m_hostName.c_str()); for (size_t i=0; i 0) { DWORD nRead = 0; if (!ReadFile(m_childOutRd, ptr, (DWORD) left, &nRead, NULL)) Log(EError, "Connection closed while reading: %s", lastErrorText().c_str()); left -= nRead; data += nRead; } #else if (fread(ptr, size, 1, m_input) != 1) { if (feof(m_input)) Log(EError, "Error in fread(): end of file!"); else if (ferror(m_input)) Log(EError, "Error in fread(): stream error!"); /* Otherwise, ignore (strange, but seems to be required) */ } #endif m_received += size; bytesRcvd += size; } void SSHStream::write(const void *ptr, size_t size) { static StatsCounter bytesSent("Network", "Bytes sent (SSH)"); #if defined(WIN32) size_t left = size; char *data = (char *) ptr; while (left > 0) { DWORD nWritten = 0; if (!WriteFile(m_childInWr, ptr, (DWORD) left, &nWritten, NULL)) Log(EError, "Connection closed while writing: %s", lastErrorText().c_str()); left -= nWritten; data += nWritten; } #else if (fwrite(ptr, size, 1, m_output) != 1) { if (feof(m_output)) Log(EError, "Error in fwrite(): end of file!"); else if (ferror(m_output)) Log(EError, "Error in fwrite(): stream error!"); /* Otherwise, ignore (strange, but seems to be required) */ } #endif m_sent += size; bytesSent += size; } bool SSHStream::canRead() const { return true; } bool SSHStream::canWrite() const { return true; } MTS_IMPLEMENT_CLASS(SSHStream, false, Stream) MTS_NAMESPACE_END