Browse code

bignag change -- lot of things primarily added in relationship with refurbushing TM; see [sr] archive (2002-08-14) -- "ser update" and "TM update" for a long list of details

Jiri Kuthan authored on 15/08/2002 08:13:29
Showing 103 changed files
... ...
@@ -1,3 +1,29 @@
1
+-------------------------------------------------------------------------
2
+IMPORTANT NOTES
3
+
4
+1) The GPL applies to this copy of SIP Express Router software (ser).
5
+   For a license to use the ser software under conditions
6
+   other than those described here, or to purchase support for this
7
+   software, please contact iptel.org by e-mail at the following addresses:
8
+
9
+    info@iptel.org
10
+
11
+   (see http://www.gnu.org/copyleft/gpl-faq.html#TOCHeardOtherLicense
12
+    for an explanation how parallel licenses comply with GPL)
13
+
14
+2) ser software allows programmers to plug-in external modules to the
15
+   core part. Note that GPL mandates all plug-ins developed for the
16
+   ser software released under GPL license to be GPL-ed as well.
17
+
18
+   (see http://www.gnu.org/copyleft/gpl-faq.html#GPLAndPlugins
19
+    for a detailed explanation)
20
+
21
+3) Note that the GPL bellow is copyrighted by the Free Software Foundation,
22
+   but the ser software is copyrighted by iptel.org.
23
+
24
+
25
+-------------------------------------------------------------------------
26
+
1 27
 		    GNU GENERAL PUBLIC LICENSE
2 28
 		       Version 2, June 1991
3 29
 
... ...
@@ -10,7 +10,7 @@ auto_gen=lex.yy.c cfg.tab.c   #lexx, yacc etc
10 10
 #include  source related defs
11 11
 include Makefile.sources
12 12
 
13
-exclude_modules=CVS mysql pike
13
+exclude_modules=CVS mysql pike 
14 14
 static_modules=
15 15
 static_modules_path=$(addprefix modules/, $(static_modules))
