4 * Copyright (C) 2005 iptelorg GmbH
6 * This file is part of ser, a free SIP server.
8 * ser is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * For a license to use the ser software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
18 * ser is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <sys/types.h>
32 #include "mem/shm_mem.h"
33 #include "sr_module.h"
40 #include "tcp_options.h"
43 #include "sctp_options.h"
47 void dns_cache_debug(rpc_t* rpc, void* ctx);
48 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
49 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
50 void dns_cache_view(rpc_t* rpc, void* ctx);
51 void dns_cache_delete_all(rpc_t* rpc, void* ctx);
52 void dns_cache_add_a(rpc_t* rpc, void* ctx);
53 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx);
54 void dns_cache_add_srv(rpc_t* rpc, void* ctx);
55 void dns_cache_delete_a(rpc_t* rpc, void* ctx);
56 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx);
57 void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
60 static const char* dns_cache_mem_info_doc[] = {
61 "dns cache memory info.", /* Documentation string */
62 0 /* Method signature(s) */
64 static const char* dns_cache_debug_doc[] = {
65 "dns debug info.", /* Documentation string */
66 0 /* Method signature(s) */
69 static const char* dns_cache_debug_all_doc[] = {
70 "complete dns debug dump", /* Documentation string */
71 0 /* Method signature(s) */
74 static const char* dns_cache_view_doc[] = {
75 "dns cache dump in a human-readable format",
79 static const char* dns_cache_delete_all_doc[] = {
80 "deletes all the entries from the DNS cache",
84 static const char* dns_cache_add_a_doc[] = {
85 "adds an A record to the DNS cache",
89 static const char* dns_cache_add_aaaa_doc[] = {
90 "adds an AAAA record to the DNS cache",
93 static const char* dns_cache_add_srv_doc[] = {
94 "adds an SRV record to the DNS cache",
98 static const char* dns_cache_delete_a_doc[] = {
99 "deletes an A record from the DNS cache",
103 static const char* dns_cache_delete_aaaa_doc[] = {
104 "deletes an AAAA record from the DNS cache",
108 static const char* dns_cache_delete_srv_doc[] = {
109 "deletes an SRV record from the DNS cache",
113 #ifdef USE_DNS_CACHE_STATS
114 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
116 static const char* dns_cache_stats_get_doc[] = {
117 "returns the dns measurement counters.",
120 #endif /* USE_DNS_CACHE_STATS */
121 #ifdef DNS_WATCHDOG_SUPPORT
122 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
124 static const char* dns_set_server_state_doc[] = {
125 "sets the state of the DNS servers " \
126 "(0: all the servers are down, 1: at least one server is up)", /* Documentation string */
127 0 /* Method signature(s) */
130 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx);
132 static const char* dns_get_server_state_doc[] = {
133 "prints the state of the DNS servers " \
134 "(0: all the servers are down, 1: at least one server is up)", /* Documentation string */
135 0 /* Method signature(s) */
138 #endif /* DNS_WATCHDOG_SUPPORT */
139 #endif /* USE_DNS_CACHE */
140 #ifdef USE_DST_BLACKLIST
141 void dst_blst_debug(rpc_t* rpc, void* ctx);
142 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
143 void dst_blst_view(rpc_t* rpc, void* ctx);
144 void dst_blst_delete_all(rpc_t* rpc, void* ctx);
145 void dst_blst_add(rpc_t* rpc, void* ctx);
147 static const char* dst_blst_mem_info_doc[] = {
148 "dst blacklist memory usage info.", /* Documentation string */
149 0 /* Method signature(s) */
151 static const char* dst_blst_debug_doc[] = {
152 "dst blacklist debug info.", /* Documentation string */
153 0 /* Method signature(s) */
155 static const char* dst_blst_view_doc[] = {
156 "dst blacklist dump in human-readable format.", /* Documentation string */
157 0 /* Method signature(s) */
159 static const char* dst_blst_delete_all_doc[] = {
160 "Deletes all the entries from the dst blacklist except the permanent ones.", /* Documentation string */
161 0 /* Method signature(s) */
163 static const char* dst_blst_add_doc[] = {
164 "Adds a new entry to the dst blacklist.", /* Documentation string */
165 0 /* Method signature(s) */
167 #ifdef USE_DST_BLACKLIST_STATS
168 void dst_blst_stats_get(rpc_t* rpc, void* ctx);
170 static const char* dst_blst_stats_get_doc[] = {
171 "returns the dst blacklist measurement counters.",
174 #endif /* USE_DST_BLACKLIST_STATS */
180 #define MAX_CTIME_LEN 128
183 static char up_since_ctime[MAX_CTIME_LEN];
186 static const char* system_listMethods_doc[] = {
187 "Lists all RPC methods supported by the server.", /* Documentation string */
188 0 /* Method signature(s) */
191 static void system_listMethods(rpc_t* rpc, void* c)
196 for(ptr = core_rpc_methods; ptr && ptr->name; ptr++) {
197 if (rpc->add(c, "s", ptr->name) < 0) return;
200 for(t = modules; t; t = t->next) {
201 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
202 if (rpc->add(c, "s", ptr->name) < 0) return;
207 static const char* system_methodSignature_doc[] = {
208 "Returns signature of given method.", /* Documentation string */
209 0 /* Method signature(s) */
212 static void system_methodSignature(rpc_t* rpc, void* c)
214 rpc->fault(c, 500, "Not Implemented Yet");
218 static const char* system_methodHelp_doc[] = {
219 "Print the help string for given method.", /* Documentation string */
220 0 /* Method signature(s) */
223 static void system_methodHelp(rpc_t* rpc, void* c)
229 if (rpc->scan(c, "s", &name) < 1) {
230 rpc->fault(c, 400, "Method Name Expected");
234 for(t = modules; t; t = t->next) {
235 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
236 if (strcmp(name, ptr->name) == 0) {
237 if (ptr->doc_str && ptr->doc_str[0]) {
238 rpc->add(c, "s", ptr->doc_str[0]);
240 rpc->add(c, "s", "undocumented");
246 /* try the core methods too */
247 for (ptr=core_rpc_methods;ptr && ptr->name; ptr++){
248 if (strcmp(name, ptr->name) == 0) {
249 if (ptr->doc_str && ptr->doc_str[0]) {
250 rpc->add(c, "s", ptr->doc_str[0]);
252 rpc->add(c, "s", "undocumented");
257 rpc->fault(c, 400, "command not found");
261 static const char* core_prints_doc[] = {
262 "Returns the string given as parameter.", /* Documentation string */
263 0 /* Method signature(s) */
267 static void core_prints(rpc_t* rpc, void* c)
270 if (rpc->scan(c, "s", &string)>0)
271 rpc->add(c, "s", string);
275 static const char* core_version_doc[] = {
276 "Returns the version string of the server.", /* Documentation string */
277 0 /* Method signature(s) */
280 static void core_version(rpc_t* rpc, void* c)
282 rpc->add(c, "s", SERVER_HDR);
287 static const char* core_uptime_doc[] = {
288 "Returns uptime of SER server.", /* Documentation string */
289 0 /* Method signature(s) */
293 static void core_uptime(rpc_t* rpc, void* c)
300 if (rpc->add(c, "{", &s) < 0) return;
301 rpc->struct_add(s, "s", "now", ctime(&now));
302 rpc->struct_add(s, "s", "up_since", up_since_ctime);
303 /* no need for a float here (unless you're concerned that your uptime)
304 rpc->struct_add(s, "f", "uptime", difftime(now, up_since));
306 /* on posix system we can substract time_t directly */
307 rpc->struct_add(s, "d", "uptime", (int)(now-up_since));
311 static const char* core_ps_doc[] = {
312 "Returns the description of running SER processes.", /* Documentation string */
313 0 /* Method signature(s) */
317 static void core_ps(rpc_t* rpc, void* c)
321 for (p=0; p<*process_count;p++) {
322 rpc->add(c, "d", pt[p].pid);
323 rpc->add(c, "s", pt[p].desc);
328 static const char* core_pwd_doc[] = {
329 "Returns the working directory of SER server.", /* Documentation string */
330 0 /* Method signature(s) */
334 static void core_pwd(rpc_t* rpc, void* c)
340 cwd_buf = pkg_malloc(max_len);
342 ERR("core_pwd: No memory left\n");
343 rpc->fault(c, 500, "Server Ran Out of Memory");
347 if (getcwd(cwd_buf, max_len)) {
348 rpc->add(c, "s", cwd_buf);
350 rpc->fault(c, 500, "getcwd Failed");
356 static const char* core_arg_doc[] = {
357 "Returns the list of command line arguments used on SER startup.", /* Documentation string */
358 0 /* Method signature(s) */
362 static void core_arg(rpc_t* rpc, void* c)
366 for (p = 0; p < my_argc; p++) {
367 if (rpc->add(c, "s", my_argv[p]) < 0) return;
372 static const char* core_kill_doc[] = {
373 "Sends the given signal to SER.", /* Documentation string */
374 0 /* Method signature(s) */
378 static void core_kill(rpc_t* rpc, void* c)
381 rpc->scan(c, "d", &sig_no);
386 static void core_shmmem(rpc_t* rpc, void* c)
392 rpc->add(c, "{", &handle);
393 rpc->struct_add(handle, "dddddd",
394 "total", (unsigned int)mi.total_size,
395 "free", (unsigned int)mi.free,
396 "used", (unsigned int)mi.used,
397 "real_used",(unsigned int)mi.real_used,
398 "max_used", (unsigned int)mi.max_used,
399 "fragments", (unsigned int)mi.total_frags
403 static const char* core_shmmem_doc[] = {
404 "Returns shared memory info.", /* Documentation string */
405 0 /* Method signature(s) */
409 #if defined(SF_MALLOC) || defined(LL_MALLOC)
410 static void core_sfmalloc(rpc_t* rpc, void* c)
414 unsigned long frags, main_s_frags, main_b_frags, pool_frags;
415 unsigned long misses;
416 unsigned long max_misses;
417 unsigned long max_frags;
418 unsigned long max_mem;
419 int max_frags_pool, max_frags_hash;
420 int max_misses_pool, max_misses_hash;
421 int max_mem_pool, max_mem_hash;
424 if (rpc->scan(c, "d", &r) >= 1) {
425 if (r>=(int)SF_HASH_POOL_SIZE){
426 rpc->fault(c, 500, "invalid hash number %d (max %d)",
427 r, (unsigned int)SF_HASH_POOL_SIZE-1);
429 }else if (r<0) goto all;
430 rpc->add(c, "{", &handle);
431 rpc->struct_add(handle, "dd",
433 "size ", r*SF_ROUNDTO);
434 for (i=0; i<SFM_POOLS_NO; i++){
435 rpc->struct_add(handle, "dddd",
437 "frags ", (unsigned int)shm_block->pool[i].pool_hash[r].no,
438 "misses", (unsigned int)shm_block->pool[i].pool_hash[r].misses,
439 "mem ", (unsigned int)shm_block->pool[i].pool_hash[r].no *
446 max_frags=max_misses=max_mem=0;
447 max_frags_pool=max_frags_hash=0;
448 max_misses_pool=max_misses_hash=0;
449 max_mem_pool=max_mem_hash=0;
451 for (i=0; i<SFM_POOLS_NO; i++){
455 for (r=0; r<SF_HASH_POOL_SIZE; r++){
456 frags+=shm_block->pool[i].pool_hash[r].no;
457 misses+=shm_block->pool[i].pool_hash[r].misses;
458 mem+=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
459 if (shm_block->pool[i].pool_hash[r].no>max_frags){
460 max_frags=shm_block->pool[i].pool_hash[r].no;
464 if (shm_block->pool[i].pool_hash[r].misses>max_misses){
465 max_misses=shm_block->pool[i].pool_hash[r].misses;
469 if (shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO>max_mem){
470 max_mem=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
475 rpc->add(c, "{", &handle);
476 rpc->struct_add(handle, "dddddd",
478 "frags ", (unsigned int)frags,
479 "t. misses", (unsigned int)misses,
480 "mem ", (unsigned int)mem,
481 "missed", (unsigned int)shm_block->pool[i].missed,
482 "hits", (unsigned int)shm_block->pool[i].hits
487 for (r=0; r<SF_HASH_POOL_SIZE; r++){
488 main_s_frags+=shm_block->free_hash[r].no;
491 for (; r<SF_HASH_SIZE; r++){
492 main_b_frags+=shm_block->free_hash[r].no;
494 rpc->add(c, "{", &handle);
495 rpc->struct_add(handle, "ddddddddddddd",
496 "max_frags ", (unsigned int)max_frags,
497 "max_frags_pool ", max_frags_pool,
498 "max_frags_hash", max_frags_hash,
499 "max_misses ", (unsigned int)max_misses,
500 "max_misses_pool", max_misses_pool,
501 "max_misses_hash", max_misses_hash,
502 "max_mem ", (unsigned int)max_mem,
503 "max_mem_pool ", max_mem_pool,
504 "max_mem_hash ", max_mem_hash,
505 "in_pools_frags ", (unsigned int)pool_frags,
506 "main_s_frags ", (unsigned int)main_s_frags,
507 "main_b_frags ", (unsigned int)main_b_frags,
508 "main_frags ", (unsigned int)(main_b_frags+main_s_frags)
514 static const char* core_sfmalloc_doc[] = {
515 "Returns sfmalloc debugging info.", /* Documentation string */
516 0 /* Method signature(s) */
523 static const char* core_tcpinfo_doc[] = {
524 "Returns tcp related info.", /* Documentation string */
525 0 /* Method signature(s) */
528 static void core_tcpinfo(rpc_t* rpc, void* c)
532 struct tcp_gen_info ti;
536 rpc->add(c, "{", &handle);
537 rpc->struct_add(handle, "dddd",
538 "readers", ti.tcp_readers,
539 "max_connections", ti.tcp_max_connections,
540 "opened_connections", ti.tcp_connections_no,
541 "write_queued_bytes", ti.tcp_write_queued
544 rpc->fault(c, 500, "tcp support disabled");
547 rpc->fault(c, 500, "tcp support not compiled");
553 static const char* core_tcp_options_doc[] = {
554 "Returns active tcp options.", /* Documentation string */
555 0 /* Method signature(s) */
558 static void core_tcp_options(rpc_t* rpc, void* c)
562 struct tcp_cfg_options t;
566 rpc->add(c, "{", &handle);
567 rpc->struct_add(handle, "ddddddddddddddd",
568 "fd_cache", t.fd_cache,
569 "tcp_buf_write", t.tcp_buf_write,
570 "tcp_connect_wait", t.tcp_connect_wait,
571 "tcpconn_wq_max", t.tcpconn_wq_max,
572 "tcp_wq_max", t.tcp_wq_max,
573 "tcp_wq_timeout", TICKS_TO_S(t.tcp_wq_timeout),
575 "defer_accept", t.defer_accept,
576 "delayed_ack", t.delayed_ack,
578 "linger2", t.linger2,
579 "keepalive", t.keepalive,
580 "keepidle", t.keepidle,
581 "keepintvl", t.keepintvl,
582 "keepcnt", t.keepcnt,
583 "crlf_ping", t.crlf_ping
586 rpc->fault(c, 500, "tcp support disabled");
589 rpc->fault(c, 500, "tcp support not compiled");
595 static const char* core_sctp_options_doc[] = {
596 "Returns active sctp options.", /* Documentation string */
597 0 /* Method signature(s) */
600 static void core_sctp_options(rpc_t* rpc, void* c)
604 struct sctp_cfg_options t;
607 sctp_options_get(&t);
608 rpc->add(c, "{", &handle);
609 rpc->struct_add(handle, "dddd",
610 "sctp_autoclose", t.sctp_autoclose,
611 "sctp_send_ttl", t.sctp_autoclose,
612 "sctp_socket_rcvbuf", t.sctp_so_rcvbuf,
613 "sctp_socket_sndbuf", t.sctp_so_sndbuf
616 rpc->fault(c, 500, "sctp support disabled");
619 rpc->fault(c, 500, "sctp support not compiled");
626 * RPC Methods exported by this module
628 rpc_export_t core_rpc_methods[] = {
629 {"system.listMethods", system_listMethods, system_listMethods_doc, RET_ARRAY},
630 {"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0 },
631 {"system.methodHelp", system_methodHelp, system_methodHelp_doc, 0 },
632 {"core.prints", core_prints, core_prints_doc, 0 },
633 {"core.version", core_version, core_version_doc, 0 },
634 {"core.uptime", core_uptime, core_uptime_doc, 0 },
635 {"core.ps", core_ps, core_ps_doc, RET_ARRAY},
636 {"core.pwd", core_pwd, core_pwd_doc, RET_ARRAY},
637 {"core.arg", core_arg, core_arg_doc, RET_ARRAY},
638 {"core.kill", core_kill, core_kill_doc, 0 },
639 {"core.shmmem", core_shmmem, core_shmmem_doc, 0 },
640 #if defined(SF_MALLOC) || defined(LL_MALLOC)
641 {"core.sfmalloc", core_sfmalloc, core_sfmalloc_doc, 0},
643 {"core.tcp_info", core_tcpinfo, core_tcpinfo_doc, 0},
644 {"core.tcp_options", core_tcp_options, core_tcp_options_doc,0},
645 {"core.sctp_options", core_sctp_options, core_sctp_options_doc,
648 {"dns.mem_info", dns_cache_mem_info, dns_cache_mem_info_doc, 0 },
649 {"dns.debug", dns_cache_debug, dns_cache_debug_doc, 0 },
650 {"dns.debug_all", dns_cache_debug_all, dns_cache_debug_all_doc, 0 },
651 {"dns.view", dns_cache_view, dns_cache_view_doc, 0 },
652 {"dns.delete_all", dns_cache_delete_all, dns_cache_delete_all_doc, 0 },
653 {"dns.add_a", dns_cache_add_a, dns_cache_add_a_doc, 0 },
654 {"dns.add_aaaa", dns_cache_add_aaaa, dns_cache_add_aaaa_doc, 0 },
655 {"dns.add_srv", dns_cache_add_srv, dns_cache_add_srv_doc, 0 },
656 {"dns.delete_a", dns_cache_delete_a, dns_cache_delete_a_doc, 0 },
657 {"dns.delete_aaaa", dns_cache_delete_aaaa, dns_cache_delete_aaaa_doc, 0 },
658 {"dns.delete_srv", dns_cache_delete_srv, dns_cache_delete_srv_doc, 0 },
659 #ifdef USE_DNS_CACHE_STATS
660 {"dns.stats_get", dns_cache_stats_get, dns_cache_stats_get_doc, 0 },
661 #endif /* USE_DNS_CACHE_STATS */
662 #ifdef DNS_WATCHDOG_SUPPORT
663 {"dns.set_server_state", dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
664 {"dns.get_server_state", dns_get_server_state_rpc, dns_get_server_state_doc, 0 },
667 #ifdef USE_DST_BLACKLIST
668 {"dst_blacklist.mem_info", dst_blst_mem_info, dst_blst_mem_info_doc, 0 },
669 {"dst_blacklist.debug", dst_blst_debug, dst_blst_debug_doc, 0 },
670 {"dst_blacklist.view", dst_blst_view, dst_blst_view_doc, 0 },
671 {"dst_blacklist.delete_all", dst_blst_delete_all, dst_blst_delete_all_doc, 0 },
672 {"dst_blacklist.add", dst_blst_add, dst_blst_add_doc, 0 },
673 #ifdef USE_DST_BLACKLIST_STATS
674 {"dst_blacklist.stats_get", dst_blst_stats_get, dst_blst_stats_get_doc, 0 },
675 #endif /* USE_DST_BLACKLIST_STATS */
680 int rpc_init_time(void)
684 if (strlen(t)+1>=MAX_CTIME_LEN) {
685 ERR("Too long data %d\n", (int)strlen(t));
688 memcpy(up_since_ctime,t,strlen(t)+1);