modules/ims_qos: added patch for flow-description bug when request originates from...
[sip-router] / lib / kmi / mi.c
1 /*
2  * $Id: mi.c 4565 2008-08-05 14:58:52Z klaus_darilion $
3  *
4  * Copyright (C) 2006 Voice Sistem SRL
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio 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  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *
22  *
23  * History:
24  * ---------
25  *  2006-09-08  first version (bogdan)
26  */
27
28 /*!
29  * \file 
30  * \brief MI :: Attributes
31  * \ingroup mi
32  */
33
34 /*!
35  * \defgroup mi Kamailio Management Interface
36  * 
37  * The Kamailio management interface (MI) is a plugin architecture with a few different 
38  * handlers that gives access to the management interface over various transports.
39  *
40  * The Kamailio core and modules register commands to the interface at runtime.
41  * Look into the various module documentation files for information of these
42  * commands.
43  *
44  */
45
46 #include <string.h>
47
48 #include "../../dprint.h"
49 #include "../../sr_module.h"
50 #include "mi_mem.h"
51 #include "mi.h"
52
53 static struct mi_cmd*  mi_cmds = 0;
54 static int mi_cmds_no = 0;
55
56
57 static inline int get_mi_id( char *name, int len)
58 {
59         int n;
60         int i;
61
62         for( n=0,i=0 ; i<len ; n+=name[i] ,i++ );
63         return n;
64 }
65
66
67 static inline struct mi_cmd* lookup_mi_cmd_id(int id,char *name, int len)
68 {
69         int i;
70
71         for( i=0 ; i<mi_cmds_no ; i++ ) {
72                 if ( id==mi_cmds[i].id && len==mi_cmds[i].name.len &&
73                 memcmp(mi_cmds[i].name.s,name,len)==0 )
74                         return &mi_cmds[i];
75         }
76
77         return 0;
78 }
79
80
81 int register_mi_mod( char *mod_name, mi_export_t *mis)
82 {
83         int ret;
84         int i;
85
86         if (mis==0)
87                 return 0;
88
89         for ( i=0 ; mis[i].name ; i++ ) {
90                 ret = register_mi_cmd( mis[i].cmd, mis[i].name, mis[i].param,
91                         mis[i].init_f, mis[i].flags);
92                 if (ret!=0) {
93                         LM_ERR("failed to register cmd <%s> for module %s\n",
94                                         mis[i].name,mod_name);
95                 }
96         }
97         return 0;
98 }
99
100
101 static int mi_commands_initialized = 0;
102
103
104 /**
105  * Init a process to work properly for MI commands
106  * - rank: rank of the process (PROC_XYZ...)
107  * - mode: 0 - don't try to init worker for SIP commands
108  *         1 - try to init worker for SIP commands
109  */
110 int init_mi_child(int rank, int mode)
111 {
112         int i;
113
114         if(mi_commands_initialized)
115                 return 0;
116         mi_commands_initialized = 1;
117         for ( i=0 ; i<mi_cmds_no ; i++ ) {
118                 if ( mi_cmds[i].init_f && mi_cmds[i].init_f()!=0 ) {
119                         LM_ERR("failed to init <%.*s>\n",
120                                         mi_cmds[i].name.len,mi_cmds[i].name.s);
121                         return -1;
122                 }
123         }
124         if(mode==1) {
125                 if(is_sip_worker(rank)) {
126                         LM_DBG("initalizing proc rpc for sip handling\n");
127                         if(init_child(PROC_SIPRPC)<0) {
128                                 LM_ERR("failed to init proc rpc for sip handling\n");
129                                 return -1;
130                         }
131                 }
132         }
133         return 0;
134 }
135
136
137
138 int register_mi_cmd( mi_cmd_f f, char *name, void *param,
139                                                                         mi_child_init_f in, unsigned int flags)
140 {
141         struct mi_cmd *cmds;
142         int id;
143         int len;
144
145         if (f==0 || name==0) {
146                 LM_ERR("invalid params f=%p, name=%s\n", f, name);
147                 return -1;
148         }
149
150         if (flags&MI_NO_INPUT_FLAG && flags&MI_ASYNC_RPL_FLAG) {
151                 LM_ERR("invalids flags for <%s> - "
152                         "async functions must take input\n",name);
153         }
154
155         len = strlen(name);
156         id = get_mi_id(name,len);
157
158         if (lookup_mi_cmd_id( id, name, len)) {
159                 LM_ERR("command <%.*s> already registered\n", len, name);
160                 return -1;
161         }
162
163         cmds = (struct mi_cmd*)mi_realloc( mi_cmds,
164                         (mi_cmds_no+1)*sizeof(struct mi_cmd) );
165         if (cmds==0) {
166                 LM_ERR("no more pkg memory\n");
167                 return -1;
168         }
169
170         mi_cmds = cmds;
171         mi_cmds_no++;
172
173         cmds = &cmds[mi_cmds_no-1];
174
175         cmds->f = f;
176         cmds->init_f = in;
177         cmds->flags = flags;
178         cmds->name.s = name;
179         cmds->name.len = len;
180         cmds->id = id;
181         cmds->param = param;
182
183         return 0;
184 }
185
186
187 struct mi_cmd* lookup_mi_cmd( char *name, int len)
188 {
189         int id;
190
191         id = get_mi_id(name,len);
192         return lookup_mi_cmd_id( id, name, len);
193 }
194
195
196 void get_mi_cmds( struct mi_cmd** cmds, int *size)
197 {
198         *cmds = mi_cmds;
199         *size = mi_cmds_no;
200 }
201
202