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 90
 # -DNOSMP
91 91
 #		don't use smp compliant locking (faster but won't work on SMP machines)
92 92
 #		(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
93
+# -DNO_PINGTEL_TAG_HACK
94
+#		if enabled, To-header-field will be less liberal and will not accept
95
+#		'tag=' (tag parameter with equal sign and without value); it is called
96
+#		this way because such message was sighted from a Pingtel phone
100 97
 
101 98
 DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
102 99
 	 -DOS='"$(OS)"' -DCOMPILER='"$(CC_VER)"'\
103 100
 	 -DPKG_MALLOC \
104 101
 	 -DSHM_MEM  -DSHM_MMAP \
105 102
 	 -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 103
 	 -DUSE_IPV6 \
104
+	 -DEXTRA_DEBUG \
105
+	 -DVQ_MALLOC  -DDBG_QM_MALLOC \
106
+	 #-DCONTACT_BUG
107
+	 #-DF_MALLOC \
108
+	 #-DDBG_LOCK
113 109
 	 #-DNO_DEBUG \
114 110
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
115 111
 	 #-DNOSMP \
116 112
 	 #-DEXTRA_DEBUG 
117
-	 #-DVQ_MALLOC  -DDBG_LOCK  #-DSTATS
118
-	 #-DDBG_QM_MALLOC 
119
-# -DUSE_SHM_MEM
120
-#-DSTATS 
121
-#-DNO_LOG
122
-
123
-
113
+	 #-DUSE_SHM_MEM
114
+	 #-DSTATS 
115
+	 #-DNO_LOG
124 116
 
125 117
 #PROFILE=  -pg #set this if you want profiling
126 118
 #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 44
 Maturity is label as stable if a module has been deployed
45 45
 for longer time, alpha if it is still being developed and
46 46
 beta if it is under test.
47
+
48
+Modules underway include presence server functionality,
49
+firewall control, message store and more. If you are
50
+interested in any of these or other modules, write us
51
+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 179
 			ret=1;
180 180
 			break;
181 181
 
182
+		/* jku -- introduce a new branch */
183
+		case APPEND_BRANCH_T:
184
+			if ((a->p1_type!=STRING_ST)) {
185
+				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
186
+					a->p1_type );
187
+				ret=E_BUG;
188
+				break;
189
+			}
190
+			ret=append_branch( msg, a->p1.string, 
191
+				a->p1.string ? strlen(a->p1.string):0 );
192
+			break;
193
+
182 194
 		/* jku begin: is_length_greater_than */
183 195
 		case LEN_GT_T:
184 196
 			if (a->p1_type!=NUMBER_ST) {
... ...
@@ -281,6 +294,14 @@ int do_action(struct action* a, struct sip_msg* msg)
281 281
 			}
282 282
 			ret=1;
283 283
 			break;
284
+		case REVERT_URI_T:
285
+			if (msg->new_uri.s) {
286
+				pkg_free(msg->new_uri.s);
287
+				msg->new_uri.len=0;
288
+				msg->new_uri.s=0;
289
+			};
290
+			ret=1;
291
+			break;
284 292
 		case SET_HOST_T:
285 293
 		case SET_HOSTPORT_T:
286 294
 		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 57
 SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
58 58
 SET_PORT		"rewriteport"|"setport"|"setp"
59 59
 SET_URI			"rewriteuri"|"seturi"
60
+REVERT_URI		"revert_uri"
60 61
 PREFIX			"prefix"
61 62
 STRIP			"strip"
63
+APPEND_BRANCH	"append_branch"
62 64
 IF				"if"
63 65
 ELSE			"else"
64 66
 
... ...
@@ -94,7 +97,12 @@ STAT	statistics
94 94
 MAXBUFFER maxbuffer
95 95
 CHILDREN children
96 96
 CHECK_VIA	check_via
97
-LOOP_CHECKS	loop_checks
97
+SYN_BRANCH syn_branch
98
+SIP_WARNING sip_warning
99
+FIFO fifo
100
+FIFO_MODE fifo_mode
101
+SERVER_SIGNATURE server_signature
102
+REPLY_TO_VIA reply_to_via
98 103
 
99 104
 LOADMODULE	loadmodule
100 105
 MODPARAM        modparam
... ...
@@ -148,6 +156,7 @@ EAT_ABLE	[\ \t\b\r]
148 148
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
149 149
 <INITIAL>{LEN_GT}	{ count(); yylval.strval=yytext; return LEN_GT; }
150 150
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
151
+<INITIAL>{REPLY_ROUTE}	{ count(); yylval.strval=yytext; return REPLY_ROUTE; }
151 152
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
152 153
 <INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
153 154
 <INITIAL>{SET_HOSTPORT}	{ count(); yylval.strval=yytext; return SET_HOSTPORT; }
... ...
@@ -155,8 +164,10 @@ EAT_ABLE	[\ \t\b\r]
155 155
 <INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
156 156
 <INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
157 157
 <INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
158
+<INITIAL>{REVERT_URI}	{ count(); yylval.strval=yytext; return REVERT_URI; }
158 159
 <INITIAL>{PREFIX}	{ count(); yylval.strval=yytext; return PREFIX; }
159 160
 <INITIAL>{STRIP}	{ count(); yylval.strval=yytext; return STRIP; }