16 16
 extra_sources=$(wildcard $(addsuffix /*.c, $(static_modules_path)))
... ...
@@ -76,9 +76,6 @@ INSTALL-MAN = $(INSTALL) -m 644
76 76
 #		issues additional debugging information if lock/unlock is called
77 77
 # -DFAST_LOCK
78 78
 #		uses fast arhitecture specific locking (see the arh. specific section)
79
-# -DNOISY_REPLIES
80
-#		turns on appending User-agent and Content-length:0 to ser-generated
81
-#		replies; 
82 79
 # -DBUSY_WAIT
83 80
 #		uses busy waiting on the lock
84 81
 # -DADAPTIVE_WAIT
... ...
@@ -90,37 +87,29 @@ INSTALL-MAN = $(INSTALL) -m 644
90 87
 # -DNOSMP
91 88
 #		don't use smp compliant locking (faster but won't work on SMP machines)
92 89
 #		(not yet enabled)
93
-# -DWAIT
94
-#		protection against race condiditions; turn off only for debugging;
95
-#       to become non-optional if stable
96
-#
97
-# -SILENT_FR
98
-#		if defined, when FR timer hits (in tm) cancel is sent only if forking
99
-#		if used; otherwise, just delete the transaction without doing anything
90
+# -DNO_PINGTEL_TAG_HACK
91
+#		if enabled, To-header-field will be less liberal and will not accept
92
+#		'tag=' (tag parameter with equal sign and without value); it is called
93
+#		this way because such message was sighted from a Pingtel phone
100 94
 
101 95
 DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
102 96
 	 -DOS='"$(OS)"' -DCOMPILER='"$(CC_VER)"'\
103 97
 	 -DPKG_MALLOC \
104 98
 	 -DSHM_MEM  -DSHM_MMAP \
105 99
 	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
106
-	 -DWAIT \
107
-	 -DSILENT_FR \
108
-	 -DNOISY_REPLIES -DVERY_NOISY_REPLIES\
109
-	 -DPINGTEL_TAG_HACK\
110
-	 -DF_MALLOC \
111
- 	 -DUSE_SYNONIM\
112 100
 	 -DUSE_IPV6 \
101
+	 -DEXTRA_DEBUG \
102
+	 -DVQ_MALLOC  -DDBG_QM_MALLOC \
103
+	 #-DCONTACT_BUG
104
+	 #-DF_MALLOC \
105
+	 #-DDBG_LOCK
113 106
 	 #-DNO_DEBUG \
114 107
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
115 108
 	 #-DNOSMP \
116 109
 	 #-DEXTRA_DEBUG 
117
-	 #-DVQ_MALLOC  -DDBG_LOCK  #-DSTATS
118
-	 #-DDBG_QM_MALLOC 
119
-# -DUSE_SHM_MEM
120
-#-DSTATS 
121
-#-DNO_LOG
122
-
123
-
110
+	 #-DUSE_SHM_MEM
111
+	 #-DSTATS 
112
+	 #-DNO_LOG
124 113
 
125 114
 #PROFILE=  -pg #set this if you want profiling
126 115
 #mode = debug
... ...
@@ -3,33 +3,59 @@
3 3
 List of currently available ser modules
4 4
 ----------------------------------------------------------
5 5
 Name	Use		 	 Maturity	Purpose/Depends on
6
+(owner)
6 7
 ----------------------------------------------------------
7 8
 acc		regular		 stable		transaction accounting
8
-		/example				(the module servers also
9
+(jku)	/example				(the module servers also
9 10
 							    as example of how to bind
10 11
 								to transaction management)
11 12
 								-tm
13
+
12 14
 auth	regular		 stable		digest authentication
13
-								-sl
15
+(jja)							-sl
14 16
 								-mysql
17
+
15 18
 cpl		experimental alpha		Call Processing Language
19
+(bia)
20
+
16 21
 ext		experimental alpha		Execution of external URI
17
-								processing logic
22
+(bia)							processing logic
23
+
18 24
 im		temporary	 alpha		Stateless instant messaging	
19
-								client
25
+(bia)							client
26
+
20 27
 jabber	experimental beta		SIP2Jabber gateway
28
+(dcm)
29
+
21 30
 maxfwd	regular		 stable		Max-Forwards check
31
+(bia)
32
+
22 33
 mysql	regular		 stable		supporting MySql interface
34
+(jja)
35
+
23 36
 pike	experimental alpha		excessive load detection
37
+(bia)
38
+
24 39
 print	example		 stable		Printing Message to stdout
40
+(ape)
41
+
25 42
 rr		regular		 stable		Record-Routing
43
+(jja)
44
+
26 45
 sl		regular		 stable		Stateless Replies
46
+(bia)
47
+
27 48
 sms		regular		 stable		SMS gateway
28
-								-tm
49
+(bia)								-tm
50
+
29 51
 textops regular		 stable		Message Textual Operations
52
+(ape)
53
+
30 54
 tm		regular		 beta		Transaction Management
55
+(ape)
56
+
31 57
 usrloc	regular		 stable		User Location
32
-								-sl
58
+(jja)								-sl
33 59
 								-mysql (optionally)
34 60
 
35 61
 
... ...
@@ -44,3 +70,8 @@ ser programmers.
44 70
 Maturity is label as stable if a module has been deployed
45 71
 for longer time, alpha if it is still being developed and
46 72
 beta if it is under test.
73
+
74
+Modules underway include presence server functionality,
75
+firewall control, message store and more. If you are
76
+interested in any of these or other modules, write us
77
+to info@iptel.org.
... ...
@@ -16,16 +16,16 @@ x (different way) add request header bitmap field for the modules
16 16
 
17 17
 
18 18
 High priority:
19
-- fix/replace T_REF/T_UNREF
20
-- review all the tm locking
19
+x fix/replace T_REF/T_UNREF
20
+x review all the tm locking
21 21
 x if () {} else {}
22 22
 x plugin interface
23 23
 x ipv6 support
24
-- reply ("response line")
25
-- drop ACKs for our replies
24
+x reply ("response line")
25
+x drop ACKs for our replies
26 26
 - icmp error handling
27
-- add To-tag (for the replies)
28
-- add User-Agent (for the replies)
27
+x add To-tag (for the replies)
28
+x add User-Agent (for the replies)
29 29
 
30 30
 Low priority:
31 31
 x fix via address someday
... ...
@@ -38,7 +38,7 @@ x forward to received= if present
38 38
 - exec improvments (add format strings to it)
39 39
 - command line switch for checking the config file syntax
40 40
 - config file version (a la sendmail)
41
-- loop detection
41
+0 loop detection
42 42
 - cfg. file reload
43 43
 - flags for using names or ip adresses in Via ?
44 44
 
... ...
@@ -55,6 +55,6 @@ x the same for rpm
55 55
 - the same for FreeBSD and Slackware
56 56
 
57 57
 
58
-- jku: branch hash computation over canonical values
59
-- jku: loop checking
58
+x jku: branch hash computation over canonical values
59
+0 jku: loop checking
60 60
 - jku: try CRC as opposed to MD5
... ...
@@ -17,6 +17,7 @@
17 17
 #include "sr_module.h"
18 18
 #include "mem/mem.h"
19 19
 #include "globals.h"
20
+#include "dset.h"
20 21
 
21 22
 #include <sys/types.h>
22 23
 #include <sys/socket.h>
... ...
@@ -179,6 +180,18 @@ int do_action(struct action* a, struct sip_msg* msg)
179 180
 			ret=1;
180 181
 			break;
181 182
 
183
+		/* jku -- introduce a new branch */
184
+		case APPEND_BRANCH_T:
185
+			if ((a->p1_type!=STRING_ST)) {
186
+				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
187
+					a->p1_type );
188
+				ret=E_BUG;
189
+				break;
190
+			}
191
+			ret=append_branch( msg, a->p1.string, 
192
+				a->p1.string ? strlen(a->p1.string):0 );
193
+			break;
194
+
182 195
 		/* jku begin: is_length_greater_than */
183 196
 		case LEN_GT_T:
184 197
 			if (a->p1_type!=NUMBER_ST) {
... ...
@@ -281,6 +294,14 @@ int do_action(struct action* a, struct sip_msg* msg)
281 294
 			}
282 295
 			ret=1;
283 296
 			break;
297
+		case REVERT_URI_T:
298
+			if (msg->new_uri.s) {
299
+				pkg_free(msg->new_uri.s);
300
+				msg->new_uri.len=0;
301
+				msg->new_uri.s=0;
302
+			};
303
+			ret=1;
304
+			break;
284 305
 		case SET_HOST_T:
285 306
 		case SET_HOSTPORT_T:
286 307
 		case SET_USER_T:
... ...
@@ -46,6 +46,7 @@ SEND	send
46 46
 LOG		log
47 47
 ERROR	error
48 48
 ROUTE	route
49
+REPLY_ROUTE reply_route
49 50
 EXEC	exec
50 51
 SETFLAG		setflag
51 52
 RESETFLAG	resetflag
... ...
@@ -57,8 +58,10 @@ SET_USER		"rewriteuser"|"setuser"|"setu"
57 58
 SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
58 59
 SET_PORT		"rewriteport"|"setport"|"setp"
59 60
 SET_URI			"rewriteuri"|"seturi"
61
+REVERT_URI		"revert_uri"
60 62
 PREFIX			"prefix"
61 63
 STRIP			"strip"
64
+APPEND_BRANCH	"append_branch"
62 65
 IF				"if"
63 66
 ELSE			"else"
64 67
 
... ...
@@ -94,7 +97,12 @@ STAT	statistics
94 97
 MAXBUFFER maxbuffer
95 98
 CHILDREN children
96 99
 CHECK_VIA	check_via
97
-LOOP_CHECKS	loop_checks
100
+SYN_BRANCH syn_branch
101
+SIP_WARNING sip_warning
102
+FIFO fifo
103
+FIFO_MODE fifo_mode
104
+SERVER_SIGNATURE server_signature
105
+REPLY_TO_VIA reply_to_via
98 106
 
99 107
 LOADMODULE	loadmodule
100 108
 MODPARAM        modparam
... ...
@@ -148,6 +156,7 @@ EAT_ABLE	[\ \t\b\r]
148 156
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
149 157
 <INITIAL>{LEN_GT}	{ count(); yylval.strval=yytext; return LEN_GT; }
150 158
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
159
+<INITIAL>{REPLY_ROUTE}	{ count(); yylval.strval=yytext; return REPLY_ROUTE; }
151 160
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
152 161
 <INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
153 162
 <INITIAL>{SET_HOSTPORT}	{ count(); yylval.strval=yytext; return SET_HOSTPORT; }
... ...
@@ -155,8 +164,10 @@ EAT_ABLE	[\ \t\b\r]
155 164
 <INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
156 165
 <INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
157 166
 <INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
167
+<INITIAL>{REVERT_URI}	{ count(); yylval.strval=yytext; return REVERT_URI; }
158 168
 <INITIAL>{PREFIX}	{ count(); yylval.strval=yytext; return PREFIX; }
159 169
 <INITIAL>{STRIP}	{ count(); yylval.strval=yytext; return STRIP; }
170
+<INITIAL>{APPEND_BRANCH}	{ count(); yylval.strval=yytext; return APPEND_BRANCH; }
160 171
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
161 172
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
162 173
 
... ...
@@ -181,7 +192,12 @@ EAT_ABLE	[\ \t\b\r]
181 192
 <INITIAL>{MAXBUFFER}	{ count(); yylval.strval=yytext; return MAXBUFFER; }
182 193
 <INITIAL>{CHILDREN}	{ count(); yylval.strval=yytext; return CHILDREN; }
183 194
 <INITIAL>{CHECK_VIA}	{ count(); yylval.strval=yytext; return CHECK_VIA; }
184
-<INITIAL>{LOOP_CHECKS}	{ count(); yylval.strval=yytext; return LOOP_CHECKS; }
195
+<INITIAL>{SYN_BRANCH}	{ count(); yylval.strval=yytext; return SYN_BRANCH; }
196
+<INITIAL>{SIP_WARNING}	{ count(); yylval.strval=yytext; return SIP_WARNING; }
197
+<INITIAL>{FIFO}	{ count(); yylval.strval=yytext; return FIFO; }
198
+<INITIAL>{FIFO_MODE}	{ count(); yylval.strval=yytext; return FIFO_MODE; }
199
+<INITIAL>{SERVER_SIGNATURE}	{ count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
200
+<INITIAL>{REPLY_TO_VIA}	{ count(); yylval.strval=yytext; return REPLY_TO_VIA; }
185 201
 <INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
186 202
 <INITIAL>{MODPARAM}     { count(); yylval.strval=yytext; return MODPARAM; }
187 203
 
... ...
@@ -56,15 +56,18 @@ void* f_tmp;
56 56
 %token LOG_TOK
57 57
 %token ERROR
58 58
 %token ROUTE
59
+%token REPLY_ROUTE
59 60
 %token EXEC
60 61
 %token SET_HOST
61 62
 %token SET_HOSTPORT
62 63
 %token PREFIX
63 64
 %token STRIP
65
+%token APPEND_BRANCH
64 66
 %token SET_USER
65 67
 %token SET_USERPASS
66 68
 %token SET_PORT
67 69
 %token SET_URI
70
+%token REVERT_URI
68 71
 %token IF
69 72
 %token ELSE
70 73
 %token URIHOST
... ...
@@ -90,7 +93,12 @@ void* f_tmp;
90 93
 %token STAT
91 94
 %token CHILDREN
92 95
 %token CHECK_VIA
93
-%token LOOP_CHECKS
96
+%token SYN_BRANCH
97
+%token SIP_WARNING
98
+%token FIFO
99
+%token FIFO_MODE
100
+%token SERVER_SIGNATURE
101
+%token REPLY_TO_VIA
94 102
 %token LOADMODULE
95 103
 %token MODPARAM
96 104
 %token MAXBUFFER
... ...
@@ -151,6 +159,7 @@ statements:	statements statement {}
151 159
 statement:	assign_stm 
152 160
 		| module_stm
153 161
 		| route_stm 
162
+		| reply_route_stm
154 163
 		| CR	/* null statement*/
155 164
 	;
156 165
 
... ...
@@ -180,8 +189,18 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
180 189
 		| CHILDREN EQUAL error { yyerror("number expected"); } 
181 190
 		| CHECK_VIA EQUAL NUMBER { check_via=$3; }
182 191
 		| CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
183
-		| LOOP_CHECKS EQUAL NUMBER { loop_checks=$3; }
184
-		| LOOP_CHECKS EQUAL error { yyerror("boolean value expected"); }
192
+		| SYN_BRANCH EQUAL NUMBER { syn_branch=$3; }
193
+		| SYN_BRANCH EQUAL error { yyerror("boolean value expected"); }
194
+		| SIP_WARNING EQUAL NUMBER { sip_warning=$3; }
195
+		| SIP_WARNING EQUAL error { yyerror("boolean value expected"); }
196
+		| FIFO EQUAL STRING { fifo=$3; }
197
+		| FIFO EQUAL error { yyerror("string value expected"); }
198
+		| FIFO_MODE EQUAL NUMBER { fifo_mode=$3; }
199
+		| FIFO_MODE EQUAL NUMBER { yyerror("int value expected"); }
200
+		| SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
201
+		| SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
202
+		| REPLY_TO_VIA EQUAL NUMBER { reply_to_via=$3; }
203
+		| REPLY_TO_VIA EQUAL error { yyerror("boolean value expected"); }
185 204
 		| LISTEN EQUAL ip  {
186 205
 								if (sock_no< MAX_LISTEN){
187 206
 									tmp=ip_addr2a($3);
... ...
@@ -347,6 +366,17 @@ route_stm:	ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
347 366
 										}
348 367
 		| ROUTE error { yyerror("invalid  route  statement"); }
349 368
 	;
369
+
370
+reply_route_stm: REPLY_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
371
+										if (($3<REPLY_RT_NO)&&($3>=1)){
372
+											push($6, &reply_rlist[$3]);
373
+										} else {
374
+											yyerror("invalid reply routing"
375
+												"table number");
376
+											YYABORT; }
377
+										}
378
+		| REPLY_ROUTE error { yyerror("invalid reply_route statement"); }
379
+	;
350 380
 /*
351 381
 rules:	rules rule { push($2, &$1); $$=$1; }
352 382
 	| rule {$$=$1; }
... ...
@@ -685,6 +715,12 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
685 715
 		| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
686 716
 														"number expected"); }
687 717
 
718
+		| APPEND_BRANCH LPAREN STRING RPAREN { $$=mk_action( APPEND_BRANCH_T,
719
+													STRING_ST, 0, $3, 0) ; }
720
+		| APPEND_BRANCH LPAREN RPAREN { $$=mk_action( APPEND_BRANCH_T,
721
+													STRING_ST, 0, 0, 0 ) ; }
722
+		| APPEND_BRANCH {  $$=mk_action( APPEND_BRANCH_T, STRING_ST, 0, 0, 0 ) ; }
723
+
688 724
 		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
689 725
 														STRING_ST, 0, $3, 0); }
690 726
 		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
... ...
@@ -710,6 +746,8 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
710 746
 		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
711 747
 		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
712 748
 										"string expected"); }
749
+		| REVERT_URI LPAREN RPAREN { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
750
+		| REVERT_URI { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
713 751
 		| ID LPAREN RPAREN			{ f_tmp=(void*)find_export($1, 0);
714 752
 									   if (f_tmp==0){
715 753
 										yyerror("unknown command, missing"
... ...
@@ -22,6 +22,7 @@
22 22
 #define CHILD_NO    8
23 23
 
24 24
 #define RT_NO 10 /* routing tables number */
25
+#define REPLY_RT_NO 10 /* reply routing tables number */
25 26
 #define DEFAULT_RT 0 /* default routing table */
26 27
 
27 28
 #define MAX_REC_LEV 100 /* maximum number of recursive calls */
... ...
@@ -46,8 +47,8 @@
46 47
 
47 48
 #define MAX_WARNING_LEN  256
48 49
 		
49
-#define MY_BRANCH ";branch=0"
50
-#define MY_BRANCH_LEN 9
50
+#define MY_BRANCH ";branch="
51
+#define MY_BRANCH_LEN 8
51 52
 
52 53
 
53 54
 #define MAX_PORT_LEN 7 /* ':' + max 5 letters + \0 */
... ...
@@ -88,8 +89,16 @@
88 89
 #define MAX_VIA_LINE_SIZE	240
89 90
 #define MAX_RECEIVED_SIZE	57
90 91
 
91
-/* maximum number of processes is constrained by capacity of
92
-   process bitmaps */
93
-#define MAX_PROCESSES (sizeof( process_bm_t) * 8 )
92
+/* maximum number of branches per transaction */
93
+#define MAX_BRANCHES    4
94 94
 
95
+/* maximum length of a FIFO server command */
96
+#define MAX_FIFO_COMMAND 512
97
+
98
+/* buffer dimensions for FIFO server */
99
+#define MAX_CONSUME_BUFFER 1024
100
+/* where reply pipes may be opened */
101
+#define FIFO_DIR "/tmp/"
102
+/* max length of the text of fifo 'print' command */
103
+#define MAX_PRINT_TEXT 256
95 104
 #endif
96 105
new file mode 100644
... ...
@@ -0,0 +1,87 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * destination set
5
+ */
6
+
7
+#include <string.h>
8
+
9
+#include "dprint.h"
10
+#include "config.h"
11
+#include "parser/parser_f.h"
12
+#include "parser/msg_parser.h"
13
+#include "ut.h"
14
+#include "hash_func.h"
15
+#include "dset.h"
16
+
17
+
18
+
19
+/* where we store URIs of additional transaction branches
20
+  (-1 because of the default branch, #0)
21
+*/
22
+static struct branch branches[ MAX_BRANCHES - 1 ];
23
+/* how many of them we have */
24
+static unsigned int nr_branches=0;
25
+/* branch iterator */
26
+static int branch_iterator=0;
27
+
28
+void init_branch_iterator(void)
29
+{
30
+	branch_iterator=0;
31
+}
32
+
33
+char *next_branch( int *len )
34
+{
35
+	unsigned int i;
36
+
37
+	i=branch_iterator;
38
+	if (i<nr_branches) {
39
+		branch_iterator++;
40
+		*len=branches[i].len;
41
+		return branches[i].uri;
42
+	} else {
43
+		*len=0;
44
+		return 0;
45
+	}
46
+}
47
+
48
+void clear_branches()
49
+{
50
+	nr_branches=0;
51
+}
52
+
53
+/* add a new branch to current transaction */
54
+int append_branch( struct sip_msg *msg, char *uri, int uri_len )
55
+{
56
+	/* if we have already set up the maximum number
57
+	   of branches, don't try new ones */
58
+	if (nr_branches==MAX_BRANCHES-1) {
59
+		LOG(L_ERR, "ERROR: append_branch: max nr of branches exceeded\n");
60
+		return -1;
61
+	}
62
+
63
+	if (uri_len>MAX_URI_SIZE-1) {
64
+		LOG(L_ERR, "ERROR: append_branch: too long uri: %.*s\n",
65
+			uri_len, uri );
66
+		return -1;
67
+	}
68
+
69
+	/* if not parameterized, take current uri */
70
+	if (uri==0) {
71
+		if (msg->new_uri.s) { 
72
+			uri=msg->new_uri.s;
73
+			uri_len=msg->new_uri.len;
74
+		} else {
75
+			uri=msg->first_line.u.request.uri.s;
76
+			uri_len=msg->first_line.u.request.uri.len;
77
+		}
78
+	}
79
+	
80
+	memcpy( branches[nr_branches].uri, uri, uri_len );
81
+	/* be safe -- add zero termination */
82
+	branches[nr_branches].uri[uri_len]=0;
83
+	branches[nr_branches].len=uri_len;
84
+	
85
+	nr_branches++;
86
+	return 1;
87
+}
0 88
new file mode 100644
... ...
@@ -0,0 +1,29 @@
1
+/*
2
+ * $Id$
3
+ */
4
+
5
+#ifndef _T_FORKS_H
6
+#define _T_FORKS_H
7
+
8
+#include "config.h"
9
+
10
+struct branch
11
+{
12
+	char uri[MAX_URI_SIZE];
13
+	unsigned int len;
14
+};
15
+
16
+struct sip_msg;
17
+
18
+/*
19
+typedef int (*tfork_f)( struct sip_msg *msg, char *uri, int uri_len );
20
+*/
21
+
22
+/* add a new branch to current transaction */
23
+int append_branch( struct sip_msg *msg, char *uri, int uri_len );
24
+/* iterate through list of new transaction branches */
25
+void init_branch_iterator();
26
+char *next_branch( int *len );
27
+void clear_branches();
28
+
29
+#endif
... ...
@@ -5,6 +5,9 @@
5 5
 
6 6
 #include <stdio.h>
7 7
 #include "error.h"
8
+#include "str.h"
9
+#include "parser/msg_parser.h"
10
+#include "mem/mem.h"
8 11
 
9 12
 /* current function's error; */
10 13
 int ser_error=-1;
... ...
@@ -43,6 +46,10 @@ int err2reason_phrase(
43 46
 			error_txt="Regretfuly, we were not able to process the URI";
44 47
 			*sip_error=-ser_error;
45 48
 			break;
49
+		case E_BAD_TUPEL:
50
+			error_txt="Transaction tupel incomplete";
51
+			*sip_error=-E_BAD_REQ;
52
+			break;
46 53
 		default:
47 54
 			error_txt="I'm terribly sorry, server error occured";
48 55
 			*sip_error=500;
... ...
@@ -51,3 +58,104 @@ int err2reason_phrase(
51 58
 	return snprintf( phrase, etl, "%s (%d/%s)", error_txt, 
52 59
 		-ser_error, signature );
53 60
 }
61
+
62
+char *error_text( int code )
63
+{
64
+	switch(code) {
65
+
66
+		case 100: return "Trying";
67
+		case 180: return "Ringing";
68
+		case 181: return "Call is Being Forwarded";
69
+		case 182: return "Queued";
70
+		case 183: return "Session Progress";
71
+
72
+		case 200: return "OK";
73
+
74
+		case 300: return "Multiple Choices";
75
+		case 301: return "Moved Permanently";
76
+		case 302: return "Moved Temporarily";
77
+		case 305: return "Use Proxy";
78
+		case 380: return "Alternative Service";
79
+
80
+		case 400: return "Bad Request";
81
+		case 401: return "Unauthorized";
82
+		case 402: return "Payement Required";
83
+		case 403: return "Forbidden";
84
+		case 404: return "Not Found";
85
+		case 405: return "Method not Allowed";
86
+		case 406: return "Not Acceptable";
87
+		case 407: return "Proxy authentication Required";
88
+		case 408: return "Request Timeout";
89
+		case 410: return "Gone";
90
+		case 413: return "Request Entity Too Large";
91
+		case 414: return "Request-URI Too Long";
92
+		case 415: return "Unsupported Media Type";
93
+		case 416: return "Unsupported URI Scheme";
94
+		case 417: return "Bad Extension";
95
+		case 421: return "Extension Required";
96
+		case 423: return "Interval Too Brief";
97
+		case 480: return "Temporarily Unavailable";
98
+		case 481: return "Call/Transaction Does not Exist";
99
+		case 482: return "Loop Detected";
100
+		case 483: return "Too Many Hops";
101
+		case 484: return "Address Incomplete";
102
+		case 485: return "Ambigous";
103
+		case 486: return "Busy Here";
104
+		case 487: return "Request Terminated";
105
+		case 488: return "Not Acceptable Here";
106
+		case 491: return "Request Pending";
107
+	
108
+		case 500: return "Server Internal Error";
109
+		case 501: return "Not Implemented";
110
+		case 502: return "Bad Gateway";
111
+		case 503: return "Service Unavailable";
112
+		case 504: return "Server Time-out";
113
+		case 505: return "Version not Supported";
114
+		case 513: return "Message Too Large";
115
+
116
+		case 600: return "Busy Everywhere";
117
+		case 603: return "Decline";
118
+		case 604: return "Does not Exist Anywhere";
119
+		case 606: return "Not Acceptable";
120
+
121
+	}
122
+
123
+	if (code>=600) return "Global Failure";
124
+	else if (code>=500) return "Server Failure";
125
+	else if (code>=400) return "Request Failure";
126
+	else if (code>=300) return "Redirection";
127
+	else if (code>=200) return "Successful";
128
+	else if (code>=100) return "Provisional";
129
+	else return "Unspecified";
130
+}
131
+
132
+void get_reply_status( str *status, struct sip_msg *reply, int code )
133
+{
134
+	str phrase;
135
+
136
+	status->s=0;
137
+
138
+	if (reply==0) {
139
+		LOG(L_CRIT, "BUG: get_reply_status called with 0 msg\n");
140
+		return;
141
+	}
142
+
143
+	if (reply==FAKED_REPLY) {
144
+		phrase.s=error_text(code);
145
+		phrase.len=strlen(phrase.s);
146
+	} else {
147
+		phrase=reply->first_line.u.reply.reason;
148
+	}
149
+	status->len=phrase.len+3/*code*/+1/*space*/+1/*ZT*/;
150
+	status->s=pkg_malloc(status->len);
151
+	if (!status->s) {
152
+		LOG(L_ERR, "ERROR: get_reply_status: no mem\n");
153
+		return;
154
+	}
155
+	status->s[3]=' ';
156
+	status->s[2]='0'+code % 10; code=code/10;
157
+	status->s[1]='0'+code% 10; code=code/10;
158
+	status->s[0]='0'+code % 10;
159
+	memcpy(&status->s[4], phrase.s, phrase.len);
160
+	status->s[status->len-1]=0;
161
+}
... ...
@@ -12,6 +12,12 @@
12 12
 #define E_BUG         -5
13 13
 #define E_CFG         -6
14 14
 #define E_NO_SOCKET		-7
15
+/* unresolveable topmost Via */
16
+#define E_BAD_VIA		-8
17
+/* incomplete transaction tupel */
18
+#define E_BAD_TUPEL		-9
19
+/* script programming error */
20
+#define E_SCRIPT		-10
15 21
 
16 22
 #define E_SEND		  -477
17 23
 /* unresolveable next-hop address */
... ...
@@ -23,12 +29,22 @@
23 29
 
24 30
 #define MAX_REASON_LEN	128
25 31
 
32
+#include "str.h"
33
+
26 34
 /* processing status of the last command */
27 35
 extern int ser_error;
28 36
 extern int prev_ser_error;
29 37
 
38
+struct sip_msg;
39
+
40
+/* ser error -> SIP error */
30 41
 int err2reason_phrase( int ser_error, int *sip_error, 
31 42
                 char *phrase, int etl, char *signature );
32 43
 
44
+/* SIP error core -> SIP text */
45
+char *error_text( int code );
46
+
47
+/* return pkg_malloc-ed reply status in status->s */
48
+void get_reply_status( str *status, struct sip_msg *reply, int code );
33 49
 
34 50
 #endif
... ...
@@ -614,5 +614,6 @@ route[3] {
614 614
 		sl_reply_error(); 
615 615
 		break; 
616 616
 	};
617
+
617 618
 }
618 619
 
619 620
new file mode 100644
... ...
@@ -0,0 +1,344 @@
1
+/*
2
+ * $Id$
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
9
+ */
10
+
11
+#include <stdlib.h>
12
+#include <sys/types.h>
13
+#include <unistd.h>
14
+#include <stdio.h>
15
+#include <errno.h>
16
+#include <sys/types.h>
17
+#include <sys/stat.h>
18
+#include <fcntl.h>
19
+#include <signal.h>
20
+#include <string.h>
21
+#include "dprint.h"
22
+#include "ut.h"
23
+#include "error.h"
24
+#include "config.h"
25
+#include "globals.h"
26
+#include "fifo_server.h"
27
+#include "mem/mem.h"
28
+
29
+/* FIFO server vars */
30
+char *fifo=0; /* FIFO name */
31
+int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
32
+pid_t fifo_pid;
33
+/* file descriptors */
34
+static int fifo_read=0;
35
+static int fifo_write=0;
36
+static FILE *fifo_stream;
37
+
38
+/* list of fifo command */
39
+static struct fifo_command *cmd_list=0;
40
+
41
+static struct fifo_command *lookup_fifo_cmd( char *name )
42
+{
43
+	struct fifo_command *c;
44
+	for(c=cmd_list; c; c=c->next) {
45
+		if (strcasecmp(c->name, name)==0) return c;
46
+	}
47
+	return 0;
48
+}
49
+
50
+int register_fifo_cmd(fifo_cmd f, char *cmd_name, void *param)
51
+{
52
+	struct fifo_command *new_cmd;
53
+
54
+	if (lookup_fifo_cmd(cmd_name)) {
55
+		LOG(L_ERR, "ERROR: register_fifo_cmd: attempt to register synonyms\n");
56
+		return E_BUG;
57
+	}
58
+	new_cmd=malloc(sizeof(struct fifo_command));
59
+	if (new_cmd==0) {
60
+		LOG(L_ERR, "ERROR: register_fifo_cmd: out of mem\n");
61
+		return E_OUT_OF_MEM;
62
+	}
63
+	new_cmd->f=f;
64
+	new_cmd->name=cmd_name;
65
+	new_cmd->param=param;
66
+
67
+	new_cmd->next=cmd_list;
68
+	cmd_list=new_cmd;
69
+
70
+	return 1;
71
+}
72
+
73
+
74
+int read_line( char *b, int max, FILE *stream, int *read )
75
+{
76
+	int len;
77
+	if (fgets(b, max, stream)==NULL) {
78
+		LOG(L_ERR, "ERROR: fifo_server fgets failed: %s\n",
79
+			strerror(errno));
80
+		kill(0, SIGTERM);
81
+	}
82
+	/* if we did not read whole line, our buffer is too small
83
+	   and we cannot process the request; consume the remainder of 
84
+	   request
85
+	*/
86
+	len=strlen(b);
87
+	if (len && !(b[len-1]=='\n' || b[len-1]=='\r')) {
88
+		LOG(L_ERR, "ERROR: read_line: request  line too long\n");
89
+		return 0;
90
+	}
91
+	/* trim from right */
92
+	while(len) {
93
+		if(b[len-1]=='\n' || b[len-1]=='\r'
94
+				|| b[len-1]==' ' || b[len-1]=='\t' ) {
95
+			len--;
96
+			b[len]=0;
97
+		} else break;
98
+	}
99
+	*read=len;
100
+	return 1;
101
+}
102
+
103
+static void consume_request( FILE *stream )
104
+{
105
+	int len;
106
+	char buffer[MAX_CONSUME_BUFFER];
107
+
108
+	while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
109
+
110
+#ifdef _OBSOLETED
111
+	int eol_count;
112
+
113
+	eol_count=0;
114
+
115
+	/* each request must be terminated by two EoLs */
116
+	while(eol_count!=2) {
117
+		/* read until EoL is encountered */
118
+		while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
119
+		eol_count=len==0?eol_count+1:1;
120
+	}
121
+#endif
122
+}
123
+
124
+int read_eol( FILE *stream )
125
+{
126
+	int len;
127
+	char buffer[MAX_CONSUME_BUFFER];
128
+	if (!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len) || len!=0) {
129
+		LOG(L_ERR, "ERROR: read_eol: EOL expected: %.10s...\n",
130
+			buffer );
131
+		return 0;
132
+	}
133
+	return 1;
134
+}
135
+	
136
+int read_line_set(char *buf, int max_len, FILE *fifo, int *len)
137
+{
138
+	int set_len;
139
+	char *c;
140
+	int line_len;
141
+
142
+	c=buf;set_len=0;
143
+	while(1) {
144
+		if (!read_line(c,max_len,fifo,&line_len)) {
145
+			LOG(L_ERR, "ERROR: fifo_server: line expected\n");
146
+			return 0;
147
+		}
148
+		/* end encountered ... return */
149
+		if (line_len==0) {
150
+			*len=set_len;
151
+			return 1;
152
+		}
153
+		max_len-=line_len; c+=line_len; set_len+=line_len;
154
+		if (max_len<CRLF_LEN) {
155
+			LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n");
156
+			return 0;
157
+		}
158
+		memcpy(c, CRLF, CRLF_LEN);
159
+		max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN;
160
+	}
161
+}
162
+
163
+static char *trim_filename( char * file )
164
+{
165
+	int prefix_len, fn_len;
166
+	char *new_fn;
167
+
168
+	/* we only allow files in "/tmp" -- any directory
169
+	   changes are not welcome
170
+	*/
171
+	if (strchr(file,'.') || strchr(file,'/')
172
+				|| strchr(file, '\\')) {
173
+		LOG(L_ERR, "ERROR: trim_filename: forbidden filename: %s\n"
174
+			, file);
175
+		return 0;
176
+	}
177
+	prefix_len=strlen(FIFO_DIR); fn_len=strlen(file);
178
+	new_fn=pkg_malloc(prefix_len+fn_len+1);
179
+	if (new_fn==0) {
180
+		LOG(L_ERR, "ERROR: trim_filename: no mem\n");
181
+		return 0;
182
+	}
183
+
184
+	memcpy(new_fn, FIFO_DIR, prefix_len);
185
+	memcpy(new_fn+prefix_len, file, fn_len );
186
+	new_fn[prefix_len+fn_len]=0;
187
+
188
+	return new_fn;
189
+}
190
+
191
+static void fifo_server(FILE *fifo_stream)
192
+{
193
+	char buf[MAX_FIFO_COMMAND];
194
+	int line_len;
195
+	char *file_sep, *command, *file;
196
+	struct fifo_command *f;
197
+
198
+	file_sep=command=file=0;
199
+
200
+	while(1) {
201
+
202
+		/* commands must look this way ':<command>:[filename]' */
203
+		if (!read_line(buf, MAX_FIFO_COMMAND, fifo_stream, &line_len)) {
204
+			/* line breaking must have failed -- consume the rest
205
+			   and proceed to a new request
206
+			*/
207
+			LOG(L_ERR, "ERROR: fifo_server: command expected\n");
208
+			goto consume;
209
+		}
210
+		if (line_len==0) {
211
+			LOG(L_ERR, "ERROR: fifo_server: command empty\n");
212
+			continue;
213
+		}
214
+		if (line_len<3) {
215
+			LOG(L_ERR, "ERROR: fifo_server: command must have at least 3 chars\n");
216
+			goto consume;
217
+		}
218
+		if (*buf!=CMD_SEPARATOR) {
219
+			LOG(L_ERR, "ERROR: fifo_server: command must start with %c\n", 
220
+				CMD_SEPARATOR);
221
+			goto consume;
222
+		}
223
+		command=buf+1;
224
+		file_sep=strchr(command, CMD_SEPARATOR );
225
+		if (file_sep==NULL) {
226
+			LOG(L_ERR, "ERROR: fifo_server: file separator missing\n");
227
+			goto consume;
228
+		}
229
+		if (file_sep==command) {
230
+			LOG(L_ERR, "ERROR: fifo_server: empty command\n");
231
+			goto consume;
232
+		}
233
+		if (*(file_sep+1)==0) file=NULL; 
234
+		else {
235
+			file=file_sep+1;
236
+			file=trim_filename(file);
237
+			if (file==0) {
238
+				LOG(L_ERR, "ERROR: fifo_server: trimming filename\n");
239
+				goto consume;
240
+			}
241
+		}
242
+		/* make command zero-terminated */
243
+		*file_sep=0;
244
+
245
+		f=lookup_fifo_cmd( command );
246
+		if (f==0) {
247
+			LOG(L_ERR, "ERROR: fifo_server: command %s is not available\n",
248
+				command);
249
+			goto consume;
250
+		}
251
+		if (f->f(fifo_stream, file)<0) {
252
+			LOG(L_ERR, "ERROR: fifo_server: command (%s) "
253
+				"processing failed\n", command );
254
+			goto consume;
255
+		}
256
+
257
+consume:
258
+		if (file) { pkg_free(file); file=0;}
259
+		consume_request(fifo_stream);
260
+	}
261
+}
262
+
263
+int open_fifo_server()
264
+{
265
+	if (fifo==NULL) {
266
+		DBG("TM: open_uac_fifo: no fifo will be opened\n");
267
+		/* everything is ok, we just do not want to start */
268
+		return 1;
269
+	}
270
+	DBG("TM: open_uac_fifo: opening fifo...\n");
271
+	if ((mkfifo(fifo, fifo_mode)<0) && (errno!=EEXIST)) {
272
+		LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: %s\n",
273
+			strerror(errno));
274
+		return -1;
275
+	}
276
+	process_no++;
277
+	fifo_pid=fork();
278
+	if (fifo_pid<0) {
279
+		LOG(L_ERR, "ERROR: open_fifo_server: failure to fork: %s\n",
280
+			strerror(errno));
281
+		return -1;
282
+	}
283
+	if (fifo_pid==0) { /* child == FIFO server */
284
+		LOG(L_INFO, "INFO: fifo process starting: %d\n", getpid());
285
+		fifo_read=open(fifo, O_RDONLY, 0);
286
+		if (fifo_read<0) {
287
+			LOG(L_ERR, "SER: open_uac_fifo: fifo_read did not open: %s\n",
288
+				strerror(errno));
289
+			return -1;
290
+		}
291
+		fifo_stream=fdopen(fifo_read, "r"	);
292
+		if (fifo_stream==NULL) {
293
+			LOG(L_ERR, "SER: open_uac_fifo: fdopen failed: %s\n",
294
+				strerror(errno));
295
+			return -1;
296
+		}
297
+		LOG(L_INFO, "SER: open_uac_fifo: fifo server up...\n");
298
+		fifo_server( fifo_stream ); /* never retruns */
299
+	}
300
+	/* dad process */
301
+	pids[process_no]=fifo_pid;
302
+	/* make sure the read fifo will not close */
303
+	fifo_write=open(fifo, O_WRONLY, 0);
304
+	if (fifo_write<0) {
305
+		LOG(L_ERR, "SER: open_uac_fifo: fifo_write did not open: %s\n",
306
+			strerror(errno));
307
+		return -1;
308
+	}
309
+	return 1;
310
+}
311
+
312
+/* diagnostic and hello-world FIFO command */
313
+int print_fifo_cmd( FILE *stream, char *response_file )
314
+{
315
+	char text[MAX_PRINT_TEXT];
316
+	int text_len;
317
+	int file;
318
+	
319
+	/* expect one line which will be printed out */
320
+	if (!read_line(text, MAX_PRINT_TEXT, stream, &text_len)) {
321
+		LOG(L_ERR, "ERROR: print_fifo_cmd: too big text\n");
322
+		return -1;
323
+	}
324
+	/* now the work begins */
325
+	if (response_file) {
326
+		file=open( response_file , O_WRONLY);
327
+		if (file<0) {
328
+			LOG(L_ERR, "ERROR: print_fifo_cmd: open error (%s): %s\n",
329
+				response_file, strerror(errno));
330
+			return -1;
331
+		}
332
+		if (write(file, text,text_len)<0) {
333
+			LOG(L_ERR, "ERROR: print_fifo_cmd: write error: %s\n",
334
+				 strerror(errno));
335
+			close(file);
336
+			return -1;
337
+		}
338
+		close(file);
339
+	} else {
340
+		LOG(L_INFO, "INFO: print_fifo_cmd: %.*s\n", 
341
+			text_len, text );
342
+	}
343
+	return 1;
344
+}
0 345
new file mode 100644
... ...
@@ -0,0 +1,34 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ */
5
+
6
+#ifndef _FIFO_SERVER_H
7
+#define _FIFO_SERVER_H
8
+
9
+#include <stdio.h>
10
+
11
+#define CMD_SEPARATOR ':'
12
+
13
+typedef int (fifo_cmd)( FILE *fifo_stream, char *response_file );
14
+
15
+struct fifo_command{
16
+	fifo_cmd *f;
17
+	struct fifo_command *next;
18
+	void *param;
19
+	char *name;
20
+};
21
+
22
+int register_fifo_cmd(fifo_cmd f, char *cmd_name, void *param);
23
+
24
+/* read a single EoL-terminated line from fifo */
25
+int read_line( char *b, int max, FILE *stream, int *read );
26
+/* consume EoL from fifo */
27
+int read_eol( FILE *stream );
28
+/* consume a set of EoL-terminated lines terminated by an additional EoL */
29
+int read_line_set(char *buf, int max_len, FILE *fifo, int *len);
30
+
31
+int open_fifo_server();
32
+
33
+int print_fifo_cmd( FILE *stream, char *response_file );
34
+#endif
... ...
@@ -16,12 +16,12 @@ int setflag( struct sip_msg* msg, flag_t flag ) {
16 16
 }
