Prepare security-manager for master-slave mode
[platform/core/security/security-manager.git] / src / server / main / server-main.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Rafal Krypa <r.krypa@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18 /*
19  * @file        server-main.cpp
20  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
21  * @version     1.0
22  * @brief       Implementation of security-manager on basis of security-server
23  */
24 #include <stdlib.h>
25 #include <signal.h>
26
27 #include <dpl/log/log.h>
28 #include <dpl/singleton.h>
29 #include <dpl/singleton_safe_impl.h>
30
31 #include <boost/program_options.hpp>
32 #include <iostream>
33
34 #include <socket-manager.h>
35 #include <file-lock.h>
36
37 #include <service.h>
38 #include <master-service.h>
39
40 namespace po = boost::program_options;
41
42 IMPLEMENT_SAFE_SINGLETON(SecurityManager::Log::LogSystem);
43
44 #define REGISTER_SOCKET_SERVICE(manager, service, allocator) \
45     registerSocketService<service>(manager, #service, allocator)
46
47 template<typename T>
48 bool registerSocketService(SecurityManager::SocketManager &manager,
49                            const std::string& serviceName,
50                            const std::function<T*(void)>& serviceAllocator)
51 {
52     T *service = NULL;
53     try {
54         service = serviceAllocator();
55         service->Create();
56         manager.RegisterSocketService(service);
57         return true;
58     } catch (const SecurityManager::Exception &exception) {
59         LogError("Error in creating service " << serviceName <<
60                  ", details:\n" << exception.DumpToString());
61     } catch (const std::exception& e) {
62         LogError("Error in creating service " << serviceName <<
63                  ", details:\n" << e.what());
64     } catch (...) {
65         LogError("Error in creating service " << serviceName <<
66                  ", unknown exception occured");
67     }
68     if (service)
69         delete service;
70     return false;
71 }
72
73 int main(int argc, char* argv[])
74 {
75     UNHANDLED_EXCEPTION_HANDLER_BEGIN
76     {
77         // initialize logging
78         SecurityManager::Singleton<SecurityManager::Log::LogSystem>::Instance().SetTag("SECURITY_MANAGER");
79
80         // parse arguments
81         bool masterMode = false, slaveMode = false;
82         po::options_description optDesc("Allowed options");
83
84         optDesc.add_options()
85         ("help,h", "Print this help message")
86         ("master,m", "Enable master mode")
87         ("slave,s", "Enable slave mode")
88         ;
89
90         po::variables_map vm;
91         po::basic_parsed_options<char> parsed =
92                 po::command_line_parser(argc, argv).options(optDesc).allow_unregistered().run();
93
94         std::vector<std::string> unrecognizedOptions =
95              po::collect_unrecognized(parsed.options, po::include_positional);
96
97         if (!unrecognizedOptions.empty()) {
98             std::cerr << "Unrecognized options: ";
99
100             for (auto& uo : unrecognizedOptions) {
101                 std::cerr << ' ' << uo;
102             }
103
104             std::cerr << std::endl << std::endl;
105             std::cerr << optDesc << std::endl;
106
107             return EXIT_FAILURE;
108         }
109
110         po::store(parsed, vm);
111         po::notify(vm);
112
113         if (vm.count("help")) {
114             std::cout << optDesc << std::endl;
115             return EXIT_SUCCESS;
116         }
117
118         masterMode = vm.count("master") > 0;
119         slaveMode = vm.count("slave") > 0;
120
121         if (masterMode && slaveMode) {
122             LogError("Cannot be both master and slave!");
123             return EXIT_FAILURE;
124         }
125
126         SecurityManager::FileLocker serviceLock(SecurityManager::SERVICE_LOCK_FILE,
127                                                 true);
128
129         sigset_t mask;
130         sigemptyset(&mask);
131         sigaddset(&mask, SIGTERM);
132         sigaddset(&mask, SIGPIPE);
133         if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL)) {
134             LogError("Error in pthread_sigmask");
135             return EXIT_FAILURE;
136         }
137
138         LogInfo("Start!");
139         SecurityManager::SocketManager manager;
140
141         if (masterMode) {
142             if (!REGISTER_SOCKET_SERVICE(manager, SecurityManager::MasterService,
143                     []() { return new SecurityManager::MasterService(); } )) {
144                 LogError("Unable to create master socket service. Exiting.");
145                 return EXIT_FAILURE;
146             }
147         } else {
148             if (!REGISTER_SOCKET_SERVICE(manager, SecurityManager::Service,
149                     [&slaveMode]() { return new SecurityManager::Service(slaveMode); } )) {
150                 LogError("Unable to create socket service. Exiting.");
151                 return EXIT_FAILURE;
152             }
153         }
154
155         manager.MainLoop();
156     } catch (const SecurityManager::FileLocker::Exception::Base &e) {
157         LogError("Unable to get a file lock. Exiting.");
158         return EXIT_FAILURE;
159     }
160     UNHANDLED_EXCEPTION_HANDLER_END
161     return EXIT_SUCCESS;
162 }