Browse code

jsonrpcs: init fifo stream via mod init callback

Daniel-Constantin Mierla authored on 21/10/2017 10:19:41
Showing 1 changed files
... ...
@@ -47,83 +47,7 @@ char *jsonrpc_fifo_gid_s = 0;			/*!< Fifo default Group ID name */
47 47
 int  jsonrpc_fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP; /* Default file mode rw-rw---- */
48 48
 
49 49
 
50
-/* FIFO TRANSPORT */
51
-
52
-/*! \brief Initialize fifo transport */
53
-int jsonrpc_init_fifo_file(void)
54
-{
55
-	int n;
56
-	struct stat filestat;
57
-
58
-	/* checking the jsonrpc_fifo module param */
59
-	if (jsonrpc_fifo==NULL || *jsonrpc_fifo == 0) {
60
-		jsonrpc_fifo=NULL;
61
-		LM_DBG("No fifo configured\n");
62
-		return 0;
63
-	}
64
-
65
-	LM_DBG("testing if fifo file exists ...\n");
66
-	n=stat(jsonrpc_fifo, &filestat);
67
-	if (n==0) {
68
-		/* FIFO exist, delete it (safer) if no config check */
69
-		if(config_check==0) {
70
-			if (unlink(jsonrpc_fifo)<0){
71
-				LM_ERR("Cannot delete old fifo (%s): %s\n",
72
-					jsonrpc_fifo, strerror(errno));
73
-				return -1;
74
-			}
75
-		}
76
-	} else if (n<0 && errno!=ENOENT){
77
-		LM_ERR("MI FIFO stat failed: %s\n", strerror(errno));
78
-		return -1;
79
-	}
80
-
81
-	/* checking the fifo_reply_dir param */
82
-	if(!jsonrpc_fifo_reply_dir || *jsonrpc_fifo_reply_dir == 0) {
83
-		LM_ERR("fifo_reply_dir parameter is empty\n");
84
-		return -1;
85
-	}
86
-
87
-	/* Check if the directory for the reply fifo exists */
88
-	n = stat(jsonrpc_fifo_reply_dir, &filestat);
89
-	if(n < 0){
90
-		LM_ERR("Directory stat for MI Fifo reply failed: %s\n", strerror(errno));
91
-		return -1;
92
-	}
93
-
94
-	if(S_ISDIR(filestat.st_mode) == 0){
95
-		LM_ERR("fifo_reply_dir parameter is not a directory\n");
96
-		return -1;
97
-	}
98
-
99
-	/* check fifo_mode */
100
-	if(!jsonrpc_fifo_mode){
101
-		LM_WARN("cannot specify fifo_mode = 0, forcing it to rw-------\n");
102
-		jsonrpc_fifo_mode = S_IRUSR | S_IWUSR;
103
-	}
104
-
105
-	if (jsonrpc_fifo_uid_s){
106
-		if (user2uid(&jsonrpc_fifo_uid, &jsonrpc_fifo_gid, jsonrpc_fifo_uid_s)<0){
107
-			LM_ERR("Bad user name %s\n", jsonrpc_fifo_uid_s);
108
-			return -1;
109
-		}
110
-	}
111
-
112
-	if (jsonrpc_fifo_gid_s){
113
-		if (group2gid(&jsonrpc_fifo_gid, jsonrpc_fifo_gid_s)<0){
114
-			LM_ERR("Bad group name %s\n", jsonrpc_fifo_gid_s);
115
-			return -1;
116
-		}
117
-	}
118
-
119
-	/* add space for one extra process */
120
-	register_procs(1);
121
-
122
-	/* add child to update local config framework structures */
123
-	cfg_register_child(1);
124
-
125
-	return 0;
126
-}
50
+static FILE *_jsonrpcs_fifo_stream = NULL;
127 51
 
128 52
 
129 53
 static int  jsonrpc_fifo_read = 0;
... ...
@@ -211,6 +135,90 @@ FILE *jsonrpc_init_fifo_server(char *fifo_name, int fifo_mode,
211 135
 	return fifo_stream;
212 136
 }
213 137
 
