root/cherokee/trunk/cherokee/admin_client.c

Revision 1439, 15.4 kB (checked in by alo, 5 months ago)

--

Line 
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* Cherokee
4  *
5  * Authors:
6  *      Alvaro Lopez Ortega <alvaro@alobbs.com>
7  *
8  * Copyright (C) 2001-2008 Alvaro Lopez Ortega
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of version 2 of the GNU General Public
12  * License as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22  * USA
23  */
24
25 #include "common-internal.h"
26
27 #include <string.h>
28 #include "admin_client.h"
29
30 #include "util.h"
31 #include "buffer.h"
32 #include "downloader_async.h"
33 #include "downloader-protected.h"
34
35 #define ENTRIES "admin,client"
36
37
38 struct cherokee_admin_client {
39         cherokee_downloader_async_t *downloader;
40
41         cherokee_buffer_t           *url_ref;
42         cherokee_buffer_t            request;
43         cherokee_buffer_t            reply;
44
45         cherokee_post_t              post;
46         cherokee_fdpoll_t           *poll_ref;
47 };
48
49 #define strcmp_begin(line,sub)       strncmp(line, sub, strlen(sub))
50 #define strcmp_begin_const(line,sub) strncmp(line, sub, sizeof(sub))
51
52
53 ret_t
54 cherokee_admin_client_new (cherokee_admin_client_t **admin)
55 {
56         CHEROKEE_NEW_STRUCT(n,admin_client);
57
58         /* Init
59          */
60         n->poll_ref = NULL;
61         n->url_ref  = NULL;
62
63         cherokee_post_init (&n->post);
64         cherokee_downloader_async_new (&n->downloader);
65         cherokee_buffer_init (&n->request);
66         cherokee_buffer_init (&n->reply);
67
68         /* Return the object
69          */
70         *admin = n;
71         return ret_ok;
72 }
73
74
75 ret_t
76 cherokee_admin_client_free (cherokee_admin_client_t *admin)
77 {
78         cherokee_buffer_mrproper (&admin->request);
79         cherokee_buffer_mrproper (&admin->reply);
80
81         cherokee_downloader_async_free (admin->downloader);
82
83         free (admin);
84         return ret_ok;
85 }
86
87
88 ret_t
89 cherokee_admin_client_prepare (cherokee_admin_client_t *admin,
90                                cherokee_fdpoll_t       *poll,
91                                cherokee_buffer_t       *url,
92                                cherokee_buffer_t       *user,
93                                cherokee_buffer_t       *pass)
94 {
95         ret_t                  ret;
96         cherokee_downloader_t *downloader = DOWNLOADER(admin->downloader);
97
98         admin->poll_ref = poll;
99         admin->url_ref  = url;
100
101         TRACE(ENTRIES, "fdpoll=%p url=%p\n", poll, url);
102
103         /* Sanity check
104          */
105         if ((admin->url_ref == NULL) ||
106             (admin->poll_ref == NULL))
107         {
108                 PRINT_ERROR_S ("ERROR: Internal error\n");
109                 return ret_error;
110         }
111        
112         /* Set up the downloader object properties
113          */
114         ret = cherokee_downloader_async_set_fdpoll (DOWNLOADER_ASYNC(downloader), admin->poll_ref);
115         if (unlikely (ret != ret_ok)) return ret;
116        
117         ret = cherokee_downloader_set_url (downloader, admin->url_ref);
118         if (unlikely (ret != ret_ok)) return ret;
119
120         ret = cherokee_downloader_set_keepalive (downloader, true);
121         if (unlikely (ret != ret_ok)) return ret;
122
123         /* Set the authentication data
124          */
125         ret = cherokee_downloader_set_auth (downloader, user, pass);
126         if (unlikely (ret != ret_ok)) return ret;       
127
128         TRACE(ENTRIES, "Exists obj=%p\n", admin);
129         return ret_ok;
130 }
131
132
133 ret_t
134 cherokee_admin_client_connect (cherokee_admin_client_t *admin)
135 {
136         return cherokee_downloader_async_connect (admin->downloader);
137 }
138
139 ret_t
140 cherokee_admin_client_get_reply_code (cherokee_admin_client_t *admin, cherokee_http_t *code)
141 {
142         return cherokee_downloader_get_reply_code (DOWNLOADER(admin->downloader), code);
143 }
144
145 ret_t
146 cherokee_admin_client_reuse (cherokee_admin_client_t *admin)
147 {
148         cherokee_downloader_reuse (DOWNLOADER(admin->downloader));
149
150         cherokee_buffer_clean (&admin->request);
151         cherokee_buffer_clean (&admin->reply);
152
153         return ret_ok;
154 }
155
156
157 static ret_t
158 internal_step (cherokee_admin_client_t *admin)
159 {
160         ret_t                  ret;
161         cherokee_downloader_t *downloader = DOWNLOADER(admin->downloader);
162
163         TRACE(ENTRIES, "Downloader phase=%d\n", downloader->phase);
164
165         /* It's stepping
166          */
167         ret = cherokee_downloader_async_step (admin->downloader);
168         switch (ret) {
169         case ret_eof:
170         case ret_eof_have_data:
171                 return ret_ok;
172         case ret_error:
173         case ret_eagain:
174                 return ret;
175         case ret_ok:
176                 return ret_eagain;
177         default:
178                 RET_UNKNOWN(ret);
179         }
180
181         return ret_eagain;
182 }
183
184
185 static void
186 prepare_and_set_post (cherokee_admin_client_t *admin, char *str, cuint_t str_len)
187 {
188         cherokee_downloader_t *downloader = DOWNLOADER(admin->downloader);
189
190         cherokee_downloader_set_url (downloader, admin->url_ref);
191         cherokee_buffer_add (&admin->request, str, str_len);
192
193         /* Build and set the post object
194          */
195         cherokee_post_init (&admin->post);
196         cherokee_post_set_len (&admin->post, str_len);
197         cherokee_post_append (&admin->post, str, str_len);
198         cherokee_downloader_post_set (downloader, &admin->post);
199 }
200
201 #define SET_POST(admin,str) \
202         prepare_and_set_post(admin, str"\n", sizeof(str))
203
204
205 #define CHECK_AND_SKIP_LITERAL(string, substr) \
206         if ((string == NULL) || (strlen(string) == 0)) \
207                 return ret_error; \
208         if (strncmp (string, substr, sizeof(substr)-1)) { \
209                 PRINT_ERROR ("ERROR: Uknown response len(" FMT_SIZE "): '%s'\n", \
210                              (CST_SIZE) strlen(string), string); \
211                 return ret_error; \
212         } \
213         string += sizeof(substr)-1;
214
215
216 static ret_t
217 check_and_skip_literal (cherokee_buffer_t *buf, const char *literal)
218 {
219         cint_t  re;
220         cuint_t len;
221        
222         len = strlen(literal);
223         cherokee_buffer_trim (buf);
224
225         re = strncmp (buf->buf, literal, len);
226         if (re != 0) {
227 #if 0
228                 PRINT_ERROR ("ERROR: Couldn't find len(%d):'%s' in len(%d):'%s'\n",
229                              strlen(literal), literal, buf->len, buf->buf);
230 #endif
231                 return ret_error;
232         }
233
234         cherokee_buffer_move_to_begin (buf, len);
235         return ret_ok;
236 }
237
238
239 static ret_t
240 common_processing (cherokee_admin_client_t *admin,
241                    void (*conf_request_func) (cherokee_admin_client_t *admin, void *argument),
242                    void *argument)
243 {
244         ret_t                  ret;
245         cherokee_downloader_t *downloader = DOWNLOADER(admin->downloader);
246
247         TRACE(ENTRIES, "Downloader phase: %d\n", downloader->phase);
248
249         /* Initial state: needs to get the Post info
250          */
251         if ((downloader->phase == downloader_phase_init) &&
252             (downloader->post == NULL))
253         {
254                 conf_request_func (admin, argument);
255                 return ret_eagain;
256         }
257
258         /* Finished
259          */
260         if (downloader->phase == downloader_phase_finished)
261                 return ret_ok;
262
263         /* It's iterating
264          */
265         ret = internal_step (admin);
266         return ret;
267 }
268
269
270 /* Port
271  */
272 static void
273 ask_get_port (cherokee_admin_client_t *admin, void *arg)
274 {
275         UNUSED(arg);
276         SET_POST (admin, "get server.port");
277 }
278
279 static ret_t
280 parse_reply_get_port (cherokee_buffer_t *reply, cuint_t *port)
281 {
282         ret_t ret;
283
284         ret = check_and_skip_literal (reply, "server.port is ");
285         if (ret != ret_ok) return ret;
286
287         *port = strtol (reply->buf, NULL, 10);
288         return ret_ok;
289 }
290
291 ret_t
292 cherokee_admin_client_ask_port (cherokee_admin_client_t *admin, cuint_t *port)
293 {
294         ret_t ret;
295
296         ret = common_processing (admin, ask_get_port, NULL);
297         if (ret != ret_ok) return ret;
298
299         return parse_reply_get_port (&DOWNLOADER(admin->downloader)->body, port);
300 }
301
302
303 /* Port TLS
304  */
305 static void
306 ask_get_port_tls (cherokee_admin_client_t *admin, void *arg)
307 {
308         UNUSED(arg);
309         SET_POST (admin, "get server.port_tls");
310 }
311
312 static ret_t
313 parse_reply_get_port_tls (cherokee_buffer_t *reply, cuint_t *port)
314 {
315         ret_t ret;
316
317         ret = check_and_skip_literal (reply, "server.port_tls is ");
318         if (ret != ret_ok) return ret;
319
320         *port = strtol (reply->buf, NULL, 10);
321         return ret_ok;
322 }
323
324 ret_t
325 cherokee_admin_client_ask_port_tls (cherokee_admin_client_t *admin, cuint_t *port)
326 {
327         ret_t ret;
328
329         ret = common_processing (admin, ask_get_port_tls, NULL);
330         if (ret != ret_ok) return ret;
331
332         return parse_reply_get_port_tls (&DOWNLOADER(admin->downloader)->body, port);
333 }
334
335
336 /* RX
337  */
338 static void
339 ask_get_rx (cherokee_admin_client_t *admin, void *arg)
340 {
341         UNUSED(arg);
342         SET_POST (admin, "get server.rx");
343 }
344
345 static ret_t
346 parse_reply_get_rx (cherokee_buffer_t *reply, cherokee_buffer_t *rx)
347 {
348         ret_t ret;
349
350         ret = check_and_skip_literal (reply, "server.rx is ");
351         if (ret != ret_ok) return ret;
352
353         cherokee_buffer_add_buffer (rx, reply);
354         return ret_ok;
355 }
356
357 ret_t
358 cherokee_admin_client_ask_rx (cherokee_admin_client_t *admin, cherokee_buffer_t *rx)
359 {
360         ret_t ret;
361
362         ret = common_processing (admin, ask_get_rx, NULL);
363         if (ret != ret_ok) return ret;
364
365         return parse_reply_get_rx (&DOWNLOADER(admin->downloader)->body, rx);   
366 }
367
368
369 /* TX
370  */
371 static void
372 ask_get_tx (cherokee_admin_client_t *admin, void *arg)
373 {
374         UNUSED(arg);
375         SET_POST (admin, "get server.tx");
376 }
377
378 static ret_t
379 parse_reply_get_tx (cherokee_buffer_t *reply, cherokee_buffer_t *tx)
380 {
381         ret_t ret;
382
383         ret = check_and_skip_literal (reply, "server.tx is ");
384         if (ret != ret_ok) return ret;
385
386         cherokee_buffer_add_buffer (tx, reply);
387         return ret_ok;
388 }
389
390 ret_t
391 cherokee_admin_client_ask_tx (cherokee_admin_client_t *admin, cherokee_buffer_t *tx)
392 {
393         ret_t ret;
394
395         ret = common_processing (admin, ask_get_tx, NULL);
396         if (ret != ret_ok) return ret;
397
398         return parse_reply_get_tx (&DOWNLOADER(admin->downloader)->body, tx);   
399 }
400
401
402 /* Connections
403  */
404 static void
405 ask_get_connections (cherokee_admin_client_t *admin, void *arg)
406 {
407         UNUSED(arg);
408         SET_POST (admin, "get server.connections");
409 }
410
411 static ret_t
412 parse_reply_get_connections (char *reply, cherokee_list_t *conns_list)
413 {
414         char              *begin;
415         char              *end;
416         cherokee_buffer_t  info_str = CHEROKEE_BUF_INIT;
417
418         char *p = reply;
419        
420         CHECK_AND_SKIP_LITERAL (reply, "server.connections are ");
421
422         for (;;) {
423                 char                       *string;
424                 char                       *token;
425                 cherokee_connection_info_t *conn_info;
426
427                 begin = strchr (p, '[');
428                 end   = strchr (p, ']');
429        
430                 if ((begin == NULL) || (end == NULL) || (end < begin))
431                         return ret_ok;
432
433                 begin++;
434                 p = end + 1;
435
436                 cherokee_buffer_add (&info_str, begin, end - begin);
437                 cherokee_connection_info_new (&conn_info);
438
439                 string = info_str.buf;
440                 while ((token = (char *) strsep(&string, ",")) != NULL)
441                 {
442                         char *equal;
443
444                         if (token == NULL) continue;
445
446                         equal = strchr (token, '=');
447                         if (equal == NULL) continue;
448                         equal++;
449
450                         if (!strncmp (token, "request=", 8))
451                                 cherokee_buffer_add (&conn_info->request, equal, strlen(equal));
452                         else if (!strncmp (token, "phase=", 6))
453                                 cherokee_buffer_add (&conn_info->phase, equal, strlen(equal));
454                         else if (!strncmp (token, "rx=", 3))
455                                 cherokee_buffer_add (&conn_info->rx, equal, strlen(equal));
456                         else if (!strncmp (token, "tx=", 3))
457                                 cherokee_buffer_add (&conn_info->tx, equal, strlen(equal));                     
458                         else if (!strncmp (token, "total_size=", 11))
459                                 cherokee_buffer_add (&conn_info->total_size, equal, strlen(equal));                     
460                         else if (!strncmp (token, "ip=", 3))
461                                 cherokee_buffer_add (&conn_info->ip, equal, strlen(equal));                     
462                         else if (!strncmp (token, "id=", 3))
463                                 cherokee_buffer_add (&conn_info->id, equal, strlen(equal));
464                         else if (!strncmp (token, "percent=", 8))
465                                 cherokee_buffer_add (&conn_info->percent, equal, strlen(equal));
466                         else if (!strncmp (token, "handler=", 8))
467                                 cherokee_buffer_add (&conn_info->handler, equal, strlen(equal));
468                         else if (!strncmp (token, "icon=", 5))
469                                 cherokee_buffer_add (&conn_info->icon, equal, strlen(equal));
470                         else
471                                 SHOULDNT_HAPPEN;
472                 }
473
474                 cherokee_list_add (LIST(conn_info), conns_list);
475                 cherokee_buffer_clean (&info_str);
476         }
477
478         return ret_ok;
479 }
480
481 ret_t
482 cherokee_admin_client_ask_connections (cherokee_admin_client_t *admin, cherokee_list_t *conns_list)
483 {
484         ret_t ret;
485
486         ret = common_processing (admin, ask_get_connections, NULL);
487         if (ret != ret_ok) return ret;
488
489         return parse_reply_get_connections (DOWNLOADER(admin->downloader)->body.buf, conns_list);               
490 }
491
492
493 /* Delete connections
494  */
495 static void
496 ask_del_connection (cherokee_admin_client_t *admin, void *arg)
497 {
498         cherokee_buffer_t tmp = CHEROKEE_BUF_INIT;
499
500         cherokee_buffer_add_va (&tmp, "del server.connection %s\n", (char *)arg);
501         prepare_and_set_post (admin, tmp.buf, tmp.len);
502         cherokee_buffer_mrproper (&tmp);
503 }
504
505 static ret_t
506 parse_reply_del_connection (char *reply, char *id)
507 {
508         ret_t             ret;
509         cherokee_buffer_t tmp = CHEROKEE_BUF_INIT;
510
511         cherokee_buffer_add_va (&tmp, "server.connection %s has been deleted", id);
512         ret = (!strcmp_begin (reply, tmp.buf))? ret_ok : ret_error;
513         cherokee_buffer_mrproper (&tmp);
514
515         return ret;
516 }
517
518 ret_t
519 cherokee_admin_client_del_connection  (cherokee_admin_client_t *admin, char *id)
520 {
521         ret_t ret;
522
523         ret = common_processing (admin, ask_del_connection, id);
524         if (ret != ret_ok) return ret;
525
526         return parse_reply_del_connection (DOWNLOADER(admin->downloader)->body.buf, id);       
527 }
528
529
530 /* Thread number
531  */
532 static void
533 ask_thread_number (cherokee_admin_client_t *admin, void *arg)
534 {
535         UNUSED(arg);
536         SET_POST (admin, "get server.thread_num");
537 }
538
539 static ret_t
540 parse_reply_thread_number (cherokee_buffer_t *reply, cherokee_buffer_t *num)
541 {
542         ret_t ret;
543
544         ret = check_and_skip_literal (reply, "server.thread_num is ");
545         if (ret != ret_ok) return ret;
546
547         cherokee_buffer_add_buffer (num, reply);
548         return ret_ok;
549 }
550
551 ret_t
552 cherokee_admin_client_ask_thread_num  (cherokee_admin_client_t *admin, cherokee_buffer_t *num)
553 {
554         ret_t ret;
555
556         ret = common_processing (admin, ask_thread_number, NULL);
557         if (ret != ret_ok) return ret;
558
559         return parse_reply_thread_number (&DOWNLOADER(admin->downloader)->body, num);
560 }
561
562
563 /* Backup mode
564  */
565 static void
566 set_backup_mode (cherokee_admin_client_t *admin, void *arg)
567 {
568         cherokee_boolean_t active = POINTER_TO_INT(arg);
569
570         if (active) {
571                 SET_POST (admin, "set server.backup_mode on\n");
572         } else {
573                 SET_POST (admin, "set server.backup_mode off\n");
574         }
575 }
576
577 static ret_t
578 parse_reply_set_backup_mode (char *reply, cherokee_boolean_t active)
579 {
580
581         if (active) {
582                 CHECK_AND_SKIP_LITERAL (reply, "server.backup_mode is on");
583         } else {
584                 CHECK_AND_SKIP_LITERAL (reply, "server.backup_mode is off");
585         }
586
587         return ret_ok;
588 }
589
590 ret_t
591 cherokee_admin_client_set_backup_mode (cherokee_admin_client_t *admin, cherokee_boolean_t active)
592 {
593         ret_t ret;
594
595         ret = common_processing (admin, set_backup_mode, INT_TO_POINTER(active));
596         if (ret != ret_ok) return ret;
597
598         return parse_reply_set_backup_mode (DOWNLOADER(admin->downloader)->body.buf, active);   
599 }
600
601
602 /* Tracing
603  */
604 static void
605 ask_trace (cherokee_admin_client_t *admin, void *arg)
606 {
607         UNUSED(arg);
608         SET_POST (admin, "get server.trace");
609 }
610
611 static ret_t
612 parse_reply_trace (cherokee_buffer_t *reply, cherokee_buffer_t *trace)
613 {
614         ret_t ret;
615
616         ret = check_and_skip_literal (reply, "server.trace is ");
617         if (ret != ret_ok) return ret;
618
619         cherokee_buffer_add_buffer (trace, reply);
620         return ret_ok;
621 }
622
623 ret_t
624 cherokee_admin_client_ask_trace (cherokee_admin_client_t *admin, cherokee_buffer_t *trace)
625 {
626         ret_t ret;
627
628         ret = common_processing (admin, ask_trace, NULL);
629         if (ret != ret_ok) return ret;
630
631         return parse_reply_trace (&DOWNLOADER(admin->downloader)->body, trace);
632 }
633
634
635 static ret_t
636 check_reply_trace (cherokee_buffer_t *reply, cherokee_buffer_t *trace)
637 {
638         ret_t ret;
639
640         UNUSED(trace);
641
642         ret = check_and_skip_literal (reply, "ok");
643         if (ret != ret_ok) return ret;
644
645         return ret_ok;
646 }
647
648 static void
649 set_trace_mode (cherokee_admin_client_t *admin, void *arg)
650 {
651         cherokee_buffer_t *trace = arg;
652         cherokee_buffer_t  tmp   = CHEROKEE_BUF_INIT;
653        
654         cherokee_buffer_add_str (&tmp, "set server.trace ");
655         cherokee_buffer_add_buffer (&tmp, trace);
656         cherokee_buffer_add_str (&tmp, "\n");
657
658         prepare_and_set_post (admin, tmp.buf, tmp.len);
659         cherokee_buffer_mrproper (&tmp);
660 }
661
662 ret_t
663 cherokee_admin_client_set_trace (cherokee_admin_client_t *admin, cherokee_buffer_t *trace)
664 {
665         ret_t ret;
666
667         ret = common_processing (admin, set_trace_mode, trace);
668         if (ret != ret_ok) return ret;
669
670         return check_reply_trace (&DOWNLOADER(admin->downloader)->body, trace);
671 }
Note: See TracBrowser for help on using the browser.