📄 extl_dtls.c
字号:
{ socket_tab_used = &dtls_socket_tab[pos]; break; } } } if (socket_tab_used==NULL) { for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn == NULL) { /* should accept this connection? */ break; } } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "creating DTLS socket at index: %i\n", pos)); if (pos<0) { /* delete an old one! */ pos=0; if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } } if (dtls_socket_tab[pos].ssl_conn==NULL) { BIO *wbio; if (!SSL_CTX_check_private_key (server_ctx)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL CTX private key check error\n")); osip_free(enc_buf); return -1; } /* behave as a server: */ dtls_socket_tab[pos].ssl_conn = SSL_new (server_ctx); if (dtls_socket_tab[pos].ssl_conn == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL_new error\n")); osip_free(enc_buf); return -1; } /* No MTU query */ SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU); SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000); /* MTU query */ /* BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); */ SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_COOKIE_EXCHANGE); wbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (wbio, &sa); SSL_set_bio (dtls_socket_tab[pos].ssl_conn, NULL, wbio); SSL_set_accept_state (dtls_socket_tab[pos].ssl_conn); dtls_socket_tab[pos].ssl_state = 0; dtls_socket_tab[pos].ssl_type = EXOSIP_AS_A_SERVER; osip_strncpy (dtls_socket_tab[pos].remote_ip, src6host, sizeof (dtls_socket_tab[pos].remote_ip)); dtls_socket_tab[pos].remote_port = recvport; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "New DTLS connection accepted\n")); } dec_buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 1); if (dec_buf==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Allocation error\n")); osip_free(enc_buf); return -1; } rbio = BIO_new_mem_buf (enc_buf, enc_buf_len); BIO_set_mem_eof_return (rbio, -1); dtls_socket_tab[pos].ssl_conn->rbio = rbio; i = SSL_read (dtls_socket_tab[pos].ssl_conn, dec_buf, SIP_MESSAGE_MAX_LENGTH); /* done with the rbio */ BIO_free (dtls_socket_tab[pos].ssl_conn->rbio); dtls_socket_tab[pos].ssl_conn->rbio = BIO_new (BIO_s_mem ()); if (i > 5) { osip_strncpy (dec_buf + i, "\0", 1); _eXosip_handle_incoming_message(dec_buf, i, dtls_socket, src6host, recvport); }#ifndef MINISIZE else if (i <= 0) { err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (err); if (err==SSL_ERROR_SYSCALL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "DTLS SYSCALL on SSL_read\n")); } else if (err==SSL_ERROR_SSL || err==SSL_ERROR_ZERO_RETURN) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "DTLS closed\n")); shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); memset (&(dtls_socket_tab[pos]), 0, sizeof (dtls_socket_tab[pos])); } } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Dummy SIP message received\n")); }#endif osip_free (dec_buf); osip_free (enc_buf); } } return 0;}static inteXtl_update_local_target(osip_message_t *req){ int pos = 0; if (dtls_firewall_ip!='\0') { while (!osip_list_eol (&req->contacts, pos)) { osip_contact_t *co; co = (osip_contact_t *) osip_list_get (&req->contacts, pos); pos++; if (co != NULL && co->url != NULL && co->url->host != NULL && 0 == osip_strcasecmp (co->url->host, dtls_firewall_ip)) { if (co->url->port == NULL && 0 != osip_strcasecmp (dtls_firewall_port, "5061")) { co->url->port = osip_strdup (dtls_firewall_port); } else if (co->url->port != NULL && 0 != osip_strcasecmp (dtls_firewall_port, co->url->port)) { osip_free (co->url->port); co->url->port = osip_strdup (dtls_firewall_port); } } } } return 0;}#ifndef INET6_ADDRSTRLEN#define INET6_ADDRSTRLEN 46#endifstatic intdtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket){ int len = 0; size_t length = 0; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; char *message; char ipbuf[INET6_ADDRSTRLEN]; int i; int pos; struct socket_tab *socket_tab_used=NULL; BIO *sbio=NULL; if (dtls_socket <= 0) return -1; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi (sip->req_uri->port); else port = 5061; } if (port == 5060) port = 5061; if (MSG_IS_REQUEST(sip)) { if (MSG_IS_REGISTER(sip) ||MSG_IS_INVITE(sip) ||MSG_IS_SUBSCRIBE(sip) || MSG_IS_NOTIFY(sip)) eXtl_update_local_target(sip); } i=-1;#ifndef MINISIZE if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n=0; for (srv = &tr->record.srventry[0]; n<10 && tr->record.srventry[0].srv[0]; srv = &tr->record.srventry[0]) { i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); i=-1; /* copy next element */ n++; } }#endif /* if SRV was used, distination may be already found */ if (i != 0) { i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP); } if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); len = addrinfo->ai_addrlen; eXosip_freeaddrinfo (addrinfo); /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route=NULL; osip_generic_param_t *tag=NULL; osip_message_get_route (sip, 0, &route); osip_to_get_tag (sip->to, &tag); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_remove(&sip->routes, 0); } i = osip_message_to_str (sip, &message, &length); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_add(&sip->routes, route, 0); } } if (i != 0 || length <= 0) { return -1; } switch ( ((struct sockaddr *)&addr)->sa_family ) { case AF_INET: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf, sizeof (ipbuf)); break; case AF_INET6: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf, sizeof (ipbuf)); break; default: strncpy (ipbuf, "(unknown)", sizeof (ipbuf)); break; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: \n%s (to dest=%s:%i)\n", message, ipbuf, port)); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } if (socket_tab_used==NULL) { for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } } if (socket_tab_used==NULL) { /* delete an old one! */ pos=0; if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } if (dtls_socket_tab[pos].ssl_conn == NULL) { /* create a new one */ SSL_CTX_set_read_ahead (client_ctx, 1); dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx); if (dtls_socket_tab[pos].ssl_conn == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_new error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS connect error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU); SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000); SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn); sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr); SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio); dtls_socket_tab[pos].ssl_type = 2; dtls_socket_tab[pos].ssl_state = 2; osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf, sizeof (dtls_socket_tab[pos].remote_ip)); dtls_socket_tab[pos].remote_port = port; } i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length); if (i<0) { i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (i); if (i==SSL_ERROR_SSL || i==SSL_ERROR_SYSCALL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_write error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); }#ifndef MINISIZE /* delete first SRV entry that is not reachable */ if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); osip_free (message); return 0; /* retry for next retransmission! */ }#endif /* SIP_NETWORK_ERROR; */ osip_free (message); return -1; } if (eXosip.keep_alive > 0) { if (MSG_IS_REGISTER (sip)) { eXosip_reg_t *reg = NULL; if (_eXosip_reg_find (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return 0;}static intdtls_tl_keepalive(void){ char buf[4] = "jaK"; eXosip_reg_t *jr; for (jr = eXosip.j_reg; jr != NULL; jr = jr->next) { if (jr->len > 0) { if (sendto (dtls_socket, (const void *) buf, 4, 0, (struct sockaddr *) &(jr->addr), jr->len) > 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Keep Alive sent on DTLS!\n")); } } } return 0;}static intdtls_tl_set_socket(int socket){ dtls_socket = socket; return 0;}static intdtls_tl_masquerade_contact(const char *public_address, int port){ if (public_address == NULL || public_address[0] == '\0') { memset (dtls_firewall_ip, '\0', sizeof (dtls_firewall_ip)); return 0; } snprintf (dtls_firewall_ip, sizeof (dtls_firewall_ip), "%s", public_address); if (port > 0) { snprintf (dtls_firewall_port, sizeof(dtls_firewall_port), "%i", port); } return 0;}static intdtls_tl_get_masquerade_contact(char *ip, int ip_size, char *port, int port_size){ memset(ip, 0, ip_size); memset(port, 0, port_size); if (dtls_firewall_ip!='\0') snprintf(ip, ip_size, "%s", dtls_firewall_ip); if (dtls_firewall_port!='\0') snprintf(port, port_size, "%s", dtls_firewall_port); return 0;}struct eXtl_protocol eXtl_dtls = { 1, 5061, "UDP-DTLS", "0.0.0.0", IPPROTO_UDP, AF_INET, 0, 0, &dtls_tl_init, &dtls_tl_free, &dtls_tl_open, &dtls_tl_set_fdset, &dtls_tl_read_message, &dtls_tl_send_message, &dtls_tl_keepalive, &dtls_tl_set_socket, &dtls_tl_masquerade_contact, &dtls_tl_get_masquerade_contact};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -