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