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