Tizen 2.1 base
[framework/security/security-server.git] / src / services / caller / security_caller.h
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        popup_service_callbacks.cpp
18  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
19  * @version     1.0
20  * @brief       Header of Security Caller class used by services socket callbacks
21  */
22
23 #ifndef SECURITY_CALLER_H__
24 #define SECURITY_CALLER_H__
25
26 #include <dpl/thread.h>
27 #include <dpl/assert.h>
28 #include <dpl/singleton.h>
29
30 #include <security_controller.h>
31
32 #include <pthread.h>
33
34 class IEventHolder
35 {
36  public:
37   virtual void FinalizeSending() = 0;
38   virtual ~IEventHolder() {};
39 };
40
41 template<class EventType>
42 class EventHolderImpl : public IEventHolder
43 {
44   EventType event;
45
46  public:
47   EventHolderImpl(const EventType& e) : event(e) {}
48   virtual void FinalizeSending()
49   {
50     LogDebug("sending real sync event");
51     CONTROLLER_POST_SYNC_EVENT(SecurityController, event);
52   }
53 };
54
55 /*
56  * Because Security Controller is a DPL::Controler class, its events
57  * can be send only from a DPL managed thread. SecurityCallerTread class
58  * has been implemented as a workaround of that constraint.
59  * This class is a DPL managed thread that waits for requests
60  * from non DPL managed threads and when receives one it posts event
61  * to the Security Controler in charge of the calling thread.
62  */
63
64
65 class SecurityCallerThread : public DPL::Thread
66 {
67  private:
68   pthread_mutex_t m_mutex2;
69   pthread_mutex_t m_mutex;
70   pthread_cond_t m_cond;
71   pthread_cond_t m_cond2;
72   bool m_continue;
73   bool m_finished;
74   IEventHolder* m_eventHolder;
75   pthread_mutex_t m_syncMutex;
76
77
78   SecurityCallerThread() :
79     Thread(),
80     m_mutex2(PTHREAD_MUTEX_INITIALIZER),
81     m_mutex(PTHREAD_MUTEX_INITIALIZER),
82     m_cond(PTHREAD_COND_INITIALIZER),
83     m_cond2(PTHREAD_COND_INITIALIZER),
84     m_continue(true),
85     m_finished(false),
86     m_eventHolder(NULL),
87     m_syncMutex(PTHREAD_MUTEX_INITIALIZER)
88   {
89     LogDebug("constructor");
90   }
91
92   virtual ~SecurityCallerThread()
93   {
94     pthread_mutex_unlock(&m_syncMutex);
95     pthread_cond_destroy(&m_cond);
96     pthread_cond_destroy(&m_cond2);
97     pthread_mutex_destroy(&m_mutex2);
98     pthread_mutex_destroy(&m_mutex);
99     pthread_mutex_destroy(&m_syncMutex);
100   }
101
102  protected:
103   /* main routine of the SecurityCallerThread */
104   virtual int ThreadEntry()
105   {
106     LogDebug("SecurityCallerThread start");
107     pthread_mutex_lock(&m_mutex); // lock shared data
108
109     while (m_continue) // main loop
110     {
111       if (m_eventHolder) // if m_eventHolder is set, the request has been received
112       {
113         m_eventHolder->FinalizeSending(); // send actual event in charge of calling thread
114         delete m_eventHolder;
115         m_eventHolder = NULL;
116         LogDebug("setting finished state");
117         pthread_mutex_lock(&m_syncMutex); // lock m_finished
118         m_finished = true;
119         pthread_mutex_unlock(&m_syncMutex); // unlock m_finished
120         LogDebug("finished");
121         pthread_cond_signal(&m_cond2); // signal a calling thread that event has been posted.
122       }
123       LogDebug("waiting for event");
124       // atomically:
125       // unlock m_mutex, wait on m_cond until signal received, lock m_mutex
126       pthread_cond_wait(&m_cond, &m_mutex);
127       LogDebug("found an event");
128     }
129
130     pthread_mutex_unlock(&m_mutex);
131
132     return 0;
133   }
134
135  public:
136   void Quit()
137   {
138     LogDebug("Quit called");
139     pthread_mutex_lock(&m_mutex);    // lock shared data
140     m_continue = false;              // main loop condition set to false
141     pthread_mutex_unlock(&m_mutex);  // unlock shard data
142     pthread_cond_signal(&m_cond);
143   }
144
145   template <class EventType>
146   void SendSyncEvent(const EventType& event)
147   {
148     // prevent SendSyncEvent being called by multiple threads at the same time.
149     pthread_mutex_lock(&m_mutex2);
150     LogDebug("sending sync event");
151     bool correct_thread = false;
152     Try {
153       LogDebug("Checking if this is unmanaged thread");
154       DPL::Thread::GetCurrentThread();
155     } Catch (DPL::Thread::Exception::UnmanagedThread) {
156       correct_thread = true;
157     }
158     Assert(correct_thread &&
159            "This method may not be called from DPL managed thread or main thread");
160     LogDebug("putting an event to be posted");
161     pthread_mutex_lock(&m_mutex);  // lock shared data
162     Assert(m_eventHolder == NULL && "Whooops");
163     m_eventHolder = new EventHolderImpl<EventType>(event); // put an event to be posted
164     pthread_mutex_unlock(&m_mutex); // unlock shared data
165     LogDebug("Signal caller thread that new event has been created");
166     pthread_cond_signal(&m_cond);   // signal SecurityCallerThread to wake up because new
167                                     // event is waiting to be posted
168
169     LogDebug("waiting untill send completes");
170     pthread_mutex_lock(&m_syncMutex); /* wait until send completes */
171     while (!m_finished)
172     {
173         pthread_cond_wait(&m_cond2, &m_syncMutex); // wait until event is posted
174     }
175     LogDebug("done");
176     m_finished = false;
177     pthread_mutex_unlock(&m_syncMutex);
178     pthread_mutex_unlock(&m_mutex2);
179   }
180
181  private:
182   friend class DPL::Singleton<SecurityCallerThread>;
183 };
184
185 typedef DPL::Singleton<SecurityCallerThread> SecurityCallerSingleton;
186
187
188
189 #endif //SECURITY_CALLER_H__