- applied patch from Dragos Vingarzan <vingarzan@fokus.fraunhofer.de> which
[sip-router] / core_cmd.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2005 iptelorg GmbH
5  *
6  * This file is part of ser, a free SIP server.
7  *
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
12  *
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:
16  *    info@iptel.org
17  *
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.
22  *
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
26  */
27
28 #include <time.h>
29 #include <sys/types.h>
30 #include <signal.h>
31 #include "mem/mem.h"
32 #include "mem/shm_mem.h"
33 #include "sr_module.h"
34 #include "dprint.h"
35 #include "core_cmd.h"
36 #include "globals.h"
37 #include "pt.h"
38 #include "ut.h"
39 #include "tcp_info.h"
40 #include "core_cmd.h"
41
42 #ifdef USE_DNS_CACHE
43 void dns_cache_debug(rpc_t* rpc, void* ctx);
44 void dns_cache_debug_all(rpc_t* rpc, void* ctx);
45 void dns_cache_mem_info(rpc_t* rpc, void* ctx);
46
47 static const char* dns_cache_mem_info_doc[] = {
48         "dns cache memory info.",    /* Documentation string */
49         0                      /* Method signature(s) */
50 };
51 static const char* dns_cache_debug_doc[] = {
52         "dns debug  info.",    /* Documentation string */
53         0                      /* Method signature(s) */
54 };
55
56 static const char* dns_cache_debug_all_doc[] = {
57         "complete dns debug  dump",    /* Documentation string */
58         0                              /* Method signature(s) */
59 };
60 #endif
61 #ifdef USE_DST_BLACKLIST
62 void dst_blst_debug(rpc_t* rpc, void* ctx);
63 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
64
65 static const char* dst_blst_mem_info_doc[] = {
66         "dst blacklist memory usage info.",  /* Documentation string */
67         0                                    /* Method signature(s) */
68 };
69 static const char* dst_blst_debug_doc[] = {
70         "dst blacklist  debug  info.",  /* Documentation string */
71         0                               /* Method signature(s) */
72 };
73 #endif
74
75
76
77 #define MAX_CTIME_LEN 128
78
79 /* up time */
80 static time_t up_since;
81 static char up_since_ctime[MAX_CTIME_LEN];
82
83
84 static const char* system_listMethods_doc[] = {
85         "Lists all RPC methods supported by the server.",  /* Documentation string */
86         0                                                  /* Method signature(s) */
87 };
88
89 static void system_listMethods(rpc_t* rpc, void* c)
90 {
91         struct sr_module* t;
92         rpc_export_t* ptr;
93
94         for(ptr = core_rpc_methods; ptr && ptr->name; ptr++) {
95                 if (rpc->add(c, "s", ptr->name) < 0) return;
96         }
97
98         for(t = modules; t; t = t->next) {
99                 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
100                         if (rpc->add(c, "s", ptr->name) < 0) return;
101                 }
102         }
103 }
104
105 static const char* system_methodSignature_doc[] = {
106         "Returns signature of given method.",  /* Documentation string */
107         0                                      /* Method signature(s) */
108 };
109
110 static void system_methodSignature(rpc_t* rpc, void* c)
111 {
112         rpc->fault(c, 500, "Not Implemented Yet");
113 }
114
115
116 static const char* system_methodHelp_doc[] = {
117         "Print the help string for given method.",  /* Documentation string */
118         0                                           /* Method signature(s) */
119 };
120
121 static void system_methodHelp(rpc_t* rpc, void* c)
122 {
123         struct sr_module* t;
124         rpc_export_t* ptr;
125         char* name;
126
127         if (rpc->scan(c, "s", &name) < 1) {
128                 rpc->fault(c, 400, "Method Name Expected");
129                 return;
130         }
131
132         for(t = modules; t; t = t->next) {
133                 for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
134                         if (strcmp(name, ptr->name) == 0) {
135                                 if (ptr->doc_str && ptr->doc_str[0]) {
136                                         rpc->add(c, "s", ptr->doc_str[0]);
137                                 } else {
138                                         rpc->add(c, "s", "undocumented");
139                                 }
140                                 return;
141                         }
142                 }
143         }
144         /* try the core methods too */
145         for (ptr=core_rpc_methods;ptr && ptr->name; ptr++){
146                         if (strcmp(name, ptr->name) == 0) {
147                                 if (ptr->doc_str && ptr->doc_str[0]) {
148                                         rpc->add(c, "s", ptr->doc_str[0]);
149                                 } else {
150                                         rpc->add(c, "s", "undocumented");
151                                 }
152                                 return;
153                         }
154         }
155         rpc->fault(c, 400, "command not found");
156 }
157
158
159 static const char* core_prints_doc[] = {
160         "Returns the string given as parameter.",   /* Documentation string */
161         0                                           /* Method signature(s) */
162 };
163
164
165 static void core_prints(rpc_t* rpc, void* c)
166 {
167         char* string = 0;
168         if (rpc->scan(c, "s", &string)>0)
169                 rpc->add(c, "s", string);
170 }
171
172
173 static const char* core_version_doc[] = {
174         "Returns the version string of the server.", /* Documentation string */
175         0                                           /* Method signature(s) */
176 };
177
178 static void core_version(rpc_t* rpc, void* c)
179 {
180         rpc->add(c, "s", SERVER_HDR);
181 }
182
183
184
185 static const char* core_uptime_doc[] = {
186         "Returns uptime of SER server.",  /* Documentation string */
187         0                                 /* Method signature(s) */
188 };
189
190
191 static void core_uptime(rpc_t* rpc, void* c)
192 {
193         void* s;
194         time_t now;
195
196         time(&now);
197
198         if (rpc->add(c, "{", &s) < 0) return;
199         rpc->struct_add(s, "s", "now", ctime(&now));
200         rpc->struct_add(s, "s", "up_since", up_since_ctime);
201         /* no need for a float here (unless you're concerned that your uptime)
202         rpc->struct_add(s, "f", "uptime",  difftime(now, up_since));
203         */
204         /* on posix system we can substract time_t directly */
205         rpc->struct_add(s, "d", "uptime",  (int)(now-up_since));
206 }
207
208
209 static const char* core_ps_doc[] = {
210         "Returns the description of running SER processes.",  /* Documentation string */
211         0                                                     /* Method signature(s) */
212 };
213
214
215 static void core_ps(rpc_t* rpc, void* c)
216 {
217         int p;
218
219         for (p=0; p<*process_count;p++) {
220                 rpc->add(c, "d", pt[p].pid);
221                 rpc->add(c, "s", pt[p].desc);
222         }
223 }
224
225
226 static const char* core_pwd_doc[] = {
227         "Returns the working directory of SER server.",    /* Documentation string */
228         0                                                  /* Method signature(s) */
229 };
230
231
232 static void core_pwd(rpc_t* rpc, void* c)
233 {
234         char *cwd_buf;
235         int max_len;
236
237         max_len = pathmax();
238         cwd_buf = pkg_malloc(max_len);
239         if (!cwd_buf) {
240                 ERR("core_pwd: No memory left\n");
241                 rpc->fault(c, 500, "Server Ran Out of Memory");
242                 return;
243         }
244
245         if (getcwd(cwd_buf, max_len)) {
246                 rpc->add(c, "s", cwd_buf);
247         } else {
248                 rpc->fault(c, 500, "getcwd Failed");
249         }
250         pkg_free(cwd_buf);
251 }
252
253
254 static const char* core_arg_doc[] = {
255         "Returns the list of command line arguments used on SER startup.",  /* Documentation string */
256         0                                                                   /* Method signature(s) */
257 };
258
259
260 static void core_arg(rpc_t* rpc, void* c)
261 {
262         int p;
263
264         for (p = 0; p < my_argc; p++) {
265                 if (rpc->add(c, "s", my_argv[p]) < 0) return;
266         }
267 }
268
269
270 static const char* core_kill_doc[] = {
271         "Sends the given signal to SER.",  /* Documentation string */
272         0                                  /* Method signature(s) */
273 };
274
275
276 static void core_kill(rpc_t* rpc, void* c)
277 {
278         int sig_no = 15;
279         rpc->scan(c, "d", &sig_no);
280         rpc->send(c);
281         kill(0, sig_no);
282 }
283
284 static void core_shmmem(rpc_t* rpc, void* c)
285 {
286         struct mem_info mi;
287         void *handle;
288
289         shm_info(&mi);
290         rpc->add(c, "{", &handle);
291         rpc->struct_add(handle, "ddddd",
292                 "total", mi.total_size,
293                 "free", mi.free,
294                 "used", mi.real_used,
295                 "max_used", mi.max_used,
296                 "fragments", mi.total_frags
297         );
298 }
299
300 static const char* core_shmmem_doc[] = {
301         "Returns shared memory info.",  /* Documentation string */
302         0                               /* Method signature(s) */
303 };
304
305
306 static const char* core_tcpinfo_doc[] = {
307         "Returns tcp related info.",    /* Documentation string */
308         0                               /* Method signature(s) */
309 };
310
311 static void core_tcpinfo(rpc_t* rpc, void* c)
312 {
313         void *handle;
314 #ifdef USE_TCP
315         struct tcp_gen_info ti;
316         
317         if (!tcp_disable){
318                 tcp_get_info(&ti);
319                 rpc->add(c, "{", &handle);
320                 rpc->struct_add(handle, "ddd",
321                         "readers", ti.tcp_readers,
322                         "max_connections", ti.tcp_max_connections,
323                         "opened_connections", ti.tcp_connections_no
324                 );
325         }else{
326                 rpc->fault(c, 500, "tcp support disabled");
327         }
328 #else
329         rpc->fault(c, 500, "tcp support not compiled");
330 #endif
331 }
332
333 /*
334  * RPC Methods exported by this module
335  */
336 rpc_export_t core_rpc_methods[] = {
337         {"system.listMethods",     system_listMethods,     system_listMethods_doc,     RET_ARRAY},
338         {"system.methodSignature", system_methodSignature, system_methodSignature_doc, 0        },
339         {"system.methodHelp",      system_methodHelp,      system_methodHelp_doc,      0        },
340         {"core.prints",            core_prints,            core_prints_doc,            0        },
341         {"core.version",           core_version,           core_version_doc,           0        },
342         {"core.uptime",            core_uptime,            core_uptime_doc,            0        },
343         {"core.ps",                core_ps,                core_ps_doc,                RET_ARRAY},
344         {"core.pwd",               core_pwd,               core_pwd_doc,               RET_ARRAY},
345         {"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
346         {"core.kill",              core_kill,              core_kill_doc,              0        },
347         {"core.shmmem",            core_shmmem,            core_shmmem_doc,            0        },
348         {"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,          0 },
349 #ifdef USE_DNS_CACHE
350         {"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0 },
351         {"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0 },
352         {"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0     },
353 #endif
354 #ifdef USE_DST_BLACKLIST
355         {"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,     0 },
356         {"dst_blacklist.debug",    dst_blst_debug,         dst_blst_debug_doc,        0 },
357 #endif
358         {0, 0, 0, 0}
359 };
360
361 int rpc_init_time(void)
362 {
363         char *t;
364         time(&up_since);
365         t=ctime(&up_since);
366         if (strlen(t)+1>=MAX_CTIME_LEN) {
367                 ERR("Too long data %d\n", (int)strlen(t));
368                 return -1;
369         }
370         memcpy(up_since_ctime,t,strlen(t)+1);
371         return 0;
372 }