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 46
 /* WARNING: all lump add/insert operations excpect a pkg_malloc'ed char* 
43 47
  * pointer the will be DEALLOCATED when the sip_msg is destroyed! */
44 48
 
49
+enum lump_dir { LD_NEXT, LD_BEFORE, LD_AFTER };
45 50
 
46 51
 /* adds a header to the end
47 52
  * returns  pointer on success, 0 on error */
... ...
@@ -248,3 +253,122 @@ void free_lump_list(struct lump* l)
248 253
 		pkg_free(crt);
249 254
 	}
250 255
 }
256
+
257
+/* free (shallow-ly) a lump and its after/before lists */
258
+static void free_shallow_lump( struct lump *l )
259
+{
260
+	struct lump *r, *foo;
261
+
262
+	r=l->before;
263
+	while(r){
264
+		foo=r; r=r->before;
265
+		pkg_free(foo);
266
+	}
267
+	r=l->after;
268
+	while(r){
269
+		foo=r; r=r->after;
270
+		pkg_free(foo);
271
+	}
272
+	pkg_free(l);
273
+}
274
+
275
+/* duplicate (shallow-ly) a lump list into pkg memory */
276
+static struct lump *dup_lump_list_r( struct lump *l, 
277
+				enum lump_dir dir, int *error)
278
+{
279
+	int deep_error;
280
+	struct lump *new_lump;
281
+
282
+	deep_error=0; /* optimist: assume success in recursion */
283
+	/* if at list end, terminate recursion successfully */
284
+	if (!l) { *error=0; return 0; }
285
+	/* otherwise duplicate current element */
286
+	new_lump=pkg_malloc(sizeof(struct lump));
287
+	if (!new_lump) { *error=1; return 0; }
288
+
289
+	memcpy(new_lump, l, sizeof(struct lump));
290
+	new_lump->flags=LUMPFLAG_DUPED;
291
+	new_lump->next=new_lump->before=new_lump->after=0;
292
+
293
+	switch(dir) {
294
+		case LD_NEXT:	
295
+				new_lump->before=dup_lump_list_r(l->before, 
296
+								LD_BEFORE, &deep_error);
297
+				if (deep_error) goto deeperror;
298
+				new_lump->after=dup_lump_list_r(l->after, 
299
+								LD_AFTER, &deep_error);
300
+				if (deep_error) goto deeperror;
301
+				new_lump->next=dup_lump_list_r(l->next, 
302
+								LD_NEXT, &deep_error);
303
+				break;
304
+		case LD_BEFORE:
305
+				new_lump->before=dup_lump_list_r(l->before, 
306
+								LD_BEFORE, &deep_error);
307
+				break;
308
+		case LD_AFTER:
309
+				new_lump->after=dup_lump_list_r(l->after, 
310
+								LD_AFTER, &deep_error);
311
+				break;
312
+		default:
313
+				LOG(L_CRIT, "BUG: dup_limp_list_r: unknown dir: "
314
+						"%d\n", dir );
315
+				deep_error=1;
316
+	}
317
+	if (deep_error) goto deeperror;
318
+
319
+	*error=0;
320
+	return new_lump;
321
+
322
+deeperror:
323
+	LOG(L_ERR, "ERROR: dup_lump_list_r: out of mem\n");
324
+	free_shallow_lump(new_lump);
325
+	*error=1;
326
+	return 0;
327
+}
328
+
329
+/* shallow pkg copy of a lump list
330
+ *
331
+ * if either original list empty or error occur returns, 0
332
+ * is returned, pointer to the copy otherwise
333
+ */
334
+struct lump* dup_lump_list( struct lump *l )
335
+{
336
+	int deep_error;
337
+
338
+	deep_error=0;
339
+	return dup_lump_list_r(l, LD_NEXT, &deep_error);
340
+}
341
+
342
+void free_duped_lump_list(struct lump* l)
343
+{
344
+	struct lump *r, *foo,*crt;
345
+	while(l){
346
+		crt=l;
347
+		l=l->next;
348
+
349
+		r=crt->before;
350
+		while(r){
351
+			foo=r; r=r->before;
352
+			/* (+): if a new item was introduced to the shallow-ly
353
+			 * duped list, remove it completely, preserve it
354
+			 * othewise (it is still refered by original list)
355
+			 */
356
+			if (foo->flags!=LUMPFLAG_DUPED) 
357
+					free_lump(foo);
358
+			pkg_free(foo);
359
+		}
360
+		r=crt->after;
361
+		while(r){
362
+			foo=r; r=r->after;
363
+			if (foo->flags!=LUMPFLAG_DUPED) /* (+) ... see above */
364
+				free_lump(foo);
365
+			pkg_free(foo);
366
+		}
367
+		
368
+		/*clean current elem*/
369
+		if (crt->flags!=LUMPFLAG_DUPED) /* (+) ... see above */
370
+			free_lump(crt);
371
+		pkg_free(crt);
372
+	}
373
+}
374
+
... ...
@@ -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 52
 							  the current one */