17 17
 
18 18
 int resetflag( struct sip_msg* msg, flag_t flag ) {
19
-	msg->flags &= ~ flag;
19
+	msg->flags &= ~ (1 << flag);
20 20
 	return 1;
21 21
 }
22 22
 
23 23
 int isflagset( struct sip_msg* msg, flag_t flag ) {
24
-	return msg->flags & (1<<flag) ? 1 : -1;
24
+	return (msg->flags & (1<<flag)) ? 1 : -1;
25 25
 }
26 26
 
27 27
 int flag_in_range( flag_t flag ) {
... ...
@@ -13,6 +13,7 @@
13 13
 #include <arpa/inet.h>
14 14
 
15 15
 #include "forward.h"
16
+#include "hash_func.h"
16 17
 #include "config.h"
17 18
 #include "parser/msg_parser.h"
18 19
 #include "route.h"
... ...
@@ -67,6 +68,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
67 68
 	char* buf;
68 69
 	union sockaddr_union* to;
69 70
 	struct socket_info* send_sock;
71
+	char md5[MD5_LEN];
70 72
 	
71 73
 	to=0;
72 74
 	buf=0;
... ...
@@ -98,13 +100,39 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
98 100
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
99 101
 				"no coresponding listening socket\n", to->s.sa_family);
