xref: /haiku/src/tests/kits/app/bmessenger/SMTarget.cpp (revision df8b692ac0ba4c71a968a22593d2195450466d27)
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