161
+<INITIAL>{APPEND_BRANCH}	{ count(); yylval.strval=yytext; return APPEND_BRANCH; }
160 162
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
161 163
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
162 164
 
... ...
@@ -181,7 +192,12 @@ EAT_ABLE	[\ \t\b\r]
181 181
 <INITIAL>{MAXBUFFER}	{ count(); yylval.strval=yytext; return MAXBUFFER; }
182 182
 <INITIAL>{CHILDREN}	{ count(); yylval.strval=yytext; return CHILDREN; }
183 183
 <INITIAL>{CHECK_VIA}	{ count(); yylval.strval=yytext; return CHECK_VIA; }
184
-<INITIAL>{LOOP_CHECKS}	{ count(); yylval.strval=yytext; return LOOP_CHECKS; }
184
+<INITIAL>{SYN_BRANCH}	{ count(); yylval.strval=yytext; return SYN_BRANCH; }
185
+<INITIAL>{SIP_WARNING}	{ count(); yylval.strval=yytext; return SIP_WARNING; }
186
+<INITIAL>{FIFO}	{ count(); yylval.strval=yytext; return FIFO; }
187
+<INITIAL>{FIFO_MODE}	{ count(); yylval.strval=yytext; return FIFO_MODE; }
188
+<INITIAL>{SERVER_SIGNATURE}	{ count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
189
+<INITIAL>{REPLY_TO_VIA}	{ count(); yylval.strval=yytext; return REPLY_TO_VIA; }
185 190
 <INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
186 191
 <INITIAL>{MODPARAM}     { count(); yylval.strval=yytext; return MODPARAM; }
187 192
 
... ...
@@ -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 90
 %token STAT
91 91
 %token CHILDREN
92 92
 %token CHECK_VIA
93
-%token LOOP_CHECKS
93
+%token SYN_BRANCH
94
+%token SIP_WARNING
95
+%token FIFO
96
+%token FIFO_MODE
97
+%token SERVER_SIGNATURE
98
+%token REPLY_TO_VIA
94 99
 %token LOADMODULE
95 100
 %token MODPARAM
96 101
 %token MAXBUFFER
... ...
@@ -151,6 +159,7 @@ statements:	statements statement {}
151 151
 statement:	assign_stm 
152 152
 		| module_stm
153 153
 		| route_stm 
154
+		| reply_route_stm
154 155
 		| CR	/* null statement*/
155 156
 	;
156 157
 
... ...
@@ -180,8 +189,18 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
180 180
 		| CHILDREN EQUAL error { yyerror("number expected"); } 
181 181
 		| CHECK_VIA EQUAL NUMBER { check_via=$3; }
182 182
 		| 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"); }
183
+		| SYN_BRANCH EQUAL NUMBER { syn_branch=$3; }
184
+		| SYN_BRANCH EQUAL error { yyerror("boolean value expected"); }
185
+		| SIP_WARNING EQUAL NUMBER { sip_warning=$3; }
186
+		| SIP_WARNING EQUAL error { yyerror("boolean value expected"); }
187
+		| FIFO EQUAL STRING { fifo=$3; }
188
+		| FIFO EQUAL error { yyerror("string value expected"); }
189
+		| FIFO_MODE EQUAL NUMBER { fifo_mode=$3; }
190
+		| FIFO_MODE EQUAL NUMBER { yyerror("int value expected"); }
191
+		| SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
192
+		| SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
193
+		| REPLY_TO_VIA EQUAL NUMBER { reply_to_via=$3; }
194
+		| REPLY_TO_VIA EQUAL error { yyerror("boolean value expected"); }
185 195
 		| LISTEN EQUAL ip  {
186 196
 								if (sock_no< MAX_LISTEN){
187 197
 									tmp=ip_addr2a($3);
... ...
@@ -347,6 +366,17 @@ route_stm:	ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
347 347
 										}
348 348
 		| ROUTE error { yyerror("invalid  route  statement"); }
349 349
 	;
350
+
351
+reply_route_stm: REPLY_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
352
+										if (($3<REPLY_RT_NO)&&($3>=1)){
353
+											push($6, &reply_rlist[$3]);
354
+										} else {
355
+											yyerror("invalid reply routing"
356
+												"table number");
357
+											YYABORT; }
358
+										}
359
+		| REPLY_ROUTE error { yyerror("invalid reply_route statement"); }
360
+	;
350 361
 /*
351 362
 rules:	rules rule { push($2, &$1); $$=$1; }
352 363
 	| rule {$$=$1; }
... ...
@@ -685,6 +715,12 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
685 685
 		| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
686 686
 														"number expected"); }
687 687
 
688
+		| APPEND_BRANCH LPAREN STRING RPAREN { $$=mk_action( APPEND_BRANCH_T,
689
+													STRING_ST, 0, $3, 0) ; }
690
+		| APPEND_BRANCH LPAREN RPAREN { $$=mk_action( APPEND_BRANCH_T,
691
+													STRING_ST, 0, 0, 0 ) ; }
692
+		| APPEND_BRANCH {  $$=mk_action( APPEND_BRANCH_T, STRING_ST, 0, 0, 0 ) ; }
693
+
688 694
 		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
689 695
 														STRING_ST, 0, $3, 0); }
690 696
 		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
... ...
@@ -710,6 +746,8 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
710 710
 		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
711 711
 		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
712 712
 										"string expected"); }
713
+		| REVERT_URI LPAREN RPAREN { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
714
+		| REVERT_URI { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
713 715
 		| ID LPAREN RPAREN			{ f_tmp=(void*)find_export($1, 0);
714 716
 									   if (f_tmp==0){
715 717
 										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 46
 
47 47
 #define MAX_WARNING_LEN  256
48 48
 		
49
-#define MY_BRANCH ";branch=0"
50
-#define MY_BRANCH_LEN 9
49
+#define MY_BRANCH ";branch="
50
+#define MY_BRANCH_LEN 8
51 51
 
52 52
 
53 53
 #define MAX_PORT_LEN 7 /* ':' + max 5 letters + \0 */
... ...
@@ -88,8 +89,16 @@
88 88
 #define MAX_VIA_LINE_SIZE	240
89 89
 #define MAX_RECEIVED_SIZE	57
90 90
 
91
-/* maximum number of processes is constrained by capacity of
92
-   process bitmaps */
93
-#define MAX_PROCESSES (sizeof( process_bm_t) * 8 )
91
+/* maximum number of branches per transaction */
92
+#define MAX_BRANCHES    4
94 93
 
94
+/* maximum length of a FIFO server command */
95
+#define MAX_FIFO_COMMAND 512
96
+
97
+/* buffer dimensions for FIFO server */
98
+#define MAX_CONSUME_BUFFER 1024
99
+/* where reply pipes may be opened */
100
+#define FIFO_DIR "/tmp/"
101
+/* max length of the text of fifo 'print' command */
102
+#define MAX_PRINT_TEXT 256
95 103
 #endif
96 104
new file mode 100644
... ...
@@ -0,0 +1,87 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * destination set
4
+ */
5
+
6
+#include <string.h>
7
+
8
+#include "dprint.h"
9
+#include "config.h"
10
+#include "parser/parser_f.h"
11
+#include "parser/msg_parser.h"
12
+#include "ut.h"
13
+#include "hash_func.h"
14
+#include "dset.h"
15
+
16
+
17
+
18
+/* where we store URIs of additional transaction branches
19
+  (-1 because of the default branch, #0)
20
+*/
21
+static struct branch branches[ MAX_BRANCHES - 1 ];
22
+/* how many of them we have */
23
+static unsigned int nr_branches=0;
24
+/* branch iterator */
25
+static int branch_iterator=0;
26
+
27
+void init_branch_iterator(void)
28
+{
29
+	branch_iterator=0;
30
+}
31
+
32
+char *next_branch( int *len )
33
+{
34
+	unsigned int i;
35
+
36
+	i=branch_iterator;
37
+	if (i<nr_branches) {
38
+		branch_iterator++;
39
+		*len=branches[i].len;
40
+		return branches[i].uri;
41
+	} else {
42
+		*len=0;
43
+		return 0;
44
+	}
45
+}
46
+
47
+void clear_branches()
48
+{
49
+	nr_branches=0;
50
+}
51
+
52
+/* add a new branch to current transaction */
53
+int append_branch( struct sip_msg *msg, char *uri, int uri_len )
54
+{
55
+	/* if we have already set up the maximum number
56
+	   of branches, don't try new ones */
57
+	if (nr_branches==MAX_BRANCHES-1) {
58
+		LOG(L_ERR, "ERROR: append_branch: max nr of branches exceeded\n");
59
+		return -1;
60
+	}
61
+
62
+	if (uri_len>MAX_URI_SIZE-1) {
63
+		LOG(L_ERR, "ERROR: append_branch: too long uri: %.*s\n",
64
+			uri_len, uri );
65
+		return -1;
66
+	}
67
+
68
+	/* if not parameterized, take current uri */
69
+	if (uri==0) {
70
+		if (msg->new_uri.s) { 
71
+			uri=msg->new_uri.s;
72
+			uri_len=msg->new_uri.len;
73
+		} else {
74
+			uri=msg->first_line.u.request.uri.s;
75
+			uri_len=msg->first_line.u.request.uri.len;
76
+		}
77
+	}
78
+	
79
+	memcpy( branches[nr_branches].uri, uri, uri_len );
80
+	/* be safe -- add zero termination */
81
+	branches[nr_branches].uri[uri_len]=0;
82
+	branches[nr_branches].len=uri_len;
83
+	
84
+	nr_branches++;
85
+	return 1;
86
+}
0 87
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+#ifndef _T_FORKS_H
5
+#define _T_FORKS_H
6
+
7
+#include "config.h"
8
+
9
+struct branch
10
+{
11
+	char uri[MAX_URI_SIZE];
12
+	unsigned int len;
13
+};
14
+
15
+struct sip_msg;
16
+
17
+/*
18
+typedef int (*tfork_f)( struct sip_msg *msg, char *uri, int uri_len );
19
+*/
20
+
21
+/* add a new branch to current transaction */
22
+int append_branch( struct sip_msg *msg, char *uri, int uri_len );
23
+/* iterate through list of new transaction branches */
24
+void init_branch_iterator();
25
+char *next_branch( int *len );
26
+void clear_branches();
27
+
28
+#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 43
 			error_txt="Regretfuly, we were not able to process the URI";
44 44
 			*sip_error=-ser_error;
45 45
 			break;
46
+		case E_BAD_TUPEL:
47
+			error_txt="Transaction tupel incomplete";
48
+			*sip_error=-E_BAD_REQ;
49
+			break;
46 50
 		default:
47 51
 			error_txt="I'm terribly sorry, server error occured";
48 52
 			*sip_error=500;
... ...
@@ -51,3 +58,104 @@ int err2reason_phrase(
51 51
 	return snprintf( phrase, etl, "%s (%d/%s)", error_txt, 
52 52
 		-ser_error, signature );
53 53
 }
54
+
55
+char *error_text( int code )
56
+{
57
+	switch(code) {
58
+
59
+		case 100: return "Trying";
60
+		case 180: return "Ringing";
61
+		case 181: return "Call is Being Forwarded";
62
+		case 182: return "Queued";
63
+		case 183: return "Session Progress";
64
+
65
+		case 200: return "OK";
66
+
67
+		case 300: return "Multiple Choices";
68
+		case 301: return "Moved Permanently";
69
+		case 302: return "Moved Temporarily";
70
+		case 305: return "Use Proxy";
71
+		case 380: return "Alternative Service";
72
+
73
+		case 400: return "Bad Request";
74
+		case 401: return "Unauthorized";
75
+		case 402: return "Payement Required";
76
+		case 403: return "Forbidden";
77
+		case 404: return "Not Found";
78
+		case 405: return "Method not Allowed";
79
+		case 406: return "Not Acceptable";
80
+		case 407: return "Proxy authentication Required";
81
+		case 408: return "Request Timeout";
82
+		case 410: return "Gone";
83
+		case 413: return "Request Entity Too Large";
84
+		case 414: return "Request-URI Too Long";
85
+		case 415: return "Unsupported Media Type";
86
+		case 416: return "Unsupported URI Scheme";
87
+		case 417: return "Bad Extension";
88
+		case 421: return "Extension Required";
89
+		case 423: return "Interval Too Brief";
90
+		case 480: return "Temporarily Unavailable";
91
+		case 481: return "Call/Transaction Does not Exist";
92
+		case 482: return "Loop Detected";
93
+		case 483: return "Too Many Hops";
94
+		case 484: return "Address Incomplete";
95
+		case 485: return "Ambigous";
96
+		case 486: return "Busy Here";
97
+		case 487: return "Request Terminated";
98
+		case 488: return "Not Acceptable Here";
99
+		case 491: return "Request Pending";
100
+	
101
+		case 500: return "Server Internal Error";
102
+		case 501: return "Not Implemented";
103
+		case 502: return "Bad Gateway";
104
+		case 503: return "Service Unavailable";
105
+		case 504: return "Server Time-out";
106
+		case 505: return "Version not Supported";
107
+		case 513: return "Message Too Large";
108
+
109
+		case 600: return "Busy Everywhere";
110
+		case 603: return "Decline";
111
+		case 604: return "Does not Exist Anywhere";
112
+		case 606: return "Not Acceptable";
113
+
114
+	}
115
+
116
+	if (code>=600) return "Global Failure";
117
+	else if (code>=500) return "Server Failure";
118
+	else if (code>=400) return "Request Failure";
119
+	else if (code>=300) return "Redirection";
120
+	else if (code>=200) return "Successful";
121
+	else if (code>=100) return "Provisional";
122
+	else return "Unspecified";
123
+}
124
+
125
+void get_reply_status( str *status, struct sip_msg *reply, int code )
126
+{
127
+	str phrase;
128
+
129
+	status->s=0;
130
+
131
+	if (reply==0) {
132
+		LOG(L_CRIT, "BUG: get_reply_status called with 0 msg\n");
133
+		return;
134
+	}
135
+
136
+	if (reply==FAKED_REPLY) {
137
+		phrase.s=error_text(code);
138
+		phrase.len=strlen(phrase.s);
139
+	} else {
140
+		phrase=reply->first_line.u.reply.reason;
141
+	}
142
+	status->len=phrase.len+3/*code*/+1/*space*/+1/*ZT*/;
143
+	status->s=pkg_malloc(status->len);
144
+	if (!status->s) {
145
+		LOG(L_ERR, "ERROR: get_reply_status: no mem\n");
146
+		return;
147
+	}
148
+	status->s[3]=' ';
149
+	status->s[2]='0'+code % 10; code=code/10;
150
+	status->s[1]='0'+code% 10; code=code/10;
151
+	status->s[0]='0'+code % 10;
152
+	memcpy(&status->s[4], phrase.s, phrase.len);
153
+	status->s[status->len-1]=0;
154
+}
... ...
@@ -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 23
 
24 24
 #define MAX_REASON_LEN	128
25 25
 
26
+#include "str.h"
27
+
26 28
 /* processing status of the last command */
27 29
 extern int ser_error;
28 30
 extern int prev_ser_error;
29 31
 
32
+struct sip_msg;
33
+
34
+/* ser error -> SIP error */
30 35
 int err2reason_phrase( int ser_error, int *sip_error, 
31 36
                 char *phrase, int etl, char *signature );
32 37
 
38
+/* SIP error core -> SIP text */
39
+char *error_text( int code );
40
+
41
+/* return pkg_malloc-ed reply status in status->s */
42
+void get_reply_status( str *status, struct sip_msg *reply, int code );
33 43
 
34 44
 #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 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * simple UAC for things such as SUBSCRIBE or SMS gateway;
4
+ * no authentication and other UAC features -- just send
5
+ * a message, retransmit and await a reply; forking is not
6
+ * supported during client generation, in all other places
7
+ * it is -- adding it should be simple
8
+ */
9
+
10
+#include <stdlib.h>
11
+#include <sys/types.h>
12
+#include <unistd.h>
13
+#include <stdio.h>
14
+#include <errno.h>
15
+#include <sys/types.h>
16
+#include <sys/stat.h>
17
+#include <fcntl.h>
18
+#include <signal.h>
19
+#include <string.h>
20
+#include "dprint.h"
21
+#include "ut.h"
22
+#include "error.h"
23
+#include "config.h"
24
+#include "globals.h"
25
+#include "fifo_server.h"
26
+#include "mem/mem.h"
27
+
28
+/* FIFO server vars */
29
+char *fifo=0; /* FIFO name */
30
+int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
31
+pid_t fifo_pid;
32
+/* file descriptors */
33
+static int fifo_read=0;
34
+static int fifo_write=0;
35
+static FILE *fifo_stream;
36
+
37
+/* list of fifo command */
38
+static struct fifo_command *cmd_list=0;
39
+
40
+static struct fifo_command *lookup_fifo_cmd( char *name )
41
+{
42
+	struct fifo_command *c;
43
+	for(c=cmd_list; c; c=c->next) {
44
+		if (strcasecmp(c->name, name)==0) return c;
45
+	}
46
+	return 0;
47
+}
48
+
49
+int register_fifo_cmd(fifo_cmd f, char *cmd_name, void *param)
50
+{
51
+	struct fifo_command *new_cmd;
52
+
53
+	if (lookup_fifo_cmd(cmd_name)) {
54
+		LOG(L_ERR, "ERROR: register_fifo_cmd: attempt to register synonyms\n");
55
+		return E_BUG;
56
+	}
57
+	new_cmd=malloc(sizeof(struct fifo_command));
58
+	if (new_cmd==0) {
59
+		LOG(L_ERR, "ERROR: register_fifo_cmd: out of mem\n");
60
+		return E_OUT_OF_MEM;
61
+	}
62
+	new_cmd->f=f;
63
+	new_cmd->name=cmd_name;
64
+	new_cmd->param=param;
65
+
66
+	new_cmd->next=cmd_list;
67
+	cmd_list=new_cmd;
68
+
69
+	return 1;
70
+}
71
+
72
+
73
+int read_line( char *b, int max, FILE *stream, int *read )
74
+{
75
+	int len;
76
+	if (fgets(b, max, stream)==NULL) {
77
+		LOG(L_ERR, "ERROR: fifo_server fgets failed: %s\n",
78
+			strerror(errno));
79
+		kill(0, SIGTERM);
80
+	}
81
+	/* if we did not read whole line, our buffer is too small
82
+	   and we cannot process the request; consume the remainder of 
83
+	   request
84
+	*/
85
+	len=strlen(b);
86
+	if (len && !(b[len-1]=='\n' || b[len-1]=='\r')) {
87
+		LOG(L_ERR, "ERROR: read_line: request  line too long\n");
88
+		return 0;
89
+	}
90
+	/* trim from right */
91
+	while(len) {
92
+		if(b[len-1]=='\n' || b[len-1]=='\r'
93
+				|| b[len-1]==' ' || b[len-1]=='\t' ) {
94
+			len--;
95
+			b[len]=0;
96
+		} else break;
97
+	}
98
+	*read=len;
99
+	return 1;
100
+}
101
+
102
+static void consume_request( FILE *stream )
103
+{
104
+	int len;
105
+	char buffer[MAX_CONSUME_BUFFER];
106
+
107
+	while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
108
+
109
+#ifdef _OBSOLETED
110
+	int eol_count;
111
+
112
+	eol_count=0;
113
+
114
+	/* each request must be terminated by two EoLs */
115
+	while(eol_count!=2) {
116
+		/* read until EoL is encountered */
117
+		while(!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len));
118
+		eol_count=len==0?eol_count+1:1;
119
+	}
120
+#endif
121
+}
122
+
123
+int read_eol( FILE *stream )
124
+{
125
+	int len;
126
+	char buffer[MAX_CONSUME_BUFFER];
127
+	if (!read_line(buffer, MAX_CONSUME_BUFFER, stream, &len) || len!=0) {
128
+		LOG(L_ERR, "ERROR: read_eol: EOL expected: %.10s...\n",
129
+			buffer );
130
+		return 0;
131
+	}
132
+	return 1;
133
+}
134
+	
135
+int read_line_set(char *buf, int max_len, FILE *fifo, int *len)
136
+{
137
+	int set_len;
138
+	char *c;
139
+	int line_len;
140
+
141
+	c=buf;set_len=0;
142
+	while(1) {
143
+		if (!read_line(c,max_len,fifo,&line_len)) {
144
+			LOG(L_ERR, "ERROR: fifo_server: line expected\n");
145
+			return 0;
146
+		}
147
+		/* end encountered ... return */
148
+		if (line_len==0) {
149
+			*len=set_len;
150
+			return 1;
151
+		}
152
+		max_len-=line_len; c+=line_len; set_len+=line_len;
153
+		if (max_len<CRLF_LEN) {
154
+			LOG(L_ERR, "ERROR: fifo_server: no place for CRLF\n");
155
+			return 0;
156
+		}
157
+		memcpy(c, CRLF, CRLF_LEN);
158
+		max_len-=CRLF_LEN; c+=CRLF_LEN; set_len+=CRLF_LEN;
159
+	}
160
+}
161
+
162
+static char *trim_filename( char * file )
163
+{
164
+	int prefix_len, fn_len;
165
+	char *new_fn;
166
+
167
+	/* we only allow files in "/tmp" -- any directory
168
+	   changes are not welcome
169
+	*/
170
+	if (strchr(file,'.') || strchr(file,'/')
171
+				|| strchr(file, '\\')) {
172
+		LOG(L_ERR, "ERROR: trim_filename: forbidden filename: %s\n"
173
+			, file);
174
+		return 0;
175
+	}
176
+	prefix_len=strlen(FIFO_DIR); fn_len=strlen(file);
177
+	new_fn=pkg_malloc(prefix_len+fn_len+1);
178
+	if (new_fn==0) {
179
+		LOG(L_ERR, "ERROR: trim_filename: no mem\n");
180
+		return 0;
181
+	}
182
+
183
+	memcpy(new_fn, FIFO_DIR, prefix_len);
184
+	memcpy(new_fn+prefix_len, file, fn_len );
185
+	new_fn[prefix_len+fn_len]=0;
186
+
187
+	return new_fn;
188
+}
189
+
190
+static void fifo_server(FILE *fifo_stream)
191
+{
192
+	char buf[MAX_FIFO_COMMAND];
193
+	int line_len;
194
+	char *file_sep, *command, *file;
195
+	struct fifo_command *f;
196
+
197
+	file_sep=command=file=0;
198
+
199
+	while(1) {
200
+
201
+		/* commands must look this way ':<command>:[filename]' */
202
+		if (!read_line(buf, MAX_FIFO_COMMAND, fifo_stream, &line_len)) {
203
+			/* line breaking must have failed -- consume the rest
204
+			   and proceed to a new request
205
+			*/
206
+			LOG(L_ERR, "ERROR: fifo_server: command expected\n");
207
+			goto consume;
208
+		}
209
+		if (line_len==0) {
210
+			LOG(L_ERR, "ERROR: fifo_server: command empty\n");
211
+			continue;
212
+		}
213
+		if (line_len<3) {
214
+			LOG(L_ERR, "ERROR: fifo_server: command must have at least 3 chars\n");
215
+			goto consume;
216
+		}
217
+		if (*buf!=CMD_SEPARATOR) {
218
+			LOG(L_ERR, "ERROR: fifo_server: command must start with %c\n", 
219
+				CMD_SEPARATOR);
220
+			goto consume;
221
+		}
222
+		command=buf+1;
223
+		file_sep=strchr(command, CMD_SEPARATOR );
224
+		if (file_sep==NULL) {
225
+			LOG(L_ERR, "ERROR: fifo_server: file separator missing\n");
226
+			goto consume;
227
+		}
228
+		if (file_sep==command) {
229
+			LOG(L_ERR, "ERROR: fifo_server: empty command\n");
230
+			goto consume;
231
+		}
232
+		if (*(file_sep+1)==0) file=NULL; 
233
+		else {
234
+			file=file_sep+1;
235
+			file=trim_filename(file);
236
+			if (file==0) {
237
+				LOG(L_ERR, "ERROR: fifo_server: trimming filename\n");
238
+				goto consume;
239
+			}
240
+		}
241
+		/* make command zero-terminated */
242
+		*file_sep=0;
243
+
244
+		f=lookup_fifo_cmd( command );
245
+		if (f==0) {
246
+			LOG(L_ERR, "ERROR: fifo_server: command %s is not available\n",
247
+				command);
248
+			goto consume;
249
+		}
250
+		if (f->f(fifo_stream, file)<0) {
251
+			LOG(L_ERR, "ERROR: fifo_server: command (%s) "
252
+				"processing failed\n", command );
253
+			goto consume;
254
+		}
255
+
256
+consume:
257
+		if (file) { pkg_free(file); file=0;}
258
+		consume_request(fifo_stream);
259
+	}
260
+}
261
+
262
+int open_fifo_server()
263
+{
264
+	if (fifo==NULL) {
265
+		DBG("TM: open_uac_fifo: no fifo will be opened\n");
266
+		/* everything is ok, we just do not want to start */
267
+		return 1;
268
+	}
269
+	DBG("TM: open_uac_fifo: opening fifo...\n");
270
+	if ((mkfifo(fifo, fifo_mode)<0) && (errno!=EEXIST)) {
271
+		LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: %s\n",
272
+			strerror(errno));
273
+		return -1;
274
+	}
275
+	process_no++;
276
+	fifo_pid=fork();
277
+	if (fifo_pid<0) {
278
+		LOG(L_ERR, "ERROR: open_fifo_server: failure to fork: %s\n",
279
+			strerror(errno));
280
+		return -1;
281
+	}
282
+	if (fifo_pid==0) { /* child == FIFO server */
283
+		LOG(L_INFO, "INFO: fifo process starting: %d\n", getpid());
284
+		fifo_read=open(fifo, O_RDONLY, 0);
285
+		if (fifo_read<0) {
286
+			LOG(L_ERR, "SER: open_uac_fifo: fifo_read did not open: %s\n",
287
+				strerror(errno));
288
+			return -1;
289
+		}
290
+		fifo_stream=fdopen(fifo_read, "r"	);
291
+		if (fifo_stream==NULL) {
292
+			LOG(L_ERR, "SER: open_uac_fifo: fdopen failed: %s\n",
293
+				strerror(errno));
294
+			return -1;
295
+		}
296
+		LOG(L_INFO, "SER: open_uac_fifo: fifo server up...\n");
297
+		fifo_server( fifo_stream ); /* never retruns */
298
+	}
299
+	/* dad process */
300
+	pids[process_no]=fifo_pid;
301
+	/* make sure the read fifo will not close */
302
+	fifo_write=open(fifo, O_WRONLY, 0);
303
+	if (fifo_write<0) {
304
+		LOG(L_ERR, "SER: open_uac_fifo: fifo_write did not open: %s\n",
305
+			strerror(errno));
306
+		return -1;
307
+	}
308
+	return 1;
309
+}
310
+
311
+/* diagnostic and hello-world FIFO command */
312
+int print_fifo_cmd( FILE *stream, char *response_file )
313
+{
314
+	char text[MAX_PRINT_TEXT];
315
+	int text_len;
316
+	int file;
317
+	
318
+	/* expect one line which will be printed out */
319
+	if (!read_line(text, MAX_PRINT_TEXT, stream, &text_len)) {
320
+		LOG(L_ERR, "ERROR: print_fifo_cmd: too big text\n");
321
+		return -1;
322
+	}
323
+	/* now the work begins */
324
+	if (response_file) {
325
+		file=open( response_file , O_WRONLY);
326
+		if (file<0) {
327
+			LOG(L_ERR, "ERROR: print_fifo_cmd: open error (%s): %s\n",
328
+				response_file, strerror(errno));
329
+			return -1;
330
+		}
331
+		if (write(file, text,text_len)<0) {
332
+			LOG(L_ERR, "ERROR: print_fifo_cmd: write error: %s\n",
333
+				 strerror(errno));
334
+			close(file);
335
+			return -1;
336
+		}
337
+		close(file);
338
+	} else {
339
+		LOG(L_INFO, "INFO: print_fifo_cmd: %.*s\n", 
340
+			text_len, text );
341
+	}
342
+	return 1;
343
+}
0 344
new file mode 100644
... ...
@@ -0,0 +1,34 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ */
4
+
5
+#ifndef _FIFO_SERVER_H
6
+#define _FIFO_SERVER_H
7
+
8
+#include <stdio.h>
9
+
10
+#define CMD_SEPARATOR ':'
11
+
12
+typedef int (fifo_cmd)( FILE *fifo_stream, char *response_file );
13
+
14
+struct fifo_command{
15
+	fifo_cmd *f;
16
+	struct fifo_command *next;
17
+	void *param;
18
+	char *name;
19
+};
20
+
21
+int register_fifo_cmd(fifo_cmd f, char *cmd_name, void *param);
22
+
23
+/* read a single EoL-terminated line from fifo */
24
+int read_line( char *b, int max, FILE *stream, int *read );
25
+/* consume EoL from fifo */
26
+int read_eol( FILE *stream );
27
+/* consume a set of EoL-terminated lines terminated by an additional EoL */
28
+int read_line_set(char *buf, int max_len, FILE *fifo, int *len);
29
+
30
+int open_fifo_server();
31
+
32
+int print_fifo_cmd( FILE *stream, char *response_file );
33
+#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 67
 	char* buf;