100 102
 		ser_error=E_NO_SOCKET;
101
-		goto error;
103
+		goto error1;
102 104
 	}
103
-	
105
+
106
+	/* calculate branch for outbound request;  if syn_branch is turned off,
107
+	   calculate is from transaction key, i.e., as an md5 of From/To/CallID/
108
+	   CSeq exactly the same way as TM does; good for reboot -- than messages
109
+	   belonging to transaction lost due to reboot will still be forwarded
110
+	   with the same branch parameter and will be match-able downstream
111
+
112
+       if it is turned on, we don't care about reboot; we simply put a simple
113
+	   value in there; better for performance
114
+	*/
115
+
116
+	if (syn_branch ) {
117
+		*msg->add_to_branch_s='0';
118
+		msg->add_to_branch_len=1;
119
+	} else {
120
+		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
121
+			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
122
+			goto error1;
123
+		}
124
+		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
125
+		if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
126
+					msg->add_to_branch_s, &msg->add_to_branch_len )) {
127
+			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
128
+			goto error1;
129
+		}
130
+	}
131
+
104 132
 	buf = build_req_buf_from_sip_req( msg, &len, send_sock);
105 133
 	if (!buf){
106
-		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
107
-		goto error;
134
+		LOG(L_ERR, "ERROR: forward_request: building failed\n");
135
+		goto error1;
108 136
 	}
