[asterisk-commits] jamesgolovich: branch group/sip-tcptls r89525 - in /team/group/sip-tcptls: ch...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Nov 22 00:12:12 CST 2007
Author: jamesgolovich
Date: Thu Nov 22 00:12:11 2007
New Revision: 89525
URL: http://svn.digium.com/view/asterisk?view=rev&rev=89525
Log:
Update TLS code.
This code has been tested to another asterisk box (TCP and TLS),
Minisip (TCP and TLS), and a cisco IOS gateway (TCP only).
Modified:
team/group/sip-tcptls/channels/chan_sip.c
team/group/sip-tcptls/include/asterisk/server.h
team/group/sip-tcptls/main/server.c
Modified: team/group/sip-tcptls/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/sip-tcptls/channels/chan_sip.c?view=diff&rev=89525&r1=89524&r2=89525
==============================================================================
--- team/group/sip-tcptls/channels/chan_sip.c (original)
+++ team/group/sip-tcptls/channels/chan_sip.c Thu Nov 22 00:12:11 2007
@@ -1380,6 +1380,8 @@
struct sip_threadinfo {
int stop;
pthread_t threadid;
+ struct server_instance *ser;
+ enum sip_transport type; /* We keep a copy of the type here so we can display it in the connection list */
AST_LIST_ENTRY(sip_threadinfo) list;
};
@@ -1947,8 +1949,7 @@
/*! \brief SIP TCP helper function */
static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct server_instance *ser)
{
- int cl;
- char buf[1024];
+ int res;
struct sip_request req = { 0, }, reqcpy = { 0, };
struct sip_threadinfo *me;
@@ -1958,6 +1959,12 @@
goto cleanup2;
me->threadid = pthread_self();
+ me->ser = ser;
+ if (ser->ssl)
+ me->type = SIP_TRANSPORT_TLS;
+ else
+ me->type = SIP_TRANSPORT_TCP;
+
AST_LIST_INSERT_TAIL(&threadl, me, list);
req.socket.lock = ast_calloc(1, sizeof(*req.socket.lock));
@@ -1968,50 +1975,44 @@
ast_mutex_init(req.socket.lock);
for (;;) {
- bzero(req.data, sizeof(req.data));
+ memset(req.data, 0, sizeof(req.data));
req.len = 0;
-
- while (req.len < 4 || strncmp((char *)&req.data + req.len - 4, "\r\n\r\n", 4)) {
- if (!fgets(buf, sizeof(buf), ser->f))
- goto cleanup;
-
- if (me->stop) goto cleanup;
-
- strncat(req.data, buf, sizeof(req.data) - req.len);
- req.len = strlen(req.data);
- }
-
- parse_copy(&reqcpy, &req);
-
- if (sscanf(get_header(&reqcpy, "Content-Length"), "%d", &cl)) {
- while (cl > 0) {
- if (!fread(buf, (cl < sizeof(buf)) ? cl : sizeof(buf), 1, ser->f))
- goto cleanup;
-
- if (me->stop) goto cleanup;
-
- cl -= strlen(buf);
- strncat(req.data, buf, sizeof(req.data) - req.len);
- req.len = strlen(req.data);
- }
- }
+ req.ignore = 0;
req.socket.fd = ser->fd;
-
- if (ser->parent->tls_cfg) {
+ if (ser->ssl) {
req.socket.type = SIP_TRANSPORT_TLS;
- req.socket.port = ourport_tls;
+ req.socket.port = htons(ourport_tls);
} else {
req.socket.type = SIP_TRANSPORT_TCP;
- req.socket.port = ourport_tcp;
- }
-
+ req.socket.port = htons(ourport_tcp);
+ }
+
+ res = ast_wait_for_input(ser->fd, -1);
+ if (res < 0)
+ ast_log(LOG_DEBUG, "ast_wait_for_input returned %d\n", res);
+ if (req.socket.lock)
+ ast_mutex_lock(req.socket.lock);
+
+ if (!(req.len = server_read(ser, req.data, sizeof(req.data)))) {
+ ast_log(LOG_DEBUG, "server_read failed: %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ if (req.socket.lock)
+ ast_mutex_unlock(req.socket.lock);
+
+ if (me->stop)
+ goto cleanup;
+
+ parse_copy(&reqcpy, &req);
req.socket.ser = ser;
-
handle_request_do(&req, &ser->requestor);
}
cleanup:
+ if (req.socket.lock)
+ ast_mutex_unlock(req.socket.lock);
AST_LIST_REMOVE(&threadl, me, list);
ast_free(me);
cleanup2:
@@ -2269,7 +2270,6 @@
return "UNKNOWN";
}
-
/*! \brief Transmit SIP message */
static int __sip_xmit(struct sip_pvt *p, char *data, int len)
{
@@ -2284,10 +2284,14 @@
if (p->socket.lock)
ast_mutex_lock(p->socket.lock);
- if (p->socket.type & SIP_TRANSPORT_TLS)
- res = fprintf(p->socket.ser->f, "%.*s", len, data);
- else
+ if (p->socket.type & SIP_TRANSPORT_UDP)
res = sendto(p->socket.fd, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+ else {
+ if (p->socket.ser->f)
+ res = server_write(p->socket.ser, data, len);
+ else
+ ast_log(LOG_DEBUG, "No p->socket.ser->f len=%d\n", len);
+ }
if (p->socket.lock)
ast_mutex_unlock(p->socket.lock);
@@ -2427,10 +2431,6 @@
int reschedule = DEFAULT_RETRANS;
int xmitres = 0;
- /* Don't retransmit TCP packets */
- if (!(pkt->owner->socket.type & SIP_TRANSPORT_UDP))
- return 0;
-
/* Lock channel PVT */
sip_pvt_lock(pkt->owner);
@@ -2551,6 +2551,18 @@
struct sip_pkt *pkt;
int siptimer_a = DEFAULT_RETRANS;
int xmitres = 0;
+
+ /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */
+ /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */
+ /* According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */
+ if (!(p->socket.type & SIP_TRANSPORT_UDP)) {
+ xmitres = __sip_xmit(dialog_ref(p), data, len); /* Send packet */
+ if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */
+ append_history(p, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
+ return AST_FAILURE;
+ } else
+ return AST_SUCCESS;
+ }
if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1)))
return AST_FAILURE;
@@ -7742,10 +7754,13 @@
static void build_contact(struct sip_pvt *p)
{
/* Construct Contact: header */
- if (!sip_standard_port(p->socket))
- ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), p->socket.port);
- else
- ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
+ if (p->socket.type & SIP_TRANSPORT_UDP) {
+ if (!sip_standard_port(p->socket))
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->socket.port));
+ else
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
+ } else
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->socket.port), get_transport(p->socket.type));
}
/*! \brief Build the Remote Party-ID & From using callingpres options */
@@ -7895,7 +7910,7 @@
}
if (!sip_standard_port(p->socket) && ast_strlen_zero(p->fromdomain))
- snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), p->socket.port, p->tag);
+ snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), ntohs(p->socket.port), p->tag);
else
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), p->tag);
@@ -8936,7 +8951,7 @@
ast_string_field_set(pvt, okcontacturi, c);
/* We should return false for URI:s we can't handle,
- like sips:, tel:, mailto:,ldap: etc */
+ like tel:, mailto:,ldap: etc */
return TRUE;
}
@@ -10961,6 +10976,41 @@
static const char *cli_yesno(int x)
{
return x ? "Yes" : "No";
+}
+
+/*! \brief Show active TCP connections */
+static char *sip_show_tcp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct sip_threadinfo *th;
+
+#define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n"
+#define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n"
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "sip show tcp";
+ e->usage =
+ "Usage: sip show tcp\n"
+ " Lists all active TCP/TLS sessions.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 3)
+ return CLI_SHOWUSAGE;
+
+ ast_cli(a->fd, FORMAT2, "Host", "Port", "Transport", "Type");
+ AST_LIST_TRAVERSE(&threadl, th, list) {
+ ast_cli(a->fd, FORMAT, ast_inet_ntoa(th->ser->requestor.sin_addr),
+ ntohs(th->ser->requestor.sin_port),
+ get_transport(th->type),
+ (th->ser->client ? "Client" : "Server"));
+
+ }
+ return CLI_SUCCESS;
+#undef FORMAT
+#undef FORMAT2
}
/*! \brief CLI Command 'SIP Show Users' */
@@ -11689,6 +11739,7 @@
ast_cli(fd, " ToHost : %s\n", peer->tohost);
ast_cli(fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port));
ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
+ ast_cli(fd, " Transport : %s\n", get_transport(peer->socket.type));
if (!ast_strlen_zero(global_regcontext))
ast_cli(fd, " Reg. exten : %s\n", peer->regexten);
ast_cli(fd, " Def. Username: %s\n", peer->username);
@@ -16812,7 +16863,7 @@
req.socket.fd = sipsock;
req.socket.type = SIP_TRANSPORT_UDP;
req.socket.ser = NULL;
- req.socket.port = ntohs(bindaddr.sin_port);
+ req.socket.port = htons(bindaddr.sin_port);
req.socket.lock = NULL;
handle_request_do(&req, &sin);
@@ -16886,9 +16937,6 @@
return 1;
}
- if (p->history)
- append_history(p, "Rx", "%s / %s / %s", req->data, get_header(req, "CSeq"), req->rlPart2);
-
nounlock = 0;
if (handle_incoming(p, req, sin, &recount, &nounlock) == -1) {
/* Request failed */
@@ -16906,17 +16954,32 @@
return 1;
}
-static int sip_standard_port(struct sip_socket s) {
+static int sip_standard_port(struct sip_socket s)
+{
if (s.type & SIP_TRANSPORT_TLS)
return s.port == STANDARD_TLS_PORT;
else
return s.port == STANDARD_SIP_PORT;
}
+static struct server_instance *sip_tcp_locate(struct sockaddr_in *s)
+{
+ struct sip_threadinfo *th;
+
+ AST_LIST_TRAVERSE(&threadl, th, list) {
+ if ((s->sin_family == th->ser->requestor.sin_family) &&
+ (s->sin_addr.s_addr == th->ser->requestor.sin_addr.s_addr) &&
+ (s->sin_port == th->ser->requestor.sin_port))
+ return th->ser;
+ }
+ return NULL;
+}
+
static int sip_prepare_socket(struct sip_pvt *p)
{
struct sip_socket *s = &p->socket;
static const char name[] = "SIP socket";
+ struct server_instance *ser;
struct server_args ca = {
.name = name,
.accept_fd = -1,
@@ -16930,15 +16993,25 @@
return s->fd;
}
+ ca.sin = *(sip_real_dst(p));
+
+ if ((ser = sip_tcp_locate(&ca.sin))) {
+ s->fd = ser->fd;
+ s->ser = ser;
+ return s->fd;
+ }
+
ca.tls_cfg = (s->ser) ? s->ser->parent->tls_cfg : NULL;
- ca.sin = *(sip_real_dst(p));
if (!ca.tls_cfg && s->type & SIP_TRANSPORT_TLS &&
!(ca.tls_cfg = ast_calloc(1, sizeof(*ca.tls_cfg))))
return -1;
s->ser = (!s->ser) ? client_start(&ca) : s->ser;
- if (!s->ser)
+ if (!s->ser) {
+ if (ca.tls_cfg)
+ ast_free(ca.tls_cfg);
return -1;
+ }
s->fd = ca.accept_fd;
@@ -18064,11 +18137,12 @@
if (handle_common_options(&peerflags[0], &mask[0], v))
continue;
if (!strcasecmp(v->name, "transport")) {
- if (!strcasecmp(v->value, "tcp")) {
+ if (!strcasecmp(v->value, "udp"))
+ peer->socket.type = SIP_TRANSPORT_UDP;
+ else if (!strcasecmp(v->value, "tcp"))
peer->socket.type = SIP_TRANSPORT_TCP;
- } else if (!strcasecmp(v->value, "tls")) {
+ else if (!strcasecmp(v->value, "tls"))
peer->socket.type = SIP_TRANSPORT_TLS;
- }
} else if (realtime && !strcasecmp(v->name, "regseconds")) {
ast_get_time_t(v->value, ®seconds, 0, NULL);
} else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
@@ -18260,6 +18334,9 @@
if (!peer->addr.sin_port)
peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
+ if (!peer->socket.port)
+ peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
+
if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) {
time_t nowtime = time(NULL);
@@ -18341,8 +18418,8 @@
}
/* Initialize tcp sockets */
- bzero(&sip_tcp_desc.sin, sizeof(sip_tcp_desc.sin));
- bzero(&sip_tls_desc.sin, sizeof(sip_tls_desc.sin));
+ memset(&sip_tcp_desc.sin, 0, sizeof(sip_tcp_desc.sin));
+ memset(&sip_tls_desc.sin, 0, sizeof(sip_tls_desc.sin));
sip_tcp_desc.sin.sin_family = AF_INET;
@@ -18959,8 +19036,10 @@
if (ssl_setup(sip_tls_desc.tls_cfg))
server_start(&sip_tls_desc);
- else if(sip_tls_desc.tls_cfg->enabled)
+ else if (sip_tls_desc.tls_cfg->enabled) {
+ sip_tls_desc.tls_cfg = NULL;
ast_log(LOG_WARNING, "SIP TLS server did not load because of errors.\n");
+ }
/* Done, tell the manager */
manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "ChannelType: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\nUser_Count: %d\r\n", channelreloadreason2txt(reason), registry_count, peer_count, user_count);
@@ -19534,6 +19613,7 @@
AST_CLI_DEFINE(sip_do_history, "Enable SIP history"),
AST_CLI_DEFINE(sip_no_history, "Disable SIP history"),
AST_CLI_DEFINE(sip_reload, "Reload SIP configuration"),
+ AST_CLI_DEFINE(sip_show_tcp, "List TCP Connections")
};
/*! \brief PBX load module - initialization */
Modified: team/group/sip-tcptls/include/asterisk/server.h
URL: http://svn.digium.com/view/asterisk/team/group/sip-tcptls/include/asterisk/server.h?view=diff&rev=89525&r1=89524&r2=89525
==============================================================================
--- team/group/sip-tcptls/include/asterisk/server.h (original)
+++ team/group/sip-tcptls/include/asterisk/server.h Thu Nov 22 00:12:11 2007
@@ -136,4 +136,7 @@
void *ast_make_file_from_fd(void *data);
+ssize_t server_read(struct server_instance *ser, void *buf, size_t count);
+ssize_t server_write(struct server_instance *ser, void *buf, size_t count);
+
#endif /* _ASTERISK_SERVER_H */
Modified: team/group/sip-tcptls/main/server.c
URL: http://svn.digium.com/view/asterisk/team/group/sip-tcptls/main/server.c?view=diff&rev=89525&r1=89524&r2=89525
==============================================================================
--- team/group/sip-tcptls/main/server.c (original)
+++ team/group/sip-tcptls/main/server.c Thu Nov 22 00:12:11 2007
@@ -65,6 +65,26 @@
return SSL_write(cookie, buf, len);
}
+ssize_t server_read(struct server_instance *ser, void *buf, size_t count)
+{
+ if (!ser->ssl)
+ return read(ser->fd, buf, count);
+#ifdef DO_SSL
+ else
+ return ssl_read(ser->ssl, buf, count);
+#endif
+}
+
+ssize_t server_write(struct server_instance *ser, void *buf, size_t count)
+{
+ if (!ser->ssl)
+ return write(ser->fd, buf, count);
+#ifdef DO_SSL
+ else
+ return ssl_write(ser->ssl, buf, count);
+#endif
+}
+
static int ssl_close(void *cookie)
{
close(SSL_get_fd(cookie));
@@ -175,7 +195,11 @@
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
- cfg->ssl_ctx = SSL_CTX_new( SSLv23_client_method() );
+ if (!(cfg->ssl_ctx = SSL_CTX_new( SSLv23_client_method() ))) {
+ ast_log(LOG_DEBUG, "SSL_CTX_new returned null\n");
+ cfg->enabled = 0;
+ return 0;
+ }
return 1;
#endif
@@ -234,7 +258,7 @@
client_setup(desc->tls_cfg);
}
- if(!ast_make_file_from_fd(ser))
+ if (!ast_make_file_from_fd(ser))
goto error;
return ser;
@@ -326,7 +350,7 @@
int ret;
char err[256];
- /*
+ /*
* open a FILE * as appropriate.
*/
if (!ser->parent->tls_cfg)
More information about the asterisk-commits
mailing list