src/server/daemon/srvctrl.c

branch
srvctrl
changeset 158
77f4f0079428
child 166
c07122f66676
equal deleted inserted replaced
156:724e107983e9 158:77f4f0079428
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2017 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "webserver.h"
33
34 #include "../util/systhr.h"
35
36 #include "../../ucx/utils.h"
37 #include "../../ucx/buffer.h"
38
39 #include "srvctrl.h"
40
41 #define SRVCTRL_THREAD_STACKSIZE 8192
42
43 static int srvctrl;
44 static WSBool srv_shutdown;
45
46 int srvctrl_init(ServerConfiguration *cfg) {
47 // create srvctrl unix domain socket
48 // this socket is used for stop, reconfigure and other operations
49 sstr_t uds_path = ucx_sprintf("%s/private/srvctrl.sock", cfg->tmp.ptr);
50 struct sockaddr_un addr;
51 if(uds_path.length > sizeof(addr.sun_path)-1) {
52 log_ereport(
53 LOG_CATASTROPHE,
54 "path '%s' too long for unix domain socket",
55 uds_path.ptr);
56 return -1;
57 }
58
59 // make sure there is no old srvctrl socket file
60 // otherweise bind would fail
61 if(unlink(uds_path.ptr)) {
62 if(errno != ENOENT) {
63 log_ereport(
64 LOG_CATASTROPHE,
65 "cannot unlink old srvctrl socket '%s': %s",
66 uds_path.ptr,
67 strerror(errno));
68 return -1;
69 }
70 }
71
72 ZERO(&addr, sizeof(addr));
73 addr.sun_family = AF_UNIX;
74 memcpy(addr.sun_path, uds_path.ptr, uds_path.length);
75
76 srvctrl = socket(AF_UNIX, SOCK_STREAM, 0);
77 if(srvctrl == -1) {
78 log_ereport(
79 LOG_CATASTROPHE,
80 "Cannot create server control socket: %s",
81 strerror(errno));
82 return -1;
83 }
84 if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) {
85 log_ereport(
86 LOG_CATASTROPHE,
87 "srvctrl socket bind failed: %s",
88 strerror(errno));
89 return -1;
90 }
91
92 free(uds_path.ptr);
93
94 return 0;
95 }
96
97 int srvctrl_wait() {
98 listen(srvctrl, 8);
99
100 for(;;) {
101 int fd = accept(srvctrl, NULL, 0);
102 if(fd < 0) {
103 if(srv_shutdown) {
104 break;
105 }
106
107 log_ereport(
108 LOG_FAILURE,
109 "srvctrl: accept failed: %s",
110 strerror(errno));
111 continue;
112 }
113
114 SrvCtrlClient *client = srvctrl_create_client(fd);
115 SYS_THREAD t = systhread_start(
116 SYSTHREAD_DEFAULT_PRIORITY,
117 SRVCTRL_THREAD_STACKSIZE,
118 (thrstartfunc)srvctrl_thread,
119 client);
120 systhread_detach(t);
121
122 }
123 }
124
125 void srvctrl_shutdown() {
126 srv_shutdown = TRUE;
127 close(srvctrl);
128 }
129
130 SrvCtrlClient* srvctrl_create_client(int fd) {
131 SrvCtrlClient *client = malloc(sizeof(SrvCtrlClient));
132 ZERO(client, sizeof(SrvCtrlClient));
133 client->fd = fd;
134 return client;
135 }
136
137 void* srvctrl_thread(SrvCtrlClient *client) {
138 char buf[64];
139 UcxBuffer *line = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND);
140
141 ssize_t r;
142 WSBool br = FALSE;
143 while((r = read(client->fd, buf, 64)) > 0) {
144 for(int i=0;i<r;i++) {
145 char c = buf[i];
146 if(c == '\n') {
147 sstr_t ln = sstrn(line->space, line->pos);
148 if(srvctrl_handle_cmd(client, ln)) {
149 br = TRUE;
150 break;
151 }
152 } else {
153 ucx_buffer_putc(line, c);
154 }
155 }
156 if(br) {
157 break;
158 }
159 }
160
161 ucx_buffer_free(line);
162 close(client->fd);
163 free(client);
164
165 return NULL;
166 }
167
168 int srvctrl_handle_cmd(SrvCtrlClient *client, sstr_t cmd) {
169 if(!sstrcmp(cmd, S("reconfig"))) {
170 write(client->fd, "reconfig\n", 9);
171
172 if(webserver_reconfig()) {
173 log_ereport(LOG_FAILURE, "cannot reload config");
174 } else {
175 log_ereport(LOG_INFORM, "reconfig: success");
176 }
177 } else if(!sstrcmp(cmd, S("shutdown"))) {
178 webserver_shutdown();
179 } else {
180 log_ereport(
181 LOG_FAILURE,
182 "unknown srvctrl command: %.*s",
183 (int)cmd.length,
184 cmd.ptr);
185 }
186 return 1;
187 }

mercurial