68 68
 	union sockaddr_union* to;
69 69
 	struct socket_info* send_sock;
70
+	char md5[MD5_LEN];
70 71
 	
71 72
 	to=0;
72 73
 	buf=0;
... ...
@@ -98,13 +100,39 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
98 98
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
99 99
 				"no coresponding listening socket\n", to->s.sa_family);
100 100
 		ser_error=E_NO_SOCKET;
101
-		goto error;
101
+		goto error1;
102 102
 	}
103
-	
103
+
104
+	/* calculate branch for outbound request;  if syn_branch is turned off,
105
+	   calculate is from transaction key, i.e., as an md5 of From/To/CallID/
106
+	   CSeq exactly the same way as TM does; good for reboot -- than messages
107
+	   belonging to transaction lost due to reboot will still be forwarded
108
+	   with the same branch parameter and will be match-able downstream
109
+
110
+       if it is turned on, we don't care about reboot; we simply put a simple
111
+	   value in there; better for performance
112
+	*/
113
+
114
+	if (syn_branch ) {
115
+		*msg->add_to_branch_s='0';
116
+		msg->add_to_branch_len=1;
117
+	} else {
118
+		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
119
+			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
120
+			goto error1;
121
+		}
122
+		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
123
+		if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
124
+					msg->add_to_branch_s, &msg->add_to_branch_len )) {
125
+			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
126
+			goto error1;
127
+		}
128
+	}
129
+
104 130
 	buf = build_req_buf_from_sip_req( msg, &len, send_sock);
