xref: /haiku/src/servers/registrar/Registrar.cpp (revision 6aff37d1c79e20748c683ae224bd629f88a5b0be)
1 /*
2  * Copyright 2001-2015, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ingo Weinhold, ingo_weinhold@gmx.de
7  */
8 
9 #include "Registrar.h"
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <exception>
15 
16 #include <Application.h>
17 #include <Clipboard.h>
18 #include <Message.h>
19 #include <OS.h>
20 #include <RegistrarDefs.h>
21 #include <RosterPrivate.h>
22 
23 #include "AuthenticationManager.h"
24 #include "ClipboardHandler.h"
25 #include "Debug.h"
26 #include "EventQueue.h"
27 #include "MessageDeliverer.h"
28 #include "MessageEvent.h"
29 #include "MessageRunnerManager.h"
30 #include "MessagingService.h"
31 #include "MIMEManager.h"
32 #include "PackageWatchingManager.h"
33 #include "ShutdownProcess.h"
34 #include "TRoster.h"
35 
36 
37 /*!
38 	\class Registrar
39 	\brief The application class of the registrar.
40 
41 	Glues the registrar services together and dispatches the roster messages.
42 */
43 
44 using std::nothrow;
45 using namespace BPrivate;
46 
47 //! Name of the event queue.
48 static const char *kEventQueueName = "timer_thread";
49 
50 //! Time interval between two roster sanity checks (1 s).
51 static const bigtime_t kRosterSanityEventInterval = 1000000LL;
52 
53 
54 /*!	\brief Creates the registrar application class.
55 	\param error Passed to the BApplication constructor for returning an
56 		   error code.
57 */
58 Registrar::Registrar(status_t* _error)
59 	:
60 	BServer(B_REGISTRAR_SIGNATURE, B_REGISTRAR_PORT_NAME, -1, false, _error),
61 	fRoster(NULL),
62 	fClipboardHandler(NULL),
63 	fMIMEManager(NULL),
64 	fEventQueue(NULL),
65 	fMessageRunnerManager(NULL),
66 	fSanityEvent(NULL),
67 	fShutdownProcess(NULL),
68 	fAuthenticationManager(NULL),
69 	fPackageWatchingManager(NULL)
70 {
71 	FUNCTION_START();
72 
73 	set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY + 1);
74 }
75 
76 
77 /*!	\brief Frees all resources associated with the registrar.
78 
79 	All registrar services, that haven't been shut down earlier, are
80 	terminated.
81 */
82 Registrar::~Registrar()
83 {
84 	FUNCTION_START();
85 	Lock();
86 	fEventQueue->Die();
87 	delete fAuthenticationManager;
88 	delete fPackageWatchingManager;
89 	delete fMessageRunnerManager;
90 	delete fEventQueue;
91 	delete fSanityEvent;
92 	fMIMEManager->Lock();
93 	fMIMEManager->Quit();
94 	RemoveHandler(fClipboardHandler);
95 	delete fClipboardHandler;
96 	delete fRoster;
97 	// Invalidate the global be_roster, so that the BApplication destructor
98 	// won't dead-lock when sending a message to itself.
99 	BRoster::Private().SetTo(BMessenger(), BMessenger());
100 	FUNCTION_END();
101 }
102 
103 
104 /*!	\brief Overrides the super class version to dispatch roster specific
105 		   messages.
106 	\param message The message to be handled
107 */
108 void
109 Registrar::MessageReceived(BMessage *message)
110 {
111 	try {
112 		_MessageReceived(message);
113 	} catch (std::exception& exception) {
114 		char buffer[1024];
115 		snprintf(buffer, sizeof(buffer),
116 			"Registrar::MessageReceived() caught exception: %s",
117 			exception.what());
118 		debugger(buffer);
119 	} catch (...) {
120 		debugger("Registrar::MessageReceived() caught unknown exception");
121 	}
122 }
123 
124 
125 /*!	\brief Overrides the super class version to initialize the registrar
126 		   services.
127 */
128 void
129 Registrar::ReadyToRun()
130 {
131 	FUNCTION_START();
132 
133 	// create message deliverer
134 	status_t error = MessageDeliverer::CreateDefault();
135 	if (error != B_OK) {
136 		FATAL("Registrar::ReadyToRun(): Failed to create the message "
137 			"deliverer: %s\n", strerror(error));
138 	}
139 
140 	// create event queue
141 	fEventQueue = new EventQueue(kEventQueueName);
142 
143 	// create authentication manager
144 	fAuthenticationManager = new AuthenticationManager;
145 	fAuthenticationManager->Init();
146 
147 	// create roster
148 	fRoster = new TRoster;
149 	fRoster->Init();
150 
151 	// create clipboard handler
152 	fClipboardHandler = new ClipboardHandler;
153 	AddHandler(fClipboardHandler);
154 
155 	// create MIME manager
156 	fMIMEManager = new MIMEManager;
157 	fMIMEManager->Run();
158 
159 	// create message runner manager
160 	fMessageRunnerManager = new MessageRunnerManager(fEventQueue);
161 
162 	// init the global be_roster
163 	BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager));
164 
165 	// create the messaging service
166 	error = MessagingService::CreateDefault();
167 	if (error != B_OK) {
168 		ERROR("Registrar::ReadyToRun(): Failed to init messaging service "
169 			"(that's by design when running under R5): %s\n", strerror(error));
170 	}
171 
172 	// create the package watching manager
173 	fPackageWatchingManager = new PackageWatchingManager;
174 
175 	// create and schedule the sanity message event
176 	fSanityEvent = new MessageEvent(system_time() + kRosterSanityEventInterval,
177 		this, B_REG_ROSTER_SANITY_EVENT);
178 	fSanityEvent->SetAutoDelete(false);
179 	fEventQueue->AddEvent(fSanityEvent);
180 
181 	FUNCTION_END();
182 }
183 
184 
185 /*!	\brief Overrides the super class version to avoid termination of the
186 		   registrar until the system shutdown.
187 */
188 bool
189 Registrar::QuitRequested()
190 {
191 	FUNCTION_START();
192 	// The final registrar must not quit. At least not that easily. ;-)
193 	return BApplication::QuitRequested();
194 }
195 
196 
197 /*!	\brief Returns the registrar's event queue.
198 	\return The registrar's event queue.
199 */
200 EventQueue*
201 Registrar::GetEventQueue() const
202 {
203 	return fEventQueue;
204 }
205 
206 
207 /*!	\brief Returns the Registrar application object.
208 	\return The Registrar application object.
209 */
210 Registrar*
211 Registrar::App()
212 {
213 	return dynamic_cast<Registrar*>(be_app);
214 }
215 
216 
217 void
218 Registrar::_MessageReceived(BMessage *message)
219 {
220 	switch (message->what) {
221 		// general requests
222 		case B_REG_GET_MIME_MESSENGER:
223 		{
224 			PRINT("B_REG_GET_MIME_MESSENGER\n");
225 			BMessenger messenger(NULL, fMIMEManager);
226 			BMessage reply(B_REG_SUCCESS);
227 			reply.AddMessenger("messenger", messenger);
228 			message->SendReply(&reply);
229 			break;
230 		}
231 
232 		case B_REG_GET_CLIPBOARD_MESSENGER:
233 		{
234 			PRINT("B_REG_GET_CLIPBOARD_MESSENGER\n");
235 			BMessenger messenger(fClipboardHandler);
236 			BMessage reply(B_REG_SUCCESS);
237 			reply.AddMessenger("messenger", messenger);
238 			message->SendReply(&reply);
239 			break;
240 		}
241 
242 		// shutdown process
243 		case B_REG_SHUT_DOWN:
244 		{
245 			PRINT("B_REG_SHUT_DOWN\n");
246 
247 			_HandleShutDown(message);
248 			break;
249 		}
250 		case B_REG_TEAM_DEBUGGER_ALERT:
251 		{
252 			if (fShutdownProcess != NULL)
253 				fShutdownProcess->PostMessage(message);
254 			break;
255 		}
256 
257 		// roster requests
258 		case B_REG_ADD_APP:
259 			fRoster->HandleAddApplication(message);
260 			break;
261 		case B_REG_COMPLETE_REGISTRATION:
262 			fRoster->HandleCompleteRegistration(message);
263 			break;
264 		case B_REG_IS_APP_REGISTERED:
265 			fRoster->HandleIsAppRegistered(message);
266 			break;
267 		case B_REG_REMOVE_PRE_REGISTERED_APP:
268 			fRoster->HandleRemovePreRegApp(message);
269 			break;
270 		case B_REG_REMOVE_APP:
271 			fRoster->HandleRemoveApp(message);
272 			break;
273 		case B_REG_SET_THREAD_AND_TEAM:
274 			fRoster->HandleSetThreadAndTeam(message);
275 			break;
276 		case B_REG_SET_SIGNATURE:
277 			fRoster->HandleSetSignature(message);
278 			break;
279 		case B_REG_GET_APP_INFO:
280 			fRoster->HandleGetAppInfo(message);
281 			break;
282 		case B_REG_GET_APP_LIST:
283 			fRoster->HandleGetAppList(message);
284 			break;
285 		case B_REG_UPDATE_ACTIVE_APP:
286 			fRoster->HandleUpdateActiveApp(message);
287 			break;
288 		case B_REG_BROADCAST:
289 			fRoster->HandleBroadcast(message);
290 			break;
291 		case B_REG_START_WATCHING:
292 			fRoster->HandleStartWatching(message);
293 			break;
294 		case B_REG_STOP_WATCHING:
295 			fRoster->HandleStopWatching(message);
296 			break;
297 		case B_REG_GET_RECENT_DOCUMENTS:
298 			fRoster->HandleGetRecentDocuments(message);
299 			break;
300 		case B_REG_GET_RECENT_FOLDERS:
301 			fRoster->HandleGetRecentFolders(message);
302 			break;
303 		case B_REG_GET_RECENT_APPS:
304 			fRoster->HandleGetRecentApps(message);
305 			break;
306 		case B_REG_ADD_TO_RECENT_DOCUMENTS:
307 			fRoster->HandleAddToRecentDocuments(message);
308 			break;
309 		case B_REG_ADD_TO_RECENT_FOLDERS:
310 			fRoster->HandleAddToRecentFolders(message);
311 			break;
312 		case B_REG_ADD_TO_RECENT_APPS:
313 			fRoster->HandleAddToRecentApps(message);
314 			break;
315 		case B_REG_CLEAR_RECENT_DOCUMENTS:
316 			fRoster->ClearRecentDocuments();
317 			break;
318 		case B_REG_CLEAR_RECENT_FOLDERS:
319 			fRoster->ClearRecentFolders();
320 			break;
321 		case B_REG_CLEAR_RECENT_APPS:
322 			fRoster->ClearRecentApps();
323 			break;
324 		case B_REG_LOAD_RECENT_LISTS:
325 			fRoster->HandleLoadRecentLists(message);
326 			break;
327 		case B_REG_SAVE_RECENT_LISTS:
328 			fRoster->HandleSaveRecentLists(message);
329 			break;
330 
331 		// message runner requests
332 		case B_REG_REGISTER_MESSAGE_RUNNER:
333 			fMessageRunnerManager->HandleRegisterRunner(message);
334 			break;
335 		case B_REG_UNREGISTER_MESSAGE_RUNNER:
336 			fMessageRunnerManager->HandleUnregisterRunner(message);
337 			break;
338 		case B_REG_SET_MESSAGE_RUNNER_PARAMS:
339 			fMessageRunnerManager->HandleSetRunnerParams(message);
340 			break;
341 		case B_REG_GET_MESSAGE_RUNNER_INFO:
342 			fMessageRunnerManager->HandleGetRunnerInfo(message);
343 			break;
344 
345 		// package watching requests
346 		case B_REG_PACKAGE_START_WATCHING:
347 		case B_REG_PACKAGE_STOP_WATCHING:
348 			fPackageWatchingManager->HandleStartStopWatching(message);
349 			break;
350 		case B_PACKAGE_UPDATE:
351 			fPackageWatchingManager->NotifyWatchers(message);
352 			break;
353 
354 		// internal messages
355 		case B_REG_ROSTER_SANITY_EVENT:
356 			fRoster->CheckSanity();
357 			fSanityEvent->SetTime(system_time() + kRosterSanityEventInterval);
358 			fEventQueue->AddEvent(fSanityEvent);
359 			break;
360 		case B_REG_SHUTDOWN_FINISHED:
361 			if (fShutdownProcess) {
362 				fShutdownProcess->PostMessage(B_QUIT_REQUESTED,
363 					fShutdownProcess);
364 				fShutdownProcess = NULL;
365 			}
366 			break;
367 
368 		case kMsgRestartAppServer:
369 		{
370 			fRoster->HandleRestartAppServer(message);
371 			break;
372 		}
373 
374 		default:
375 			BApplication::MessageReceived(message);
376 			break;
377 	}
378 }
379 
380 
381 /*!	\brief Handle a shut down request message.
382 	\param request The request to be handled.
383 */
384 void
385 Registrar::_HandleShutDown(BMessage *request)
386 {
387 	status_t error = B_OK;
388 
389 	// check, whether we're already shutting down
390 	if (fShutdownProcess)
391 		error = B_SHUTTING_DOWN;
392 
393 	bool needsReply = true;
394 	if (error == B_OK) {
395 		// create a ShutdownProcess
396 		fShutdownProcess = new(nothrow) ShutdownProcess(fRoster, fEventQueue);
397 		if (fShutdownProcess) {
398 			error = fShutdownProcess->Init(request);
399 			if (error == B_OK) {
400 				DetachCurrentMessage();
401 				fShutdownProcess->Run();
402 				needsReply = false;
403 			} else {
404 				delete fShutdownProcess;
405 				fShutdownProcess = NULL;
406 			}
407 		} else
408 			error = B_NO_MEMORY;
409 	}
410 
411 	if (needsReply)
412 		ShutdownProcess::SendReply(request, error);
413 }
414 
415 
416 //	#pragma mark -
417 
418 
419 /*!	\brief Creates and runs the registrar application.
420 
421 	The main thread is renamed.
422 
423 	\return 0.
424 */
425 int
426 main()
427 {
428 	FUNCTION_START();
429 
430 	// Create the global be_clipboard manually -- it will not work, since it
431 	// wants to talk to the registrar in its constructor, but it doesn't have
432 	// to and we would otherwise deadlock when initializing our GUI in the
433 	// app thread.
434 	be_clipboard = new BClipboard(NULL);
435 
436 	// create and run the registrar application
437 	status_t error;
438 	Registrar *app = new Registrar(&error);
439 	if (error != B_OK) {
440 		fprintf(stderr, "REG: Failed to create the BApplication: %s\n",
441 			strerror(error));
442 		return 1;
443 	}
444 
445 	// rename the main thread
446 	rename_thread(find_thread(NULL), "roster");
447 
448 	PRINT("app->Run()...\n");
449 
450 	try {
451 		app->Run();
452 	} catch (std::exception& exception) {
453 		char buffer[1024];
454 		snprintf(buffer, sizeof(buffer),
455 			"registrar main() caught exception: %s", exception.what());
456 		debugger(buffer);
457 	} catch (...) {
458 		debugger("registrar main() caught unknown exception");
459 	}
460 
461 	PRINT("delete app...\n");
462 	delete app;
463 
464 	FUNCTION_END();
465 	return 0;
466 }
467 
468