138
+/*! \brief Initialize fifo transport */
139
+int jsonrpc_init_fifo_file(void)
140
+{
141
+	int n;
142
+	struct stat filestat;
143
+
144
+	/* checking the jsonrpc_fifo module param */
145
+	if (jsonrpc_fifo==NULL || *jsonrpc_fifo == 0) {
146
+		jsonrpc_fifo=NULL;
147
+		LM_DBG("No fifo configured\n");
148
+		return 0;
149
+	}
150
+
151
+	LM_DBG("testing if fifo file exists ...\n");
152
+	n=stat(jsonrpc_fifo, &filestat);
153
+	if (n==0) {
154
+		/* FIFO exist, delete it (safer) if no config check */
155
+		if(config_check==0) {
156
+			if (unlink(jsonrpc_fifo)<0){
157
+				LM_ERR("Cannot delete old fifo (%s): %s\n",
158
+					jsonrpc_fifo, strerror(errno));
159
+				return -1;
160
+			}
161
+		}
162
+	} else if (n<0 && errno!=ENOENT){
163
+		LM_ERR("MI FIFO stat failed: %s\n", strerror(errno));
164
+		return -1;
165
+	}
166
+
167
+	/* checking the fifo_reply_dir param */
168
+	if(!jsonrpc_fifo_reply_dir || *jsonrpc_fifo_reply_dir == 0) {
169
+		LM_ERR("fifo_reply_dir parameter is empty\n");
170
+		return -1;
171
+	}
172
+
173
+	/* Check if the directory for the reply fifo exists */
174
+	n = stat(jsonrpc_fifo_reply_dir, &filestat);
175
+	if(n < 0){
176
+		LM_ERR("Directory stat for MI Fifo reply failed: %s\n", strerror(errno));
177
+		return -1;
178
+	}
179
+
180
+	if(S_ISDIR(filestat.st_mode) == 0){
181
+		LM_ERR("fifo_reply_dir parameter is not a directory\n");
182
+		return -1;
183
+	}
184
+
185
+	/* check fifo_mode */
186
+	if(!jsonrpc_fifo_mode){
187
+		LM_WARN("cannot specify fifo_mode = 0, forcing it to rw-------\n");
188
+		jsonrpc_fifo_mode = S_IRUSR | S_IWUSR;
189
+	}
190
+
191
+	if (jsonrpc_fifo_uid_s){
192
+		if (user2uid(&jsonrpc_fifo_uid, &jsonrpc_fifo_gid, jsonrpc_fifo_uid_s)<0){
193
+			LM_ERR("Bad user name %s\n", jsonrpc_fifo_uid_s);
194
+			return -1;
195
+		}
196
+	}
197
+
198
+	if (jsonrpc_fifo_gid_s){
199
+		if (group2gid(&jsonrpc_fifo_gid, jsonrpc_fifo_gid_s)<0){
200
+			LM_ERR("Bad group name %s\n", jsonrpc_fifo_gid_s);
201
+			return -1;
202
+		}
203
+	}
204
+
205
+
206
+	_jsonrpcs_fifo_stream = jsonrpc_init_fifo_server( jsonrpc_fifo, jsonrpc_fifo_mode,
207
+		jsonrpc_fifo_uid, jsonrpc_fifo_gid, jsonrpc_fifo_reply_dir);
208
+	if ( _jsonrpcs_fifo_stream==NULL ) {
209
+		LM_CRIT("failed to init jsonrpc fifo server file stream\n");
210
+		return -1;
211
+	}
212
+
213
+	/* add space for one extra process */
214
+	register_procs(1);
215
+
216
+	/* add child to update local config framework structures */
217
+	cfg_register_child(1);
218
+
219
+	return 0;
220
+}
221
+
214 222
 /*! \brief Read input on fifo */
215 223
 int jsonrpc_read_stream(char *b, int max, FILE *stream, int *lread)
216 224
 {
... ...
@@ -479,18 +487,14 @@ static void jsonrpc_fifo_server(FILE *fifo_stream)
479 487
 
480 488
 static void jsonrpc_fifo_process(int rank)
481 489
 {
482
-	FILE *fifo_stream;
483
-
484 490
 	LM_DBG("new process with pid = %d created\n",getpid());
485 491
 
486
-	fifo_stream = jsonrpc_init_fifo_server( jsonrpc_fifo, jsonrpc_fifo_mode,
487
-		jsonrpc_fifo_uid, jsonrpc_fifo_gid, jsonrpc_fifo_reply_dir);
488
-	if ( fifo_stream==NULL ) {
489
-		LM_CRIT("failed to init jsonrpc fifo server\n");
492
+	if ( _jsonrpcs_fifo_stream==NULL ) {
493
+		LM_CRIT("fifo server stream not initialized\n");
490 494
 		exit(-1);
491 495
 	}
492 496
 
493
-	jsonrpc_fifo_server( fifo_stream );
497
+	jsonrpc_fifo_server( _jsonrpcs_fifo_stream );
494 498
 
495 499
 	LM_CRIT("failed to run jsonrpc fifo server\n");
496 500
 	exit(-1);
... ...
@@ -601,4 +605,3 @@ int jsonrpc_fifo_destroy(void)
601 605
 error:
602 606
 	return -1;
603 607
 }
604
-
Browse code

jsonrpcs: set rank PROC_RPC for fifo and dgram processes

Daniel-Constantin Mierla authored on 21/10/2017 09:47:35
Showing 1 changed files
... ...
@@ -550,7 +550,7 @@ int jsonrpc_fifo_child_init(int rank)
550 550
 		LM_ERR("invalid fifo file path\n");
551 551
 	}
552 552
 
553
-	pid=fork_process(PROC_NOCHLDINIT, "JSONRPCS FIFO", 1);
553
+	pid=fork_process(PROC_RPC, "JSONRPCS FIFO", 1);
554 554
 	if (pid<0) {
555 555
 		return -1; /* error */
556 556
 	}
Browse code

jsonrpcs: updated the name of module in description of extra procs

Daniel-Constantin Mierla authored on 20/10/2017 09:23:06
Showing 1 changed files
... ...
@@ -550,7 +550,7 @@ int jsonrpc_fifo_child_init(int rank)
550 550
 		LM_ERR("invalid fifo file path\n");
551 551
 	}
