diff --git a/direct/src/directd/Sources.pp b/direct/src/directd/Sources.pp new file mode 100644 index 0000000000..6f14c8195a --- /dev/null +++ b/direct/src/directd/Sources.pp @@ -0,0 +1,16 @@ + +//#define LOCAL_LIBS \ +// directbase +#define OTHER_LIBS \ + net:c linmath:c putil:c express:c panda:m pandaexpress:m dtoolconfig dtool +#define WIN_SYS_LIBS $[WIN_SYS_LIBS] user32.lib //advapi32.lib + +//#define C++FLAGS -DWITHIN_PANDA + +#begin bin_target + #define TARGET directd + + #define SOURCES \ + directd.h directd.cxx + +#end bin_target diff --git a/direct/src/directd/directd.cxx b/direct/src/directd/directd.cxx new file mode 100644 index 0000000000..5be663db9d --- /dev/null +++ b/direct/src/directd/directd.cxx @@ -0,0 +1,439 @@ +// Filename: directd.cxx +// Created by: skyler 2002.04.08 +// Based on test_tcp_*.* by drose. +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +/*#include "directd.h" +#include "pandaFramework.h" +#include "queuedConnectionManager.h"*/ + +#include +#include +#include "pandabase.h" + +#include "queuedConnectionManager.h" +#include "queuedConnectionListener.h" +#include "queuedConnectionReader.h" +#include "connectionWriter.h" +#include "netAddress.h" +#include "connection.h" +#include "datagramIterator.h" +#include "netDatagram.h" + +#include "pset.h" + + + +namespace { + // The following is from an MSDN example: + + #define TA_FAILED 0 + #define TA_SUCCESS_CLEAN 1 + #define TA_SUCCESS_KILL 2 + #define TA_SUCCESS_16 3 + + BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam) { + DWORD dwID; + GetWindowThreadProcessId(hwnd, &dwID); + if(dwID == (DWORD)lParam) { + PostMessage(hwnd, WM_CLOSE, 0, 0); + } + return TRUE; + } + + /* + DWORD WINAPI TerminateApp(DWORD dwPID, DWORD dwTimeout) + + Purpose: + Shut down a 32-Bit Process (or 16-bit process under Windows 95) + + Parameters: + dwPID + Process ID of the process to shut down. + + dwTimeout + Wait time in milliseconds before shutting down the process. + + Return Value: + TA_FAILED - If the shutdown failed. + TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE. + TA_SUCCESS_KILL - if the process was shut down with + TerminateProcess(). + NOTE: See header for these defines. + */ + DWORD WINAPI + TerminateApp(DWORD dwPID, DWORD dwTimeout) { + HANDLE hProc; + DWORD dwRet; + + // If we can't open the process with PROCESS_TERMINATE rights, + // then we give up immediately. + hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID); + if(hProc == NULL) { + return TA_FAILED; + } + + // TerminateAppEnum() posts WM_CLOSE to all windows whose PID + // matches your process's. + EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID); + + // Wait on the handle. If it signals, great. If it times out, + // then you kill it. + if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0) { + dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED); + } else { + dwRet = TA_SUCCESS_CLEAN; + } + CloseHandle(hProc); + + return dwRet; + } + +} + + +class DirectD { +public: + DirectD(); + ~DirectD(); + + void set_host_name(const string& host_name); + void set_port(int port); + void spawn_background_server(); + + void run_server(); + void run_client(); + void run_controller(); + + void send_start_app(const string& cmd); + void start_app(const string& cmd); + + void send_kill_app(const string& pid); + void kill_app(); + +protected: + QueuedConnectionManager _cm; + string _host_name; + int _port; + intptr_t _app_pid; + bool _controller; + bool _verbose; +}; + + + + +DirectD::DirectD() : + _host_name("localhost"), + _port(8001), _app_pid(0), + _controller(false), _verbose(false) { +} + +DirectD::~DirectD() { + +} + +void +DirectD::set_host_name(const string& host_name) { + _host_name=host_name; +} + +void +DirectD::set_port(int port) { + _port=port; +} + +void +DirectD::send_start_app(const string& cmd) { + +} + +void +DirectD::start_app(const string& cmd) { + #if 0 //[ + const char* args[]={ + cmd.c_str(), + 0 + }; + _app_pid=_spawnvp(_P_NOWAIT, args[0], args); + cerr<<"started app "<<_app_pid<<" errno "< Clients; + Clients clients; + + QueuedConnectionReader reader(&_cm, 1); + ConnectionWriter writer(&_cm, 1); + + bool shutdown = false; + while (!shutdown) { + // Check for new clients. + while (listener.new_connection_available()) { + PT(Connection) rv; + NetAddress address; + PT(Connection) new_connection; + if (listener.get_new_connection(rv, address, new_connection)) { + if (_verbose) nout << "Got connection from " << address << "\n"; + reader.add_connection(new_connection); + clients.insert(new_connection); + } + } + + // Check for reset clients. + while (_cm.reset_connection_available()) { + PT(Connection) connection; + if (_cm.get_reset_connection(connection)) { + nout << "Lost connection from " + << connection->get_address() << "\n"; + clients.erase(connection); + _cm.close_connection(connection); + } + } + + // Process all available datagrams. + while (reader.data_available()) { + NetDatagram datagram; + if (reader.get_data(datagram)) { + nout << "Got datagram " /*<< datagram <<*/ "from " + << datagram.get_address() << ", sending to " + << clients.size() << " clients.\n"; + if (_verbose) datagram.dump_hex(nout); + + Clients::iterator ci; + for (ci = clients.begin(); ci != clients.end(); ++ci) { + writer.send(datagram, (*ci)); + } + + if (datagram.get_length() <= 1) { + /* + // An empty datagram means to close the connection. + PT(Connection) connection = datagram.get_connection(); + if (connection.is_null()) { + nout << "Empty datagram from a null connection.\n"; + } else { + nout << "Closing connection from " + << connection->get_address() << "\n"; + clients.erase(connection); + _cm.close_connection(connection); + nout << "Closed " << connection << "\n"; + } + */ + + // No, an empty datagram means to shut down the server. + shutdown = true; + } + } + } + + // Yield the timeslice before we poll again. + PR_Sleep(PR_MillisecondsToInterval(100)); + } +} + +void +DirectD::run_client() { + if (!_controller) { + cerr<<"client"<get_address().get_port() << " and IP " + << c->get_address() << "\n"; + + QueuedConnectionReader reader(&_cm, 0); + reader.add_connection(c); + ConnectionWriter writer(&_cm, 0); + + bool lost_connection = false; + + while (!cin.fail() && !lost_connection) { + NetDatagram datagram; + if (_controller) { + cout << "directd send: " << flush; + string d; + cin >> d; + datagram.add_string(d); + // Send the datagram. + writer.send(datagram, c); + } + + // Check for a lost connection. + while (_cm.reset_connection_available()) { + PT(Connection) connection; + if (_cm.get_reset_connection(connection)) { + nout << "Lost connection from " + << connection->get_address() << "\n"; + _cm.close_connection(connection); + if (connection == c) { + lost_connection = true; + } + } + } + + // Now poll for new datagrams on the socket. + while (reader.data_available()) { + if (reader.get_data(datagram)) { + nout << "Got datagram " /*<< datagram*/ << "from " + << datagram.get_address() << "\n"; + datagram.dump_hex(nout); + if (!_controller) { + DatagramIterator di(datagram); + string cmd=di.get_string(); + cerr<<"cmd="< 1 && strcmp(argv[1], "--help")==0) { + cerr<<"directd [-c ] \n" + " -c run as client (else run as server).\n" + " host e.g. localhost\n" + " port default 8001\n"; + return 1; + } + + cerr<<"directd"<= 3) { + string host=argv[argc-2]; + directd.set_host_name(host); + } + char run_as=' '; + if (argc > 1) { + directd.set_port(atoi(argv[argc-1])); + if (strlen(argv[1]) > 1 && argv[1][0] == '-') { + run_as=argv[1][1]; + } + } + switch (run_as) { + case 's': + directd.run_server(); + break; + case 'c': + directd.run_client(); + break; + default: + directd.spawn_background_server(); + PR_Sleep(PR_MillisecondsToInterval(1000)); + directd.run_controller(); + break; + } + + return 0; +} diff --git a/direct/src/directd/directd.h b/direct/src/directd/directd.h new file mode 100644 index 0000000000..929400646c --- /dev/null +++ b/direct/src/directd/directd.h @@ -0,0 +1 @@ +// directd.h diff --git a/direct/src/directd/directd.py b/direct/src/directd/directd.py new file mode 100755 index 0000000000..e89b80dde5 --- /dev/null +++ b/direct/src/directd/directd.py @@ -0,0 +1,49 @@ +#!python +"""directd stuff""" + +from AIBaseGlobal import * +import DirectNotifyGlobal +import Datagram +import DatagramIterator + + +print "hello" + + +class DirectDServer: + notify = DirectNotifyGlobal.directNotify.newCategory("DirectD") + + def __init__(self): + pass + + def connect(self, ip, port, timeout=35000): + self.qcm=QueuedConnectionManager() + self.tcpConn=self.qcm.openTCPClientConnection(ip, port, timeout) + + if self.tcpConn == None: + # Bad Connection + print "noConnection" + else: + # Good Connection + # Set up connection reader and writer + self.qcr=QueuedConnectionReader(self.qcm, 0) + self.qcr.addConnection(self.tcpConn) + self.cw=ConnectionWriter(self.qcm, 0) + while 1: + s=raw_input("send: ") + d=Datagram.Datagram() + d.addString(s) + self.cw.send(d, self.tcpConn) + while self.qcr.dataAvailable(): + nd=NetDatagram() + self.qcr.getData(nd) + print "address", nd.getAddress().getIp() + nd.dumpHex(ostream) + #self.startReaderPollTask() + + # Register our channel + #self.registerForChannel(self.ourChannel) + +def foo(): + dds = DirectDServer() + dds.connect("127.0.0.1", 8000)