109 137
 	 /* send it! */
110 138
 	DBG("Sending:\n%s.\n", buf);
... ...
@@ -116,7 +144,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
116 144
 			p->errors++;
117 145
 			p->ok=0;
118 146
 			STATS_TX_DROPS;
119
-			goto error;
147
+			goto error1;
120 148
 	}
121 149
 	/* sent requests stats */
122 150
 	else STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
... ...
@@ -124,13 +152,26 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
124 152
 	free(to);
125 153
 	/* received_buf & line_buf will be freed in receiv_msg by free_lump_list*/
126 154
 	return 0;
155
+
156
+error1:
157
+	free(to);
127 158
 error:
128 159
 	if (buf) pkg_free(buf);
129
-	if (to) free(to);
130 160
 	return -1;
131 161
 }
132 162
 
133 163
 
164
+int update_sock_struct_from_ip( union sockaddr_union* to,
165
+	struct sip_msg *msg )
166
+{
167
+	to->sin.sin_port=(msg->via1->port)
168
+		?htons(msg->via1->port): htons(SIP_PORT);
169
+	to->sin.sin_family=msg->src_ip.af;
170
+	memcpy(&to->sin.sin_addr, &msg->src_ip.u, msg->src_ip.len);
171
+
172
+	return 1;
173
+}
174
+
134 175
 int update_sock_struct_from_via( union sockaddr_union* to,
135 176
 								 struct via_body* via )
