BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file BInputProcess.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 #include <unistd.h>
31  
32 #include <base/BLog.h>
33 #include <system/BNetwork.h>
34  
35 #include "BInputProcess.h"
36  
37 #include <generated/blog_channel_BInputProcess.h>
38  
39 static void connection_handler (BInputProcess *o, int event);
40 static void process_handler (BInputProcess *o, int normally, uint8_t normally_exit_status);
41  
42 void connection_handler (BInputProcess *o, int event)
43 {
44 DebugObject_Access(&o->d_obj);
45 ASSERT(o->pipe_fd >= 0)
46  
47 if (event == BCONNECTION_EVENT_RECVCLOSED) {
48 BLog(BLOG_INFO, "pipe closed");
49 } else {
50 BLog(BLOG_ERROR, "pipe error");
51 }
52  
53 // free pipe connection read interface
54 BConnection_RecvAsync_Free(&o->pipe_con);
55  
56 // free pipe connection
57 BConnection_Free(&o->pipe_con);
58  
59 // close pipe read end
60 ASSERT_FORCE(close(o->pipe_fd) == 0)
61  
62 // forget pipe
63 o->pipe_fd = -1;
64  
65 // call closed handler
66 o->handler_closed(o->user, (event != BCONNECTION_EVENT_RECVCLOSED));
67 return;
68 }
69  
70 void process_handler (BInputProcess *o, int normally, uint8_t normally_exit_status)
71 {
72 DebugObject_Access(&o->d_obj);
73 ASSERT(o->started)
74 ASSERT(o->have_process)
75  
76 // free process
77 BProcess_Free(&o->process);
78  
79 // set not have process
80 o->have_process = 0;
81  
82 // call terminated handler
83 o->handler_terminated(o->user, normally, normally_exit_status);
84 return;
85 }
86  
87 int BInputProcess_Init (BInputProcess *o, BReactor *reactor, BProcessManager *manager, void *user,
88 BInputProcess_handler_terminated handler_terminated,
89 BInputProcess_handler_closed handler_closed)
90 {
91 BNetwork_Assert();
92  
93 // init arguments
94 o->reactor = reactor;
95 o->manager = manager;
96 o->user = user;
97 o->handler_terminated = handler_terminated;
98 o->handler_closed = handler_closed;
99  
100 // create pipe
101 int pipefds[2];
102 if (pipe(pipefds) < 0) {
103 BLog(BLOG_ERROR, "pipe failed");
104 goto fail0;
105 }
106  
107 // init pipe connection
108 if (!BConnection_Init(&o->pipe_con, BConnection_source_pipe(pipefds[0], 0), o->reactor, o, (BConnection_handler)connection_handler)) {
109 BLog(BLOG_ERROR, "BConnection_Init failed");
110 goto fail1;
111 }
112  
113 // init pipe connection read interface
114 BConnection_RecvAsync_Init(&o->pipe_con);
115  
116 // remember pipe fds
117 o->pipe_fd = pipefds[0];
118 o->pipe_write_fd = pipefds[1];
119  
120 // set not started
121 o->started = 0;
122  
123 DebugObject_Init(&o->d_obj);
124 return 1;
125  
126 fail1:
127 ASSERT_FORCE(close(pipefds[0]) == 0)
128 ASSERT_FORCE(close(pipefds[1]) == 0)
129 fail0:
130 return 0;
131 }
132  
133 void BInputProcess_Free (BInputProcess *o)
134 {
135 DebugObject_Free(&o->d_obj);
136  
137 if (!o->started) {
138 // close pipe write end
139 ASSERT_FORCE(close(o->pipe_write_fd) == 0)
140 } else {
141 // free process
142 if (o->have_process) {
143 BProcess_Free(&o->process);
144 }
145 }
146  
147 if (o->pipe_fd >= 0) {
148 // free pipe connection read interface
149 BConnection_RecvAsync_Free(&o->pipe_con);
150  
151 // free pipe connection
152 BConnection_Free(&o->pipe_con);
153  
154 // close pipe read end
155 ASSERT_FORCE(close(o->pipe_fd) == 0)
156 }
157 }
158  
159 int BInputProcess_Start (BInputProcess *o, const char *file, char *const argv[], const char *username)
160 {
161 DebugObject_Access(&o->d_obj);
162 ASSERT(!o->started)
163  
164 // start process
165 int fds[] = { o->pipe_write_fd, -1 };
166 int fds_map[] = { 1 };
167 if (!BProcess_InitWithFds(&o->process, o->manager, (BProcess_handler)process_handler, o, file, argv, username, fds, fds_map)) {
168 BLog(BLOG_ERROR, "BProcess_Init failed");
169 goto fail0;
170 }
171  
172 // close pipe write end
173 ASSERT_FORCE(close(o->pipe_write_fd) == 0)
174  
175 // set started
176 o->started = 1;
177  
178 // set have process
179 o->have_process = 1;
180  
181 return 1;
182  
183 fail0:
184 return 0;
185 }
186  
187 int BInputProcess_Terminate (BInputProcess *o)
188 {
189 DebugObject_Access(&o->d_obj);
190 ASSERT(o->started)
191 ASSERT(o->have_process)
192  
193 return BProcess_Terminate(&o->process);
194 }
195  
196 int BInputProcess_Kill (BInputProcess *o)
197 {
198 DebugObject_Access(&o->d_obj);
199 ASSERT(o->started)
200 ASSERT(o->have_process)
201  
202 return BProcess_Kill(&o->process);
203 }
204  
205 StreamRecvInterface * BInputProcess_GetInput (BInputProcess *o)
206 {
207 DebugObject_Access(&o->d_obj);
208 ASSERT(o->pipe_fd >= 0)
209  
210 return BConnection_RecvAsync_GetIf(&o->pipe_con);
211 }