Browse code

bunch of changes related to ability to process original request in reply_route: - textops: append_urihf(p,s) appends a hf with uri between p and s - core: supporting functions for duplicating a lump list from shmem to pkgmem (which allows further processing with pkgmem-oriented actions) - tm: reply_routes now creates a temporary, mostly pkg-mem-ed replica of shmem-ed request for additional processing

Jiri Kuthan authored on 19/01/2003 01:37:45
Showing 5 changed files
... ...
@@ -23,6 +23,10 @@
23 23
  * You should have received a copy of the GNU General Public License 
24 24
  * along with this program; if not, write to the Free Software 
25 25
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ *
27
+ * History:
28
+ * --------
29
+ * 2003-01-19 support for duplication lump lists added (jiri)
26 30
  */
27 31
 
28 32
 
... ...
@@ -42,6 +46,7 @@
42 42
 /* WARNING: all lump add/insert operations excpect a pkg_malloc'ed char* 
43 43
  * pointer the will be DEALLOCATED when the sip_msg is destroyed! */
44 44
 
45
+enum lump_dir { LD_NEXT, LD_BEFORE, LD_AFTER };
45 46
 
46 47
 /* adds a header to the end
47 48
  * returns  pointer on success, 0 on error */
... ...
@@ -248,3 +253,122 @@ void free_lump_list(struct lump* l)
248 248
 		pkg_free(crt);
249 249
 	}
250 250
 }
251
+
252
+/* free (shallow-ly) a lump and its after/before lists */
253
+static void free_shallow_lump( struct lump *l )
254
+{
255
+	struct lump *r, *foo;
256
+
257
+	r=l->before;
258
+	while(r){
259
+		foo=r; r=r->before;
260
+		pkg_free(foo);
261
+	}
262
+	r=l->after;
263
+	while(r){
264
+		foo=r; r=r->after;
265
+		pkg_free(foo);
266
+	}
267
+	pkg_free(l);
268
+}
269
+
270
+/* duplicate (shallow-ly) a lump list into pkg memory */
271
+static struct lump *dup_lump_list_r( struct lump *l, 
272
+				enum lump_dir dir, int *error)
273
+{
274
+	int deep_error;
275
+	struct lump *new_lump;
276
+
277
+	deep_error=0; /* optimist: assume success in recursion */
278
+	/* if at list end, terminate recursion successfully */
279
+	if (!l) { *error=0; return 0; }
280
+	/* otherwise duplicate current element */
281
+	new_lump=pkg_malloc(sizeof(struct lump));
282
+	if (!new_lump) { *error=1; return 0; }
283
+
284
+	memcpy(new_lump, l, sizeof(struct lump));
285
+	new_lump->flags=LUMPFLAG_DUPED;
286
+	new_lump->next=new_lump->before=new_lump->after=0;
287
+
288
+	switch(dir) {
289
+		case LD_NEXT:	
290
+				new_lump->before=dup_lump_list_r(l->before, 
291
+								LD_BEFORE, &deep_error);
292
+				if (deep_error) goto deeperror;
293
+				new_lump->after=dup_lump_list_r(l->after, 
294
+								LD_AFTER, &deep_error);
295
+				if (deep_error) goto deeperror;
296
+				new_lump->next=dup_lump_list_r(l->next, 
297
+								LD_NEXT, &deep_error);
298
+				break;
299
+		case LD_BEFORE:
300
+				new_lump->before=dup_lump_list_r(l->before, 
301
+								LD_BEFORE, &deep_error);
302
+				break;
303
+		case LD_AFTER:
304
+				new_lump->after=dup_lump_list_r(l->after, 
305
+								LD_AFTER, &deep_error);
306
+				break;
307
+		default:
308
+				LOG(L_CRIT, "BUG: dup_limp_list_r: unknown dir: "
309
+						"%d\n", dir );
310
+				deep_error=1;
311
+	}
312
+	if (deep_error) goto deeperror;
313
+
314
+	*error=0;
315
+	return new_lump;
316
+
317
+deeperror:
318
+	LOG(L_ERR, "ERROR: dup_lump_list_r: out of mem\n");
319
+	free_shallow_lump(new_lump);
320
+	*error=1;
321
+	return 0;
322
+}
323
+
324
+/* shallow pkg copy of a lump list
325
+ *
326
+ * if either original list empty or error occur returns, 0
327
+ * is returned, pointer to the copy otherwise
328
+ */
329
+struct lump* dup_lump_list( struct lump *l )
330
+{
331
+	int deep_error;
332
+
333
+	deep_error=0;
334
+	return dup_lump_list_r(l, LD_NEXT, &deep_error);
335
+}
336
+
337
+void free_duped_lump_list(struct lump* l)
338
+{
339
+	struct lump *r, *foo,*crt;
340
+	while(l){
341
+		crt=l;
342
+		l=l->next;
343
+
344
+		r=crt->before;
345
+		while(r){
346
+			foo=r; r=r->before;
347
+			/* (+): if a new item was introduced to the shallow-ly
348
+			 * duped list, remove it completely, preserve it
349
+			 * othewise (it is still refered by original list)
350
+			 */
351
+			if (foo->flags!=LUMPFLAG_DUPED) 
352
+					free_lump(foo);
353
+			pkg_free(foo);
354
+		}
355
+		r=crt->after;
356
+		while(r){
357
+			foo=r; r=r->after;
358
+			if (foo->flags!=LUMPFLAG_DUPED) /* (+) ... see above */
359
+				free_lump(foo);
360
+			pkg_free(foo);
361
+		}
362
+		
363
+		/*clean current elem*/
364
+		if (crt->flags!=LUMPFLAG_DUPED) /* (+) ... see above */
365
+			free_lump(crt);
366
+		pkg_free(crt);
367
+	}
368
+}
369
+
... ...
@@ -33,6 +33,7 @@
33 33
 
