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"
44 void dns_cache_debug(rpc_t* rpc, void* ctx);
45 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
46 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
47 void dns_cache_view(rpc_t* rpc, void* ctx);
48 void dns_cache_delete_all(rpc_t* rpc, void* ctx);
49 void dns_cache_add_a(rpc_t* rpc, void* ctx);
50 void dns_cache_add_aaaa(rpc_t* rpc, void* ctx);
51 void dns_cache_add_srv(rpc_t* rpc, void* ctx);
52 void dns_cache_delete_a(rpc_t* rpc, void* ctx);
53 void dns_cache_delete_aaaa(rpc_t* rpc, void* ctx);
54 void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
57 static const char* dns_cache_mem_info_doc[] = {
58 "dns cache memory info.", /* Documentation string */
59 0 /* Method signature(s) */
61 static const char* dns_cache_debug_doc[] = {
62 "dns debug info.", /* Documentation string */
63 0 /* Method signature(s) */
66 static const char* dns_cache_debug_all_doc[] = {
67 "complete dns debug dump", /* Documentation string */
68 0 /* Method signature(s) */
71 static const char* dns_cache_view_doc[] = {
72 "dns cache dump in a human-readable format",
76 static const char* dns_cache_delete_all_doc[] = {
77 "deletes all the entries from the DNS cache",
81 static const char* dns_cache_add_a_doc[] = {
82 "adds an A record to the DNS cache",
86 static const char* dns_cache_add_aaaa_doc[] = {
87 "adds an AAAA record to the DNS cache",
90 static const char* dns_cache_add_srv_doc[] = {
91 "adds an SRV record to the DNS cache",
95 static const char* dns_cache_delete_a_doc[] = {
96 "deletes an A record from the DNS cache",
100 static const char* dns_cache_delete_aaaa_doc[] = {
101 "deletes an AAAA record from the DNS cache",
105 static const char* dns_cache_delete_srv_doc[] = {
106 "deletes an SRV record from the DNS cache",
110 #ifdef USE_DNS_CACHE_STATS
111 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
113 static const char* dns_cache_stats_get_doc[] = {
114 "returns the dns measurement counters.",
117 #endif /* USE_DNS_CACHE_STATS */
118 #ifdef DNS_WATCHDOG_SUPPORT
119 void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
121 static const char* dns_set_server_state_doc[] = {
122 "sets the state of the DNS servers " \
123 "(0: all the servers are down, 1: at least one server is up)", /* Documentation string */
124 0 /* Method signature(s) */
127 void dns_get_server_state_rpc(rpc_t* rpc, void* ctx);
129 static const char* dns_get_server_state_doc[] = {
130 "prints the state of the DNS servers " \
131 "(0: all the servers are down, 1: at least one server is up)", /* Documentation string */
132 0 /* Method signature(s) */
135 #endif /* DNS_WATCHDOG_SUPPORT */
136 #endif /* USE_DNS_CACHE */
137 #ifdef USE_DST_BLACKLIST
138 void dst_blst_debug(rpc_t* rpc, void* ctx);
139 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
140 void dst_blst_view(rpc_t* rpc, void* ctx);
141 void dst_blst_delete_all(rpc_t* rpc, void* ctx);
142 void dst_blst_add(rpc_t* rpc, void* ctx);
144 static const char* dst_blst_mem_info_doc[] = {
145 "dst blacklist memory usage info.", /* Documentation string */
146 0 /* Method signature(s) */
148 static const char* dst_blst_debug_doc[] = {
149 "dst blacklist debug info.", /* Documentation string */
150 0 /* Method signature(s) */
152 static const char* dst_blst_view_doc[] = {
153 "dst blacklist dump in human-readable format.", /* Documentation string */
154 0 /* Method signature(s) */
156 static const char* dst_blst_delete_all_doc[] = {
157 "Deletes all the entries from the dst blacklist except the permanent ones.", /* Documentation string */
158 0 /* Method signature(s) */
160 static const char* dst_blst_add_doc[] = {
161 "Adds a new entry to the dst blacklist.", /* Documentation string */
162 0 /* Method signature(s) */
164 #ifdef USE_DST_BLACKLIST_STATS
165 void dst_blst_stats_get(rpc_t* rpc, void* ctx);
167 static const char* dst_blst_stats_get_doc[] = {
168 "returns the dst blacklist measurement counters.",
171 #endif /* USE_DST_BLACKLIST_STATS */
177 #define MAX_CTIME_LEN 128
180 static char up_since_ctime[MAX_CTIME_LEN];
183 static const char* system_listMethods_doc[] = {
184 "Lists all RPC methods supported by the server.", /* Documentation string */
185 0 /* Method signature(s) */
188 static void system_listMethods(rpc_t* rpc, void* c)
193 for(ptr = core_rpc_methods; ptr && ptr->name; ptr++) {
194 if (rpc->add(c, "s", ptr->name) < 0) return;
197 for(t = modules; t; t = t->next) {
198 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
199 if (rpc->add(c, "s", ptr->name) < 0) return;
204 static const char* system_methodSignature_doc[] = {
205 "Returns signature of given method.", /* Documentation string */
206 0 /* Method signature(s) */
209 static void system_methodSignature(rpc_t* rpc, void* c)
211 rpc->fault(c, 500, "Not Implemented Yet");
215 static const char* system_methodHelp_doc[] = {
216 "Print the help string for given method.", /* Documentation string */
217 0 /* Method signature(s) */
220 static void system_methodHelp(rpc_t* rpc, void* c)
226 if (rpc->scan(c, "s", &name) < 1) {
227 rpc->fault(c, 400, "Method Name Expected");
231 for(t = modules; t; t = t->next) {
232 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
233 if (strcmp(name, ptr->name) == 0) {
234 if (ptr->doc_str && ptr->doc_str[0]) {
235 rpc->add(c, "s", ptr->doc_str[0]);
237 rpc->add(c, "s", "undocumented");
243 /* try the core methods too */
244 for (ptr=core_rpc_methods;ptr && ptr->name; ptr++){
245 if (strcmp(name, ptr->name) == 0) {
246 if (ptr->doc_str && ptr->doc_str[0]) {
247 rpc->add(c, "s", ptr->doc_str[0]);
249 rpc->add(c, "s", "undocumented");
254 rpc->fault(c, 400, "command not found");
258 static const char* core_prints_doc[] = {
259 "Returns the string given as parameter.", /* Documentation string */
260 0 /* Method signature(s) */
264 static void core_prints(rpc_t* rpc, void* c)
267 if (rpc->scan(c, "s", &string)>0)
268 rpc->add(c, "s", string);
272 static const char* core_version_doc[] = {
273 "Returns the version string of the server.", /* Documentation string */
274 0 /* Method signature(s) */
277 static void core_version(rpc_t* rpc, void* c)
279 rpc->add(c, "s", SERVER_HDR);
284 static const char* core_uptime_doc[] = {
285 "Returns uptime of SER server.", /* Documentation string */
286 0 /* Method signature(s) */
290 static void core_uptime(rpc_t* rpc, void* c)
297 if (rpc->add(c, "{", &s) < 0) return;
298 rpc->struct_add(s, "s", "now", ctime(&now));
299 rpc->struct_add(s, "s", "up_since", up_since_ctime);
300 /* no need for a float here (unless you're concerned that your uptime)
301 rpc->struct_add(s, "f", "uptime", difftime(now, up_since));
303 /* on posix system we can substract time_t directly */
304 rpc->struct_add(s, "d", "uptime", (int)(now-up_since));
308 static const char* core_ps_doc[] = {
309 "Returns the description of running SER processes.", /* Documentation string */
310 0 /* Method signature(s) */
314 static void core_ps(rpc_t* rpc, void* c)
318 for (p=0; p<*process_count;p++) {
319 rpc->add(c, "d", pt[p].pid);
320 rpc->add(c, "s", pt[p].desc);
325 static const char* core_pwd_doc[] = {
326 "Returns the working directory of SER server.", /* Documentation string */
327 0 /* Method signature(s) */
331 static void core_pwd(rpc_t* rpc, void* c)
337 cwd_buf = pkg_malloc(max_len);
339 ERR("core_pwd: No memory left\n");
340 rpc->fault(c, 500, "Server Ran Out of Memory");
344 if (getcwd(cwd_buf, max_len)) {
345 rpc->add(c, "s", cwd_buf);
347 rpc->fault(c, 500, "getcwd Failed");
353 static const char* core_arg_doc[] = {
354 "Returns the list of command line arguments used on SER startup.", /* Documentation string */
355 0 /* Method signature(s) */
359 static void core_arg(rpc_t* rpc, void* c)
363 for (p = 0; p < my_argc; p++) {
364 if (rpc->add(c, "s", my_argv[p]) < 0) return;
369 static const char* core_kill_doc[] = {
370 "Sends the given signal to SER.", /* Documentation string */
371 0 /* Method signature(s) */
375 static void core_kill(rpc_t* rpc, void* c)
378 rpc->scan(c, "d", &sig_no);
383 static void core_shmmem(rpc_t* rpc, void* c)
389 rpc->add(c, "{", &handle);
390 rpc->struct_add(handle, "dddddd",
391 "total", (unsigned int)mi.total_size,
392 "free", (unsigned int)mi.free,
393 "used", (unsigned int)mi.used,
394 "real_used",(unsigned int)mi.real_used,
395 "max_used", (unsigned int)mi.max_used,
396 "fragments", (unsigned int)mi.total_frags
400 static const char* core_shmmem_doc[] = {
401 "Returns shared memory info.", /* Documentation string */
402 0 /* Method signature(s) */
406 #if defined(SF_MALLOC) || defined(LL_MALLOC)
407 static void core_sfmalloc(rpc_t* rpc, void* c)
411 unsigned long frags, main_s_frags, main_b_frags, pool_frags;
412 unsigned long misses;
413 unsigned long max_misses;
414 unsigned long max_frags;
415 unsigned long max_mem;
416 int max_frags_pool, max_frags_hash;
417 int max_misses_pool, max_misses_hash;
418 int max_mem_pool, max_mem_hash;
421 if (rpc->scan(c, "d", &r) >= 1) {
422 if (r>=(int)SF_HASH_POOL_SIZE){
423 rpc->fault(c, 500, "invalid hash number %d (max %d)",
424 r, (unsigned int)SF_HASH_POOL_SIZE-1);
426 }else if (r<0) goto all;
427 rpc->add(c, "{", &handle);
428 rpc->struct_add(handle, "dd",
430 "size ", r*SF_ROUNDTO);
431 for (i=0; i<SFM_POOLS_NO; i++){
432 rpc->struct_add(handle, "dddd",
434 "frags ", (unsigned int)shm_block->pool[i].pool_hash[r].no,
435 "misses", (unsigned int)shm_block->pool[i].pool_hash[r].misses,
436 "mem ", (unsigned int)shm_block->pool[i].pool_hash[r].no *
443 max_frags=max_misses=max_mem=0;
444 max_frags_pool=max_frags_hash=0;
445 max_misses_pool=max_misses_hash=0;
446 max_mem_pool=max_mem_hash=0;
448 for (i=0; i<SFM_POOLS_NO; i++){
452 for (r=0; r<SF_HASH_POOL_SIZE; r++){
453 frags+=shm_block->pool[i].pool_hash[r].no;
454 misses+=shm_block->pool[i].pool_hash[r].misses;
455 mem+=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
456 if (shm_block->pool[i].pool_hash[r].no>max_frags){
457 max_frags=shm_block->pool[i].pool_hash[r].no;
461 if (shm_block->pool[i].pool_hash[r].misses>max_misses){
462 max_misses=shm_block->pool[i].pool_hash[r].misses;
466 if (shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO>max_mem){
467 max_mem=shm_block->pool[i].pool_hash[r].no*r*SF_ROUNDTO;
472 rpc->add(c, "{", &handle);
473 rpc->struct_add(handle, "dddddd",
475 "frags ", (unsigned int)frags,
476 "t. misses", (unsigned int)misses,
477 "mem ", (unsigned int)mem,
478 "missed", (unsigned int)shm_block->pool[i].missed,
479 "hits", (unsigned int)shm_block->pool[i].hits
484 for (r=0; r<SF_HASH_POOL_SIZE; r++){
485 main_s_frags+=shm_block->free_hash[r].no;
488 for (; r<SF_HASH_SIZE; r++){
489 main_b_frags+=shm_block->free_hash[r].no;
491 rpc->add(c, "{", &handle);
492 rpc->struct_add(handle, "ddddddddddddd",
493 "max_frags ", (unsigned int)max_frags,
494 "max_frags_pool ", max_frags_pool,
495 "max_frags_hash", max_frags_hash,
496 "max_misses ", (unsigned int)max_misses,
497 "max_misses_pool", max_misses_pool,
498 "max_misses_hash", max_misses_hash,
499 "max_mem ", (unsigned int)max_mem,
500 "max_mem_pool ", max_mem_pool,
501 "max_mem_hash ", max_mem_hash,
502 "in_pools_frags ", (unsigned int)pool_frags,
503 "main_s_frags ", (unsigned int)main_s_frags,
504 "main_b_frags ", (unsigned int)main_b_frags,
505 "main_frags ", (unsigned int)(main_b_frags+main_s_frags)
511 static const char* core_sfmalloc_doc[] = {
512 "Returns sfmalloc debugging info.", /* Documentation string */
513 0 /* Method signature(s) */
520 static const char* core_tcpinfo_doc[] = {
521 "Returns tcp related info.", /* Documentation string */
522 0 /* Method signature(s) */
525 static void core_tcpinfo(rpc_t* rpc, void* c)
529 struct tcp_gen_info ti;
533 rpc->add(c, "{", &handle);
534 rpc->struct_add(handle, "dddd",
535 "readers", ti.tcp_readers,
536 "max_connections", ti.tcp_max_connections,
537 "opened_connections", ti.tcp_connections_no,
538 "write_queued_bytes", ti.tcp_write_queued
541 rpc->fault(c, 500, "tcp support disabled");
544 rpc->fault(c, 500, "tcp support not compiled");
550 static const char* core_tcp_options_doc[] = {
551 "Returns active tcp options.", /* Documentation string */
552 0 /* Method signature(s) */
555 static void core_tcp_options(rpc_t* rpc, void* c)
559 struct tcp_cfg_options t;
563 rpc->add(c, "{", &handle);
564 rpc->struct_add(handle, "ddddddddddddddd",
565 "fd_cache", t.fd_cache,
566 "tcp_buf_write", t.tcp_buf_write,
567 "tcp_connect_wait", t.tcp_connect_wait,
568 "tcpconn_wq_max", t.tcpconn_wq_max,
569 "tcp_wq_max", t.tcp_wq_max,
570 "tcp_wq_timeout", TICKS_TO_S(t.tcp_wq_timeout),
572 "defer_accept", t.defer_accept,
573 "delayed_ack", t.delayed_ack,
575 "linger2", t.linger2,
576 "keepalive", t.keepalive,
577 "keepidle", t.keepidle,
578 "keepintvl", t.keepintvl,
579 "keepcnt", t.keepcnt,
580 "crlf_ping", t.crlf_ping
583 rpc->fault(c, 500, "tcp support disabled");
586 rpc->fault(c, 500, "tcp support not compiled");
593 * RPC Methods exported by this module
595 rpc_export_t core_rpc_methods[] = {
596 {"system.listMethods", system_listMethods, system_listMethods_doc, RET_ARRAY},
597 {"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0 },
598 {"system.methodHelp", system_methodHelp, system_methodHelp_doc, 0 },
599 {"core.prints", core_prints, core_prints_doc, 0 },
600 {"core.version", core_version, core_version_doc, 0 },
601 {"core.uptime", core_uptime, core_uptime_doc, 0 },
602 {"core.ps", core_ps, core_ps_doc, RET_ARRAY},
603 {"core.pwd", core_pwd, core_pwd_doc, RET_ARRAY},
604 {"core.arg", core_arg, core_arg_doc, RET_ARRAY},
605 {"core.kill", core_kill, core_kill_doc, 0 },
606 {"core.shmmem", core_shmmem, core_shmmem_doc, 0 },
607 #if defined(SF_MALLOC) || defined(LL_MALLOC)
608 {"core.sfmalloc", core_sfmalloc, core_sfmalloc_doc, 0},
610 {"core.tcp_info", core_tcpinfo, core_tcpinfo_doc, 0},
611 {"core.tcp_options", core_tcp_options, core_tcp_options_doc,0},
613 {"dns.mem_info", dns_cache_mem_info, dns_cache_mem_info_doc, 0 },
614 {"dns.debug", dns_cache_debug, dns_cache_debug_doc, 0 },
615 {"dns.debug_all", dns_cache_debug_all, dns_cache_debug_all_doc, 0 },
616 {"dns.view", dns_cache_view, dns_cache_view_doc, 0 },
617 {"dns.delete_all", dns_cache_delete_all, dns_cache_delete_all_doc, 0 },
618 {"dns.add_a", dns_cache_add_a, dns_cache_add_a_doc, 0 },
619 {"dns.add_aaaa", dns_cache_add_aaaa, dns_cache_add_aaaa_doc, 0 },
620 {"dns.add_srv", dns_cache_add_srv, dns_cache_add_srv_doc, 0 },
621 {"dns.delete_a", dns_cache_delete_a, dns_cache_delete_a_doc, 0 },
622 {"dns.delete_aaaa", dns_cache_delete_aaaa, dns_cache_delete_aaaa_doc, 0 },
623 {"dns.delete_srv", dns_cache_delete_srv, dns_cache_delete_srv_doc, 0 },
624 #ifdef USE_DNS_CACHE_STATS
625 {"dns.stats_get", dns_cache_stats_get, dns_cache_stats_get_doc, 0 },
626 #endif /* USE_DNS_CACHE_STATS */
627 #ifdef DNS_WATCHDOG_SUPPORT
628 {"dns.set_server_state", dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
629 {"dns.get_server_state", dns_get_server_state_rpc, dns_get_server_state_doc, 0 },
632 #ifdef USE_DST_BLACKLIST
633 {"dst_blacklist.mem_info", dst_blst_mem_info, dst_blst_mem_info_doc, 0 },
634 {"dst_blacklist.debug", dst_blst_debug, dst_blst_debug_doc, 0 },
635 {"dst_blacklist.view", dst_blst_view, dst_blst_view_doc, 0 },
636 {"dst_blacklist.delete_all", dst_blst_delete_all, dst_blst_delete_all_doc, 0 },
637 {"dst_blacklist.add", dst_blst_add, dst_blst_add_doc, 0 },
638 #ifdef USE_DST_BLACKLIST_STATS
639 {"dst_blacklist.stats_get", dst_blst_stats_get, dst_blst_stats_get_doc, 0 },
640 #endif /* USE_DST_BLACKLIST_STATS */
645 int rpc_init_time(void)
649 if (strlen(t)+1>=MAX_CTIME_LEN) {
650 ERR("Too long data %d\n", (int)strlen(t));
653 memcpy(up_since_ctime,t,strlen(t)+1);