From 40c28b75d4e1f94802f6e41e5bba3383584cc910 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 21 Jul 2002 14:48:09 +0000 Subject: [PATCH] Added class RemoteSMTarget that starts application SMRemoteTargetApp and communicates with it via ports. The remote app runs a looper with an optional handler. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@365 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kits/app/bmessenger/SMRemoteTargetApp.cpp | 107 +++++++++++++++++ .../kits/app/bmessenger/SMRemoteTargetApp.h | 30 +++++ src/tests/kits/app/bmessenger/SMTarget.cpp | 108 ++++++++++++++++++ src/tests/kits/app/bmessenger/SMTarget.h | 25 ++++ 4 files changed, 270 insertions(+) create mode 100644 src/tests/kits/app/bmessenger/SMRemoteTargetApp.cpp create mode 100644 src/tests/kits/app/bmessenger/SMRemoteTargetApp.h diff --git a/src/tests/kits/app/bmessenger/SMRemoteTargetApp.cpp b/src/tests/kits/app/bmessenger/SMRemoteTargetApp.cpp new file mode 100644 index 0000000000..185ce31e34 --- /dev/null +++ b/src/tests/kits/app/bmessenger/SMRemoteTargetApp.cpp @@ -0,0 +1,107 @@ +// SMRemoteTargetApp.cpp + +#include +#include +#include + +#include + +#include "SMRemoteTargetApp.h" +#include "SMLooper.h" + +// debugging +//#define DBG(x) x +#define DBG(x) +#define OUT printf + +int +main(int argc, char **argv) +{ +DBG(OUT("REMOTE: main()\n")); + assert(argc > 1); + const char *portName = argv[1]; + bool preferred = (argc > 2 && !strcmp(argv[2], "preferred")); + // create local port + port_id localPort = create_port(5, "SMRemoteTargetApp port"); + assert(localPort >= 0); +DBG(OUT("REMOTE: local port created\n")); + // create looper/handler + SMHandler *handler = NULL; + SMLooper *looper = new SMLooper; + looper->Run(); + if (!preferred) { + handler = new SMHandler; + assert(looper->Lock()); + looper->AddHandler(handler); + looper->Unlock(); + } +DBG(OUT("REMOTE: looper/handler created\n")); + // find remote port +DBG(OUT("REMOTE: find remote port `%s'\n", portName)); + port_id remotePort = find_port(portName); + assert(remotePort >= 0); +DBG(OUT("REMOTE: found remote port\n")); + // send init message + smrt_init initData; + initData.port = localPort; + initData.messenger = BMessenger(handler, looper); + assert(write_port(remotePort, SMRT_INIT, &initData, sizeof(smrt_init)) + == B_OK); +DBG(OUT("REMOTE: init message sent\n")); + // loop until quit message + bool running = true; + while (running) { + char buffer[sizeof(smrt_get_ready)]; + int32 code; + ssize_t readSize = read_port(localPort, &code, buffer, sizeof(buffer)); + if (readSize < 0) + running = readSize; +DBG(OUT("REMOTE: read port: %.4s\n", (char*)&code)); + switch (code) { + case SMRT_GET_READY: + { +DBG(OUT("REMOTE: SMRT_GET_READY\n")); + assert(readSize == sizeof(smrt_get_ready)); + smrt_get_ready &data = *(smrt_get_ready*)buffer; + looper->SetReplyDelay(data.reply_delay); + looper->BlockUntil(data.unblock_time); +DBG(OUT("REMOTE: SMRT_GET_READY done\n")); + break; + } + case SMRT_DELIVERY_SUCCESS_REQUEST: + { +DBG(OUT("REMOTE: SMRT_DELIVERY_SUCCESS_REQUEST\n")); + assert(readSize == 0); + smrt_delivery_success data; + data.success = looper->DeliverySuccess(); + assert(write_port(remotePort, SMRT_DELIVERY_SUCCESS_REPLY, + &data, sizeof(smrt_delivery_success)) + == B_OK); +DBG(OUT("REMOTE: SMRT_DELIVERY_SUCCESS_REQUEST done\n")); + break; + } + case SMRT_QUIT: +DBG(OUT("REMOTE: QUIT\n")); + default: +if (code != SMRT_QUIT) +DBG(OUT("REMOTE: UNKNOWN COMMAND!\n")); + running = false; + break; + } + } + // delete looper/handler + if (looper) { + looper->Lock(); + if (handler) { + looper->RemoveHandler(handler); + delete handler; + } + looper->Quit(); + } +DBG(OUT("REMOTE: looper/handler deleted\n")); + // delete local port + delete_port(localPort); +DBG(OUT("REMOTE: main() done\n")); + return 0; +} + diff --git a/src/tests/kits/app/bmessenger/SMRemoteTargetApp.h b/src/tests/kits/app/bmessenger/SMRemoteTargetApp.h new file mode 100644 index 0000000000..9fa1f7d361 --- /dev/null +++ b/src/tests/kits/app/bmessenger/SMRemoteTargetApp.h @@ -0,0 +1,30 @@ +// SMRemoteTargetApp.h + +#ifndef SM_REMOTE_TARGET_APP_H +#define SM_REMOTE_TARGET_APP_H + +#include + +enum { + SMRT_INIT = 'init', + SMRT_QUIT = 'quit', + SMRT_GET_READY = 'gtrd', + SMRT_DELIVERY_SUCCESS_REQUEST = 'dsrq', + SMRT_DELIVERY_SUCCESS_REPLY = 'dsre', +}; + +struct smrt_init { + port_id port; + BMessenger messenger; +}; + +struct smrt_delivery_success { + bool success; +}; + +struct smrt_get_ready { + bigtime_t unblock_time; + bigtime_t reply_delay; +}; + +#endif // SM_REMOTE_TARGET_APP_H diff --git a/src/tests/kits/app/bmessenger/SMTarget.cpp b/src/tests/kits/app/bmessenger/SMTarget.cpp index 604f95cc7e..966ad80f62 100644 --- a/src/tests/kits/app/bmessenger/SMTarget.cpp +++ b/src/tests/kits/app/bmessenger/SMTarget.cpp @@ -1,10 +1,17 @@ // SMTarget.cpp +#include +#include + +#include +#include +#include #include #include #include "SMTarget.h" #include "SMLooper.h" +#include "SMRemoteTargetApp.h" // SMTarget @@ -107,3 +114,104 @@ LocalSMTarget::DeliverySuccess() return fLooper->DeliverySuccess(); } + +// RemoteSMTarget + +static const char *kSMRemotePortName = "BMessenger_SMRemoteTarget"; + +// constructor +RemoteSMTarget::RemoteSMTarget(bool preferred) + : SMTarget(), + fLocalPort(-1), + fRemotePort(-1), + fTarget() +{ + // create unused port name + int32 id = atomic_add(&fID, 1); + string portName(kSMRemotePortName); + BString idString; + idString << id; + portName += idString.String(); + // create local port + fLocalPort = create_port(5, portName.c_str()); + CHK(fLocalPort >= 0); + // execute the remote app + BString unescapedTestDir(BTestShell::GlobalTestDir()); + unescapedTestDir.CharacterEscape(" \t\n!\"'`$&()?*+{}[]<>|", '\\'); + string remoteApp(unescapedTestDir.String()); + remoteApp += "/kits/app/SMRemoteTargetApp "; + remoteApp += portName; + if (preferred) + remoteApp += " preferred"; + else + remoteApp += " specific"; + remoteApp += " &"; + system(remoteApp.c_str()); + // wait for the remote app to send its init data + smrt_init initData; + CHK(_GetReply(SMRT_INIT, &initData, sizeof(smrt_init)) == B_OK); + fRemotePort = initData.port; + fTarget = initData.messenger; +} + +// destructor +RemoteSMTarget::~RemoteSMTarget() +{ + _SendRequest(SMRT_QUIT); + delete_port(fLocalPort); +} + +// Init +void +RemoteSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) +{ + smrt_get_ready data; + data.unblock_time = unblockTime; + data.reply_delay = replyDelay; + CHK(_SendRequest(SMRT_GET_READY, &data, sizeof(smrt_get_ready)) == B_OK); +} + +// Messenger +BMessenger +RemoteSMTarget::Messenger() +{ + return fTarget; +} + +// DeliverySuccess +bool +RemoteSMTarget::DeliverySuccess() +{ + CHK(_SendRequest(SMRT_DELIVERY_SUCCESS_REQUEST) == B_OK); + smrt_delivery_success data; + CHK(_GetReply(SMRT_DELIVERY_SUCCESS_REPLY, &data, + sizeof(smrt_delivery_success)) == B_OK); + return data.success; +} + +// _SendRequest +status_t +RemoteSMTarget::_SendRequest(int32 code, const void *buffer, size_t size) +{ + return write_port(fRemotePort, code, buffer, size); +} + +// _GetReply +status_t +RemoteSMTarget::_GetReply(int32 expectedCode, void *buffer, size_t size) +{ + status_t error = B_OK; + int32 code; + ssize_t readSize = read_port(fLocalPort, &code, buffer, size); + if (readSize < 0) + error = readSize; + else if ((uint32)readSize != size) + error = B_ERROR; + else if (code != expectedCode) + error = B_ERROR; + return error; +} + +// ID +int32 RemoteSMTarget::fID = 0; + diff --git a/src/tests/kits/app/bmessenger/SMTarget.h b/src/tests/kits/app/bmessenger/SMTarget.h index d4cdc9525a..a30b6aba73 100644 --- a/src/tests/kits/app/bmessenger/SMTarget.h +++ b/src/tests/kits/app/bmessenger/SMTarget.h @@ -39,4 +39,29 @@ private: SMLooper *fLooper; }; +// RemoteSMTarget +class RemoteSMTarget : public SMTarget { +public: + RemoteSMTarget(bool preferred); + virtual ~RemoteSMTarget(); + + virtual void Init(bigtime_t unblockTime, bigtime_t replyDelay); + + virtual BMessenger Messenger(); + + virtual bool DeliverySuccess(); + +private: + status_t _SendRequest(int32 code, const void *buffer = NULL, + size_t size = 0); + status_t _GetReply(int32 code, void *buffer, size_t size); + +private: + port_id fLocalPort; + port_id fRemotePort; + BMessenger fTarget; + + static int32 fID; +}; + #endif // SM_TARGET_H