34 34
 
35 35
 enum { LUMP_NOP=0, LUMP_DEL, LUMP_ADD };
36
+enum { LUMPFLAG_NONE=0, LUMPFLAG_DUPED=1, LUMPFLAG_SHMEM=2 };
36 37
 
37 38
 struct lump{
38 39
 	int type; /* VIA, OTHER, UNSPEC(=0), ... */
... ...
@@ -51,6 +52,8 @@ struct lump{
51 51
 							  the current one */
52 52
 	
53 53
 	struct lump* next;
54
+
55
+	int flags; /* additional hints for use from TM's shmem */
54 56
 };
55 57
 
56 58
 /*
... ...
@@ -97,4 +100,9 @@ void free_lump(struct lump* l);
97 97
 /*frees an entire lump list, recursively */
98 98
 void free_lump_list(struct lump* lump_list);
99 99
 
100
+/* duplicates a lump list shallowly in pkg-mem */
101
+struct lump* dup_lump_list( struct lump *l );
102
+/* frees a shallowly duplicated lump list */
103
+void free_duped_lump_list(struct lump* l);
104
+
100 105
 #endif
... ...
@@ -58,6 +58,7 @@
58 58
 	{\
59 59
 		(_new) = (struct lump*)(_ptr);\
60 60
 		memcpy( (_new), (_old), sizeof(struct lump) );\
61
+		(_new)->flags|=LUMPFLAG_SHMEM; \
61 62
 		(_ptr)+=ROUND4(sizeof(struct lump));\
62 63
 		if ( (_old)->op==LUMP_ADD) {\
63 64
 			(_new)->u.value = (char*)(_ptr);\
... ...
@@ -24,6 +24,10 @@
24 24
  * You should have received a copy of the GNU General Public License 
25 25
  * along with this program; if not, write to the Free Software 
26 26
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
+ *
28
+ * History:
29
+ * --------
30
+ * 2003-01-19 faked lump list created in on_reply handlers
27 31
  */
28 32
 
29 33
 
... ...
@@ -39,6 +43,7 @@
39 39
 #include "../../action.h"
40 40
 #include "../../dset.h"
41 41
 #include "../../tags.h"
42
+#include "../../data_lump.h"
42 43
 
43 44
 #include "t_hooks.h"
44 45
 #include "t_funcs.h"
... ...
@@ -107,6 +112,136 @@ static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,
107 107
 }
108 108
 
109 109
 
110
+/* create a temporary faked message environment in which a conserved
111
+ * t->uas.request in shmem is partially duplicated to pkgmem
112
+ * to allow pkg-based actions to use it; 
113
+ *
114
+ * if restore parameter is set, the environment is restored to the
115
+ * original setting and return value is unsignificant (always 0); 
116
+ * otherwise  a faked environment if created; if that fails,
117
+ * false is returned
118
+ */
119
+static int faked_env(struct sip_msg *fake, 
120
+				struct cell *_t,
121
+				struct sip_msg *shmem_msg,
122
+				int _restore )
123
+{
124
+	static enum route_mode backup_mode;
125
+	static struct cell *backup_t;
126
+	static unsigned int backup_msgid;
127
+
128
+	if (_restore) goto restore;
129
+
130
+	/* 
131
+     on_negative_reply faked msg now copied from shmem msg (as opposed
132
+     to zero-ing) -- more "read-only" actions (exec in particular) will 
133
+     work from reply_route as they will see msg->from, etc.; caution, 
134
+     rw actions may append some pkg stuff to msg, which will possibly be 
135
+     never released (shmem is released in a single block)
136
+    */
137
+	memcpy( fake, shmem_msg, sizeof(struct sip_msg));
138
+
139
+	/* if we set msg_id to something different from current's message
140
+       id, the first t_fork will properly clean new branch URIs
141
+	*/
142
+	fake->id=shmem_msg->id-1;
143
+	/* set items, which will be duped to pkg_mem, to zero, so that
144
+	 * "restore" called on error does not free the original items */
145
+	fake->add_rm=0;
146
+	fake->new_uri.s=0; fake->new_uri.len=0; 
147
+
148
+	/* remember we are back in request processing, but process
149
+	 * a shmem-ed replica of the request; advertise it in rmode;
150
+	 * for example t_reply needs to know that
151
+	 */
152
+	backup_mode=rmode;
153
+	rmode=MODE_ONREPLY_REQUEST;
154
+	/* also, tm actions look in beginning whether tranaction is
155
+	 * set -- whether we are called from a reply-processing 
156
+	 * or a timer process, we need to set current transaction;
157
+	 * otherwise the actions would attempt to look the transaction
158
+	 * up (unnecessary overhead, refcounting)
159
+	 */
160
+	/* backup */
161
+	backup_t=get_t();
162
+	backup_msgid=global_msg_id;
163
+	/* fake transaction and message id */
164
+	global_msg_id=fake->id;
165
+	set_t(_t);
166
+
167
+	/* environment is set up now, try to fake the message */
168
+
169
+	/* new_uri can change -- make a private copy */
170
+	if (shmem_msg->new_uri.s!=0 && shmem_msg->new_uri.len!=0) {
171
+		fake->new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1);
172
+		if (!fake->new_uri.s) {
173
+			LOG(L_ERR, "ERROR: faked_env: no uri/pkg mem\n");
174
+			goto restore;
175
+		}
176
+		fake->new_uri.len=shmem_msg->new_uri.len;
177
+		memcpy( fake->new_uri.s, shmem_msg->new_uri.s, 
178
+			fake->new_uri.len);
179
+		fake->new_uri.s[fake->new_uri.len]=0;
180
+	} 
181
+
182
+	/* create a duplicated lump list to which actions can add
183
+	 * new pkg items 
184
+	 */
185
+	if (shmem_msg->add_rm) {
186
+		fake->add_rm=dup_lump_list(shmem_msg->add_rm);
187
+		if (!fake->add_rm) { /* non_emty->empty ... failure */
188
+			LOG(L_ERR, "ERROR: on_negative_reply: lump dup failed\n");
189
+			goto restore;
190
+		}
191
+	}
192
+	/* success */
193
+	return 1;
194
+
195
+restore:
196
+	/* restore original environment and destroy faked message */
197
+	free_duped_lump_list(fake->add_rm);
198
+	if (fake->new_uri.s) pkg_free(fake->new_uri.s);
199
+	set_t(backup_t);
200
+	global_msg_id=backup_msgid;
201
+	rmode=backup_mode;
202
+	return 0;
203
+}
204
+
205
+#ifdef _OBSOLETED
206
+void on_negative_reply( struct cell* t, struct sip_msg* msg, 
207
+	int code, void *param )
208
+{
209
+	int act_ret;
210
+	struct sip_msg faked_msg;
211
+
212
+	/* nobody cares about a negative transaction -- ok, return */
213
+	if (!t->on_negative) {
214
+		DBG("DBG: on_negative_reply: no on_negative\n");
215
+		return;
216
+	}
217
+
218
+	DBG("DBG: on_negative_reply processed for transaction %p\n", t);
219
+	if (!faked_env(&faked_msg, t, t->uas.request, 0 /* create fake */ )) {
220
+		LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
221
+		goto restore;
222
+	}
223
+
224
+	/* run */
225
+	act_ret=run_actions(reply_rlist[t->on_negative], &faked_msg );
226
+	if (act_ret<0) {
227
+		LOG(L_ERR, "ERROR: on_negative_reply: Error in do_action\n");
228
+	}
229
+
230
+
231
+restore:
232
+	faked_env(&faked_msg, 0, 0 /* don't need t and shmem_rq */ , 
233
+					1 /* restore fake */ );
234
+
235
+}
236
+#endif
237
+
238
+
239
+
110 240
 
111 241
 /* the main code of stateful replying */
112 242
 static int _reply( struct cell *t, struct sip_msg* p_msg, unsigned int code,
... ...
@@ -128,6 +263,8 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
128 128
 	branch_bm_t *cancel_bitmap, struct sip_msg *reply )
129 129
 {
130 130
 	int b, lowest_b, lowest_s, dummy;
131
+	struct sip_msg faked_msg, *origin_rq;
132
+	unsigned int on_neg;
131 133
 
132 134
 	/* note: this code never lets replies to CANCEL go through;
133 135
 	   we generate always a local 200 for CANCEL; 200s are
... ...
@@ -207,6 +344,30 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
207 207
 		callback_event( TMCB_ON_NEGATIVE, Trans, 
208 208
 			lowest_b==branch?reply:Trans->uac[lowest_b].reply, 
209 209
 			lowest_s );
210
+
211
+		/* here, we create a faked environment, from which we
212
+		 * return to request processing, if marked to do so */
213
+		origin_rq=Trans->uas.request;
214
+		on_neg=Trans->on_negative;
215
+		if (on_neg) {
216
+			DBG("DBG: on_negative_reply processed for transaction %p\n", 
217
+					Trans);
218
+			if (faked_env(&faked_msg, Trans, Trans->uas.request, 
219
+									0 /* create fake */ )) 
220
+			{
221
+				/* use the faked message later in forwarding */
222
+				origin_rq=&faked_msg;
223
+	  		 	/* run a reply_route action if some was marked */
224
+				if (run_actions(reply_rlist[on_neg], &faked_msg )<0)
225
+					LOG(L_ERR, "ERROR: on_negative_reply: "
226
+						"Error in do_action\n");
227
+			} else { /* faked_env creation error */
228
+				LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
229
+				on_neg=0;
230
+			} 
231
+		} /* if (on_neg) */
232
+
233
+
210 234
 		/* look if the callback perhaps replied transaction; it also
211 235
 		   covers the case in which a transaction is replied localy
212 236
 		   on CANCEL -- then it would make no sense to proceed to
... ...
@@ -221,17 +382,19 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
221 221
 			   put it on wait again; perhaps splitting put_on_wait
222 222
 			   from send_reply or a new RPS_ code would be healthy
223 223
 			*/
224
+			if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
224 225
 			return RPS_COMPLETED;
225 226
 		}
226 227
 		/* look if the callback introduced new branches ... */
227 228
 		init_branch_iterator();
228 229
 		if (next_branch(&dummy)) {
229
-			if (t_forward_nonack(Trans, Trans->uas.request, 
230
+			if (t_forward_nonack(Trans, origin_rq,
230 231
 						(struct proxy_l *) 0 ) <0) {
231 232
 				/* error ... behave as if we did not try to
232 233
 				   add a new branch */
233 234
 				*should_store=0;
234 235
 				*should_relay=lowest_b;
236
+				if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
235 237
 				return RPS_COMPLETED;
236 238
 			}
237 239
 			/* we succeded to launch new branches -- await
... ...
@@ -239,11 +402,13 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
239 239
 			*/
240 240
 			*should_store=1;
241 241
 			*should_relay=-1;
242
+			if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
242 243
 			return RPS_STORE;
243 244
 		}
244 245
 		/* really no more pending branches -- return lowest code */
245 246
 		*should_store=0;
246 247
 		*should_relay=lowest_b;
248
+		if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
247 249
 		/* we dont need 'which_cancel' here -- all branches 
248 250
 		   known to have completed */
249 251
 		/* which_cancel( Trans, cancel_bitmap ); */
... ...
@@ -854,105 +1019,3 @@ done:
854 854
 	return 0;
855 855
 }
856 856
 
857
-
858
-
859
-void on_negative_reply( struct cell* t, struct sip_msg* msg, 
860
-	int code, void *param )
861
-{
862
-	int act_ret;
863
-	struct sip_msg faked_msg;
864
-	enum route_mode backup_mode;
865
-	struct cell *backup_t;
866
-	unsigned int backup_msgid;
867
-
868
-	/* nobody cares about a negative transaction -- ok, return */
869
-	if (!t->on_negative) {
870
-		DBG("DBG: on_negative_reply: no on_negative\n");
871
-		return;
872
-	}
873
-
874
-	DBG("DBG: on_negative_reply processed for transaction %p\n", t);
875
-
876
-	/* create faked environment  -- uri rewriting stuff needs the
877
-	   original uri
878
-	*/
879
-#ifdef _OBSOLETED
880
-	memset( &faked_msg, 0, sizeof( struct sip_msg ));
881
-	faked_msg.flags=t->uas.request->flags;	
882
-	/* original URI doesn't change -- feel free to refer to shmem */
883
-	faked_msg.first_line.u.request.uri=
884
-		t->uas.request->first_line.u.request.uri;
885
-#else
886
-    /* 
887
-     on_negative_reply faked msg now copied from shmem msg (as opposed
888
-     to zero-ing) -- more "read-only" actions (exec in particular) will 
889
-     work from reply_route as they will see msg->from, etc.; caution, 
890
-     rw actions may append some pkg stuff to msg, which will possibly be 
891
-     never released (shmem is released in a single block)
892
-    */
893
-	memcpy( &faked_msg, t->uas.request, sizeof(struct sip_msg));
894
-#endif
895
-	/* new_uri can change -- make a private copy */
896
-	if (t->uas.request->new_uri.s!=0 && t->uas.request->new_uri.len!=0) {
897
-		faked_msg.new_uri.s=pkg_malloc(t->uas.request->new_uri.len+1);
898
-		if (!faked_msg.new_uri.s) return;
899
-		faked_msg.new_uri.len=t->uas.request->new_uri.len;
900
-		memcpy( faked_msg.new_uri.s, t->uas.request->new_uri.s, 
901
-			faked_msg.new_uri.len);
902
-		faked_msg.new_uri.s[faked_msg.new_uri.len]=0;
903
-	} else { faked_msg.new_uri.s=0; faked_msg.new_uri.len=0; }
904
-	/* if we set msg_id to something different from current's message
905
-       id, the first t_fork will properly clean new branch URIs
906
-	*/
907
-	faked_msg.id=t->uas.request->id-1;
908
-
909
-	/* remember we are back in request processing, but process
910
-	 * a shmem-ed replica of the request; advertise it in rmode;
911
-	 * for example t_reply needs to know that
912
-	 */
913
-	backup_mode=rmode;
914
-	rmode=MODE_ONREPLY_REQUEST;
915
-	/* also, tm actions look in beginning whether tranaction is
916
-	 * set -- whether we are called from a reply-processing 
917
-	 * or a timer process, we need to set current transaction;
918
-	 * otherwise the actions would attempt to look the transaction
919
-	 * up (unnecessary overhead, refcounting)
920
-	 */
921
-	/* backup */
922
-	backup_t=get_t();
923
-	backup_msgid=global_msg_id;
924
-	/* fake */
925
-	global_msg_id=faked_msg.id;
926
-	set_t(t);
927
-	/* run */
928
-	act_ret=run_actions(reply_rlist[t->on_negative], &faked_msg );
929
-	/* restore */
930
-	global_msg_id=backup_msgid;
931
-	rmode=backup_mode;
932
-
933
-	if (act_ret<0) {
934
-		LOG(L_ERR, "on_negative_reply: Error in do_action\n");
935
-	}
936
-
937
-#ifdef _OBSOLETED
938
-	/* this didn't work becaue URI is a part of shmem "monoblock";
939
-	   I could split it but it does not seem to be worth the
940
-	   effor
941
-	*/
942
-	/* project changes in faked message back to shmem copy */
943
-	t->uas.request->flags=faked_msg.flags;
944
-	if (faked_msg.new_uri.s) {
945
-		t->uas.request->new_uri.s=shm_resize(t->uas.request->new_uri.s,
946
-			faked_msg.new_uri.len);
947
-		if (!t->uas.request->new_uri.s) goto done;
948
-		memcpy(t->uas.request->new_uri.s, faked_msg.new_uri.s, 
949
-			faked_msg.new_uri.len );
950
-		t->uas.request->new_uri.len=faked_msg.new_uri.len;
951
-	}
952
-done:
953
-#endif
954
-	/* destroy faked environment, new_uri in particular */
955
-	if (faked_msg.new_uri.s) pkg_free(faked_msg.new_uri.s);
956
-}
957
-
958
-
... ...
@@ -348,8 +348,10 @@ static int mod_init(void)
348 348
 		LOG(L_ERR, "ERROR: mod_init: uac_init failed\n");
349 349
 		return -1;
350 350
 	}
351
+#ifdef _OBSO
351 352
 	register_tmcb( TMCB_ON_NEGATIVE, on_negative_reply, 
352 353
 			0 /* empty param */);
354
+#endif
353 355
 	/* register post-script clean-up function */
354 356
 	register_script_cb( w_t_unref, POST_SCRIPT_CB, 
355 357
 			0 /* empty param */ );