136 177
 {
... ...
@@ -252,9 +293,10 @@ int forward_reply(struct sip_msg* msg)
252 293
 			if (mod->exports->response_f(msg)==0) goto skip;
253 294
 		}
254 295
 	}
255
-	
296
+
256 297
 	/* we have to forward the reply stateless, so we need second via -bogdan*/
257
-	if ((msg->via2==0) || (msg->via2->error!=PARSE_OK))
298
+	if (parse_headers( msg, HDR_VIA2, 0 )==-1 
299
+		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
258 300
 	{
259 301
 		/* no second via => error */
260 302
 		LOG(L_ERR, "ERROR: forward_msg: no 2nd via found in reply\n");
... ...
@@ -16,6 +16,8 @@ struct socket_info* get_send_socket(union sockaddr_union* su);
16 16
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
17 17
 int update_sock_struct_from_via( union sockaddr_union* to,
18 18
 								struct via_body* via );
19
+int update_sock_struct_from_ip( union sockaddr_union* to,
20
+    struct sip_msg *msg );
19 21
 int forward_reply( struct sip_msg* msg);
20 22
 
21 23
 #endif
... ...
@@ -44,8 +44,10 @@ extern int children_no;
44 44
 extern int dont_fork;
45 45
 extern int check_via;
46 46
 extern int received_dns;
47
-extern int loop_checks;
47
+extern int syn_branch;
48 48
 extern int process_no;
49
+extern int sip_warning;
50
+extern int server_signature;
49 51
 /*
50 52
  * debug & log_stderr moved to dprint.h*/
51 53
 
... ...
@@ -57,4 +59,13 @@ extern unsigned int msg_no;
57 59
 
58 60
 extern unsigned int shm_mem_size;
59 61
 
62
+/* FIFO server config */
63
+char extern *fifo; /* FIFO name */
64
+extern int fifo_mode;
65
+
66
+extern int *pids;
67
+extern int process_no;
68
+
69
+extern int reply_to_via;
70
+
60 71
 #endif
... ...
@@ -36,6 +36,7 @@
36 36
 #include "resolve.h"
37 37
 #include "parser/parse_hname2.h"
38 38
 #include "parser/digest/digest_parser.h"
39
+#include "fifo_server.h"
39 40
 
40 41
 
41 42
 #include "stats.h"
... ...
@@ -93,21 +94,6 @@ static char flags[]=
93 94
 #ifdef DEBUG_DMALLOC
94 95
 ", DEBUG_DMALLOC"
95 96
 #endif
96
-#ifdef SILENT_FR
97
-", SILENT_FR"
98
-#endif
99
-#ifdef USE_SYNONIM
100
-", USE_SYNONIM"
101
-#endif
102
-#ifdef NOISY_REPLIES
103
-", NOISY_REPLIES"
104
-#endif
105
-#ifdef VERY_NOISY_REPLIES
106
-", VERY_NOISY_REPLIES"
107
-#endif
108
-#ifdef NEW_HNAME
109
-", NEW_HNAME"
110
-#endif
111 97
 #ifdef FAST_LOCK
112 98
 ", FAST_LOCK"
113 99
 #ifdef BUSY_WAIT
... ...
@@ -125,7 +111,6 @@ static char flags[]=
125 111
 static char help_msg[]= "\
126 112
 Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\
127 113
 Options:\n\
128
-    -c           Perform loop checks and compute branches\n\
129 114
     -f file      Configuration file (default " CFG_FILE ")\n\
130 115
     -p port      Listen on the specified port (default: 5060)\n\
131 116
                  applies to the last address in -l and to all \n\
... ...
@@ -173,8 +158,8 @@ void print_ct_constants()
173 158
 #endif
174 159
 */
175 160
 	printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d,"
176
-			" MAX_URI_SIZE %d, MAX_PROCESSES %d, BUF_SIZE %d\n",
177
-		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES,
161
+			" MAX_URI_SIZE %d, BUF_SIZE %d\n",
162
+		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, 
178 163
 		BUF_SIZE );
179 164
 }