52 53
 	
53 54
 	struct lump* next;
55
+
56
+	int flags; /* additional hints for use from TM's shmem */
54 57
 };
55 58
 
56 59
 /*
... ...
@@ -97,4 +100,9 @@ void free_lump(struct lump* l);
97 100
 /*frees an entire lump list, recursively */
98 101
 void free_lump_list(struct lump* lump_list);
99 102
 
103
+/* duplicates a lump list shallowly in pkg-mem */
104
+struct lump* dup_lump_list( struct lump *l );
105
+/* frees a shallowly duplicated lump list */
106
+void free_duped_lump_list(struct lump* l);
107
+
100 108
 #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 43
 #include "../../action.h"
40 44
 #include "../../dset.h"
41 45
 #include "../../tags.h"
46
+#include "../../data_lump.h"
42 47
 
43 48
 #include "t_hooks.h"
44 49
 #include "t_funcs.h"
... ...
@@ -107,6 +112,136 @@ static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,
107 112
 }
108 113
 
109 114
 
115
+/* create a temporary faked message environment in which a conserved
116
+ * t->uas.request in shmem is partially duplicated to pkgmem
117
+ * to allow pkg-based actions to use it; 
118
+ *
119
+ * if restore parameter is set, the environment is restored to the
120
+ * original setting and return value is unsignificant (always 0); 
121
+ * otherwise  a faked environment if created; if that fails,
122
+ * false is returned
123
+ */
124
+static int faked_env(struct sip_msg *fake, 
125
+				struct cell *_t,
126
+				struct sip_msg *shmem_msg,
127
+				int _restore )
128
+{
129
+	static enum route_mode backup_mode;
130
+	static struct cell *backup_t;
131
+	static unsigned int backup_msgid;
132
+
133
+	if (_restore) goto restore;
134
+
135
+	/* 
136
+     on_negative_reply faked msg now copied from shmem msg (as opposed
137
+     to zero-ing) -- more "read-only" actions (exec in particular) will 
138
+     work from reply_route as they will see msg->from, etc.; caution, 
139
+     rw actions may append some pkg stuff to msg, which will possibly be 
140
+     never released (shmem is released in a single block)
141
+    */
142
+	memcpy( fake, shmem_msg, sizeof(struct sip_msg));
143
+
144
+	/* if we set msg_id to something different from current's message
145
+       id, the first t_fork will properly clean new branch URIs
146
+	*/
147
+	fake->id=shmem_msg->id-1;
148
+	/* set items, which will be duped to pkg_mem, to zero, so that
149
+	 * "restore" called on error does not free the original items */
150
+	fake->add_rm=0;
151
+	fake->new_uri.s=0; fake->new_uri.len=0; 
152
+
153
+	/* remember we are back in request processing, but process
154
+	 * a shmem-ed replica of the request; advertise it in rmode;
155
+	 * for example t_reply needs to know that
156
+	 */
157
+	backup_mode=rmode;
158
+	rmode=MODE_ONREPLY_REQUEST;
159
+	/* also, tm actions look in beginning whether tranaction is
160
+	 * set -- whether we are called from a reply-processing 
161
+	 * or a timer process, we need to set current transaction;
162
+	 * otherwise the actions would attempt to look the transaction
163
+	 * up (unnecessary overhead, refcounting)
164
+	 */
165
+	/* backup */
166
+	backup_t=get_t();
167
+	backup_msgid=global_msg_id;
168
+	/* fake transaction and message id */
169
+	global_msg_id=fake->id;
170
+	set_t(_t);
171
+
172
+	/* environment is set up now, try to fake the message */
173
+
174
+	/* new_uri can change -- make a private copy */
175
+	if (shmem_msg->new_uri.s!=0 && shmem_msg->new_uri.len!=0) {
176
+		fake->new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1);
177
+		if (!fake->new_uri.s) {
178
+			LOG(L_ERR, "ERROR: faked_env: no uri/pkg mem\n");
179
+			goto restore;
180
+		}
181
+		fake->new_uri.len=shmem_msg->new_uri.len;
182
+		memcpy( fake->new_uri.s, shmem_msg->new_uri.s, 
183
+			fake->new_uri.len);
184
+		fake->new_uri.s[fake->new_uri.len]=0;
185
+	} 
186
+
187
+	/* create a duplicated lump list to which actions can add
188
+	 * new pkg items 
189
+	 */
190
+	if (shmem_msg->add_rm) {
191
+		fake->add_rm=dup_lump_list(shmem_msg->add_rm);
192
+		if (!fake->add_rm) { /* non_emty->empty ... failure */
193
+			LOG(L_ERR, "ERROR: on_negative_reply: lump dup failed\n");
194
+			goto restore;
195
+		}
196
+	}
197
+	/* success */
198
+	return 1;
199
+
200
+restore:
201
+	/* restore original environment and destroy faked message */
202
+	free_duped_lump_list(fake->add_rm);
203
+	if (fake->new_uri.s) pkg_free(fake->new_uri.s);
204
+	set_t(backup_t);
205
+	global_msg_id=backup_msgid;
206
+	rmode=backup_mode;
207
+	return 0;
208
+}
209
+
210
+#ifdef _OBSOLETED
211
+void on_negative_reply( struct cell* t, struct sip_msg* msg, 
212
+	int code, void *param )
213
+{
214
+	int act_ret;
215
+	struct sip_msg faked_msg;
216
+
217
+	/* nobody cares about a negative transaction -- ok, return */
218
+	if (!t->on_negative) {
219
+		DBG("DBG: on_negative_reply: no on_negative\n");
220
+		return;
221
+	}
222
+
223
+	DBG("DBG: on_negative_reply processed for transaction %p\n", t);
224
+	if (!faked_env(&faked_msg, t, t->uas.request, 0 /* create fake */ )) {
225
+		LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
226
+		goto restore;
227
+	}
228
+
229
+	/* run */
230
+	act_ret=run_actions(reply_rlist[t->on_negative], &faked_msg );
231
+	if (act_ret<0) {
232
+		LOG(L_ERR, "ERROR: on_negative_reply: Error in do_action\n");
233
+	}
234
+
235
+
236
+restore:
237
+	faked_env(&faked_msg, 0, 0 /* don't need t and shmem_rq */ , 
238
+					1 /* restore fake */ );
239
+
240
+}
241
+#endif
242
+
243
+
244
+
110 245
 
