[asterisk-commits] bbryant: branch bbryant/ssl-tcp-tls r70650 - in /team/bbryant/ssl-tcp-tls: ch...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jun 21 00:11:29 CDT 2007
Author: bbryant
Date: Thu Jun 21 00:11:29 2007
New Revision: 70650
URL: http://svn.digium.com/view/asterisk?view=rev&rev=70650
Log:
Save progress to sip/tcp code.
Modified:
team/bbryant/ssl-tcp-tls/channels/chan_sip.c
team/bbryant/ssl-tcp-tls/main/server.c
Modified: team/bbryant/ssl-tcp-tls/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/bbryant/ssl-tcp-tls/channels/chan_sip.c?view=diff&rev=70650&r1=70649&r2=70650
==============================================================================
--- team/bbryant/ssl-tcp-tls/channels/chan_sip.c (original)
+++ team/bbryant/ssl-tcp-tls/channels/chan_sip.c Thu Jun 21 00:11:29 2007
@@ -590,7 +590,6 @@
static int global_t1min; /*!< T1 roundtrip time minimum */
static int global_regextenonqualify; /*!< Whether to add/remove regexten when qualifying peers */
static int global_autoframing; /*!< Turn autoframing on or off. */
-static int global_tcpenable; /*!< Turn TCP on/off */
static enum transfermodes global_allowtransfer; /*!< SIP Refer restriction scheme */
static struct sip_proxy global_outboundproxy; /*!< Outbound proxy */
@@ -868,6 +867,11 @@
#define sipdebug_console ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONSOLE)
#define sipdebug_text ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_TEXT)
+/*!< Define some SIP transports */
+#define SIP_TRANSPORT_UDP (1 << 0)
+#define SIP_TRANSPORT_TCP (1 << 1)
+#define SIP_TRANSPORT_TLS (1 << 2)
+
/*! \brief T38 States for a call */
enum t38state {
T38_DISABLED = 0, /*!< Not enabled */
@@ -980,8 +984,9 @@
AST_STRING_FIELD(rpid); /*!< Our RPID header */
AST_STRING_FIELD(rpid_from); /*!< Our RPID From header */
AST_STRING_FIELD(url); /*!< URL to be sent with next message to peer */
- AST_STRING_FIELD(transport); /*!< Transport type (i.e. UDP, TCP, TLS ... etc) */
);
+ int transport;
+ struct server_instance *ser;
unsigned int ocseq; /*!< Current outgoing seqno */
unsigned int icseq; /*!< Current incoming seqno */
ast_group_t callgroup; /*!< Call group */
@@ -1083,7 +1088,7 @@
struct sip_pkt {
struct sip_pkt *next; /*!< Next packet in linked list */
int retrans; /*!< Retransmission number */
- int method; /*!< SIP me`:thod for this packet */
+ int method; /*!< SIP method for this packet */
int seqno; /*!< Sequence number */
unsigned int flags; /*!< non-zero if this is a response packet (e.g. 200 OK) */
struct sip_pvt *owner; /*!< Owner AST call */
@@ -1288,6 +1293,9 @@
static int sip_senddigit_begin(struct ast_channel *ast, char digit);
static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
+static char *get_transport(struct sip_pvt *p);
+static int handle_request_do(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *nounlock);
+
/*--- Transmitting responses and requests */
static int sipsock_read(int *id, int fd, short events, void *ignore);
static int __sip_xmit(struct sip_pvt *p, char *data, int len);
@@ -1468,6 +1476,11 @@
static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
static inline int sip_debug_test_addr(const struct sockaddr_in *addr);
static inline int sip_debug_test_pvt(struct sip_pvt *p);
+
+
+/*! \brief Append to SIP dialog history
+ \return Always returns 0 */
+#define append_history(p, event, fmt , args... ) append_history_full(p, "%-15s " fmt, event, ## args)
static void append_history_full(struct sip_pvt *p, const char *fmt, ...);
static void sip_dump_history(struct sip_pvt *dialog);
@@ -1696,14 +1709,72 @@
get_codec: sip_get_codec,
};
-/*! \brieft SIP TCP helper function */
+static void sip_pvt_unlock(struct sip_pvt *);
+
+/*! \brief SIP TCP helper function */
static void *sip_tcp_helper_thread(void *data) {
- char buf[4096];
-
+ struct sip_pvt *p;
struct server_instance *ser = data;
-
- while (fgets(buf, sizeof(buf), ser->f)) {
- ast_log(LOG_WARNING, buf);
+ int req_len, lockretry, nounlock;
+ char buf[1024];
+ struct sip_request req = { 0, };
+
+ for (;;) {
+ bzero(req.data, sizeof(req.data));
+ fgets(req.data, sizeof(req.data), ser->f);
+ req_len = strlen(req.data);
+
+ while (req_len < 4 || strncmp((char *)&req.data + req_len - 4, "\r\n\r\n", 4)) {
+ if(!fgets(buf, sizeof(buf), ser->f))
+ return NULL;
+
+ strncat(req.data, buf, sizeof(req.data) - req_len - 1);
+ req_len = strlen(req.data);
+ }
+
+ for (lockretry = 100; lockretry > 0; lockretry--) {
+ ast_mutex_lock(&netlock);
+
+ /* Find the active SIP dialog or create a new one */
+ p = find_call(&req, &ser->parent->sin, req.method); /* returns p locked */
+
+ if (p == NULL) {
+ ast_debug(1, "Invalid SIP message - rejected , no callid, len %d\n", req.len);
+ ast_mutex_unlock(&netlock);
+ return NULL;
+ }
+
+ p->transport = (ser->parent->tls_cfg) ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP;
+ /* Go ahead and lock the owner if it has one -- we may need it */
+ /* becaues this is deadlock-prone, we need to try and unlock if failed */
+ if (!p->owner || !ast_channel_trylock(p->owner))
+ break; /* locking succeeded */
+ ast_debug(1, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
+ sip_pvt_unlock(p);
+ ast_mutex_unlock(&netlock);
+ /* Sleep for a very short amount of time */
+ usleep(1);
+ }
+
+ p->recv = ser->parent->sin;
+
+ if (!lockretry) {
+ if (p->owner)
+ ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", S_OR(p->owner->name, "- no channel name ??? - "));
+ ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid);
+ if (req.method != SIP_ACK)
+ transmit_response(p, "503 Server error", &req); /* We must respond according to RFC 3261 sec 12.2 */
+ /* XXX We could add retry-after to make sure they come back */
+ append_history(p, "LockFail", "Owner lock failed, transaction failed.");
+ return NULL;
+ }
+
+ handle_request_do(p, &req, &ser->parent->sin, &nounlock);
+
+ if (p->owner && !nounlock)
+ ast_channel_unlock(p->owner);
+ sip_pvt_unlock(p);
+ ast_mutex_unlock(&netlock);
}
return NULL;
@@ -1755,10 +1826,6 @@
get_udptl_info: sip_get_udptl_peer,
set_udptl_peer: sip_set_udptl_peer,
};
-
-/*! \brief Append to SIP dialog history
- \return Always returns 0 */
-#define append_history(p, event, fmt , args... ) append_history_full(p, "%-15s " fmt, event, ## args)
static void append_history_full(struct sip_pvt *p, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
@@ -1965,8 +2032,12 @@
static int __sip_xmit(struct sip_pvt *p, char *data, int len)
{
int res;
+ int fd;
const struct sockaddr_in *dst = sip_real_dst(p);
- res = sendto(sipsock, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+
+ fd = (p->transport & SIP_TRANSPORT_UDP) ? sipsock : p->ser->parent->accept_fd;
+
+ res = sendto(fd, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
if (res == -1) {
switch (errno) {
@@ -1990,8 +2061,9 @@
const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
- ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
- ast_inet_ntoa(p->ourip), ourport, p->branch, rport);
+ ast_string_field_build(p, via, "%s/2.0/%s %s:%d;branch=z9hG4bK%08x%s",
+ ((p->transport & SIP_TRANSPORT_TLS) ? "SIPS" : "SIP"),
+ get_transport(p), ast_inet_ntoa(p->ourip), ourport, p->branch, rport);
}
/*! \brief NAT fix - decide which IP address to use for ASterisk server?
@@ -2514,6 +2586,9 @@
ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp);
}
}
+ /* TODO Fix this to something cleaner */
+ if (!strncmp(tmp, "sips:", 5))
+ sprintf(tmp, "sip%s", tmp+4);
return tmp;
}
@@ -4869,6 +4944,7 @@
/* Found the call */
sip_pvt_lock(p);
dialoglist_unlock();
+ p->transport = SIP_TRANSPORT_UDP;
return p;
}
}
@@ -4901,6 +4977,8 @@
ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n");
}
}
+ p->transport = SIP_TRANSPORT_UDP;
+
return p;
} else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) {
/* A method we do not support, let's take it on the volley */
@@ -4915,6 +4993,8 @@
the session quickly */
if (intended_method == SIP_RESPONSE)
ast_debug(2, "That's odd... Got a response on a call we dont know about. Callid %s\n", callid ? callid : "<unknown>");
+
+ p->transport = SIP_TRANSPORT_UDP;
return p;
}
@@ -9580,7 +9660,7 @@
if (c) {
*c = '\0';
c = ast_skip_blanks(c+1);
- if (strcasecmp(via, "SIP/2.0/UDP")) {
+ if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIPS/2.0/TCP")) {
ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via);
return;
}
@@ -15730,14 +15810,11 @@
struct sip_request req;
struct sockaddr_in sin = { 0, };
struct sip_pvt *p;
- int res;
+ int res, lockretry, nounlock;
socklen_t len = sizeof(sin);
- int nounlock;
- int recount = 0;
- int lockretry;
memset(&req, 0, sizeof(req));
- res = recvfrom(sipsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
+ res = recvfrom(fd, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
if (res < 0) {
#if !defined(__FreeBSD__)
if (errno == EAGAIN)
@@ -15759,7 +15836,9 @@
if (pedanticsipchecking)
req.len = lws2sws(req.data, req.len); /* Fix multiline headers */
if (ast_test_flag(&req, SIP_PKT_DEBUG))
- ast_verbose("\n<--- SIP read from %s:%d --->\n%s\n<------------->\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), req.data);
+ ast_verbose("\n<--- SIP read from %s://%s:%d %s--->\n%s\n<------------->\n",
+ get_transport(p), ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+ ((p->transport & SIP_TRANSPORT_TLS) ? "(Secure) " : ""), req.data);
parse_request(&req);
req.method = find_sip_method(req.rlPart1);
@@ -15793,9 +15872,6 @@
}
p->recv = sin;
- if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) /* This is a request or response, note what it was for */
- append_history(p, "Rx", "%s / %s / %s", req.data, get_header(&req, "CSeq"), req.rlPart2);
-
if (!lockretry) {
if (p->owner)
ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", S_OR(p->owner->name, "- no channel name ??? - "));
@@ -15806,16 +15882,34 @@
append_history(p, "LockFail", "Owner lock failed, transaction failed.");
return 1;
}
- nounlock = 0;
- if (handle_request(p, &req, &sin, &recount, &nounlock) == -1) {
- /* Request failed */
- ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
- }
-
+
+ handle_request_do(p, &req, &sin, &nounlock);
+
if (p->owner && !nounlock)
ast_channel_unlock(p->owner);
sip_pvt_unlock(p);
ast_mutex_unlock(&netlock);
+
+ return 1;
+}
+
+static char *get_transport(struct sip_pvt *p) {
+ char *str = (p->transport & SIP_TRANSPORT_UDP) ? "UDP" : "TCP";
+ return ast_strdup(str);
+}
+
+static int handle_request_do(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *nounlock) {
+ int recount = 0;
+
+ if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) /* This is a request or response, note what it was for */
+ append_history(p, "Rx", "%s / %s / %s", req->data, get_header(req, "CSeq"), req->rlPart2);
+
+ nounlock = 0;
+ if (handle_request(p, req, sin, &recount, nounlock) == -1) {
+ /* Request failed */
+ ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
+ }
+
if (recount)
ast_update_use_count();
@@ -17120,9 +17214,19 @@
/* Initialize tcp sockets */
bzero(&sip_tcp_desc.sin, sizeof(sip_tcp_desc.sin));
bzero(&sip_tls_desc.sin, sizeof(sip_tls_desc.sin));
-
+
+ sip_tcp_desc.sin.sin_family = AF_INET;
+
sip_tcp_desc.sin.sin_port = htons(STANDARD_SIP_PORT);
sip_tls_desc.sin.sin_port = htons(STANDARD_TLS_PORT);
+
+ if((hp = ast_gethostbyname("0.0.0.0", &ahp))) { // Default bind address for TCP / TLS
+ memcpy(&sip_tcp_desc.sin.sin_addr, hp->h_addr, sizeof(sip_tcp_desc.sin.sin_addr));
+ memcpy(&sip_tls_desc.sin.sin_addr, hp->h_addr, sizeof(sip_tls_desc.sin.sin_addr));
+ }
+
+ sip_tls_desc.tls_cfg->certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */
+ sip_tls_desc.tls_cfg->cipher = ast_strdup("");
/* Initialize copy of current global_regcontext for later use in removing stale contexts */
ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts));
@@ -17257,6 +17361,12 @@
global_t1min = atoi(v->value);
} else if (!strcasecmp(v->name, "tcpenable")) {
sip_tcp_desc.sin.sin_family = ast_false(v->value) ? 0 : AF_INET;
+ } else if (!strcasecmp(v->name, "tcpbindaddr")) {
+ if((hp = ast_gethostbyname(v->value, &ahp))) {
+ memcpy(&sip_tcp_desc.sin.sin_addr, hp->h_addr, sizeof(sip_tcp_desc.sin.sin_addr));
+ } else {
+ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config);
+ }
} else if (!strcasecmp(v->name, "tcpbindport")) {
if (sscanf(v->value, "%d", &ourport) == 1) {
sip_tcp_desc.sin.sin_port = htons(ourport);
@@ -17267,6 +17377,14 @@
sip_tls_desc.tls_cfg->enabled = ast_true(v->value) ? AF_INET : 0;
} else if (!strcasecmp(v->name, "tlscertfile")) {
sip_tls_desc.tls_cfg->certfile = ast_strdup(v->value);
+ } else if (!strcasecmp(v->name, "tlscipher")) {
+ sip_tls_desc.tls_cfg->cipher = ast_strdup(v->value);
+ } else if (!strcasecmp(v->name, "tlsbindaddr")) {
+ if((hp = ast_gethostbyname(v->value, &ahp))) {
+ memcpy(&sip_tls_desc.sin.sin_addr, hp->h_addr, sizeof(sip_tls_desc.sin.sin_addr));
+ } else {
+ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config);
+ }
} else if (!strcasecmp(v->name,"tlsbindport")) {
if (sscanf(v->value, "%d", &ourport) == 1) {
sip_tls_desc.sin.sin_port = htons(ourport);
Modified: team/bbryant/ssl-tcp-tls/main/server.c
URL: http://svn.digium.com/view/asterisk/team/bbryant/ssl-tcp-tls/main/server.c?view=diff&rev=70650&r1=70649&r2=70650
==============================================================================
--- team/bbryant/ssl-tcp-tls/main/server.c (original)
+++ team/bbryant/ssl-tcp-tls/main/server.c Thu Jun 21 00:11:29 2007
@@ -115,7 +115,6 @@
close(ser->fd);
ast_free(ser);
}
-
}
return NULL;
}
@@ -229,43 +228,45 @@
*/
void *ast_make_file_from_fd(void *data)
{
- struct server_instance *ser = data;
+ struct server_instance *ser = data;
+ int ret;
+ char err[256];
/*
* open a FILE * as appropriate.
*/
- if (!ser->parent->tls_cfg)
- ser->f = fdopen(ser->fd, "w+");
+ if (!ser->parent->tls_cfg)
+ ser->f = fdopen(ser->fd, "w+");
#ifdef DO_SSL
- else if ( (ser->ssl = SSL_new(ser->parent->tls_cfg->ssl_ctx)) ) {
- SSL_set_fd(ser->ssl, ser->fd);
- if (SSL_accept(ser->ssl) == 0)
- ast_verbose(" error setting up ssl connection");
- else {
+ else if ( (ser->ssl = SSL_new(ser->parent->tls_cfg->ssl_ctx)) ) {
+ SSL_set_fd(ser->ssl, ser->fd);
+ if ((ret = SSL_accept(ser->ssl)) <= 0) {
+ if(option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "Problem setting up ssl connection: %s\n", ERR_error_string(ERR_get_error(), err));
+ } else {
#if defined(HAVE_FUNOPEN) /* the BSD interface */
- ser->f = funopen(ser->ssl, ssl_read, ssl_write, NULL, ssl_close);
+ ser->f = funopen(ser->ssl, ssl_read, ssl_write, NULL, ssl_close);
#elif defined(HAVE_FOPENCOOKIE) /* the glibc/linux interface */
- static const cookie_io_functions_t cookie_funcs = {
- ssl_read, ssl_write, NULL, ssl_close
- };
- ser->f = fopencookie(ser->ssl, "w+", cookie_funcs);
+ static const cookie_io_functions_t cookie_funcs = {
+ ssl_read, ssl_write, NULL, ssl_close
+ };
+ ser->f = fopencookie(ser->ssl, "w+", cookie_funcs);
#else
- /* could add other methods here */
+ /* could add other methods here */
ast_log(LOG_WARNING, "no ser->f methods attempted!");
#endif
- }
- if (!ser->f) /* no success opening descriptor stacking */
- SSL_free(ser->ssl);
+ }
+ if (!ser->f) /* no success opening descriptor stacking */
+ SSL_free(ser->ssl);
}
#endif /* DO_SSL */
if (!ser->f) {
- close(ser->fd);
- ast_log(LOG_WARNING, "FILE * open failed!\n");
- ast_log(LOG_WARNING, "strerror: %s\n", strerror(errno));
- ast_free(ser);
- return NULL;
+ close(ser->fd);
+ ast_log(LOG_WARNING, "FILE * open failed!\n");
+ ast_free(ser);
+ return NULL;
}
return ser->parent->worker_fn(ser);
}
More information about the asterisk-commits
mailing list