mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
new files
This commit is contained in:
parent
54c3e34f6e
commit
8cf47fea92
14
direct/src/plugin/p3dAuthSession.I
Normal file
14
direct/src/plugin/p3dAuthSession.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: p3dAuthSession.I
|
||||
// Created by: drose (17Sep09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
404
direct/src/plugin/p3dAuthSession.cxx
Normal file
404
direct/src/plugin/p3dAuthSession.cxx
Normal file
@ -0,0 +1,404 @@
|
||||
// Filename: P3DAuthSession.cxx
|
||||
// Created by: drose (17Sep09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "p3dAuthSession.h"
|
||||
#include "p3dInstance.h"
|
||||
#include "p3dInstanceManager.h"
|
||||
#include "p3dMultifileReader.h"
|
||||
#include "p3d_plugin_config.h"
|
||||
#include "mkdir_complete.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/select.h>
|
||||
#include <signal.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DAuthSession::
|
||||
P3DAuthSession(P3DInstance *inst) :
|
||||
_inst(inst)
|
||||
{
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
|
||||
_p3dcert_started = false;
|
||||
_p3dcert_running = false;
|
||||
_started_wait_thread = false;
|
||||
INIT_THREAD(_wait_thread);
|
||||
|
||||
// Write the cert chain to a temporary file.
|
||||
_cert_filename = new P3DTemporaryFile(".crt");
|
||||
string filename = _cert_filename->get_filename();
|
||||
FILE *fp = fopen(filename.c_str(), "w");
|
||||
if (fp == NULL) {
|
||||
nout << "Couldn't write temporary file\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (inst->_mf_reader.get_num_signatures() > 0) {
|
||||
const P3DMultifileReader::CertChain &cert_chain =
|
||||
inst->_mf_reader.get_signature(0);
|
||||
|
||||
if (cert_chain.size() > 0) {
|
||||
// Save the cert_dir, this is where the p3dcert program will
|
||||
// need to write the cert when it is approved.
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
_cert_dir = inst_mgr->get_cert_dir(cert_chain[0]._cert);
|
||||
}
|
||||
|
||||
P3DMultifileReader::CertChain::const_iterator ci;
|
||||
for (ci = cert_chain.begin(); ci != cert_chain.end(); ++ci) {
|
||||
X509 *c = (*ci)._cert;
|
||||
PEM_write_X509(fp, c);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
start_p3dcert();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DAuthSession::
|
||||
~P3DAuthSession() {
|
||||
shutdown(false);
|
||||
|
||||
if (_cert_filename != NULL) {
|
||||
delete _cert_filename;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::shutdown
|
||||
// Access: Public
|
||||
// Description: Terminates the session by killing the subprocess.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DAuthSession::
|
||||
shutdown(bool send_message) {
|
||||
if (!send_message) {
|
||||
// If we're not to send the instance the shutdown message as a
|
||||
// result of this, then clear the _inst pointer now.
|
||||
_inst = NULL;
|
||||
}
|
||||
|
||||
if (_p3dcert_started) {
|
||||
nout << "Killing p3dcert process\n";
|
||||
#ifdef _WIN32
|
||||
TerminateProcess(_p3dcert_handle, 2);
|
||||
CloseHandle(_p3dcert_handle);
|
||||
|
||||
#else // _WIN32
|
||||
kill(_p3dcert_pid, SIGKILL);
|
||||
#endif // _WIN32
|
||||
|
||||
_p3dcert_running = false;
|
||||
_p3dcert_started = false;
|
||||
}
|
||||
|
||||
// Now that the process has stopped, the thread should stop itself
|
||||
// quickly too.
|
||||
join_wait_thread();
|
||||
|
||||
// We're no longer bound to any particular instance.
|
||||
_inst = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::start_p3dcert
|
||||
// Access: Private
|
||||
// Description: Starts the p3dcert program running in a child
|
||||
// process.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DAuthSession::
|
||||
start_p3dcert() {
|
||||
if (_p3dcert_started) {
|
||||
// Already started.
|
||||
return;
|
||||
}
|
||||
|
||||
if (_inst->_p3dcert_package == NULL) {
|
||||
nout << "Couldn't start Python: no p3dcert package.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
|
||||
_start_dir = inst_mgr->get_root_dir() + "/start";
|
||||
|
||||
string root_dir = _inst->_p3dcert_package->get_package_dir();
|
||||
mkdir_complete(_start_dir, nout);
|
||||
|
||||
_p3dcert_exe = root_dir + "/p3dcert";
|
||||
#ifdef _WIN32
|
||||
_p3dcert_exe += ".exe";
|
||||
#endif
|
||||
|
||||
// Populate the new process' environment.
|
||||
_env = string();
|
||||
|
||||
// These are the enviroment variables we forward from the current
|
||||
// environment, if they are set.
|
||||
const char *keep[] = {
|
||||
"TMP", "TEMP", "HOME", "USER",
|
||||
#ifdef _WIN32
|
||||
"SYSTEMROOT", "USERPROFILE", "COMSPEC",
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
"DISPLAY",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
for (int ki = 0; keep[ki] != NULL; ++ki) {
|
||||
char *value = getenv(keep[ki]);
|
||||
if (value != NULL) {
|
||||
_env += keep[ki];
|
||||
_env += "=";
|
||||
_env += value;
|
||||
_env += '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// Define some new environment variables.
|
||||
_env += "PATH=";
|
||||
_env += root_dir;
|
||||
_env += '\0';
|
||||
|
||||
_env += "LD_LIBRARY_PATH=";
|
||||
_env += root_dir;
|
||||
_env += '\0';
|
||||
|
||||
_env += "DYLD_LIBRARY_PATH=";
|
||||
_env += root_dir;
|
||||
_env += '\0';
|
||||
|
||||
_env += "P3DCERT_ROOT=";
|
||||
_env += root_dir;
|
||||
_env += '\0';
|
||||
|
||||
nout << "Attempting to start p3dcert from " << _p3dcert_exe << "\n";
|
||||
|
||||
bool started_p3dcert = false;
|
||||
#ifdef _WIN32
|
||||
_p3dcert_handle = win_create_process();
|
||||
started_p3dcert = (_p3dcert_handle != INVALID_HANDLE_VALUE);
|
||||
#else
|
||||
_p3dcert_pid = posix_create_process();
|
||||
started_p3dcert = (_p3dcert_pid > 0);
|
||||
#endif
|
||||
if (!started_p3dcert) {
|
||||
nout << "Failed to create process.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
_p3dcert_started = true;
|
||||
_p3dcert_running = true;
|
||||
|
||||
spawn_wait_thread();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::spawn_wait_thread
|
||||
// Access: Private
|
||||
// Description: Starts the wait thread. This thread is responsible
|
||||
// for waiting for the process to finish, and notifying
|
||||
// the instance when it does.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DAuthSession::
|
||||
spawn_wait_thread() {
|
||||
SPAWN_THREAD(_wait_thread, wt_thread_run, this);
|
||||
_started_wait_thread = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::join_wait_thread
|
||||
// Access: Private
|
||||
// Description: Waits for the wait thread to stop.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DAuthSession::
|
||||
join_wait_thread() {
|
||||
if (!_started_wait_thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
JOIN_THREAD(_wait_thread);
|
||||
_started_wait_thread = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::wt_thread_run
|
||||
// Access: Private
|
||||
// Description: The main function for the wait thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DAuthSession::
|
||||
wt_thread_run() {
|
||||
// All we do here is wait for the process to terminate.
|
||||
nout << "wt_thread_run in " << this << " beginning\n";
|
||||
#ifdef _WIN32
|
||||
DWORD result = WaitForSingleObject(_p3dcert_handle, INFINITE);
|
||||
if (result != 0) {
|
||||
nout << "Wait for process failed: " << GetLastError() << "\n";
|
||||
}
|
||||
nout << "p3dcert process has successfully stopped.\n";
|
||||
#else
|
||||
int status;
|
||||
pid_t result = waitpid(_p3dcert_pid, &status, WNOHANG);
|
||||
if (result == -1) {
|
||||
perror("waitpid");
|
||||
break;
|
||||
}
|
||||
|
||||
nout << "p3dcert process has successfully stopped.\n";
|
||||
if (WIFEXITED(status)) {
|
||||
nout << " exited normally, status = "
|
||||
<< WEXITSTATUS(status) << "\n";
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
nout << " signalled by " << WTERMSIG(status) << ", core = "
|
||||
<< WCOREDUMP(status) << "\n";
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
nout << " stopped by " << WSTOPSIG(status) << "\n";
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
// Notify the instance that we're done.
|
||||
P3DInstance *inst = _inst;
|
||||
if (inst != NULL) {
|
||||
inst->auth_finished_sub_thread();
|
||||
}
|
||||
|
||||
nout << "Exiting wt_thread_run in " << this << "\n";
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::win_create_process
|
||||
// Access: Private
|
||||
// Description: Creates a sub-process to run _p3dcert_exe, with
|
||||
// the appropriate command-line arguments, and the
|
||||
// environment string defined in _env.
|
||||
//
|
||||
// Returns the handle to the created process on success,
|
||||
// or INVALID_HANDLE_VALUE on falure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
HANDLE P3DAuthSession::
|
||||
win_create_process() {
|
||||
// Make sure we see an error dialog if there is a missing DLL.
|
||||
SetErrorMode(0);
|
||||
|
||||
STARTUPINFO startup_info;
|
||||
ZeroMemory(&startup_info, sizeof(STARTUPINFO));
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
|
||||
// Make sure the initial window is *shown* for this graphical app.
|
||||
startup_info.wShowWindow = SW_SHOW;
|
||||
startup_info.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
|
||||
const char *start_dir_cstr = _start_dir.c_str();
|
||||
|
||||
// Construct the command-line string, containing the quoted
|
||||
// command-line arguments.
|
||||
ostringstream stream;
|
||||
stream << "\"" << _p3dcert_exe << "\" \""
|
||||
<< _cert_filename->get_filename() << "\" \""
|
||||
<< _cert_dir << "\"";
|
||||
|
||||
// I'm not sure why CreateProcess wants a non-const char pointer for
|
||||
// its command-line string, but I'm not taking chances. It gets a
|
||||
// non-const char array that it can modify.
|
||||
string command_line_str = stream.str();
|
||||
nout << "command is: " << command_line_str << "\n";
|
||||
char *command_line = new char[command_line_str.size() + 1];
|
||||
strcpy(command_line, command_line_str.c_str());
|
||||
|
||||
PROCESS_INFORMATION process_info;
|
||||
BOOL result = CreateProcess
|
||||
(_p3dcert_exe.c_str(), command_line, NULL, NULL, TRUE, 0,
|
||||
(void *)_env.c_str(), start_dir_cstr,
|
||||
&startup_info, &process_info);
|
||||
bool started_program = (result != 0);
|
||||
|
||||
delete[] command_line;
|
||||
|
||||
if (!started_program) {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
CloseHandle(process_info.hThread);
|
||||
return process_info.hProcess;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DAuthSession::posix_create_process
|
||||
// Access: Private
|
||||
// Description: Creates a sub-process to run _p3dcert_exe, with
|
||||
// the appropriate command-line arguments, and the
|
||||
// environment string defined in _env.
|
||||
//
|
||||
// Returns the pid of the created process on success, or
|
||||
// -1 on falure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int P3DAuthSession::
|
||||
posix_create_process() {
|
||||
// Fork and exec.
|
||||
pid_t child = fork();
|
||||
if (child < 0) {
|
||||
perror("fork");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (child == 0) {
|
||||
// Here we are in the child process.
|
||||
|
||||
if (chdir(_start_dir.c_str()) < 0) {
|
||||
nout << "Could not chdir to " << _start_dir << "\n";
|
||||
// This is a warning, not an error. We don't actually care
|
||||
// that much about the starting directory.
|
||||
}
|
||||
|
||||
// build up an array of char strings for the environment.
|
||||
vector<const char *> ptrs;
|
||||
size_t p = 0;
|
||||
size_t zero = _env.find('\0', p);
|
||||
while (zero != string::npos) {
|
||||
ptrs.push_back(_env.data() + p);
|
||||
p = zero + 1;
|
||||
zero = _env.find('\0', p);
|
||||
}
|
||||
ptrs.push_back((char *)NULL);
|
||||
|
||||
execle(_p3dcert_exe.c_str(), _p3dcert_exe.c_str(),
|
||||
_cert_filename->get_filename().c_str(), _cert_dir.c_str(),
|
||||
(char *)0, &ptrs[0]);
|
||||
nout << "Failed to exec " << _p3dcert_exe << "\n";
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
#endif // _WIN32
|
83
direct/src/plugin/p3dAuthSession.h
Normal file
83
direct/src/plugin/p3dAuthSession.h
Normal file
@ -0,0 +1,83 @@
|
||||
// Filename: P3DAuthSession.h
|
||||
// Created by: drose (17Sep09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef P3DAUTHSESSION_H
|
||||
#define P3DAUTHSESSION_H
|
||||
|
||||
#include "p3d_plugin_common.h"
|
||||
#include "p3dPackage.h"
|
||||
#include "get_tinyxml.h"
|
||||
#include "p3dTemporaryFile.h"
|
||||
#include "p3dReferenceCount.h"
|
||||
|
||||
class P3DInstance;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DAuthSession
|
||||
// Description : This is an instance of a p3dcert program running in a
|
||||
// subprocess. There's no communication with the
|
||||
// process, or none of that complicated stuff the
|
||||
// P3DSession has to do; all we do here is fire off the
|
||||
// process, then wait for it to exit.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class P3DAuthSession : public P3DReferenceCount {
|
||||
public:
|
||||
P3DAuthSession(P3DInstance *inst);
|
||||
~P3DAuthSession();
|
||||
|
||||
void shutdown(bool send_message);
|
||||
|
||||
private:
|
||||
void start_p3dcert();
|
||||
|
||||
void spawn_wait_thread();
|
||||
void join_wait_thread();
|
||||
|
||||
private:
|
||||
// These methods run only within the read thread.
|
||||
THREAD_CALLBACK_DECLARATION(P3DAuthSession, wt_thread_run);
|
||||
void wt_thread_run();
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE win_create_process();
|
||||
#else
|
||||
int posix_create_process();
|
||||
#endif
|
||||
|
||||
private:
|
||||
P3DInstance *_inst;
|
||||
string _start_dir;
|
||||
|
||||
// This information is passed to create_process().
|
||||
P3DTemporaryFile *_cert_filename;
|
||||
string _cert_dir;
|
||||
string _p3dcert_exe;
|
||||
string _env;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE _p3dcert_handle;
|
||||
#else
|
||||
int _p3dcert_pid;
|
||||
#endif
|
||||
bool _p3dcert_started;
|
||||
bool _p3dcert_running;
|
||||
|
||||
// The remaining members are manipulated by or for the read thread.
|
||||
bool _started_wait_thread;
|
||||
THREAD _wait_thread;
|
||||
};
|
||||
|
||||
#include "P3DAuthSession.I"
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user