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
SMTarget()24 SMTarget::SMTarget()
25 {
26 }
27
28 // destructor
~SMTarget()29 SMTarget::~SMTarget()
30 {
31 }
32
33 // Init
34 void
Init(bigtime_t unblockTime,bigtime_t replyDelay)35 SMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay)
36 {
37 }
38
39 // Handler
40 BHandler *
Handler()41 SMTarget::Handler()
42 {
43 return NULL;
44 }
45
46 // Messenger
47 BMessenger
Messenger()48 SMTarget::Messenger()
49 {
50 return BMessenger();
51 }
52
53 // DeliverySuccess
54 bool
DeliverySuccess()55 SMTarget::DeliverySuccess()
56 {
57 return false;
58 }
59
60
61 // LocalSMTarget
62
63 // constructor
LocalSMTarget(bool preferred)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
~LocalSMTarget()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
Init(bigtime_t unblockTime,bigtime_t replyDelay)95 LocalSMTarget::Init(bigtime_t unblockTime, bigtime_t replyDelay)
96 {
97 fLooper->SetReplyDelay(replyDelay);
98 fLooper->BlockUntil(unblockTime);
99 }
100
101 // Handler
102 BHandler *
Handler()103 LocalSMTarget::Handler()
104 {
105 return fHandler;
106 }
107
108 // Messenger
109 BMessenger
Messenger()110 LocalSMTarget::Messenger()
111 {
112 return BMessenger(fHandler, fLooper);
113 }
114
115 // DeliverySuccess
116 bool
DeliverySuccess()117 LocalSMTarget::DeliverySuccess()
118 {
119 return fLooper->DeliverySuccess();
120 }
121
122
123 // RemoteSMTarget
124
125 static const char *kSMRemotePortName = "BMessenger_SMRemoteTarget";
126
127 // constructor
RemoteSMTarget(bool preferred)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 += "/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
~RemoteSMTarget()163 RemoteSMTarget::~RemoteSMTarget()
164 {
165 _SendRequest(SMRT_QUIT);
166 delete_port(fLocalPort);
167 }
168
169 // Init
170 void
Init(bigtime_t unblockTime,bigtime_t replyDelay)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
Messenger()181 RemoteSMTarget::Messenger()
182 {
183 return fTarget;
184 }
185
186 // DeliverySuccess
187 bool
DeliverySuccess()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
_SendRequest(int32 code,const void * buffer,size_t size)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
_GetReply(int32 expectedCode,void * buffer,size_t size)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