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