... | ... |
@@ -1,11 +1,31 @@ |
1 | 1 |
/* |
2 | 2 |
* $Id$ |
3 | 3 |
* |
4 |
- * simple UAC for things such as SUBSCRIBE or SMS gateway; |
|
5 |
- * no authentication and other UAC features -- just send |
|
6 |
- * a message, retransmit and await a reply; forking is not |
|
7 |
- * supported during client generation, in all other places |
|
8 |
- * it is -- adding it should be simple |
|
4 |
+ * Fifo server is a very powerful tool used to access easily |
|
5 |
+ * ser's internals via textual interface, similarly to |
|
6 |
+ * how internals of many operating systems are accessible |
|
7 |
+ * via the proc file system. This might be used for |
|
8 |
+ * making ser do things for you (such as initiating new |
|
9 |
+ * transaction from webpages) or inspect server's health. |
|
10 |
+ * |
|
11 |
+ * FIFO server allows new functionality to be registered |
|
12 |
+ * with it -- thats what register_fifo_cmd is good for. |
|
13 |
+ * Remember, the initialization must take place before |
|
14 |
+ * forking; best in init_module functions. When a function |
|
15 |
+ * is registered, it can be always evoked by sending its |
|
16 |
+ * name prefixed by colon to the FIFO. |
|
17 |
+ * |
|
18 |
+ * There are few commands already implemented in core. |
|
19 |
+ * These are 'uptime' for looking at how long the server |
|
20 |
+ * is alive and 'print' for debugging purposes. |
|
21 |
+ * |
|
22 |
+ * Every command sent to FIFO must be sent atomically to |
|
23 |
+ * avoid intermixing with other commands and MUST be |
|
24 |
+ * terminated by empty line so that the server is to able |
|
25 |
+ * to find its end if it does not understand the command. |
|
26 |
+ * |
|
27 |
+ * File test/transaction.fifo illustrates example of use |
|
28 |
+ * of t_uac command (part of TM module). |
|
9 | 29 |
*/ |
10 | 30 |
|
11 | 31 |
#include <stdlib.h> |
... | ... |
@@ -29,7 +49,8 @@ |
29 | 49 |
|
30 | 50 |
/* FIFO server vars */ |
31 | 51 |
char *fifo=0; /* FIFO name */ |
32 |
-int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; |
|
52 |
+int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | |
|
53 |
+ S_IWGRP | S_IROTH | S_IWOTH; |
|
33 | 54 |
pid_t fifo_pid; |
34 | 55 |
/* file descriptors */ |
35 | 56 |
static int fifo_read=0; |
... | ... |
@@ -136,7 +157,8 @@ int read_eol( FILE *stream ) |
136 | 157 |
} |
137 | 158 |
return 1; |
138 | 159 |
} |
139 |
- |
|
160 |
+ |
|
161 |
+/* read from input until empty line is encountered */ |
|
140 | 162 |
int read_line_set(char *buf, int max_len, FILE *fifo, int *len) |
141 | 163 |
{ |
142 | 164 |
int set_len; |
... | ... |
@@ -164,6 +186,34 @@ int read_line_set(char *buf, int max_len, FILE *fifo, int *len) |
164 | 186 |
} |
165 | 187 |
} |
166 | 188 |
|
189 |
+/* read from input until line with only dot in it is encountered */ |
|
190 |
+int read_body(char *buf, int max_len, FILE *fifo, int *len) |
|
191 |
+{ |
|
192 |
+ int set_len; |
|
193 |
+ char *c; |
|
194 |
+ int line_len; |
|
195 |
+ |
|
196 |
+ c=buf;set_len=0; |
|
197 |
+ while(1) { |
|
198 |
+ if (!read_line(c,max_len,fifo,&line_len)) { |
|
199 |
+ LOG(L_ERR, "ERROR: fifo_server: line expected\n"); |
|
200 |
+ return 0; |
|
201 |
+ } |
|
202 |
+ /* end encountered ... return */ |
|
203 |
+ if (line_len==1 && *c=='.') { |
|
204 |
+ *len=set_len; |
|
205 |
+ return 1; |
|
206 |
+ } |
|
207 |
+ max_len-=line_len; c+=line_len; set_len+=line_len; |
|
208 |
+ if (max_len<CRLF_LEN) { |
|
209 |
+ LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n"); |
|
210 |
+ return 0; |
|
211 |
+ } |
|
212 |
+ memcpy(c, CRLF, CRLF_LEN); |
|
213 |
+ max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN; |
|
214 |
+ } |
|
215 |
+} |
|
216 |
+ |
|
167 | 217 |
static char *trim_filename( char * file ) |
168 | 218 |
{ |
169 | 219 |
int prefix_len, fn_len; |
... | ... |
@@ -311,10 +361,12 @@ int open_fifo_server() |
311 | 361 |
} |
312 | 362 |
DBG("TM: open_uac_fifo: opening fifo...\n"); |
313 | 363 |
if ((mkfifo(fifo, fifo_mode)<0) && (errno!=EEXIST)) { |
314 |
- LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: %s\n", |
|
315 |
- strerror(errno)); |
|
364 |
+ LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: " |
|
365 |
+ "%s (mode=%d)\n", |
|
366 |
+ strerror(errno), fifo_mode); |
|
316 | 367 |
return -1; |
317 |
- } |
|
368 |
+ } |
|
369 |
+ DBG("DEBUG: fifo %s opened, mode=%d\n", fifo, fifo_mode ); |
|
318 | 370 |
time(&up_since); |
319 | 371 |
process_no++; |
320 | 372 |
fifo_pid=fork(); |
... | ... |
@@ -31,6 +31,8 @@ int read_line( char *b, int max, FILE *stream, int *read ); |
31 | 31 |
int read_eol( FILE *stream ); |
32 | 32 |
/* consume a set of EoL-terminated lines terminated by an additional EoL */ |
33 | 33 |
int read_line_set(char *buf, int max_len, FILE *fifo, int *len); |
34 |
+/* consume a set of EoL-terminated lines terminated by a single dot line */ |
|
35 |
+int read_body(char *buf, int max_len, FILE *fifo, int *len); |
|
34 | 36 |
|
35 | 37 |
int open_fifo_server(); |
36 | 38 |
|
... | ... |
@@ -5,7 +5,7 @@ |
5 | 5 |
|
6 | 6 |
#include "t_dlg.h" |
7 | 7 |
|
8 |
-static struct dialog *dlg=0; |
|
8 |
+dlg_t dlg=0; |
|
9 | 9 |
|
10 | 10 |
int t_newdlg( struct sip_msg *msg ) |
11 | 11 |
{ |
... | ... |
@@ -14,7 +14,7 @@ int t_newdlg( struct sip_msg *msg ) |
14 | 14 |
return 0; |
15 | 15 |
} |
16 | 16 |
|
17 |
-struct dialog *t_getdlg() { |
|
17 |
+dlg_t t_getdlg() { |
|
18 | 18 |
return dlg; |
19 | 19 |
} |
20 | 20 |
|
... | ... |
@@ -143,7 +143,7 @@ error: |
143 | 143 |
|
144 | 144 |
|
145 | 145 |
|
146 |
-char *build_uac_request( str msg_type, str dst, |
|
146 |
+char *build_uac_request( str msg_type, str dst, str from, |
|
147 | 147 |
str headers, str body, int branch, |
148 | 148 |
struct cell *t, int *len) |
149 | 149 |
{ |
... | ... |
@@ -158,10 +158,18 @@ char *build_uac_request( str msg_type, str dst, |
158 | 158 |
char branch_buf[MAX_BRANCH_PARAM_LEN]; |
159 | 159 |
int branch_len; |
160 | 160 |
|
161 |
- static int from_len=0; |
|
161 |
+ int from_len; |
|
162 |
+ char *from_str; |
|
162 | 163 |
|
163 | 164 |
buf=0; |
164 |
- if (from_len==0) from_len=strlen(uac_from); |
|
165 |
+ |
|
166 |
+ if (from.len) { |
|
167 |
+ from_len=from.len; |
|
168 |
+ from_str=from.s; |
|
169 |
+ } else { |
|
170 |
+ from_len=strlen(uac_from); |
|
171 |
+ from_str=uac_from; |
|
172 |
+ } |
|
165 | 173 |
|
166 | 174 |
*len=SIP_VERSION_LEN+msg_type.len+2/*spaces*/+CRLF_LEN+ |
167 | 175 |
dst.len; |
... | ... |
@@ -231,7 +239,7 @@ char *build_uac_request( str msg_type, str dst, |
231 | 239 |
CRLF_LEN+FROM_LEN); |
232 | 240 |
} |
233 | 241 |
t->from.s=w-FROM_LEN; t->from.len=FROM_LEN+from_len+FROMTAG_LEN+MD5_LEN; |
234 |
- memapp( w, uac_from, from_len ); |
|
242 |
+ memapp( w, from_str, from_len ); |
|
235 | 243 |
memapp( w, FROMTAG, FROMTAG_LEN ); |
236 | 244 |
memapp( w, from_tag, MD5_LEN ); |
237 | 245 |
memapp( w, CRLF, CRLF_LEN ); |
... | ... |
@@ -49,7 +49,7 @@ |
49 | 49 |
char *build_local(struct cell *Trans, unsigned int branch, |
50 | 50 |
unsigned int *len, char *method, int method_len, str *to); |
51 | 51 |
|
52 |
-char *build_uac_request( str msg_type, str dst, |
|
52 |
+char *build_uac_request( str msg_type, str dst, str from, |
|
53 | 53 |
str headers, str body, int branch, |
54 | 54 |
struct cell *t, int *len); |
55 | 55 |
|
... | ... |
@@ -97,8 +97,9 @@ void generate_callid() { |
97 | 97 |
|
98 | 98 |
|
99 | 99 |
int t_uac( str *msg_type, str *dst, |
100 |
- str *headers, str *body, transaction_cb completion_cb, |
|
101 |
- void *cbp, struct dialog *dlg) |
|
100 |
+ str *headers, str *body, str *from, |
|
101 |
+ transaction_cb completion_cb, void *cbp, |
|
102 |
+ dlg_t dlg) |
|
102 | 103 |
{ |
103 | 104 |
|
104 | 105 |
struct cell *new_cell; |
... | ... |
@@ -110,6 +111,7 @@ int t_uac( str *msg_type, str *dst, |
110 | 111 |
union sockaddr_union to; |
111 | 112 |
struct socket_info* send_sock; |
112 | 113 |
struct retr_buf *request; |
114 |
+ str dummy_from; |
|
113 | 115 |
|
114 | 116 |
/* be optimist -- assume success for return value */ |
115 | 117 |
ret=1; |
... | ... |
@@ -155,7 +157,8 @@ int t_uac( str *msg_type, str *dst, |
155 | 157 |
request->to=to; |
156 | 158 |
request->send_sock=send_sock; |
157 | 159 |
|
158 |
- buf=build_uac_request( *msg_type, *dst, *headers, *body, branch, |
|
160 |
+ if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; } |
|
161 |
+ buf=build_uac_request( *msg_type, *dst, dummy_from, *headers, *body, branch, |
|
159 | 162 |
new_cell /* t carries hash_index, label, md5, uac[].send_sock and |
160 | 163 |
other pieces of information needed to print a message*/ |
161 | 164 |
, &req_len ); |
... | ... |
@@ -270,7 +273,7 @@ int fifo_uac( FILE *stream, char *response_file ) |
270 | 273 |
} |
271 | 274 |
DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header ); |
272 | 275 |
/* and eventually body */ |
273 |
- if (!read_line_set(body, MAX_BODY, stream, &sb.len)) { |
|
276 |
+ if (!read_body(body, MAX_BODY, stream, &sb.len)) { |
|
274 | 277 |
LOG(L_ERR, "ERROR: fifo_uac: body expected\n"); |
275 | 278 |
return -1; |
276 | 279 |
} |
... | ... |
@@ -292,7 +295,8 @@ int fifo_uac( FILE *stream, char *response_file ) |
292 | 295 |
will not be triggered and no feedback will be printed |
293 | 296 |
to shmem_file |
294 | 297 |
*/ |
295 |
- t_uac(&sm,&sd,&sh,&sb,fifo_callback,shmem_file,0 /* no dialog */); |
|
298 |
+ t_uac(&sm,&sd,&sh,&sb, 0 /* default from */, |
|
299 |
+ fifo_callback,shmem_file,0 /* no dialog */); |
|
296 | 300 |
return 1; |
297 | 301 |
|
298 | 302 |
} |
... | ... |
@@ -29,7 +29,7 @@ void uac_child_init( int rank ); |
29 | 29 |
void generate_callid(); |
30 | 30 |
|
31 | 31 |
typedef int (*tuac_f)(str *msg_type, str *dst, str *headers,str *body, |
32 |
- transaction_cb completion_cb ); |
|
32 |
+ str *from, transaction_cb completion_cb ); |
|
33 | 33 |
|
34 | 34 |
/* transactional UAC; look for an example of usage at fifo_uac */ |
35 | 35 |
int t_uac( |
... | ... |
@@ -42,6 +42,9 @@ int t_uac( |
42 | 42 |
generated by UAC: To, Content_length, CSeq, Call-ID, Via, From |
43 | 43 |
(From is taken from config option) |
44 | 44 |
*/ |
45 |
+ str *from, /* optional value to be included in From *without* tag; |
|
46 |
+ if 0, then config value uac_from will be used |
|
47 |
+ */ |
|
45 | 48 |
str *headers, |
46 | 49 |
/* body of the message if any */ |
47 | 50 |
str *body, |
... | ... |
@@ -14,9 +14,9 @@ SER_FIFO=/tmp/ser_fifo |
14 | 14 |
WATCH_PERIOD=2 |
15 | 15 |
|
16 | 16 |
# SQL config |
17 |
-SQL_DB=csps107 |
|
17 |
+SQL_DB=ser |
|
18 | 18 |
SQL_HOST=dbhost |
19 |
-SQL_USER=csps |
|
19 |
+SQL_USER=ser |
|
20 | 20 |
|
21 | 21 |
# the read-only user for whom password may be stored here |
22 | 22 |
RO_USER=serro |
... | ... |
@@ -29,7 +29,12 @@ SER='sr' |
29 | 29 |
|
30 | 30 |
# ACL name verification |
31 | 31 |
VERIFY_ACL=1 |
32 |
-ACL_GROUPS="local ld int" |
|
32 |
+ACL_GROUPS="local ld int voicemail free-pstn" |
|
33 |
+ |
|
34 |
+# expiration time for alias table |
|
35 |
+if [ -z "$FOREVER" ]; then |
|
36 |
+ FOREVER='2020-05-28 21:32:15' |
|
37 |
+fi |
|
33 | 38 |
|
34 | 39 |
#### SQL names |
35 | 40 |
|
... | ... |
@@ -187,7 +192,7 @@ ser_alias() { |
187 | 192 |
($A_USER_COLUMN, $A_CONTACT_COLUMN, $A_EXPIRES_COLUMN, \ |
188 | 193 |
$A_Q_COLUMN, $A_CALLID_COLUMN, $A_CSEQ_COLUMN, \ |
189 | 194 |
$A_LAST_MODIFIED_COLUMN) \ |
190 |
- values ( '$2', '$3', '2099-05-28 21:32:15', \ |
|
195 |
+ values ( '$2', '$3', '$FOREVER', \ |
|
191 | 196 |
'1.00', 'call-id-for-ever', '1', |
192 | 197 |
now() );" |
193 | 198 |
sql_query "$QUERY" |
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
:t_uac:hh |
2 | 2 |
MESSAGE |
3 |
-sip:jirim@iptel.org |
|
3 |
+sip:gh@iptel.org |
|
4 | 4 |
foo: bar |
5 | 5 |
x: y |
6 | 6 |
p_header: p_value |
... | ... |
@@ -8,5 +8,5 @@ Contact: <sip:195.37.77.100:9> |
8 | 8 |
Content-Type: text/plain; charset=UTF-8;msgr=WAAtAE0ATQBTAC0ASQBNAC0ARgBvAHIAbQBhAHQAOgAgAEYATgA9AE0AUwAlADIAMABTAGgAZQBsAGwAJQAyADAARABsAGcAOwAgAEUARgA9ADsAIABDAE8APQAwADsAIABDAFMAPQAwADsAIABQAEYAPQAwAA0ACgANAAoA |
9 | 9 |
|
10 | 10 |
I love you man!!!! |
11 |
- |
|
11 |
+. |
|
12 | 12 |
|