111 246
 /* the main code of stateful replying */
112 247
 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 263
 	branch_bm_t *cancel_bitmap, struct sip_msg *reply )
129 264
 {
130 265
 	int b, lowest_b, lowest_s, dummy;
266
+	struct sip_msg faked_msg, *origin_rq;
267
+	unsigned int on_neg;
131 268
 
132 269
 	/* note: this code never lets replies to CANCEL go through;
133 270
 	   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 344
 		callback_event( TMCB_ON_NEGATIVE, Trans, 
208 345
 			lowest_b==branch?reply:Trans->uac[lowest_b].reply, 
209 346
 			lowest_s );
347
+
348
+		/* here, we create a faked environment, from which we
349
+		 * return to request processing, if marked to do so */
350
+		origin_rq=Trans->uas.request;
351
+		on_neg=Trans->on_negative;
352
+		if (on_neg) {
353
+			DBG("DBG: on_negative_reply processed for transaction %p\n", 
354
+					Trans);
355
+			if (faked_env(&faked_msg, Trans, Trans->uas.request, 
356
+									0 /* create fake */ )) 
357
+			{
358
+				/* use the faked message later in forwarding */
359
+				origin_rq=&faked_msg;
360
+	  		 	/* run a reply_route action if some was marked */
361
+				if (run_actions(reply_rlist[on_neg], &faked_msg )<0)
362
+					LOG(L_ERR, "ERROR: on_negative_reply: "
363
+						"Error in do_action\n");
364
+			} else { /* faked_env creation error */
365
+				LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
366
+				on_neg=0;
367
+			} 
368
+		} /* if (on_neg) */
369
+
370
+
210 371
 		/* look if the callback perhaps replied transaction; it also
211 372
 		   covers the case in which a transaction is replied localy
212 373
 		   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 382
 			   put it on wait again; perhaps splitting put_on_wait
222 383
 			   from send_reply or a new RPS_ code would be healthy
223 384
 			*/
385
+			if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
224 386
 			return RPS_COMPLETED;
225 387
 		}
226 388
 		/* look if the callback introduced new branches ... */
227 389
 		init_branch_iterator();
228 390
 		if (next_branch(&dummy)) {
229
-			if (t_forward_nonack(Trans, Trans->uas.request, 
391
+			if (t_forward_nonack(Trans, origin_rq,
230 392
 						(struct proxy_l *) 0 ) <0) {
231 393
 				/* error ... behave as if we did not try to
232 394
 				   add a new branch */
233 395
 				*should_store=0;
234 396
 				*should_relay=lowest_b;
397
+				if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
235 398
 				return RPS_COMPLETED;
236 399
 			}
237 400
 			/* 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 402
 			*/
240 403
 			*should_store=1;
241 404
 			*should_relay=-1;
405
+			if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
242 406
 			return RPS_STORE;
243 407
 		}
244 408
 		/* really no more pending branches -- return lowest code */
245 409
 		*should_store=0;
246 410
 		*should_relay=lowest_b;
411
+		if (on_neg) faked_env(&faked_msg, 0, 0, 1 );
247 412
 		/* we dont need 'which_cancel' here -- all branches 
248 413
 		   known to have completed */
249 414
 		/* which_cancel( Trans, cancel_bitmap ); */
... ...
@@ -854,105 +1019,3 @@ done:
854 1019
 	return 0;
855 1020
 }
856 1021
 
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 */ );