1// SMTarget.cpp 2 3#include <stdio.h> 4#include <stdlib.h> 5#include <string> 6 7#include <OS.h> 8#include <String.h> 9#include <TestShell.h> 10#include <TestUtils.h> 11#include <cppunit/TestAssert.h> 12 13#include "SMTarget.h" 14#include "SMLooper.h" 15#include "SMRemoteTargetApp.h" 16 17 18using namespace std; 19 20 21// SMTarget 22 23// constructor 24SMTarget::SMTarget() 25{ 26} 27 28// destructor 29SMTarget::~SMTarget() 30{ 31} 32 33// Init 34void 35SMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) 36{ 37} 38 39// Handler 40BHandler * 41SMTarget::Handler() 42{ 43 return NULL; 44} 45 46// Messenger 47BMessenger 48SMTarget::Messenger() 49{ 50 return BMessenger(); 51} 52 53// DeliverySuccess 54bool 55SMTarget::DeliverySuccess() 56{ 57 return false; 58} 59 60 61// LocalSMTarget 62 63// constructor 64LocalSMTarget::LocalSMTarget(bool preferred) 65 : SMTarget(), 66 fHandler(NULL), 67 fLooper(NULL) 68{ 69 // create looper and handler 70 fLooper = new SMLooper; 71 fLooper->Run(); 72 if (!preferred) { 73 fHandler = new SMHandler; 74 CHK(fLooper->Lock()); 75 fLooper->AddHandler(fHandler); 76 fLooper->Unlock(); 77 } 78} 79 80// destructor 81LocalSMTarget::~LocalSMTarget() 82{ 83 if (fLooper) { 84 fLooper->Lock(); 85 if (fHandler) { 86 fLooper->RemoveHandler(fHandler); 87 delete fHandler; 88 } 89 fLooper->Quit(); 90 } 91} 92 93// Init 94void 95LocalSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) 96{ 97 fLooper->SetReplyDelay(replyDelay); 98 fLooper->BlockUntil(unblockTime); 99} 100 101// Handler 102BHandler * 103LocalSMTarget::Handler() 104{ 105 return fHandler; 106} 107 108// Messenger 109BMessenger 110LocalSMTarget::Messenger() 111{ 112 return BMessenger(fHandler, fLooper); 113} 114 115// DeliverySuccess 116bool 117LocalSMTarget::DeliverySuccess() 118{ 119 return fLooper->DeliverySuccess(); 120} 121 122 123// RemoteSMTarget 124 125static const char *kSMRemotePortName = "BMessenger_SMRemoteTarget"; 126 127// constructor 128RemoteSMTarget::RemoteSMTarget(bool preferred) 129 : SMTarget(), 130 fLocalPort(-1), 131 fRemotePort(-1), 132 fTarget() 133{ 134 // create unused port name 135 int32 id = atomic_add(&fID, 1); 136 string portName(kSMRemotePortName); 137 BString idString; 138 idString << id; 139 portName += idString.String(); 140 // create local port 141 fLocalPort = create_port(5, portName.c_str()); 142 CHK(fLocalPort >= 0); 143 // execute the remote app 144 BString unescapedTestDir(BTestShell::GlobalTestDir()); 145 unescapedTestDir.CharacterEscape(" \t\n!\"'`$&()?*+{}[]<>|", '\\'); 146 string remoteApp(unescapedTestDir.String()); 147 remoteApp += "/SMRemoteTargetApp "; 148 remoteApp += portName; 149 if (preferred) 150 remoteApp += " preferred"; 151 else 152 remoteApp += " specific"; 153 remoteApp += " &"; 154 system(remoteApp.c_str()); 155 // wait for the remote app to send its init data 156 smrt_init initData; 157 CHK(_GetReply(SMRT_INIT, &initData, sizeof(smrt_init)) == B_OK); 158 fRemotePort = initData.port; 159 fTarget = initData.messenger; 160} 161 162// destructor 163RemoteSMTarget::~RemoteSMTarget() 164{ 165 _SendRequest(SMRT_QUIT); 166 delete_port(fLocalPort); 167} 168 169// Init 170void 171RemoteSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) 172{ 173 smrt_get_ready data; 174 data.unblock_time = unblockTime; 175 data.reply_delay = replyDelay; 176 CHK(_SendRequest(SMRT_GET_READY, &data, sizeof(smrt_get_ready)) == B_OK); 177} 178 179// Messenger 180BMessenger 181RemoteSMTarget::Messenger() 182{ 183 return fTarget; 184} 185 186// DeliverySuccess 187bool 188RemoteSMTarget::DeliverySuccess() 189{ 190 CHK(_SendRequest(SMRT_DELIVERY_SUCCESS_REQUEST) == B_OK); 191 smrt_delivery_success data; 192 CHK(_GetReply(SMRT_DELIVERY_SUCCESS_REPLY, &data, 193 sizeof(smrt_delivery_success)) == B_OK); 194 return data.success; 195} 196 197// _SendRequest 198status_t 199RemoteSMTarget::_SendRequest(int32 code, const void *buffer, size_t size) 200{ 201 return write_port(fRemotePort, code, buffer, size); 202} 203 204// _GetReply 205status_t 206RemoteSMTarget::_GetReply(int32 expectedCode, void *buffer, size_t size) 207{ 208 status_t error = B_OK; 209 int32 code; 210 ssize_t readSize = read_port(fLocalPort, &code, buffer, size); 211 if (readSize < 0) 212 error = readSize; 213 else if ((uint32)readSize != size) 214 error = B_ERROR; 215 else if (code != expectedCode) 216 error = B_ERROR; 217 return error; 218} 219 220// ID 221int32 RemoteSMTarget::fID = 0; 222 223 224