105 131
 	if (!buf){
106
-		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
107
-		goto error;
132
+		LOG(L_ERR, "ERROR: forward_request: building failed\n");
133
+		goto error1;
108 134
 	}
109 135
 	 /* send it! */
110 136
 	DBG("Sending:\n%s.\n", buf);
... ...
@@ -116,7 +144,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
116 116
 			p->errors++;
117 117
 			p->ok=0;
118 118
 			STATS_TX_DROPS;
119
-			goto error;
119
+			goto error1;
120 120
 	}
121 121
 	/* sent requests stats */
122 122
 	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 124
 	free(to);
125 125
 	/* received_buf & line_buf will be freed in receiv_msg by free_lump_list*/
126 126
 	return 0;
127
+
128
+error1:
129
+	free(to);
127 130
 error:
128 131
 	if (buf) pkg_free(buf);
129
-	if (to) free(to);
130 132
 	return -1;
131 133
 }
132 134
 
133 135
 
136
+int update_sock_struct_from_ip( union sockaddr_union* to,
137
+	struct sip_msg *msg )
138
+{
139
+	to->sin.sin_port=(msg->via1->port)
140
+		?htons(msg->via1->port): htons(SIP_PORT);
141
+	to->sin.sin_family=msg->src_ip.af;
142
+	memcpy(&to->sin.sin_addr, &msg->src_ip.u, msg->src_ip.len);
143
+
144
+	return 1;
145
+}
146
+
134 147
 int update_sock_struct_from_via( union sockaddr_union* to,
135 148
 								 struct via_body* via )