180 165
 
... ...
@@ -209,14 +194,29 @@ int sig_flag = 0;              /* last signal received */
209 194
 int debug = 0;
210 195
 int dont_fork = 0;
211 196
 int log_stderr = 0;
212
-int check_via =  0;        /* check if reply first via host==us */
213
-int loop_checks = 0;	/* calculate branches and check for loops/spirals */
214
-int received_dns = 0;      /* use dns and/or rdns or to see if we need to 
215
-                              add a ;received=x.x.x.x to via: */
197
+/* check if reply first via host==us */
198
+int check_via =  0;        
199
+/* shall use stateful synonym branches? faster but not reboot-safe */
200
+int syn_branch = 0;
201
+/* should replies include extensive warnings? by default yes,
202
+   good for trouble-shooting
203
+*/
204
+int sip_warning = 1;
205
+/* should localy-generated messages include server's signature?
206
+   be default yes, good for trouble-shooting
207
+*/
208
+int server_signature=1;
209
+/* use dns and/or rdns or to see if we need to add 
210
+   a ;received=x.x.x.x to via: */
211
+int received_dns = 0;      
216 212
 char* working_dir = 0;
217 213
 char* chroot_dir = 0;
218 214
 int uid = 0;
219 215
 int gid = 0;
216
+/* a hint to reply modules whether they should send reply
217
+   to IP advertised in Via or IP from which a request came
218
+*/
219
+int reply_to_via=0;
220 220
 
