1/*
2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 *		Erik Jaesler, erik@cgsoftware.com
8 */
9
10
11#include <TokenSpace.h>
12
13#include <AppDefs.h>
14#include <Handler.h>
15#include <Looper.h>
16#include <Message.h>
17#include <MessageFilter.h>
18#include <Messenger.h>
19#include <PropertyInfo.h>
20
21#include <algorithm>
22#include <new>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <vector>
27
28using std::map;
29using std::vector;
30using BPrivate::gDefaultTokens;
31
32
33static const char* kArchiveNameField = "_name";
34
35static const uint32 kMsgStartObserving = '_OBS';
36static const uint32 kMsgStopObserving = '_OBP';
37static const char* kObserveTarget = "be:observe_target";
38
39
40static property_info sHandlerPropInfo[] = {
41	{
42		"Suites",					// name
43		{ B_GET_PROPERTY },			// commands
44		{ B_DIRECT_SPECIFIER },		// specifiers
45		NULL,						// usage
46		0,							// extra data
47		{ 0 },						// types
48		{							// ctypes (compound_type)
49			{						// ctypes[0]
50				{					// pairs[0]
51					{
52						"suites",		// name
53						B_STRING_TYPE	// type
54					}
55				}
56			},
57			{						// ctypes[1]
58				{					// pairs[0]
59					{
60						"messages",
61						B_PROPERTY_INFO_TYPE
62					}
63				}
64			}
65		},
66		{}		// reserved
67	},
68	{
69		"Messenger",
70			{ B_GET_PROPERTY },
71			{ B_DIRECT_SPECIFIER },
72			NULL, 0,
73			{ B_MESSENGER_TYPE },
74			{},
75			{}
76	},
77	{
78		"InternalName",
79			{ B_GET_PROPERTY },
80			{ B_DIRECT_SPECIFIER },
81			NULL, 0,
82			{ B_STRING_TYPE },
83			{},
84			{}
85	},
86
87	{ 0 }
88};
89
90bool FilterDeleter(void* filter);
91
92namespace BPrivate {
93
94class ObserverList {
95	public:
96		ObserverList();
97		~ObserverList();
98
99		status_t SendNotices(uint32 what, const BMessage* notice);
100		status_t Add(const BHandler* handler, uint32 what);
101		status_t Add(const BMessenger& messenger, uint32 what);
102		status_t Remove(const BHandler* handler, uint32 what);
103		status_t Remove(const BMessenger& messenger, uint32 what);
104		bool IsEmpty();
105
106	private:
107		typedef map<uint32, vector<const BHandler*> > HandlerObserverMap;
108		typedef map<uint32, vector<BMessenger> > MessengerObserverMap;
109
110		void _ValidateHandlers(uint32 what);
111		void _SendNotices(uint32 what, BMessage* notice);
112
113		HandlerObserverMap		fHandlerMap;
114		MessengerObserverMap	fMessengerMap;
115};
116
117}	// namespace BPrivate
118
119using namespace BPrivate;
120
121
122//	#pragma mark -
123
124
125BHandler::BHandler(const char* name)
126	: BArchivable(),
127	fName(NULL)
128{
129	_InitData(name);
130}
131
132
133BHandler::~BHandler()
134{
135	if (LockLooper()) {
136		BLooper* looper = Looper();
137		looper->RemoveHandler(this);
138		looper->Unlock();
139	}
140
141	// remove all filters
142	if (fFilters) {
143		int32 count = fFilters->CountItems();
144		for (int32 i = 0; i < count; i++)
145			delete (BMessageFilter*)fFilters->ItemAtFast(i);
146		delete fFilters;
147	}
148
149	// remove all observers (the observer list manages itself)
150	delete fObserverList;
151
152	// free rest
153	free(fName);
154	gDefaultTokens.RemoveToken(fToken);
155}
156
157
158BHandler::BHandler(BMessage* data)
159	: BArchivable(data),
160	fName(NULL)
161{
162	const char* name = NULL;
163
164	if (data)
165		data->FindString(kArchiveNameField, &name);
166
167	_InitData(name);
168}
169
170
171BArchivable*
172BHandler::Instantiate(BMessage* data)
173{
174	if (!validate_instantiation(data, "BHandler"))
175		return NULL;
176
177	return new BHandler(data);
178}
179
180
181status_t
182BHandler::Archive(BMessage* data, bool deep) const
183{
184	status_t status = BArchivable::Archive(data, deep);
185	if (status < B_OK)
186		return status;
187
188	if (fName == NULL)
189		return B_OK;
190
191	return data->AddString(kArchiveNameField, fName);
192}
193
194
195void
196BHandler::MessageReceived(BMessage* message)
197{
198	BMessage reply(B_REPLY);
199
200	switch (message->what) {
201		case kMsgStartObserving:
202		case kMsgStopObserving:
203		{
204			BMessenger target;
205			uint32 what;
206			if (message->FindMessenger(kObserveTarget, &target) != B_OK
207				|| message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what)
208					!= B_OK) {
209				break;
210			}
211
212			ObserverList* list = _ObserverList();
213			if (list != NULL) {
214				if (message->what == kMsgStartObserving)
215					list->Add(target, what);
216				else
217					list->Remove(target, what);
218			}
219			break;
220		}
221
222		case B_GET_PROPERTY:
223		{
224			int32 cur;
225			BMessage specifier;
226			int32 form;
227			const char* prop;
228
229			status_t err = message->GetCurrentSpecifier(&cur, &specifier,
230				&form, &prop);
231			if (err != B_OK && err != B_BAD_SCRIPT_SYNTAX)
232				break;
233			bool known = false;
234			// B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
235			if (err == B_BAD_SCRIPT_SYNTAX || cur < 0
236				|| (strcmp(prop, "Messenger") == 0)) {
237				err = reply.AddMessenger("result", this);
238				known = true;
239			} else if (strcmp(prop, "Suites") == 0) {
240				err = GetSupportedSuites(&reply);
241				known = true;
242			} else if (strcmp(prop, "InternalName") == 0) {
243				err = reply.AddString("result", Name());
244				known = true;
245			}
246
247			if (known) {
248				reply.AddInt32("error", B_OK);
249				message->SendReply(&reply);
250				return;
251			}
252			// let's try next handler
253			break;
254		}
255
256		case B_GET_SUPPORTED_SUITES:
257		{
258			reply.AddInt32("error", GetSupportedSuites(&reply));
259			message->SendReply(&reply);
260			return;
261		}
262	}
263
264	// ToDo: there is some more work needed here
265	// (someone in the know should fill in)!
266
267	if (fNextHandler) {
268		// we need to apply the next handler's filters here, too
269		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
270		if (target != NULL && target != this) {
271			// TODO: we also need to make sure that "target" is not before
272			//	us in the handler chain - at least in case it wasn't before
273			//	the handler actually targeted with this message - this could
274			//	get ugly, though.
275			target->MessageReceived(message);
276		}
277	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
278		&& (message->WasDropped() || message->HasSpecifiers())) {
279		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
280		message->PrintToStream();
281		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
282	}
283}
284
285
286BLooper*
287BHandler::Looper() const
288{
289	return fLooper;
290}
291
292
293void
294BHandler::SetName(const char* name)
295{
296	if (fName != NULL) {
297		free(fName);
298		fName = NULL;
299	}
300
301	if (name != NULL)
302		fName = strdup(name);
303}
304
305
306const char*
307BHandler::Name() const
308{
309	return fName;
310}
311
312
313void
314BHandler::SetNextHandler(BHandler* handler)
315{
316	if (fLooper == NULL) {
317		debugger("handler must belong to looper before setting NextHandler");
318		return;
319	}
320
321	if (!fLooper->IsLocked()) {
322		debugger("The handler's looper must be locked before setting NextHandler");
323		return;
324	}
325
326	if (handler != NULL && fLooper != handler->Looper()) {
327		debugger("The handler and its NextHandler must have the same looper");
328		return;
329	}
330
331	fNextHandler = handler;
332}
333
334
335BHandler*
336BHandler::NextHandler() const
337{
338	return fNextHandler;
339}
340
341
342void
343BHandler::AddFilter(BMessageFilter* filter)
344{
345	BLooper* looper = fLooper;
346	if (looper != NULL && !looper->IsLocked()) {
347		debugger("Owning Looper must be locked before calling SetFilterList");
348		return;
349	}
350
351	if (looper != NULL)
352		filter->SetLooper(looper);
353
354	if (fFilters == NULL)
355		fFilters = new BList;
356
357	fFilters->AddItem(filter);
358}
359
360
361bool
362BHandler::RemoveFilter(BMessageFilter* filter)
363{
364	BLooper* looper = fLooper;
365	if (looper != NULL && !looper->IsLocked()) {
366		debugger("Owning Looper must be locked before calling SetFilterList");
367		return false;
368	}
369
370	if (fFilters != NULL && fFilters->RemoveItem((void*)filter)) {
371		filter->SetLooper(NULL);
372		return true;
373	}
374
375	return false;
376}
377
378
379void
380BHandler::SetFilterList(BList* filters)
381{
382	BLooper* looper = fLooper;
383	if (looper != NULL && !looper->IsLocked()) {
384		debugger("Owning Looper must be locked before calling SetFilterList");
385		return;
386	}
387
388	/**
389		@note	I would like to use BObjectList internally, but this function is
390				spec'd such that fFilters would get deleted and then assigned
391				'filters', which would obviously mess this up.  Wondering if
392				anyone ever assigns a list of filters and then checks against
393				FilterList() to see if they are the same.
394	 */
395
396	// TODO: Explore issues with using BObjectList
397	if (fFilters != NULL) {
398		fFilters->DoForEach(FilterDeleter);
399		delete fFilters;
400	}
401
402	fFilters = filters;
403	if (fFilters) {
404		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
405			BMessageFilter* filter =
406				static_cast<BMessageFilter*>(fFilters->ItemAt(i));
407			if (filter != NULL)
408				filter->SetLooper(looper);
409		}
410	}
411}
412
413
414BList*
415BHandler::FilterList()
416{
417	return fFilters;
418}
419
420
421bool
422BHandler::LockLooper()
423{
424	BLooper* looper = fLooper;
425	// Locking the looper also makes sure that the looper is valid
426	if (looper != NULL && looper->Lock()) {
427		// Have we locked the right looper? That's as far as the
428		// "pseudo-atomic" operation mentioned in the BeBook.
429		if (fLooper == looper)
430			return true;
431
432		// we locked the wrong looper, bail out
433		looper->Unlock();
434	}
435
436	return false;
437}
438
439
440status_t
441BHandler::LockLooperWithTimeout(bigtime_t timeout)
442{
443	BLooper* looper = fLooper;
444	if (looper == NULL)
445		return B_BAD_VALUE;
446
447	status_t status = looper->LockWithTimeout(timeout);
448	if (status != B_OK)
449		return status;
450
451	if (fLooper != looper) {
452		// we locked the wrong looper, bail out
453		looper->Unlock();
454		return B_MISMATCHED_VALUES;
455	}
456
457	return B_OK;
458}
459
460
461void
462BHandler::UnlockLooper()
463{
464	fLooper->Unlock();
465}
466
467
468BHandler*
469BHandler::ResolveSpecifier(BMessage* message, int32 index,
470	BMessage* specifier, int32 what, const char* property)
471{
472	// Straight from the BeBook
473	BPropertyInfo propertyInfo(sHandlerPropInfo);
474	if (propertyInfo.FindMatch(message, index, specifier, what, property) >= 0)
475		return this;
476
477	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
478	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
479	reply.AddString("message", "Didn't understand the specifier(s)");
480	message->SendReply(&reply);
481
482	return NULL;
483}
484
485
486status_t
487BHandler::GetSupportedSuites(BMessage* data)
488{
489/**
490	@note	This is the output from the original implementation (calling
491			PrintToStream() on both data and the contained BPropertyInfo):
492
493BMessage: what =  (0x0, or 0)
494	entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
495	entry       messages, type='SCTD', c=1, size= 0,
496	  property   commands                       types                specifiers
497--------------------------------------------------------------------------------
498		Suites   PGET                                               1
499				 (RTSC,suites)
500				 (DTCS,messages)
501
502	 Messenger   PGET                          GNSM                 1
503  InternalName   PGET                          RTSC                 1
504
505			With a good deal of trial and error, I determined that the
506			parenthetical clauses are entries in the 'ctypes' field of
507			property_info.  'ctypes' is an array of 'compound_type', which
508			contains an array of 'field_pair's.  I haven't the foggiest what
509			either 'compound_type' or 'field_pair' is for, being as the
510			scripting docs are so bloody horrible.  The corresponding
511			property_info array is declared in the globals section.
512 */
513
514	if (data == NULL)
515		return B_BAD_VALUE;
516
517	status_t result = data->AddString("suites", "suite/vnd.Be-handler");
518	if (result == B_OK) {
519		BPropertyInfo propertyInfo(sHandlerPropInfo);
520		result = data->AddFlat("messages", &propertyInfo);
521	}
522
523	return result;
524}
525
526
527status_t
528BHandler::StartWatching(BMessenger target, uint32 what)
529{
530	BMessage message(kMsgStartObserving);
531	message.AddMessenger(kObserveTarget, this);
532	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
533
534	return target.SendMessage(&message);
535}
536
537
538status_t
539BHandler::StartWatchingAll(BMessenger target)
540{
541	return StartWatching(target, B_OBSERVER_OBSERVE_ALL);
542}
543
544
545status_t
546BHandler::StopWatching(BMessenger target, uint32 what)
547{
548	BMessage message(kMsgStopObserving);
549	message.AddMessenger(kObserveTarget, this);
550	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
551
552	return target.SendMessage(&message);
553}
554
555
556status_t
557BHandler::StopWatchingAll(BMessenger target)
558{
559	return StopWatching(target, B_OBSERVER_OBSERVE_ALL);
560}
561
562
563status_t
564BHandler::StartWatching(BHandler* handler, uint32 what)
565{
566	ObserverList* list = _ObserverList();
567	if (list == NULL)
568		return B_NO_MEMORY;
569
570	return list->Add(handler, what);
571}
572
573
574status_t
575BHandler::StartWatchingAll(BHandler* handler)
576{
577	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
578}
579
580
581status_t
582BHandler::StopWatching(BHandler* handler, uint32 what)
583{
584	ObserverList* list = _ObserverList();
585	if (list == NULL)
586		return B_NO_MEMORY;
587
588	return list->Remove(handler, what);
589}
590
591
592status_t
593BHandler::StopWatchingAll(BHandler* handler)
594{
595	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
596}
597
598
599status_t
600BHandler::Perform(perform_code d, void* arg)
601{
602	return BArchivable::Perform(d, arg);
603}
604
605
606void
607BHandler::SendNotices(uint32 what, const BMessage* notice)
608{
609	if (fObserverList != NULL)
610		fObserverList->SendNotices(what, notice);
611}
612
613
614bool
615BHandler::IsWatched() const
616{
617	return fObserverList && !fObserverList->IsEmpty();
618}
619
620
621void
622BHandler::_InitData(const char* name)
623{
624	SetName(name);
625
626	fLooper = NULL;
627	fNextHandler = NULL;
628	fFilters = NULL;
629	fObserverList = NULL;
630
631	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
632}
633
634
635ObserverList*
636BHandler::_ObserverList()
637{
638	if (fObserverList == NULL)
639		fObserverList = new (std::nothrow) BPrivate::ObserverList();
640
641	return fObserverList;
642}
643
644
645void
646BHandler::SetLooper(BLooper* looper)
647{
648	fLooper = looper;
649	gDefaultTokens.SetHandlerTarget(fToken,
650		looper ? looper->fDirectTarget : NULL);
651
652	if (fFilters != NULL) {
653		for (int32 i = 0; i < fFilters->CountItems(); i++) {
654			static_cast<BMessageFilter*>(
655				fFilters->ItemAtFast(i))->SetLooper(looper);
656		}
657	}
658}
659
660
661#if __GNUC__ < 3
662// binary compatibility with R4.5
663
664extern "C" void
665_ReservedHandler1__8BHandler(BHandler* handler, uint32 what,
666	const BMessage* notice)
667{
668	handler->BHandler::SendNotices(what, notice);
669}
670
671
672BHandler::BHandler(const BHandler &)
673{
674	// No copy construction allowed.
675}
676
677
678BHandler &
679BHandler::operator=(const BHandler &)
680{
681	// No assignments allowed.
682	return *this;
683}
684#endif
685
686void BHandler::_ReservedHandler2() {}
687void BHandler::_ReservedHandler3() {}
688void BHandler::_ReservedHandler4() {}
689
690
691//	#pragma mark -
692
693
694ObserverList::ObserverList()
695{
696}
697
698
699ObserverList::~ObserverList()
700{
701}
702
703
704void
705ObserverList::_ValidateHandlers(uint32 what)
706{
707	vector<const BHandler*>& handlers = fHandlerMap[what];
708	vector<const BHandler*>::iterator iterator = handlers.begin();
709
710	while (iterator != handlers.end()) {
711		BMessenger target(*iterator);
712		if (!target.IsValid()) {
713			iterator++;
714			continue;
715		}
716
717		Add(target, what);
718		iterator = handlers.erase(iterator);
719	}
720}
721
722
723void
724ObserverList::_SendNotices(uint32 what, BMessage* notice)
725{
726	// first iterate over the list of handlers and try to make valid
727	// messengers out of them
728	_ValidateHandlers(what);
729
730	// now send it to all messengers we know
731	vector<BMessenger>& messengers = fMessengerMap[what];
732	vector<BMessenger>::iterator iterator = messengers.begin();
733
734	while (iterator != messengers.end()) {
735		if (!(*iterator).IsValid()) {
736			iterator = messengers.erase(iterator);
737			continue;
738		}
739
740		(*iterator).SendMessage(notice);
741		iterator++;
742	}
743}
744
745
746status_t
747ObserverList::SendNotices(uint32 what, const BMessage* notice)
748{
749	BMessage* copy = NULL;
750	if (notice != NULL) {
751		copy = new BMessage(*notice);
752		copy->what = B_OBSERVER_NOTICE_CHANGE;
753		copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, notice->what);
754	} else
755		copy = new BMessage(B_OBSERVER_NOTICE_CHANGE);
756
757	copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
758
759	_SendNotices(what, copy);
760	_SendNotices(B_OBSERVER_OBSERVE_ALL, copy);
761
762	delete copy;
763
764	return B_OK;
765}
766
767
768status_t
769ObserverList::Add(const BHandler* handler, uint32 what)
770{
771	if (handler == NULL)
772		return B_BAD_HANDLER;
773
774	// if this handler already represents a valid target, add its messenger
775	BMessenger target(handler);
776	if (target.IsValid())
777		return Add(target, what);
778
779	vector<const BHandler*> &handlers = fHandlerMap[what];
780
781	vector<const BHandler*>::iterator iter;
782	iter = find(handlers.begin(), handlers.end(), handler);
783	if (iter != handlers.end()) {
784		// TODO: do we want to have a reference count for this?
785		return B_OK;
786	}
787
788	handlers.push_back(handler);
789	return B_OK;
790}
791
792
793status_t
794ObserverList::Add(const BMessenger &messenger, uint32 what)
795{
796	vector<BMessenger> &messengers = fMessengerMap[what];
797
798	vector<BMessenger>::iterator iter;
799	iter = find(messengers.begin(), messengers.end(), messenger);
800	if (iter != messengers.end()) {
801		// TODO: do we want to have a reference count for this?
802		return B_OK;
803	}
804
805	messengers.push_back(messenger);
806	return B_OK;
807}
808
809
810status_t
811ObserverList::Remove(const BHandler* handler, uint32 what)
812{
813	if (handler == NULL)
814		return B_BAD_HANDLER;
815
816	// look into the list of messengers
817	BMessenger target(handler);
818	if (target.IsValid() && Remove(target, what) == B_OK)
819		return B_OK;
820
821	vector<const BHandler*> &handlers = fHandlerMap[what];
822
823	vector<const BHandler*>::iterator iterator = find(handlers.begin(),
824		handlers.end(), handler);
825	if (iterator != handlers.end()) {
826		handlers.erase(iterator);
827		if (handlers.empty())
828			fHandlerMap.erase(what);
829
830		return B_OK;
831	}
832
833	return B_BAD_HANDLER;
834}
835
836
837status_t
838ObserverList::Remove(const BMessenger &messenger, uint32 what)
839{
840	vector<BMessenger> &messengers = fMessengerMap[what];
841
842	vector<BMessenger>::iterator iterator = find(messengers.begin(),
843		messengers.end(), messenger);
844	if (iterator != messengers.end()) {
845		messengers.erase(iterator);
846		if (messengers.empty())
847			fMessengerMap.erase(what);
848
849		return B_OK;
850	}
851
852	return B_BAD_HANDLER;
853}
854
855
856bool
857ObserverList::IsEmpty()
858{
859	return fHandlerMap.empty() && fMessengerMap.empty();
860}
861
862
863//	#pragma mark -
864
865
866bool
867FilterDeleter(void* _filter)
868{
869	delete static_cast<BMessageFilter*>(_filter);
870	return false;
871}
872