136 149
 {
... ...
@@ -252,9 +293,10 @@ int forward_reply(struct sip_msg* msg)
252 252
 			if (mod->exports->response_f(msg)==0) goto skip;
253 253
 		}
254 254
 	}
255
-	
255
+
256 256
 	/* we have to forward the reply stateless, so we need second via -bogdan*/
257
-	if ((msg->via2==0) || (msg->via2->error!=PARSE_OK))
257
+	if (parse_headers( msg, HDR_VIA2, 0 )==-1 
258
+		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
258 259
 	{
259 260
 		/* no second via => error */
260 261
 		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 57
 
58 58
 extern unsigned int shm_mem_size;
59 59
 
60
+/* FIFO server config */
61
+char extern *fifo; /* FIFO name */
62
+extern int fifo_mode;
63
+
64
+extern int *pids;
65
+extern int process_no;
66
+
67
+extern int reply_to_via;
68
+
60 69
 #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 93
 #ifdef DEBUG_DMALLOC
94 94
 ", DEBUG_DMALLOC"
95 95
 #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 96
 #ifdef FAST_LOCK
112 97
 ", FAST_LOCK"
113 98
 #ifdef BUSY_WAIT
... ...
@@ -125,7 +111,6 @@ static char flags[]=
125 125
 static char help_msg[]= "\
126 126
 Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\
127 127
 Options:\n\
128
-    -c           Perform loop checks and compute branches\n\
129 128
     -f file      Configuration file (default " CFG_FILE ")\n\
130 129
     -p port      Listen on the specified port (default: 5060)\n\
131 130
                  applies to the last address in -l and to all \n\
... ...
@@ -173,8 +158,8 @@ void print_ct_constants()
173 173
 #endif
174 174
 */
175 175
 	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,
176
+			" MAX_URI_SIZE %d, BUF_SIZE %d\n",
177
+		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, 
178 178
 		BUF_SIZE );
179 179
 }