221 221
 #if 0
222 222
 char* names[MAX_LISTEN];              /* our names */
... ...
@@ -497,6 +497,12 @@ int main_loop()
497 497
 			LOG(L_ERR, "init_child failed\n");
498 498
 			goto error;
499 499
 		}
500
+
501
+		/* if configured to do so, start a server for accepting FIFO commands */
502
+		if (open_fifo_server()<0) {
503
+			LOG(L_ERR, "opening fifo server failed\n");
504
+			goto error;
505
+		}
500 506
 		is_main=1; /* hack 42: call init_child with is_main=0 in case
501 507
 					 some modules wants to fork a child */
502 508
 		
... ...
@@ -543,6 +549,11 @@ int main_loop()
543 549
 			/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
544 550
 		}
545 551
 	}
552
+	/* if configured to do so, start a server for accepting FIFO commands */
553
+	if (open_fifo_server()<0) {
554
+		LOG(L_ERR, "opening fifo server failed\n");
555
+		goto error;
556
+	}
546 557
 	/*this is the main process*/
547 558
 	pids[process_no]=getpid();
548 559
 	process_bit = 0;
... ...
@@ -590,6 +601,7 @@ int main_loop()
590 601
 static void sig_usr(int signo)
591 602
 {
592 603
 
604
+
593 605
 	if (is_main){
594