1 /*-
2  * Copyright 2016 Vsevolod Stakhov
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 #ifndef WORKER_UTIL_H_
17 #define WORKER_UTIL_H_
18 
19 #include "config.h"
20 #include "util.h"
21 #include "libserver/http/http_connection.h"
22 #include "rspamd.h"
23 
24 #ifdef  __cplusplus
25 extern "C" {
26 #endif
27 
28 #ifndef HAVE_SA_SIGINFO
29 typedef void (*rspamd_sig_handler_t) (gint);
30 #else
31 
32 typedef void (*rspamd_sig_handler_t) (gint, siginfo_t *, void *);
33 
34 #endif
35 
36 struct rspamd_worker;
37 struct rspamd_worker_signal_handler;
38 
39 /**
40  * Init basic signals for a worker
41  * @param worker
42  * @param event_loop
43  */
44 void rspamd_worker_init_signals (struct rspamd_worker *worker, struct ev_loop *event_loop);
45 
46 typedef void (*rspamd_accept_handler) (struct ev_loop *loop, ev_io *w, int revents);
47 
48 /**
49  * Prepare worker's startup
50  * @param worker worker structure
51  * @param name name of the worker
52  * @param sig_handler handler of main signals
53  * @param accept_handler handler of accept event for listen sockets
54  * @return event base suitable for a worker
55  */
56 struct ev_loop *
57 rspamd_prepare_worker (struct rspamd_worker *worker, const char *name,
58 					   rspamd_accept_handler hdl);
59 
60 /**
61  * Should be used to validate context for a worker as in assert like invocation
62  * @param ctx
63  * @param magic
64  * @return
65  */
66 gboolean rspamd_worker_check_context (gpointer ctx, guint64 magic);
67 
68 /**
69  * Set special signal handler for a worker
70  */
71 void rspamd_worker_set_signal_handler (int signo,
72 									   struct rspamd_worker *worker,
73 									   struct ev_loop *event_loop,
74 									   rspamd_worker_signal_cb_t handler,
75 									   void *handler_data);
76 
77 /**
78  * Stop accepting new connections for a worker
79  * @param worker
80  */
81 void rspamd_worker_stop_accept (struct rspamd_worker *worker);
82 
83 typedef gint (*rspamd_controller_func_t) (
84 		struct rspamd_http_connection_entry *conn_ent,
85 		struct rspamd_http_message *msg,
86 		struct module_ctx *ctx);
87 
88 struct rspamd_custom_controller_command {
89 	const gchar *command;
90 	struct module_ctx *ctx;
91 	gboolean privilleged;
92 	gboolean require_message;
93 	rspamd_controller_func_t handler;
94 };
95 
96 struct rspamd_controller_worker_ctx;
97 struct rspamd_lang_detector;
98 
99 struct rspamd_controller_session {
100 	struct rspamd_controller_worker_ctx *ctx;
101 	struct rspamd_worker *wrk;
102 	rspamd_mempool_t *pool;
103 	struct rspamd_task *task;
104 	gchar *classifier;
105 	rspamd_inet_addr_t *from_addr;
106 	struct rspamd_config *cfg;
107 	struct rspamd_lang_detector *lang_det;
108 	gboolean is_spam;
109 	gboolean is_enable;
110 };
111 
112 /**
113  * Send error using HTTP and JSON output
114  * @param entry router entry
115  * @param code error code
116  * @param error_msg error message
117  */
118 void rspamd_controller_send_error (struct rspamd_http_connection_entry *entry,
119 								   gint code, const gchar *error_msg, ...);
120 
121 /**
122  * Send openmetrics-formatted strings using HTTP
123  * @param entry router entry
124  * @param str rspamd fstring buffer, ownership is transferred
125  */
126 void
127 rspamd_controller_send_openmetrics (struct rspamd_http_connection_entry *entry,
128 									rspamd_fstring_t *str);
129 
130 /**
131  * Send a custom string using HTTP
132  * @param entry router entry
133  * @param str string to send
134  */
135 void rspamd_controller_send_string (struct rspamd_http_connection_entry *entry,
136 									const gchar *str);
137 
138 /**
139  * Send UCL using HTTP and JSON serialization
140  * @param entry router entry
141  * @param obj object to send
142  */
143 void rspamd_controller_send_ucl (struct rspamd_http_connection_entry *entry,
144 								 ucl_object_t *obj);
145 
146 /**
147  * Return worker's control structure by its type
148  * @param type
149  * @return worker's control structure or NULL
150  */
151 worker_t *rspamd_get_worker_by_type (struct rspamd_config *cfg, GQuark type);
152 
153 /**
154  * Block signals before terminations
155  */
156 void rspamd_worker_block_signals (void);
157 
158 /**
159  * Unblock signals
160  */
161 void rspamd_worker_unblock_signals (void);
162 
163 /**
164  * Kill rspamd main and all workers
165  * @param rspamd_main
166  */
167 void rspamd_hard_terminate (struct rspamd_main *rspamd_main) G_GNUC_NORETURN;
168 
169 /**
170  * Returns TRUE if a specific worker is a scanner worker
171  * @param w
172  * @return
173  */
174 gboolean rspamd_worker_is_scanner (struct rspamd_worker *w);
175 
176 /**
177  * Returns TRUE if a specific worker is a primary controller
178  * @param w
179  * @return
180  */
181 gboolean rspamd_worker_is_primary_controller (struct rspamd_worker *w);
182 
183 /**
184  * Creates new session cache
185  * @param w
186  * @return
187  */
188 void *rspamd_worker_session_cache_new (struct rspamd_worker *w,
189 									   struct ev_loop *ev_base);
190 
191 /**
192  * Adds a new session identified by pointer
193  * @param cache
194  * @param tag
195  * @param pref
196  * @param ptr
197  */
198 void rspamd_worker_session_cache_add (void *cache, const gchar *tag,
199 									  guint *pref, void *ptr);
200 
201 /**
202  * Removes session from cache
203  * @param cache
204  * @param ptr
205  */
206 void rspamd_worker_session_cache_remove (void *cache, void *ptr);
207 
208 /**
209  * Fork new worker with the specified configuration
210  */
211 struct rspamd_worker *rspamd_fork_worker (struct rspamd_main *,
212 										  struct rspamd_worker_conf *, guint idx,
213 										  struct ev_loop *ev_base,
214 										  rspamd_worker_term_cb term_handler,
215 										  GHashTable *listen_sockets);
216 
217 /**
218  * Sets crash signals handlers if compiled with libunwind
219  */
220 RSPAMD_NO_SANITIZE void rspamd_set_crash_handler (struct rspamd_main *);
221 
222 /**
223  * Initialise the main monitoring worker
224  * @param worker
225  * @param ev_base
226  * @param resolver
227  */
228 void rspamd_worker_init_monitored (struct rspamd_worker *worker,
229 								   struct ev_loop *ev_base,
230 								   struct rspamd_dns_resolver *resolver);
231 
232 /**
233  * Performs throttling for accept events
234  * @param sock
235  * @param data struct rspamd_worker_accept_event * list
236  */
237 void rspamd_worker_throttle_accept_events (gint sock, void *data);
238 
239 /**
240  * Checks (and logs) the worker's termination status. Returns TRUE if a worker
241  * should be restarted.
242  * @param rspamd_main
243  * @param wrk
244  * @param status waitpid res
245  * @return TRUE if refork is desired
246  */
247 gboolean rspamd_check_termination_clause (struct rspamd_main *rspamd_main,
248 										  struct rspamd_worker *wrk, int status);
249 
250 /**
251  * Call for final scripts for a worker
252  * @param worker
253  * @return
254  */
255 gboolean rspamd_worker_call_finish_handlers (struct rspamd_worker *worker);
256 
257 struct rspamd_rrd_file;
258 /**
259  * Terminate controller worker
260  * @param worker
261  */
262 void rspamd_controller_on_terminate (struct rspamd_worker *worker,
263 		struct rspamd_rrd_file *rrd);
264 
265 /**
266  * Inits controller worker
267  * @param worker
268  * @param ev_base
269  * @param prrd
270  */
271 void rspamd_worker_init_controller (struct rspamd_worker *worker,
272 								   struct rspamd_rrd_file **prrd);
273 
274 /**
275  * Saves stats
276  * @param rspamd_main
277  * @param cfg
278  */
279 void rspamd_controller_store_saved_stats (struct rspamd_main *rspamd_main,
280 									 struct rspamd_config *cfg);
281 
282 #ifdef WITH_HYPERSCAN
283 struct rspamd_control_command;
284 
285 gboolean rspamd_worker_hyperscan_ready (struct rspamd_main *rspamd_main,
286 										struct rspamd_worker *worker, gint fd,
287 										gint attached_fd,
288 										struct rspamd_control_command *cmd,
289 										gpointer ud);
290 
291 #endif
292 
293 #define msg_err_main(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
294         rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
295         RSPAMD_LOG_FUNC, \
296         __VA_ARGS__)
297 #define msg_warn_main(...)   rspamd_default_log_function (G_LOG_LEVEL_WARNING, \
298         rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
299         RSPAMD_LOG_FUNC, \
300         __VA_ARGS__)
301 #define msg_notice_main(...)   rspamd_default_log_function (G_LOG_LEVEL_MESSAGE, \
302         rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
303         RSPAMD_LOG_FUNC, \
304         __VA_ARGS__)
305 #define msg_info_main(...)   rspamd_default_log_function (G_LOG_LEVEL_INFO, \
306         rspamd_main->server_pool->tag.tagname, rspamd_main->server_pool->tag.uid, \
307         RSPAMD_LOG_FUNC, \
308         __VA_ARGS__)
309 
310 #ifdef  __cplusplus
311 }
312 #endif
313 
314 #endif /* WORKER_UTIL_H_ */
315