180 180
 
... ...
@@ -209,14 +194,29 @@ int sig_flag = 0;              /* last signal received */
209 209
 int debug = 0;
210 210
 int dont_fork = 0;
211 211
 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: */
212
+/* check if reply first via host==us */
213
+int check_via =  0;        
214
+/* shall use stateful synonym branches? faster but not reboot-safe */
215
+int syn_branch = 0;
216
+/* should replies include extensive warnings? by default yes,
217
+   good for trouble-shooting
218
+*/
219
+int sip_warning = 1;
220
+/* should localy-generated messages include server's signature?
221
+   be default yes, good for trouble-shooting
222
+*/
223
+int server_signature=1;
224
+/* use dns and/or rdns or to see if we need to add 
225
+   a ;received=x.x.x.x to via: */
226
+int received_dns = 0;      
216 227
 char* working_dir = 0;
217 228
 char* chroot_dir = 0;
218 229
 int uid = 0;
219 230
 int gid = 0;
231
+/* a hint to reply modules whether they should send reply
232
+   to IP advertised in Via or IP from which a request came
233
+*/
234
+int reply_to_via=0;
220 235
 
221 236
 #if 0
222 237
 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 543
 			/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
544 544
 		}
545 545
 	}
546
+	/* if configured to do so, start a server for accepting FIFO commands */
547
+	if (open_fifo_server()<0) {
548
+		LOG(L_ERR, "opening fifo server failed\n");
549
+		goto error;
550
+	}
546 551
 	/*this is the main process*/
547 552
 	pids[process_no]=getpid();
548 553
 	process_bit = 0;
... ...
@@ -590,6 +601,7 @@ int main_loop()
590 590
 static void sig_usr(int signo)
591 591
 {
592 592
 
593
+
593 594
 	if (is_main){
594 595
 		if (sig_flag==0) sig_flag=signo;
595 596
 		else /*  previous sig. not processed yet, ignoring? */
... ...