This patch does it for me:
---
--- modules/rr/record.c.ori 2010-05-25 13:10:48.000000000 +0200
+++ modules/rr/record.c 2010-05-25 13:37:26.000000000 +0200
@@ -41,6 +41,7 @@
#include "../../data_lump.h"
#include "record.h"
#include "rr_mod.h"
+#include "loose.h"
#define RR_PREFIX "Record-Route: <sip:"
@@ -291,12 +292,20 @@
}
if (append_fromtag) {
- if (parse_from_header(_m) < 0) {
- LM_ERR("From parsing failed\n");
- return -2;
+ if (is_direction(_m, RR_FLOW_UPSTREAM)==0) {
+ /* use to-tag in script! */
+
+ LM_DBG("from-tag not added on upstream request
(it's wrong anyway)! Must be done manually using
record_route(\";ftag=$tt\");");
+
+ tag = 0;
+ } else {
+ if (parse_from_header(_m) < 0) {
+ LM_ERR("From parsing failed\n");
+ return -2;
+ }
+ from = (struct to_body*)_m->from->parsed;
+ tag = &from->tag_value;
}
- from = (struct to_body*)_m->from->parsed;
- tag = &from->tag_value;
} else {
tag = 0;
}
---
Plus in script after loose_route():
if (check_route_param("vsf=")) {
# fix broken UAC not
sending initial route-set
$(var(vsf)) =
$(hdr(Route)[0]{s.select,0,,}{param.value,vsf}{s.select,0,>});
xlog("L_INFO", ">>
Stored UAC param vsf=$(var(vsf))");
if
(is_direction("upstream")) {
record_route(";ftag=$tt;vsf=$(var(vsf))");
} else {
record_route(";vsf=$(var(vsf))");
}
} else {
if
(is_direction("upstream")) {
record_route(";ftag=$tt");
} else {
record_route();
}
}
Br
Walter
Von: sr-dev-bounces(a)lists.sip-router.org
[mailto:sr-dev-bounces@lists.sip-router.org] Im Auftrag von NeoTel Lists
Gesendet: Dienstag, 25. Mai 2010 13:04
An: sr-dev(a)lists.sip-router.org
Betreff: [sr-dev] direction check missing in record_route()
Hi!
Can someone of the experts pls help me with a fix in
record.c/record_route() please?
IMHO in append_fromtag=1 mode the direction check is missing, if
record_route() is called in loose_route block.
(Sure, I know, there is no need to call record_route() there, but since
nearly all of the UA out there don't use first record set on reInvites,
I must do record routing on reInvites, too!)
(And I really do need the vsf parameter in subsequent messages J)
So I would do the following:
if (append_fromtag) {
if (is_direction(_m, RR_FLOW_UPSTREAM)) { /* if not in
dialog, would return 0 anyway, e.g. no Route param ftag present */
/* use to-tag! */
Unfortunately there is no "parse_to_header", bec. then it would be
simple....
How to access the to-tag, if any?
} else {
if (parse_from_header(_m) < 0) {
LM_ERR("From parsing failed\n");
return -2;
}
from = (struct to_body*)_m->from->parsed;
tag = &from->tag_value;
}
} else {
tag = 0;
}
--
What I do now is not nice: I set modparam("rr", "append_fromtag", 0) and
patched rr_mod.c and uac.c not to return an Error, if append_fromtag is
0 J
[root@p01-1 rr]# more ../../../rr_mod.c.patch
--- modules/rr/rr_mod.c.ori 2010-05-25 11:03:29.000000000 +0200
+++ modules/rr/rr_mod.c 2010-05-25 12:08:34.000000000 +0200
@@ -172,9 +172,10 @@
int n;
if (!append_fromtag) {
- LM_ERR("usage of \"is_direction\" function requires
parameter"
- "\"append_fromtag\" enabled!!");
- return E_CFG;
+ LM_WARN("usage of \"is_direction\" function requires
parameter"
+ "\"append_fromtag\" enabled!!"
+ " - must be done manually to work
correctly!");
+ /* return E_CFG; */
}
if (param_no==1) {
n = 0;
[root@p01-1 rr]# more ../../../uac.c.patch
--- modules/uac/uac.c.orig 2010-05-25 10:57:59.000000000 +0200
+++ modules/uac/uac.c 2010-05-25 11:00:40.000000000 +0200
@@ -206,9 +206,13 @@
if (from_restore_mode==FROM_AUTO_RESTORE) {
/* we need the append_fromtag on in RR */
if (!uac_rrb.append_fromtag) {
- LM_ERR("'append_fromtag' RR param is not
enabled!"
- " - required by AUTO restore
mode\n");
- goto error;
+ LM_WARN("'append_fromtag' RR param is
not enabled!"
+ " - required by AUTO restore
mode"
+ " - make sure it's done
manually!\n");
+ /* normally ERR, but just remind script
writer, that she has to do ;ftag=$ft/$tt manually
+ normally this would be OK, but
record_route() add $ft in upsteam request
+ should be fixed in rr module!
+ goto error; */
}
/* get all requests doing loose route */
if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
--
Many thanks!
Walter
---------------------------------------
NeoTel Telefonservice GmbH & Co KG
Esterhazygasse 18a/15
A-1060 Wien
T: +43 1 4094181 - 81
M: +43 660 88866 - 81
F: +43 1 4094181 - 981
Hi!
Can someone of the experts pls help me with a fix in
record.c/record_route() please?
IMHO in append_fromtag=1 mode the direction check is missing, if
record_route() is called in loose_route block.
(Sure, I know, there is no need to call record_route() there, but since
nearly all of the UA out there don't use first record set on reInvites,
I must do record routing on reInvites, too!)
(And I really do need the vsf parameter in subsequent messages J)
So I would do the following:
if (append_fromtag) {
if (is_direction(_m, RR_FLOW_UPSTREAM)) { /* if not in
dialog, would return 0 anyway, e.g. no Route param ftag present */
/* use to-tag! */
Unfortunately there is no "parse_to_header", bec. then it would be
simple....
How to access the to-tag, if any?
} else {
if (parse_from_header(_m) < 0) {
LM_ERR("From parsing failed\n");
return -2;
}
from = (struct to_body*)_m->from->parsed;
tag = &from->tag_value;
}
} else {
tag = 0;
}
--
What I do now is not nice: I set modparam("rr", "append_fromtag", 0) and
patched rr_mod.c and uac.c not to return an Error, if append_fromtag is
0 J
[root@p01-1 rr]# more ../../../rr_mod.c.patch
--- modules/rr/rr_mod.c.ori 2010-05-25 11:03:29.000000000 +0200
+++ modules/rr/rr_mod.c 2010-05-25 12:08:34.000000000 +0200
@@ -172,9 +172,10 @@
int n;
if (!append_fromtag) {
- LM_ERR("usage of \"is_direction\" function requires
parameter"
- "\"append_fromtag\" enabled!!");
- return E_CFG;
+ LM_WARN("usage of \"is_direction\" function requires
parameter"
+ "\"append_fromtag\" enabled!!"
+ " - must be done manually to work
correctly!");
+ /* return E_CFG; */
}
if (param_no==1) {
n = 0;
[root@p01-1 rr]# more ../../../uac.c.patch
--- modules/uac/uac.c.orig 2010-05-25 10:57:59.000000000 +0200
+++ modules/uac/uac.c 2010-05-25 11:00:40.000000000 +0200
@@ -206,9 +206,13 @@
if (from_restore_mode==FROM_AUTO_RESTORE) {
/* we need the append_fromtag on in RR */
if (!uac_rrb.append_fromtag) {
- LM_ERR("'append_fromtag' RR param is not
enabled!"
- " - required by AUTO restore
mode\n");
- goto error;
+ LM_WARN("'append_fromtag' RR param is
not enabled!"
+ " - required by AUTO restore
mode"
+ " - make sure it's done
manually!\n");
+ /* normally ERR, but just remind script
writer, that she has to do ;ftag=$ft/$tt manually
+ normally this would be OK, but
record_route() add $ft in upsteam request
+ should be fixed in rr module!
+ goto error; */
}
/* get all requests doing loose route */
if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
--
Many thanks!
Walter
---------------------------------------
NeoTel Telefonservice GmbH & Co KG
Esterhazygasse 18a/15
A-1060 Wien
T: +43 1 4094181 - 81
M: +43 660 88866 - 81
F: +43 1 4094181 - 981
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: 93c495f34ebb001f9509db82acad5a7483b61d41
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=93c495f…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Thu May 20 18:24:38 2010 +0200
tls: async support (major tls core rewrite)
The new tls hook interface (exported by the tcp code) is now used.
All the IO operations are made through a custom SSL BIO, that
reads and writes in some memory buffers (see tls_bio.h), while
externally emulating a socket. This BIO provides in fact some
functions that will be called by the openssl code on IO.
In the case of a read event, the data is first read in memory
(using tcp_read_data()), then assigned to the BIO and after that
one of SSL_read(), SSL_connect/accept (if the connection is not
yet established) or SSL_write (if the last write wanted to read
some data due to re-keying) are called. They will all read from
the custom BIO. A SSL_read() might not use all the data (in some
very unlikely situations), so in this case the encrypted data is
queued and the tcp code is signaled (via some flags) that it
should repeat the read call when more space is available.
Writes are split in 2: 1st write on a new connection in async mode
and other writes (they need to be handled slightly differently).
The encrypted data will end up in a memory buffer (via SSL_write()
and the custom BIO). From there it will be either sent directly if
possible or queued (tcp_async). In the case when the SSL_write()
needs to read some data (e.g. re-keying), the whole clear text
data will be queued and the SSL_write() will be retried on the
first read event.
There is no separate async mode for tls, if tcp is in async mode,
then tls will be too and vice versa.
Runtime tunning (queue sizes a.s.o) and statistics are missing for
now.
(C) and license changes:
- moved tls_dump_verification_failure into a separate file
(tls_dump_vf.c), out of tls_server.c.
- the remaining tcp_server.[ch] code is either re-written (most of it,
the entire read & write part) or comes from old iptel code =>
changed the (c) to iptelorg only and the license to BSD-like
(only for tcp_server.[ch]).
---
modules/tls/tls_dump_vf.c | 144 ++++++
modules/tls/tls_dump_vf.h | 41 ++
modules/tls/tls_init.c | 2 +
modules/tls/tls_mod.c | 34 +-
modules/tls/tls_server.c | 1105 ++++++++++++++++++++++++---------------------
modules/tls/tls_server.h | 76 ++--
6 files changed, 831 insertions(+), 571 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=93c…
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: c914809c9f70fe15d1a2459fa0668d722d83726c
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c914809…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Thu May 20 16:22:16 2010 +0200
tls: added a minimum overhead shm buffer queue
Minimum overhead buffer queue in shm memory, based on
tcp_wbuffer_queue (tcp_conn.h).
---
modules/tls/sbufq.h | 292 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 292 insertions(+), 0 deletions(-)
diff --git a/modules/tls/sbufq.h b/modules/tls/sbufq.h
new file mode 100644
index 0000000..6b59751
--- /dev/null
+++ b/modules/tls/sbufq.h
@@ -0,0 +1,292 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 iptelorg GmbH
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/** minimal overhead buffer queue in shm memory.
+ * @file modules/tls/sbufq.h
+ * @ingroup: tls
+ * Module: @ref tls
+ */
+/*
+ * History:
+ * --------
+ * 2010-03-31 initial version, based on tcp_conn.h tcp_wbuffer_queue (andrei)
+*/
+
+#ifndef __sbufq_h
+#define __sbufq_h
+
+#include "../../compiler_opt.h"
+#include "../../ut.h"
+#include "../../mem/shm_mem.h"
+#include "../../timer_ticks.h"
+#include "../../timer.h"
+#include "../../dprint.h"
+#include <string.h>
+
+
+struct sbuf_elem {
+ struct sbuf_elem* next;
+ unsigned int b_size; /**< buf size */
+ char buf[1]; /**< variable size buffer */
+};
+
+struct sbuffer_queue {
+ struct sbuf_elem* first;
+ struct sbuf_elem* last;
+ ticks_t last_chg; /**< last change (creation time or partial flush)*/
+ unsigned int queued; /**< total size */
+ unsigned int offset; /**< offset in the first buffer where unflushed data
+ starts */
+ unsigned int last_used; /**< how much of the last buffer is used */
+};
+
+
+/* sbufq_flush() output flags */
+#define F_BUFQ_EMPTY 1
+#define F_BUFQ_ERROR_FLUSH 2
+
+
+#define sbufq_empty(bq) ((bq)->first==0)
+#define sbufq_non_empty(bq) ((bq)->first!=0)
+
+
+
+/** adds/appends data to a buffer queue.
+ * WARNING: it does no attempt to synchronize access/lock. If needed it should
+ * be called under lock.
+ * @param q - buffer queue
+ * @param data
+ * @param size
+ * @param min_buf_size - min size to allocate for new buffer elements
+ * @return 0 on success, -1 on error (mem. allocation)
+ */
+inline static int sbufq_add(struct sbuffer_queue* q, const void* data,
+ unsigned int size, unsigned int min_buf_size)
+{
+ struct sbuf_elem* b;
+ unsigned int last_free;
+ unsigned int b_size;
+ unsigned int crt_size;
+ ticks_t t;
+
+ t=get_ticks_raw();
+
+ if (likely(q->last==0)) {
+ b_size=MAX_unsigned(min_buf_size, size);
+ b=shm_malloc(sizeof(*b)+b_size-sizeof(b->buf));
+ if (unlikely(b==0))
+ goto error;
+ b->b_size=b_size;
+ b->next=0;
+ q->last=b;
+ q->first=b;
+ q->last_used=0;
+ q->offset=0;
+ q->last_chg=get_ticks_raw();
+ last_free=b_size;
+ crt_size=size;
+ goto data_cpy;
+ }else{
+ b=q->last;
+ }
+
+ while(size){
+ last_free=b->b_size-q->last_used;
+ if (last_free==0){
+ b_size=MAX_unsigned(min_buf_size, size);
+ b=shm_malloc(sizeof(*b)+b_size-sizeof(b->buf));
+ if (unlikely(b==0))
+ goto error;
+ b->b_size=b_size;
+ b->next=0;
+ q->last->next=b;
+ q->last=b;
+ q->last_used=0;
+ last_free=b->b_size;
+ }
+ crt_size=MIN_unsigned(last_free, size);
+data_cpy:
+ memcpy(b->buf+q->last_used, data, crt_size);
+ q->last_used+=crt_size;
+ size-=crt_size;
+ data+=crt_size;
+ q->queued+=crt_size;
+ }
+ return 0;
+error:
+ return -1;
+}
+
+
+
+/** inserts data (at the beginning) in a buffer queue.
+ * Note: should never be called after sbufq_run().
+ * WARNING: it does no attempt to synchronize access/lock. If needed it should
+ * be called under lock.
+ * @param q - buffer queue
+ * @param data
+ * @param size
+ * @param min_buf_size - min size to allocate for new buffer elements
+ * @return 0 on success, -1 on error (mem. allocation)
+ */
+inline static int sbufq_insert(struct sbuffer_queue* q, const void* data,
+ unsigned int size, unsigned int min_buf_size)
+{
+ struct sbuf_elem* b;
+
+ if (likely(q->first==0)) /* if empty, use sbufq_add */
+ return sbufq_add(q, data, size, min_buf_size);
+
+ if (unlikely(q->offset)){
+ LOG(L_CRIT, "BUG: non-null offset %d (bad call, should"
+ "never be called after sbufq_run())\n", q->offset);
+ goto error;
+ }
+ if ((q->first==q->last) && ((q->last->b_size-q->last_used)>=size)){
+ /* one block with enough space in it for size bytes */
+ memmove(q->first->buf+size, q->first->buf, size);
+ memcpy(q->first->buf, data, size);
+ q->last_used+=size;
+ }else{
+ /* create a size bytes block directly */
+ b=shm_malloc(sizeof(*b)+size-sizeof(b->buf));
+ if (unlikely(b==0))
+ goto error;
+ b->b_size=size;
+ /* insert it */
+ b->next=q->first;
+ q->first=b;
+ memcpy(b->buf, data, size);
+ }
+
+ q->queued+=size;
+ return 0;
+error:
+ return -1;
+}
+
+
+/** destroy a buffer queue.
+ * Only the content is destroyed (shm_free()'d), the queue head is
+ * re-intialized.
+ * WARNING: it does no attempt to synchronize access/lock. If needed it should
+ * be called under lock.
+ * @param q - buffer queue
+ * @return - number of bytes that used to be queued (>=0).
+ */
+inline static unsigned int sbufq_destroy(struct sbuffer_queue* q)
+{
+ struct sbuf_elem* b;
+ struct sbuf_elem* next_b;
+ int unqueued;
+
+ unqueued=0;
+ if (likely(q->first)){
+ b=q->first;
+ do{
+ next_b=b->next;
+ unqueued+=(b==q->last)?q->last_used:b->b_size;
+ if (b==q->first)
+ unqueued-=q->offset;
+ shm_free(b);
+ b=next_b;
+ }while(b);
+ }
+ memset(q, 0, sizeof(*q));
+ return unqueued;
+}
+
+
+
+/** tries to flush the queue.
+ * Tries to flush as much as possible from the given queue, using the
+ * given callback.
+ * WARNING: it does no attempt to synchronize access/lock. If needed it should
+ * be called under lock.
+ * @param q - buffer queue
+ * @param *flags - set to:
+ * F_BUFQ_EMPTY if the queued is completely flushed
+ * F_BUFQ_ERROR_FLUSH if the flush_f callback returned error.
+ * @param flush_f - flush function (callback). modeled after write():
+ * flush_f(param1, param2, const void* buf, unsigned size).
+ * It should return the number of bytes "flushed" on
+ * success, or <0 on error. If the number of bytes
+ * "flushed" is smaller then the requested size, it
+ * would be assumed that no more bytes can be flushed
+ * and sbufq_flush will exit.
+ * @param flush_p1 - parameter for the flush function callback.
+ * @param flush_p2 - parameter for the flush function callback.
+ * @return -1 on internal error, or the number of bytes flushed on
+ * success (>=0). Note that the flags param is
+ * always set and it should be used to check for errors, since
+ * a flush_f() failure will not result in a negative return.
+ */
+inline static int sbufq_flush(struct sbuffer_queue* q, int* flags,
+ int (*flush_f)(void* p1, void* p2,
+ const void* buf,
+ unsigned size),
+ void* flush_p1, void* flush_p2)
+{
+ struct sbuf_elem *b;
+ int n;
+ int ret;
+ int block_size;
+ char* buf;
+
+ *flags=0;
+ ret=0;
+ while(q->first){
+ block_size=((q->first==q->last)?q->last_used:q->first->b_size)-
+ q->offset;
+ buf=q->first->buf+q->offset;
+ n=flush_f(flush_p1, flush_p2, buf, block_size);
+ if (likely(n>0)){
+ ret+=n;
+ if (likely(n==block_size)){
+ b=q->first;
+ q->first=q->first->next;
+ shm_free(b);
+ q->offset=0;
+ q->queued-=block_size;
+ ret+=block_size;
+ }else{
+ q->offset+=n;
+ q->queued-=n;
+ ret+=n;
+ break;
+ }
+ }else{
+ if (unlikely(n<0))
+ *flags|=F_BUFQ_ERROR_FLUSH;
+ break;
+ }
+ }
+ if (likely(q->first==0)){
+ q->last=0;
+ q->last_used=0;
+ q->offset=0;
+ *flags|=F_BUFQ_EMPTY;
+ }
+ return ret;
+}
+
+
+
+
+#endif /*__sbufq_h*/
+
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: c38de320d864507b38d6f99beb649fef9211a3cf
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c38de32…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Thu May 20 16:26:22 2010 +0200
tls: clear text write queue implementation
In some cases the not-yet-encrypted data must be queued on write
and the write retried later (e.g. a SSL_write returns WANT_READ
because of an ongoing re-keying or trying to write while the SSL
connection is not yet fully established).
---
modules/tls/tls_ct_q.h | 131 ++++++++++++++++++++++++++++++++++++
modules/tls/tls_ct_wrq.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++
modules/tls/tls_ct_wrq.h | 53 +++++++++++++++
3 files changed, 348 insertions(+), 0 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=c38…
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: ce51fbb84e56921030b62d8617db2365ad934b51
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ce51fbb…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Thu May 20 16:00:29 2010 +0200
tcp: new tls hooks interface and async tls changes
- new tls hooks interface that better accommodates tls async use.
Changed read() (takes an extra flags parameter now), removed
blocking_write() and fix_read_con(), added do_send() and
fst_send() (both of them handle snd_flags now and might return a
command that should be sent to tcp_main).
- more tcp send functions (tcpconn_1st_send(),
tcpconn_send_unsafe()) and more send functions exported
(tls_int_send.h) for use from the tls module.
- split tcp_read() into tcp_read() and tcp_read_data() and
exported tcp_read_data() (tcp_read.h).
- support for repeating a tcp_read() if indicated
(RD_CONN_REPEAT_READ), needed for tls.
---
tcp_int_send.h | 50 +++++
tcp_main.c | 651 ++++++++++++++++++++++++++++++++------------------------
tcp_read.c | 144 ++++++++-----
tcp_read.h | 46 ++++
tls_hooks.h | 31 ++--
5 files changed, 579 insertions(+), 343 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=ce5…