/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2010 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