vfs: check userland buffers before reading them.
[haiku.git] / src / servers / registrar / Registrar.cpp
blob7987a1bc6355718f903a896767565f4b4e9e12dd
1 /*
2 * Copyright 2001-2015, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ingo Weinhold, ingo_weinhold@gmx.de
7 */
9 #include "Registrar.h"
11 #include <stdio.h>
12 #include <string.h>
14 #include <exception>
16 #include <Application.h>
17 #include <Clipboard.h>
18 #include <Message.h>
19 #include <OS.h>
20 #include <RegistrarDefs.h>
21 #include <RosterPrivate.h>
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"
37 /*!
38 \class Registrar
39 \brief The application class of the registrar.
41 Glues the registrar services together and dispatches the roster messages.
44 using std::nothrow;
45 using namespace BPrivate;
47 //! Name of the event queue.
48 static const char *kEventQueueName = "timer_thread";
50 //! Time interval between two roster sanity checks (1 s).
51 static const bigtime_t kRosterSanityEventInterval = 1000000LL;
54 /*! \brief Creates the registrar application class.
55 \param error Passed to the BApplication constructor for returning an
56 error code.
58 Registrar::Registrar(status_t* _error)
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)
71 FUNCTION_START();
73 set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY + 1);
77 /*! \brief Frees all resources associated with the registrar.
79 All registrar services, that haven't been shut down earlier, are
80 terminated.
82 Registrar::~Registrar()
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();
104 /*! \brief Overrides the super class version to dispatch roster specific
105 messages.
106 \param message The message to be handled
108 void
109 Registrar::MessageReceived(BMessage *message)
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");
125 /*! \brief Overrides the super class version to initialize the registrar
126 services.
128 void
129 Registrar::ReadyToRun()
131 FUNCTION_START();
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));
140 // create event queue
141 fEventQueue = new EventQueue(kEventQueueName);
143 // create authentication manager
144 fAuthenticationManager = new AuthenticationManager;
145 fAuthenticationManager->Init();
147 // create roster
148 fRoster = new TRoster;
149 fRoster->Init();
151 // create clipboard handler
152 fClipboardHandler = new ClipboardHandler;
153 AddHandler(fClipboardHandler);
155 // create MIME manager
156 fMIMEManager = new MIMEManager;
157 fMIMEManager->Run();
159 // create message runner manager
160 fMessageRunnerManager = new MessageRunnerManager(fEventQueue);
162 // init the global be_roster
163 BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager));
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));
172 // create the package watching manager
173 fPackageWatchingManager = new PackageWatchingManager;
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);
181 FUNCTION_END();
185 /*! \brief Overrides the super class version to avoid termination of the
186 registrar until the system shutdown.
188 bool
189 Registrar::QuitRequested()
191 FUNCTION_START();
192 // The final registrar must not quit. At least not that easily. ;-)
193 return BApplication::QuitRequested();
197 /*! \brief Returns the registrar's event queue.
198 \return The registrar's event queue.
200 EventQueue*
201 Registrar::GetEventQueue() const
203 return fEventQueue;
207 /*! \brief Returns the Registrar application object.
208 \return The Registrar application object.
210 Registrar*
211 Registrar::App()
213 return dynamic_cast<Registrar*>(be_app);
217 void
218 Registrar::_MessageReceived(BMessage *message)
220 switch (message->what) {
221 // general requests
222 case B_REG_GET_MIME_MESSENGER:
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;
232 case B_REG_GET_CLIPBOARD_MESSENGER:
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;
242 // shutdown process
243 case B_REG_SHUT_DOWN:
245 PRINT("B_REG_SHUT_DOWN\n");
247 _HandleShutDown(message);
248 break;
250 case B_REG_TEAM_DEBUGGER_ALERT:
252 if (fShutdownProcess != NULL)
253 fShutdownProcess->PostMessage(message);
254 break;
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;
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;
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;
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;
366 break;
368 case kMsgRestartAppServer:
370 fRoster->HandleRestartAppServer(message);
371 break;
374 default:
375 BApplication::MessageReceived(message);
376 break;
381 /*! \brief Handle a shut down request message.
382 \param request The request to be handled.
384 void
385 Registrar::_HandleShutDown(BMessage *request)
387 status_t error = B_OK;
389 // check, whether we're already shutting down
390 if (fShutdownProcess)
391 error = B_SHUTTING_DOWN;
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;
407 } else
408 error = B_NO_MEMORY;
411 if (needsReply)
412 ShutdownProcess::SendReply(request, error);
416 // #pragma mark -
419 /*! \brief Creates and runs the registrar application.
421 The main thread is renamed.
423 \return 0.
426 main()
428 FUNCTION_START();
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);
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;
445 // rename the main thread
446 rename_thread(find_thread(NULL), "roster");
448 PRINT("app->Run()...\n");
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");
461 PRINT("delete app...\n");
462 delete app;
464 FUNCTION_END();
465 return 0;