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 18 using namespace std; 19 20 21 // SMTarget 22 23 // constructor 24 SMTarget::SMTarget() 25 { 26 } 27 28 // destructor 29 SMTarget::~SMTarget() 30 { 31 } 32 33 // Init 34 void 35 SMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) 36 { 37 } 38 39 // Handler 40 BHandler * 41 SMTarget::Handler() 42 { 43 return NULL; 44 } 45 46 // Messenger 47 BMessenger 48 SMTarget::Messenger() 49 { 50 return BMessenger(); 51 } 52 53 // DeliverySuccess 54 bool 55 SMTarget::DeliverySuccess() 56 { 57 return false; 58 } 59 60 61 // LocalSMTarget 62 63 // constructor 64 LocalSMTarget::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 81 LocalSMTarget::~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 94 void 95 LocalSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay) 96 { 97 fLooper->SetReplyDelay(replyDelay); 98 fLooper->BlockUntil(unblockTime); 99 } 100 101 // Handler 102 BHandler * 103 LocalSMTarget::Handler() 104 { 105 return fHandler; 106 } 107 108 // Messenger 109 BMessenger 110 LocalSMTarget::Messenger() 111 { 112 return BMessenger(fHandler, fLooper); 113 } 114 115 // DeliverySuccess 116 bool 117 LocalSMTarget::DeliverySuccess() 118 { 119 return fLooper->DeliverySuccess(); 120 } 121 122 123 // RemoteSMTarget 124 125 static const char *kSMRemotePortName = "BMessenger_SMRemoteTarget"; 126 127 // constructor 128 RemoteSMTarget::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 += "/../kits/app/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 163 RemoteSMTarget::~RemoteSMTarget() 164 { 165 _SendRequest(SMRT_QUIT); 166 delete_port(fLocalPort); 167 } 168 169 // Init 170 void 171 RemoteSMTarget::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 180 BMessenger 181 RemoteSMTarget::Messenger() 182 { 183 return fTarget; 184 } 185 186 // DeliverySuccess 187 bool 188 RemoteSMTarget::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 198 status_t 199 RemoteSMTarget::_SendRequest(int32 code, const void *buffer, size_t size) 200 { 201 return write_port(fRemotePort, code, buffer, size); 202 } 203 204 // _GetReply 205 status_t 206 RemoteSMTarget::_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 221 int32 RemoteSMTarget::fID = 0; 222 223 224