552 552
 
553
-	pid=fork_process(PROC_NOCHLDINIT, "JSONRPC-S FIFO", 1);
553
+	pid=fork_process(PROC_NOCHLDINIT, "JSONRPCS FIFO", 1);
554 554
 	if (pid<0) {
555 555
 		return -1; /* error */
556 556
 	}
Browse code

jsonrpcs: close file for nice cleanup if fifo server fails to be initialized

Daniel-Constantin Mierla authored on 30/01/2017 16:40:38
Showing 1 changed files
... ...
@@ -181,21 +181,25 @@ FILE *jsonrpc_init_fifo_server(char *fifo_name, int fifo_mode,
181 181
 	jsonrpc_fifo_write=open(fifo_name, O_WRONLY|O_NONBLOCK, 0);
182 182
 	if (jsonrpc_fifo_write<0) {
183 183
 		LM_ERR("fifo_write did not open: %s\n", strerror(errno));
184
+		fclose(fifo_stream);
184 185
 		return 0;
185 186
 	}
186 187
 	/* set read fifo blocking mode */
187 188
 	if ((opt=fcntl(jsonrpc_fifo_read, F_GETFL))==-1){
188 189
 		LM_ERR("fcntl(F_GETFL) failed: %s [%d]\n", strerror(errno), errno);
190
+		fclose(fifo_stream);
189 191
 		return 0;
190 192
 	}
191 193
 	if (fcntl(jsonrpc_fifo_read, F_SETFL, opt & (~O_NONBLOCK))==-1){
192 194
 		LM_ERR("cntl(F_SETFL) failed: %s [%d]\n", strerror(errno), errno);
195
+		fclose(fifo_stream);
193 196
 		return 0;
194 197
 	}
195 198
 
196 199
 	jsonrpc_reply_fifo_s = pkg_malloc(JSONRPC_MAX_FILENAME);
197 200
 	if (jsonrpc_reply_fifo_s==NULL) {
198 201
 		LM_ERR("no more private memory\n");
202
+		fclose(fifo_stream);
199 203
 		return 0;
200 204
 	}
201 205
 
Browse code

jsonrpcs: set default transports to fifo and udp unixsock

- default fifo file name is kamailio_rpc.fifo
- default unix socket file name is kamailio_rpc.sock
- they are created in the runtime dir

Daniel-Constantin Mierla authored on 19/12/2016 17:20:32
Showing 1 changed files
... ...
@@ -38,7 +38,7 @@
38 38
 #include "jsonrpcs_mod.h"
39 39
 
40 40
 /* FIFO server parameters */
41
-char *jsonrpc_fifo = NULL;				/*!< FIFO file name */
41
+char *jsonrpc_fifo = NAME "_rpc.fifo";		/*!< FIFO file name */
42 42
 char *jsonrpc_fifo_reply_dir = "/tmp/"; 	/*!< dir where reply fifos are allowed */
43 43
 int  jsonrpc_fifo_uid = -1;				/*!< Fifo default UID */
44 44
 char *jsonrpc_fifo_uid_s = 0;			/*!< Fifo default User ID name */
Browse code

jsonrpc modules: removed - (dash) from json rpc modules

- jsonrpc-c is now jsonrpcc
- jsonrpc-s is now jsonrpcs
- janssonrpc-s is now janssonrpcs

Daniel-Constantin Mierla authored on 12/12/2016 20:53:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,600 @@
1
+/**
2
+ * Copyright (C) 2014-2017 Daniel-Constantin Mierla (asipto.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * Kamailio is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * Kamailio is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ *
20
+ */
21
+
22
+#include <string.h>
23
+#include <stdlib.h>
24
+#include <stdio.h>
25
+#include <stdarg.h>
26
+#include <sys/stat.h>
27
+#include <sys/types.h>
28
+#include <unistd.h>
29
+#include <errno.h>
30
+#include <fcntl.h>
31
+
32
+#include "../../core/ver.h"
33
+#include "../../core/trim.h"
34
+#include "../../core/pt.h"
35
+#include "../../core/sr_module.h"
36
+#include "../../core/cfg/cfg_struct.h"
37
+
38
+#include "jsonrpcs_mod.h"
39
+
40
+/* FIFO server parameters */
41
+char *jsonrpc_fifo = NULL;				/*!< FIFO file name */
42
+char *jsonrpc_fifo_reply_dir = "/tmp/"; 	/*!< dir where reply fifos are allowed */
43
+int  jsonrpc_fifo_uid = -1;				/*!< Fifo default UID */
44
+char *jsonrpc_fifo_uid_s = 0;			/*!< Fifo default User ID name */
45
+int  jsonrpc_fifo_gid = -1;				/*!< Fifo default Group ID */
46
+char *jsonrpc_fifo_gid_s = 0;			/*!< Fifo default Group ID name */
47
+int  jsonrpc_fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP; /* Default file mode rw-rw---- */
48
+
49
+
50
+/* FIFO TRANSPORT */
51
+
52
+/*! \brief Initialize fifo transport */
53
+int jsonrpc_init_fifo_file(void)
54
+{
55
+	int n;
56
+	struct stat filestat;
57
+
58
+	/* checking the jsonrpc_fifo module param */
59
+	if (jsonrpc_fifo==NULL || *jsonrpc_fifo == 0) {
60
+		jsonrpc_fifo=NULL;
61
+		LM_DBG("No fifo configured\n");
62
+		return 0;
63
+	}
64
+
65
+	LM_DBG("testing if fifo file exists ...\n");
66
+	n=stat(jsonrpc_fifo, &filestat);
67
+	if (n==0) {
68
+		/* FIFO exist, delete it (safer) if no config check */
69
+		if(config_check==0) {
70
+			if (unlink(jsonrpc_fifo)<0){
71
+				LM_ERR("Cannot delete old fifo (%s): %s\n",
72
+					jsonrpc_fifo, strerror(errno));
73
+				return -1;
74
+			}
75
+		}
76
+	} else if (n<0 && errno!=ENOENT){
77
+		LM_ERR("MI FIFO stat failed: %s\n", strerror(errno));
78
+		return -1;
79
+	}
80
+
81
+	/* checking the fifo_reply_dir param */
82
+	if(!jsonrpc_fifo_reply_dir || *jsonrpc_fifo_reply_dir == 0) {
83
+		LM_ERR("fifo_reply_dir parameter is empty\n");
84
+		return -1;
85
+	}
86
+
87
+	/* Check if the directory for the reply fifo exists */
88
+	n = stat(jsonrpc_fifo_reply_dir, &filestat);
89
+	if(n < 0){
90
+		LM_ERR("Directory stat for MI Fifo reply failed: %s\n", strerror(errno));
91
+		return -1;
92
+	}
93
+
94
+	if(S_ISDIR(filestat.st_mode) == 0){
95
+		LM_ERR("fifo_reply_dir parameter is not a directory\n");
96
+		return -1;
97
+	}
98
+
99
+	/* check fifo_mode */
100
+	if(!jsonrpc_fifo_mode){
101
+		LM_WARN("cannot specify fifo_mode = 0, forcing it to rw-------\n");
102
+		jsonrpc_fifo_mode = S_IRUSR | S_IWUSR;
103
+	}
104
+
105
+	if (jsonrpc_fifo_uid_s){
106
+		if (user2uid(&jsonrpc_fifo_uid, &jsonrpc_fifo_gid, jsonrpc_fifo_uid_s)<0){
107
+			LM_ERR("Bad user name %s\n", jsonrpc_fifo_uid_s);
108
+			return -1;
109
+		}
110
+	}
111
+
112
+	if (jsonrpc_fifo_gid_s){
113
+		if (group2gid(&jsonrpc_fifo_gid, jsonrpc_fifo_gid_s)<0){
114
+			LM_ERR("Bad group name %s\n", jsonrpc_fifo_gid_s);
115
+			return -1;
116
+		}
117
+	}
118
+
119
+	/* add space for one extra process */
120
+	register_procs(1);
121
+
122
+	/* add child to update local config framework structures */
123
+	cfg_register_child(1);
124
+
125
+	return 0;
126
+}
127
+
128
+
129
+static int  jsonrpc_fifo_read = 0;
130
+static int  jsonrpc_fifo_write = 0;
131
+#define JSONRPC_MAX_FILENAME	128
132
+static char *jsonrpc_reply_fifo_s = NULL;
133
+static int jsonrpc_reply_fifo_len = 0;
134
+
135
+/*! \brief Initialize Fifo server */
136
+FILE *jsonrpc_init_fifo_server(char *fifo_name, int fifo_mode,
137
+						int fifo_uid, int fifo_gid, char* fifo_reply_dir)
138
+{
139
+	FILE *fifo_stream;
140
+	long opt;
141
+
142
+	/* create FIFO ... */
143
+	if ((mkfifo(fifo_name, fifo_mode)<0)) {
144
+		LM_ERR("Can't create FIFO: %s (mode=%d)\n", strerror(errno), fifo_mode);
145
+		return 0;
146
+	}
147
+
148
+	LM_DBG("FIFO created @ %s\n", fifo_name );
149
+
150
+	if ((chmod(fifo_name, fifo_mode)<0)) {
151
+		LM_ERR("Can't chmod FIFO: %s (mode=%d)\n", strerror(errno), fifo_mode);
152
+		return 0;
153
+	}
154
+
155
+	if ((fifo_uid!=-1) || (fifo_gid!=-1)){
156
+		if (chown(fifo_name, fifo_uid, fifo_gid)<0){
157
+			LM_ERR("Failed to change the owner/group for %s  to %d.%d; %s[%d]\n",
158
+				fifo_name, fifo_uid, fifo_gid, strerror(errno), errno);
159
+			return 0;
160
+		}
161
+	}
162
+
163
+	LM_DBG("fifo %s opened, mode=%o\n", fifo_name, fifo_mode );
164
+
165
+	/* open it non-blocking or else wait here until someone
166
+	 * opens it for writing */
167
+	jsonrpc_fifo_read=open(fifo_name, O_RDONLY|O_NONBLOCK, 0);
168
+	if (jsonrpc_fifo_read<0) {
169
+		LM_ERR("Can't open fifo %s for reading - fifo_read did not open: %s\n",
170
+				fifo_name, strerror(errno));
171
+		return 0;
172
+	}
173
+
174
+	fifo_stream = fdopen(jsonrpc_fifo_read, "r");
175
+	if (fifo_stream==NULL) {
176
+		LM_ERR("fdopen failed on %s: %s\n", fifo_name, strerror(errno));
177
+		return 0;
178
+	}
179
+
180
+	/* make sure the read fifo will not close */
181
+	jsonrpc_fifo_write=open(fifo_name, O_WRONLY|O_NONBLOCK, 0);
182
+	if (jsonrpc_fifo_write<0) {
183
+		LM_ERR("fifo_write did not open: %s\n", strerror(errno));
184
+		return 0;
185
+	}
186
+	/* set read fifo blocking mode */
187
+	if ((opt=fcntl(jsonrpc_fifo_read, F_GETFL))==-1){
188
+		LM_ERR("fcntl(F_GETFL) failed: %s [%d]\n", strerror(errno), errno);
189
+		return 0;
190
+	}
191
+	if (fcntl(jsonrpc_fifo_read, F_SETFL, opt & (~O_NONBLOCK))==-1){
192
+		LM_ERR("cntl(F_SETFL) failed: %s [%d]\n", strerror(errno), errno);
193
+		return 0;
194
+	}
195
+
196
+	jsonrpc_reply_fifo_s = pkg_malloc(JSONRPC_MAX_FILENAME);
197
+	if (jsonrpc_reply_fifo_s==NULL) {
198
+		LM_ERR("no more private memory\n");
199
+		return 0;
200
+	}
201
+
202
+	/* init fifo reply dir buffer */
203
+	jsonrpc_reply_fifo_len = strlen(fifo_reply_dir);
204
+	memcpy(jsonrpc_reply_fifo_s, jsonrpc_fifo_reply_dir, jsonrpc_reply_fifo_len);
205
+	jsonrpc_reply_fifo_s[jsonrpc_reply_fifo_len] = '\0';
206
+
207
+	return fifo_stream;
208
+}
209
+
210
+/*! \brief Read input on fifo */
211
+int jsonrpc_read_stream(char *b, int max, FILE *stream, int *lread)
212
+{
213
+	int retry_cnt;
214
+	int len;
215
+	char *p;
216
+	int sstate;
217
+	int pcount;
218
+	int pfound;
219
+	int stype;
220
+
221
+	sstate = 0;
222
+	retry_cnt=0;
223
+
224
+	*lread = 0;
225
+	p = b;
226
+	pcount = 0;
227
+	pfound = 0;
228
+	stype = 0;
229
+
230
+	while(1) {
231
+		len = fread (p, 1, 1, stream);
232
+		if(len==0) {
233
+			LM_ERR("fifo server fread failed: %s\n", strerror(errno));
234
+			/* on Linux, sometimes returns ESPIPE -- give
235
+			   it few more chances
236
+			*/
237
+			if (errno==ESPIPE) {
238
+				retry_cnt++;
239
+				if (retry_cnt>4)
240
+					return -1;
241
+				continue;
242
+			}
243
+			/* interrupted by signal or ... */
244
+			if ((errno==EINTR)||(errno==EAGAIN))
245
+				continue;
246
+			return -1;
247
+		}
248
+		if(*p=='"' && (sstate==0 || stype==1)) {
249
+			if(*lread>0) {
250
+				if(*(p-1)!='\\') {
251
+					sstate = (sstate+1) % 2;
252
+					stype = 1;
253
+				}
254
+			} else {
255
+				sstate = (sstate+1) % 2;
256
+				stype = 1;
257
+			}
258
+		} else if(*p=='\'' && (sstate==0 || stype==2)) {
259
+			if(*lread>0) {
260
+				if(*(p-1)!='\\') {
261
+					sstate = (sstate+1) % 2;
262
+					stype = 2;
263
+				}
264
+			} else {
265
+				sstate = (sstate+1) % 2;
266
+				stype = 2;
267
+			}
268
+		} else if(*p=='{') {
269
+			if(sstate==0) {
270
+				pfound = 1;
271
+				pcount++;
272
+			}
273
+		} else if(*p=='}') {
274
+			if(sstate==0)
275
+				pcount--;
276
+		}
277
+		*lread = *lread + 1;
278
+		if(*lread>=max-1) {
279
+			LM_WARN("input data too large (%d)\n", *lread);
280
+			return -1;
281
+		}
282
+		p++;
283
+		if(pfound==1 && pcount==0) {
284
+			*p = 0;
285
+			return 0;
286
+		}
287
+	}
288
+
289
+	return -1;
290
+}
291
+
292
+/*! \brief reply fifo security checks:
293
+ *
294
+ * checks if fd is a fifo, is not hardlinked and it's not a softlink
295
+ * opened file descriptor + file name (for soft link check)
296
+ * \return 0 if ok, <0 if not */
297
+static int jsonrpc_fifo_check(int fd, char* fname)
298
+{
299
+	struct stat fst;
300
+	struct stat lst;
301
+
302
+	if (fstat(fd, &fst)<0){
303
+		LM_ERR("security: fstat on %s failed: %s\n", fname, strerror(errno));
304
+		return -1;
305
+	}
306
+	/* check if fifo */
307
+	if (!S_ISFIFO(fst.st_mode)){
308
+		LM_ERR("security: %s is not a fifo\n", fname);
309
+		return -1;
310
+	}
311
+	/* check if hard-linked */
312
+	if (fst.st_nlink>1){
313
+		LM_ERR("security: fifo_check: %s is hard-linked %d times\n", fname, (unsigned)fst.st_nlink);
314
+		return -1;
315
+	}
316
+
317
+	/* lstat to check for soft links */
318
+	if (lstat(fname, &lst)<0){
319
+		LM_ERR("security: lstat on %s failed: %s\n", fname, strerror(errno));
320
+		return -1;
321
+	}
322
+	if (S_ISLNK(lst.st_mode)){
323
+		LM_ERR("security: fifo_check: %s is a soft link\n", fname);
324
+		return -1;
325
+	}
326
+	/* if this is not a symbolic link, check to see if the inode didn't
327
+	 * change to avoid possible sym.link, rm sym.link & replace w/ fifo race
328
+	 */
329
+	if ((lst.st_dev!=fst.st_dev)||(lst.st_ino!=fst.st_ino)){
330
+		LM_ERR("security: fifo_check: inode/dev number differ: %d %d (%s)\n",
331
+			(int)fst.st_ino, (int)lst.st_ino, fname);
332
+		return -1;
333
+	}
334
+	/* success */
335
+	return 0;
336
+}
337
+
338
+#define JSONRPC_REPLY_RETRIES 4
339
+FILE *jsonrpc_open_reply_fifo(str *srpath)
340
+{
341
+	int retries=JSONRPC_REPLY_RETRIES;
342
+	int fifofd;
343
+	FILE *file_handle;
344
+	int flags;
345
+
346
+	if ( memchr(srpath->s, '.', srpath->len)
347
+			|| memchr(srpath->s, '/', srpath->len)
348
+			|| memchr(srpath->s, '\\', srpath->len) ) {
349
+		LM_ERR("Forbidden reply fifo filename: %.*s\n",
350
+				srpath->len, srpath->s);
351
+		return 0;
352
+	}
353
+
354
+	if (jsonrpc_reply_fifo_len + srpath->len + 1 > JSONRPC_MAX_FILENAME) {
355
+		LM_ERR("Reply fifo filename too long %d\n",
356
+				jsonrpc_reply_fifo_len + srpath->len);
357
+		return 0;
358
+	}
359
+
360
+	memcpy(jsonrpc_reply_fifo_s + jsonrpc_reply_fifo_len, srpath->s, srpath->len);
361
+	jsonrpc_reply_fifo_s[jsonrpc_reply_fifo_len + srpath->len]=0;
362
+
363
+
364
+tryagain:
365
+	/* open non-blocking to make sure that a broken client will not
366
+	 * block the FIFO server forever */
367
+	fifofd=open( jsonrpc_reply_fifo_s, O_WRONLY | O_NONBLOCK );
368
+	if (fifofd==-1) {
369
+		/* retry several times if client is not yet ready for getting
370
+		   feedback via a reply pipe
371
+		*/
372
+		if (errno==ENXIO) {
373
+			/* give up on the client - we can't afford server blocking */
374
+			if (retries==0) {
375
+				LM_ERR("no client at %s\n", jsonrpc_reply_fifo_s );
376
+				return 0;
377
+			}
378
+			/* don't be noisy on the very first try */
379
+			if (retries != JSONRPC_REPLY_RETRIES)
380
+				LM_DBG("mi_fifo retry countdown: %d\n", retries );
381
+			sleep_us( 80000 );
382
+			retries--;
383
+			goto tryagain;
384
+		}
385
+		/* some other opening error */
386
+		LM_ERR("open error (%s): %s\n", jsonrpc_reply_fifo_s, strerror(errno));
387
+		return 0;
388
+	}
389
+
390
+	/* security checks: is this really a fifo?, is
391
+	 * it hardlinked? is it a soft link? */
392
+	if (jsonrpc_fifo_check(fifofd, jsonrpc_reply_fifo_s)<0)
393
+		goto error;
394
+
395
+	/* we want server blocking for big writes */
396
+	if ( (flags=fcntl(fifofd, F_GETFL, 0))<0) {
397
+		LM_ERR("pipe (%s): getfl failed: %s\n", jsonrpc_reply_fifo_s, strerror(errno));
398
+		goto error;
399
+	}
400
+	flags&=~O_NONBLOCK;
401
+	if (fcntl(fifofd, F_SETFL, flags)<0) {
402
+		LM_ERR("pipe (%s): setfl cntl failed: %s\n", jsonrpc_reply_fifo_s, strerror(errno));
403
+		goto error;
404
+	}
405
+
406
+	/* create an I/O stream */
407
+	file_handle=fdopen( fifofd, "w");
408
+	if (file_handle==NULL) {
409
+		LM_ERR("open error (%s): %s\n",
410
+			jsonrpc_reply_fifo_s, strerror(errno));
411
+		goto error;
412
+	}
413
+	return file_handle;
414
+error:
415
+	close(fifofd);
416
+	return 0;
417
+}
418
+
419
+#define JSONRPC_BUF_IN_SIZE	8192
420
+static void jsonrpc_fifo_server(FILE *fifo_stream)
421
+{
422
+	FILE *reply_stream;
423
+	char buf_in[JSONRPC_BUF_IN_SIZE];
424
+	char buf_rpath[128];
425
+	int lread;
426
+	str scmd;
427
+	str srpath;
428
+	int nw;
429
+	jsonrpc_plain_reply_t* jr = NULL;
430
+
431
+	while(1) {
432
+		/* update the local config framework structures */
433
+		cfg_update();
434
+
435
+		reply_stream = NULL;
436
+		lread = 0;
437
+		if(jsonrpc_read_stream(buf_in, JSONRPC_BUF_IN_SIZE,
438
+					fifo_stream, &lread)<0 || lread<=0) {
439
+			LM_DBG("failed to get the json document from fifo stream\n");
440
+			continue;
441
+		}
442
+		scmd.s = buf_in;
443
+		scmd.len = lread;
444
+		trim(&scmd);
445
+		LM_DBG("preparing to execute fifo jsonrpc [%.*s]\n", scmd.len, scmd.s);
446
+		srpath.s = buf_rpath;
447
+		srpath.len = 128;
448
+		if(jsonrpc_exec_ex(&scmd, &srpath)<0) {
449
+			LM_ERR("failed to execute the json document from fifo stream\n");
450
+			continue;
451
+		}
452
+
453
+		jr = jsonrpc_plain_reply_get();
454
+		LM_DBG("command executed - result: [%.*s] [%d] [%p] [%.*s]\n",
455
+				srpath.len, srpath.s,
456
+				jr->rcode, jr->rbody.s,
457
+				jr->rbody.len, jr->rbody.s);
458
+		if(srpath.len>0) {
459
+			reply_stream = jsonrpc_open_reply_fifo(&srpath);
460
+			if (reply_stream==NULL) {
461
+				LM_ERR("cannot open reply fifo: %.*s\n", srpath.len, srpath.s);
462
+				continue;
463
+			}
464
+			nw = fwrite(jr->rbody.s, 1, jr->rbody.len, reply_stream);
465
+			if(nw < jr->rbody.len) {
466
+				LM_ERR("failed to write the reply to fifo: %d out of %d\n",
467
+						nw, jr->rbody.len);
468
+			}
469
+			fclose(reply_stream);
470
+
471
+		}
472
+	}
473
+	return;
474
+}
475
+
476
+static void jsonrpc_fifo_process(int rank)
477
+{
478
+	FILE *fifo_stream;
479
+
480
+	LM_DBG("new process with pid = %d created\n",getpid());
481
+
482
+	fifo_stream = jsonrpc_init_fifo_server( jsonrpc_fifo, jsonrpc_fifo_mode,
483
+		jsonrpc_fifo_uid, jsonrpc_fifo_gid, jsonrpc_fifo_reply_dir);
484
+	if ( fifo_stream==NULL ) {
485
+		LM_CRIT("failed to init jsonrpc fifo server\n");
486
+		exit(-1);
487
+	}
488
+
489
+	jsonrpc_fifo_server( fifo_stream );
490
+
491
+	LM_CRIT("failed to run jsonrpc fifo server\n");
492
+	exit(-1);
493
+}
494
+
495
+/**
496
+ *
497
+ */
498
+int jsonrpc_fifo_mod_init(void)
499
+{
500
+	int len;
501
+	int sep;
502
+	char *p;
503
+
504
+	if(jsonrpc_fifo == NULL || *jsonrpc_fifo==0) {
505
+		LM_ERR("no fifo file path provided\n");
506
+		return -1;
507
+	}
508
+
509
+	if(*jsonrpc_fifo != '/') {
510
+		if(runtime_dir!=NULL && *runtime_dir!=0) {
511
+			len = strlen(runtime_dir);
512
+			sep = 0;
513
+			if(runtime_dir[len-1]!='/') {
514
+				sep = 1;
515
+			}
516
+			len += sep + strlen(jsonrpc_fifo);
517
+			p = pkg_malloc(len + 1);
518
+			if(p==NULL) {
519
+				LM_ERR("no more pkg\n");
520
+				return -1;
521
+			}
522
+			strcpy(p, runtime_dir);
523
+			if(sep) strcat(p, "/");
524
+			strcat(p, jsonrpc_fifo);
525
+			jsonrpc_fifo = p;
526
+			LM_DBG("fifo path is [%s]\n", jsonrpc_fifo);
527
+		}
528
+	}
529
+
530
+	if(jsonrpc_init_fifo_file()<0) {
531
+		LM_ERR("cannot initialize fifo transport\n");
532
+		return -1;
533
+	}
534
+
535
+	return 0;
536
+}
537
+
538
+/**
539
+ *
540
+ */
541
+int jsonrpc_fifo_child_init(int rank)
542
+{
543
+	int pid;
544
+
545
+	if(jsonrpc_fifo == NULL) {
546
+		LM_ERR("invalid fifo file path\n");
547
+	}
548
+
549
+	pid=fork_process(PROC_NOCHLDINIT, "JSONRPC-S FIFO", 1);
550
+	if (pid<0) {
551
+		return -1; /* error */
552
+	}
553
+
554
+	if(pid==0) {
555
+		/* child */
556
+
557
+		/* initialize the config framework */
558
+		if (cfg_child_init())
559
+			return -1;
560
+
561
+		jsonrpc_fifo_process(1);
562
+	}
563
+
564
+	return 0;
565
+}
566
+
567
+/**
568
+ *
569
+ */
570
+int jsonrpc_fifo_destroy(void)
571
+{
572
+	int n;
573
+	struct stat filestat;
574
+
575
+	if(jsonrpc_fifo==NULL) {
576
+		return 0;
577
+	}
578
+
579
+	/* destroying the fifo file */
580
+	n=stat(jsonrpc_fifo, &filestat);
581
+	if (n==0){
582
+		/* FIFO exist, delete it (safer) if not config check */
583
+		if(config_check==0) {
584
+			if (unlink(jsonrpc_fifo)<0){
585
+				LM_ERR("cannot delete the fifo (%s): %s\n",
586
+					jsonrpc_fifo, strerror(errno));
587
+				goto error;
588
+			}
589
+		}
590
+	} else if (n<0 && errno!=ENOENT) {
591
+		LM_ERR("FIFO stat failed: %s\n", strerror(errno));
592
+		goto error;
593
+	}
594
+
595
+	return 0;
596
+
597
+error:
598
+	return -1;
599
+}
600
+