BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file BSignal.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #ifdef BADVPN_USE_WINAPI
31 #include <windows.h>
32 #else
33 #include <signal.h>
34 #include <system/BUnixSignal.h>
35 #endif
36  
37 #include <misc/debug.h>
38 #include <base/BLog.h>
39  
40 #include <system/BSignal.h>
41  
42 #include <generated/blog_channel_BSignal.h>
43  
44 static struct {
45 int initialized;
46 int finished;
47 BReactor *reactor;
48 BSignal_handler handler;
49 void *user;
50 #ifdef BADVPN_USE_WINAPI
51 BReactorIOCPOverlapped olap;
52 CRITICAL_SECTION iocp_handle_mutex;
53 HANDLE iocp_handle;
54 #else
55 BUnixSignal signal;
56 #endif
57 } bsignal_global = {
58  
59 };
60  
61 #ifdef BADVPN_USE_WINAPI
62  
63 static void olap_handler (void *user, int event, DWORD bytes)
64 {
65 ASSERT(bsignal_global.initialized)
66 ASSERT(!(event == BREACTOR_IOCP_EVENT_EXITING) || bsignal_global.finished)
67  
68 if (event == BREACTOR_IOCP_EVENT_EXITING) {
69 BReactorIOCPOverlapped_Free(&bsignal_global.olap);
70 return;
71 }
72  
73 if (!bsignal_global.finished) {
74 // call handler
75 bsignal_global.handler(bsignal_global.user);
76 return;
77 }
78 }
79  
80 static BOOL WINAPI ctrl_handler (DWORD type)
81 {
82 EnterCriticalSection(&bsignal_global.iocp_handle_mutex);
83  
84 if (bsignal_global.iocp_handle) {
85 PostQueuedCompletionStatus(bsignal_global.iocp_handle, 0, 0, &bsignal_global.olap.olap);
86 }
87  
88 LeaveCriticalSection(&bsignal_global.iocp_handle_mutex);
89  
90 return TRUE;
91 }
92  
93 #else
94  
95 static void unix_signal_handler (void *user, int signo)
96 {
97 ASSERT(signo == SIGTERM || signo == SIGINT || signo == SIGHUP)
98 ASSERT(bsignal_global.initialized)
99 ASSERT(!bsignal_global.finished)
100  
101 BLog(BLOG_DEBUG, "Dispatching signal");
102  
103 // call handler
104 bsignal_global.handler(bsignal_global.user);
105 return;
106 }
107  
108 #endif
109  
110 int BSignal_Init (BReactor *reactor, BSignal_handler handler, void *user)
111 {
112 ASSERT(!bsignal_global.initialized)
113  
114 // init arguments
115 bsignal_global.reactor = reactor;
116 bsignal_global.handler = handler;
117 bsignal_global.user = user;
118  
119 BLog(BLOG_DEBUG, "BSignal initializing");
120  
121 #ifdef BADVPN_USE_WINAPI
122  
123 // init olap
124 BReactorIOCPOverlapped_Init(&bsignal_global.olap, bsignal_global.reactor, NULL, olap_handler);
125  
126 // init handler mutex
127 InitializeCriticalSection(&bsignal_global.iocp_handle_mutex);
128  
129 // remember IOCP handle
130 bsignal_global.iocp_handle = BReactor_GetIOCPHandle(bsignal_global.reactor);
131  
132 // configure ctrl handler
133 if (!SetConsoleCtrlHandler(ctrl_handler, TRUE)) {
134 BLog(BLOG_ERROR, "SetConsoleCtrlHandler failed");
135 goto fail1;
136 }
137  
138 #else
139  
140 sigset_t sset;
141 ASSERT_FORCE(sigemptyset(&sset) == 0)
142 ASSERT_FORCE(sigaddset(&sset, SIGTERM) == 0)
143 ASSERT_FORCE(sigaddset(&sset, SIGINT) == 0)
144 ASSERT_FORCE(sigaddset(&sset, SIGHUP) == 0)
145  
146 // init BUnixSignal
147 if (!BUnixSignal_Init(&bsignal_global.signal, bsignal_global.reactor, sset, unix_signal_handler, NULL)) {
148 BLog(BLOG_ERROR, "BUnixSignal_Init failed");
149 goto fail0;
150 }
151  
152 #endif
153  
154 bsignal_global.initialized = 1;
155 bsignal_global.finished = 0;
156  
157 return 1;
158  
159 #ifdef BADVPN_USE_WINAPI
160 fail1:
161 DeleteCriticalSection(&bsignal_global.iocp_handle_mutex);
162 BReactorIOCPOverlapped_Free(&bsignal_global.olap);
163 #endif
164  
165 fail0:
166 return 0;
167 }
168  
169 void BSignal_Finish (void)
170 {
171 ASSERT(bsignal_global.initialized)
172 ASSERT(!bsignal_global.finished)
173  
174 #ifdef BADVPN_USE_WINAPI
175  
176 // forget IOCP handle
177 EnterCriticalSection(&bsignal_global.iocp_handle_mutex);
178 bsignal_global.iocp_handle = NULL;
179 LeaveCriticalSection(&bsignal_global.iocp_handle_mutex);
180  
181 #else
182  
183 // free BUnixSignal
184 BUnixSignal_Free(&bsignal_global.signal, 0);
185  
186 #endif
187  
188 bsignal_global.finished = 1;
189 }