Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: 5f65308938f456770638ed5bac4768f94391005b
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=5f65308…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Wed Jun 23 23:17:15 2010 +0200
tcp: change tls send callback interface
Instead of 2 different tls send callbacks (with a 3rd one needed),
switch to a different model: 1 tls callback that is supposed to
replace the passed buffer with a tls processed version of it.
This simplifies the tls code and more importantly doesn't require
that the tls send code has very detailed knowledge about the tcp
state machine. Some of the saved complexity moved from the tls
module to the tcp code, but at least this way on changes there's
only one place to update.
The tls callbacks for reading and sending are now very different:
while the send callback has become now more of an encoder
callback, the read callback should still perform the tcp read by
itself. While this is not very consistent it does saves unneeded
memory copies.
---
tcp_int_send.h | 12 +----
tcp_main.c | 141 +++++++++++++++++++++++++++++++++++++++++---------------
tcp_server.h | 2 +-
tls_hooks.c | 2 +-
tls_hooks.h | 23 ++++-----
5 files changed, 119 insertions(+), 61 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=5f6…
Module: sip-router
Branch: master
Commit: 1b30ae44d71332d7e96221ee444a1aede2d3da01
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1b30ae4…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Wed Jun 23 16:34:56 2010 +0200
dns cache: dns_cache_rec_pref config var added
The config variable, dns_cache_rec_pref, can be used
to set the DNS cache preference as follows:
0 - do not check duplicates (default)
1 - prefer old records
2 - prefer new records
3 - prefer records with longer lifetime
This variable is checked when a duplicated record is
tried to be inserted into the cache. For instance the
SRV query answer contains also an A record which is
already in the cache.
If the config var is not 0, then permanent entries
are always preferred.
Note: works only with #define CACHE_RELEVANT_RECS_ONLY
at the moment.
---
NEWS | 6 ++++++
cfg_core.c | 7 +++++++
cfg_core.h | 1 +
dns_cache.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
4 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/NEWS b/NEWS
index 0112243..5d691cb 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ core:
See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask).
- per message blacklist ignore masks
- route() now supports rvalue expressions (e.g. route("test"+$i))
+ - support for permanent entries in the DNS cache.
new config variables:
- dst_blacklist_udp_imask - global blacklist events ignore mask for udp
@@ -27,6 +28,11 @@ new config variables:
- dst_blacklist_tcp_imask - like dst_blacklist_udp_imask, but for tcp.
- dst_blacklist_tls_imask - like dst_blacklist_tls_imask, but for tcp.
- dst_blacklist_sctp_imask -like dst_blacklist_sctp_imask, but for tcp.
+ - dns_cache_rec_pref - DNS cache record preference:
+ 0 - do not check duplicates (default)
+ 1 - prefer old records
+ 2 - prefer new records
+ 3 - prefer records with longer lifetime
modules:
- blst: functions for ignoring blacklist events per message:
diff --git a/cfg_core.c b/cfg_core.c
index 101ba9f..d819dee 100644
--- a/cfg_core.c
+++ b/cfg_core.c
@@ -102,6 +102,7 @@ struct cfg_group_core default_core_cfg = {
DEFAULT_DNS_CACHE_MAX_TTL, /*!< maximum ttl */
DEFAULT_DNS_MAX_MEM, /*!< dns_cache_max_mem */
0, /*!< dns_cache_del_nonexp -- delete only expired entries by default */
+ 0, /*!< dns_cache_rec_pref -- 0 by default, do not check the existing entries. */
#endif
#ifdef PKG_MALLOC
0, /*!< mem_dump_pkg */
@@ -206,6 +207,12 @@ cfg_def_t core_cfg_def[] = {
{"dns_cache_del_nonexp", CFG_VAR_INT, 0, 1, 0, 0,
"allow deletion of non-expired records from the cache when "
"there is no more space left for new ones"},
+ {"dns_cache_rec_pref", CFG_VAR_INT, 0, 3, 0, 0,
+ "DNS cache record preference: "
+ " 0 - do not check duplicates"
+ " 1 - prefer old records"
+ " 2 - prefer new records"
+ " 3 - prefer records with longer lifetime"},
#endif
#ifdef PKG_MALLOC
{"mem_dump_pkg", CFG_VAR_INT, 0, 0, 0, mem_dump_pkg_cb,
diff --git a/cfg_core.h b/cfg_core.h
index 1e86692..c0d83c8 100644
--- a/cfg_core.h
+++ b/cfg_core.h
@@ -92,6 +92,7 @@ struct cfg_group_core {
unsigned int dns_cache_max_ttl;
unsigned int dns_cache_max_mem;
int dns_cache_del_nonexp;
+ int dns_cache_rec_pref;
#endif
#ifdef PKG_MALLOC
int mem_dump_pkg;
diff --git a/dns_cache.c b/dns_cache.c
index 2ec3d3e..adf2940 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -1874,10 +1874,14 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
struct ip_addr* ip;
str cname_val;
char name_buf[MAX_DNS_NAME];
+ struct dns_hash_entry* old;
+ str rec_name;
+ int add_record, h, err;
e=0;
l=0;
cname_val.s=0;
+ old = NULL;
#ifdef USE_DNS_CACHE_STATS
if (dns_cache_stats)
@@ -1944,10 +1948,55 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
LOCK_DNS_HASH(); /* optimization */
for (r=l; r; r=t){
t=r->next;
- dns_cache_add_unsafe(r); /* refcnt++ inside */
- if (atomic_get(&r->refcnt)==0){
- /* if cache adding failed and nobody else is interested
- * destroy this entry */
+ /* add the new record to the cache by default */
+ add_record = 1;
+ if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
+ /* check whether there is an old record with the
+ * same type in the cache */
+ rec_name.s = r->name;
+ rec_name.len = r->name_len;
+ old = _dns_hash_find(&rec_name, r->type, &h, &err);
+ if (old) {
+ if (old->type != r->type) {
+ /* probably CNAME found */
+ old = NULL;
+
+ } else if (old->ent_flags & DNS_FLAG_PERMANENT) {
+ /* never overwrite permanent entries */
+ add_record = 0;
+
+ } else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
+ /* Non-negative, non-permanent entry found with
+ * the same type. */
+ add_record =
+ /* prefer new records */
+ ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
+ /* prefer the record with the longer lifetime */
+ || ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
+ && TICKS_LT(old->expire, r->expire)));
+ }
+ }
+ }
+ if (add_record) {
+ dns_cache_add_unsafe(r); /* refcnt++ inside */
+ if (atomic_get(&r->refcnt)==0){
+ /* if cache adding failed and nobody else is interested
+ * destroy this entry */
+ dns_destroy_entry(r);
+ }
+ if (old) {
+ _dns_hash_remove(old);
+ old = NULL;
+ }
+ } else {
+ if (old) {
+ if (r == e) {
+ /* this entry has to be returned */
+ e = old;
+ atomic_inc(&e->refcnt);
+ }
+ old = NULL;
+ }
dns_destroy_entry(r);
}
}
Hi all,
i'm happy to announce a new developer for the sip-router project:
Timo Reimann.
Timo is an experienced developer in our offices in Karlsruhe and since over
one year part of the team that develops our VoIP backend services. His past
work involved extensions for the dialog module and also a new lawful
interception solution that we use in-house. He contributed (with some other
developers) to the new dialog design in the last months and will continue to
work on this in the future.
Best regards,
Henning
--
Henning Westerholt - Development Consumer Products / Consumer Core
1&1 Internet AG, Ernst-Frey-Str. 9, 76135 Karlsruhe, Germany
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: 21b8cf904aa6abe20d930385bf912ccf66666341
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=21b8cf9…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Sun Jun 20 19:20:12 2010 +0200
tcp: don't reset read_flags on RD_CONN_REPEAT_READ
Allow flags value propagation between tcp_read*() that asked to be
repeated (RD_CONN_REPEAT_READ). This allows an optimization in the
tls read code: when repeating a tls_read, don't try a tcp read
syscall if the previous attempt did get the whole socket receive
buffer (RD_CONN_SHORT_READ) or detected EOF (use only the buffered
data if any).
---
tcp_read.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/tcp_read.c b/tcp_read.c
index 441521f..4881844 100644
--- a/tcp_read.c
+++ b/tcp_read.c
@@ -137,8 +137,8 @@ static ticks_t tcp_reader_prev_ticks;
* RD_CONN_FORCE_EOF.
* RD_CONN_REPEAT_READ - the read should be repeated immediately
* (used only by the tls code for now).
- * Note: RD_CONN_SHORT_READ & RD_CONN_EOF must be cleared
- * before calling this function.
+ * Note: RD_CONN_SHORT_READ & RD_CONN_EOF _are_ not cleared internally,
+ * so one should clear them before calling this function.
* @return number of bytes read, 0 on EOF or -1 on error,
* on EOF it also sets c->state to S_CONN_EOF.
* (to distinguish from reads that would block which could return 0)
@@ -955,14 +955,14 @@ again:
con, con->id, atomic_get(&con->refcnt));
goto con_error;
}
-#ifdef USE_TLS
-repeat_1st_read:
-#endif /* USE_TLS */
/* if we received the fd there is most likely data waiting to
* be read => process it first to avoid extra sys calls */
read_flags=((con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)) &&
!(con->flags & F_CONN_OOB_DATA))? RD_CONN_FORCE_EOF
:0;
+#ifdef USE_TLS
+repeat_1st_read:
+#endif /* USE_TLS */
resp=tcp_read_req(con, &n, &read_flags);
if (unlikely(resp<0)){
/* some error occured, but on the new fd, not on the tcp
@@ -1011,9 +1011,6 @@ repeat_1st_read:
con, con->id, atomic_get(&con->refcnt));
goto read_error;
}
-#ifdef USE_TLS
-repeat_read:
-#endif /* USE_TLS */
#ifdef POLLRDHUP
read_flags=(((events & POLLRDHUP) |
(con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)))
@@ -1021,6 +1018,9 @@ repeat_read:
#else /* POLLRDHUP */
read_flags=0;
#endif /* POLLRDHUP */
+#ifdef USE_TLS
+repeat_read:
+#endif /* USE_TLS */
resp=tcp_read_req(con, &ret, &read_flags);
if (unlikely(resp<0)){
read_error:
Module: sip-router
Branch: andrei/tcp_tls_changes
Commit: 0d8b211d146dad87a5751928b44c6f791352559a
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0d8b211…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Sun Jun 20 18:58:58 2010 +0200
tls: deal with internal openssl buffering
SSL_read() will not only buffer data internally (behaviour
exacerbated by setting readahead to 1), but will also return the
decrypted data on a record basis (even if readahead is 1 and it
has read several records, it will return only the decrypted data
from the current record). SSL_pending() can be used to see if
there is more data buffered internally only if readaahead is not
set and if the SSL_read() returned because it did not have enough
space in the output buffer (it's useless for any other case
because it returns the bytes in the current record that can be
retrieved immediately and hence if SSL_read() stopped at a record
boundary it will return 0).
The solution is to repeat the SSL_read() call until the output
buffer is completely filled or error (repeat it even if it did
consume the whole input, it could still have the data buffered
internally).
In the case when the output buffer is completely filled, the
entire tls_read_f() call should be retried as soon as more space
becomes available (set RD_CONN_REPEAT_READ).
Fixes read data delayed until the next packet arrives or possible
lost reads (if no other data is sent and part of the previous
data is buffered inside openssl).
---
modules/tls/tls_server.c | 178 +++++++++++++++++++++++++++++++++------------
modules/tls/tls_server.h | 1 -
2 files changed, 130 insertions(+), 49 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=0d8…