17 #define _WIN32_WINNT 0x0500 31 #include "netAddress.h" 32 #include "connection.h" 33 #include "datagramIterator.h" 34 #include "netDatagram.h" 45 #define TA_SUCCESS_CLEAN 1 46 #define TA_SUCCESS_KILL 2 47 #define TA_SUCCESS_16 3 50 TerminateAppEnum(HWND hwnd, LPARAM lParam) {
52 GetWindowThreadProcessId(hwnd, &dwID);
53 if(dwID == (DWORD)lParam) {
54 PostMessage(hwnd, WM_CLOSE, 0, 0);
79 TerminateApp(DWORD dwPID, DWORD dwTimeout) {
85 hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID);
92 EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)dwPID);
96 if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0) {
97 dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
99 dwRet = TA_SUCCESS_CLEAN;
111 StartApp(
const string& cmd) {
114 PROCESS_INFORMATION pi;
115 ZeroMemory(&si,
sizeof(STARTUPINFO));
116 si.cb =
sizeof(STARTUPINFO);
117 ZeroMemory(&pi,
sizeof(PROCESS_INFORMATION));
118 if (CreateProcess(NULL, (
char*)cmd.c_str(),
119 0, 0, 1, NORMAL_PRIORITY_CLASS,
122 CloseHandle(pi.hProcess);
123 CloseHandle(pi.hThread);
125 nout<<
"CreateProcess failed: "<<cmd<<endl;
133 _reader(&_cm, 1), _writer(&_cm, 0), _listener(&_cm, 0),
134 _jobObject(0), _shutdown(false), _useOldStuff(false) {
137 DirectD::~DirectD() {
139 ConnectionSet::iterator ci;
140 for (ci = _connections.begin(); ci != _connections.end(); ++ci) {
141 _cm.close_connection((*ci));
143 _connections.clear();
149 DirectD::client_ready(
const string& server_host,
int port,
153 send_one_message(server_host, port, ss.str());
158 DirectD::tell_server(
const string& server_host,
int port,
160 send_one_message(server_host, port, cmd);
165 DirectD::wait_for_servers(
int count,
int timeout_ms) {
170 const int wait_ms=200;
171 int cycles=timeout_ms/wait_ms;
173 check_for_new_clients();
174 check_for_lost_connection();
181 while (_reader.data_available()) {
183 if (_reader.get_data(datagram)) {
184 cout << count <<
": Server at " << datagram.
get_address()
185 <<
" is ready." << endl;
189 string s=di.get_string();
190 if (s==
"r" && !--count) {
206 DirectD::server_ready(
const string& client_host,
int port) {
207 send_one_message(client_host, port,
"r");
213 DirectD::start_app(
const string& cmd) {
214 nout<<
"start_app(cmd="<<cmd<<
")"<<endl;
216 _pids.push_back(StartApp(cmd));
217 nout<<
" pid="<<_pids.back()<<endl;
220 _jobObject=CreateJobObject(0, 0);
222 nout<<
"CreateProcess failed: no _jobObject: "<<GetLastError()<<endl;
228 PROCESS_INFORMATION pi;
229 ZeroMemory(&si,
sizeof(STARTUPINFO));
230 si.cb =
sizeof(STARTUPINFO);
231 ZeroMemory(&pi,
sizeof(PROCESS_INFORMATION));
232 if (CreateProcess(NULL, (
char*)cmd.c_str(),
233 0, 0, 1, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED,
238 if (!AssignProcessToJobObject(_jobObject, pi.hProcess)) {
240 cerr<<
"StartJob AssignProcessToJobObject Error: "<<GetLastError()<<endl;
242 CloseHandle(pi.hProcess);
245 if (ResumeThread(pi.hThread) == -1) {
246 cerr<<
"StartJob ResumeThread Error: "<<GetLastError()<<endl;
248 CloseHandle(pi.hThread);
250 nout<<
"StartJob CreateProcess failed: "<<cmd<<endl;
256 DirectD::kill_app(
int index) {
258 int i = _pids.size() - 1 - index % _pids.size();
259 PidStack::iterator pi = _pids.begin() + i;
260 if (pi!=_pids.end()) {
261 nout<<
"trying kill "<<(*pi)<<endl;
262 TerminateApp((*pi), 1000);
266 cerr<<
"kill_app(index) not implemented, calling kill_all() instead."<<endl;
272 DirectD::kill_all() {
274 PidStack::reverse_iterator pi;
275 for (pi = _pids.rbegin(); pi != _pids.rend(); ++pi) {
276 nout<<
"trying kill "<<(*pi)<<endl;
277 TerminateApp((*pi), 1000);
282 cerr<<
"kill_all(): No open _jobObject"<<endl;
283 }
else if (!TerminateJobObject(_jobObject, 0)) {
284 cerr<<
"kill_all() TerminateJobObject Error: "<<GetLastError()<<endl;
286 CloseHandle(_jobObject);
292 DirectD::send_command(
const string& cmd) {
296 ConnectionSet::iterator ci;
297 for (ci = _connections.begin(); ci != _connections.end(); ++ci) {
298 _writer.send(datagram, (*ci));
305 string cmd=di.get_string();
310 DirectD::handle_command(
const string& cmd) {
311 nout<<
"DirectD::handle_command: "<<cmd<<endl;
315 DirectD::send_one_message(
const string& host_name,
317 const string& message) {
319 if (!host.
set_host(host_name, port)) {
320 nout <<
"Unknown host: " << host_name <<
"\n";
323 const int timeout_ms=5000;
324 PT(
Connection) c = _cm.open_TCP_client_connection(host, timeout_ms);
326 nout <<
"No connection.\n";
330 nout <<
"Successfully opened TCP connection to " << host_name
332 << c->get_address().get_port() <<
" and IP " 333 << c->get_address() <<
"\n";
339 _writer.send(datagram, c);
344 _cm.close_connection(c);
348 DirectD::connect_to(
const string& host_name,
int port) {
350 if (!host.
set_host(host_name, port)) {
351 nout <<
"Unknown host: " << host_name <<
"\n";
354 const int timeout_ms=5000;
355 PT(
Connection) c = _cm.open_TCP_client_connection(host, timeout_ms);
357 nout <<
"No connection.\n";
361 nout <<
"Successfully opened TCP connection to " << host_name
363 << c->get_address().get_port() <<
" and IP " 364 << c->get_address() <<
"\n";
366 _reader.add_connection(c);
367 _connections.insert(c);
368 return c->get_address().get_port();
372 DirectD::disconnect_from(
const string& host_name,
int port) {
373 nout<<
"disconnect_from(\""<<host_name<<
", port="<<port<<
")"<<endl;
374 for (ConnectionSet::iterator i=_connections.begin(); i != _connections.end(); ++i) {
375 nout<<
" found "<<(*i)->get_address().get_ip_string()<<
", port "<<(*i)->get_address().get_port()<<endl;
376 if ((*i)->get_address().get_ip_string()==host_name) {
377 nout<<
" disconnecting."<<endl;
378 _reader.remove_connection((*i));
379 _cm.close_connection((*i));
380 _connections.erase(i);
387 DirectD::check_for_lost_connection() {
388 while (_cm.reset_connection_available()) {
390 if (_cm.get_reset_connection(c)) {
391 nout<<
"Lost connection from "<<c->get_address()<<endl;
392 _connections.erase(c);
393 _cm.close_connection(c);
399 DirectD::check_for_datagrams(){
401 while (_reader.data_available()) {
403 if (_reader.get_data(datagram)) {
404 nout <<
"Got datagram " "from " 407 handle_datagram(datagram);
413 DirectD::listen_to(
int port,
int backlog) {
414 PT(
Connection) rendezvous = _cm.open_TCP_server_rendezvous(port, backlog);
415 if (rendezvous.is_null()) {
416 nout <<
"Cannot grab port " << port <<
".\n";
419 nout <<
"Listening for connections on port " << port <<
"\n";
420 _listener.add_connection(rendezvous);
424 DirectD::check_for_new_clients() {
425 while (_listener.new_connection_available()) {
429 if (_listener.get_new_connection(rv, address, new_connection)) {
430 nout <<
"Got connection from " << address <<
"\n";
431 _reader.add_connection(new_connection);
432 _connections.insert(new_connection);
A specific kind of Datagram, especially for sending across or receiving from a network.
void add_string(const string &str)
Adds a variable-length string to the datagram.
void dump_hex(ostream &out, unsigned int indent=0) const
Writes a representation of the entire datagram contents, as a sequence of hex (and ASCII) values...
bool set_host(const string &hostname, int port)
Sets the address up to refer to a particular port on a particular host.
const NetAddress & get_address() const
Retrieves the host from which the datagram was read, or to which it is scheduled to be sent...
A class to retrieve the individual data elements previously stored in a Datagram. ...
Represents a single TCP or UDP socket for input or output.
Represents a network address to which UDP packets may be sent or to which a TCP socket may be bound...