Skip to content

Commit 6b0e7d2

Browse files
alfredhrichaas
authored andcommitted
rtmp: add rtmps (tls) support (#195)
1 parent 9ec2b17 commit 6b0e7d2

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed

include/re_rtmp.h

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ enum rtmp_event_type {
5757

5858

5959
/* forward declarations */
60+
struct tls;
6061
struct dnsc;
6162
struct odict;
6263
struct tcp_sock;
@@ -75,9 +76,11 @@ typedef void (rtmp_command_h)(const struct odict *msg, void *arg);
7576
typedef void (rtmp_close_h)(int err, void *arg);
7677

7778
int rtmp_connect(struct rtmp_conn **connp, struct dnsc *dnsc, const char *uri,
79+
struct tls *tls,
7880
rtmp_estab_h *estabh, rtmp_command_h *cmdh,
7981
rtmp_close_h *closeh, void *arg);
8082
int rtmp_accept(struct rtmp_conn **connp, struct tcp_sock *ts,
83+
struct tls *tls,
8184
rtmp_command_h *cmdh, rtmp_close_h *closeh, void *arg);
8285
int rtmp_control(const struct rtmp_conn *conn,
8386
enum rtmp_packet_type type, ...);

include/re_tls.h

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ int tls_srtp_keyinfo(const struct tls_conn *tc, enum srtp_suite *suite,
5555
const char *tls_cipher_name(const struct tls_conn *tc);
5656
int tls_set_ciphers(struct tls *tls, const char *cipherv[], size_t count);
5757
int tls_set_servername(struct tls_conn *tc, const char *servername);
58+
int tls_set_verify_server(struct tls_conn *tc, const char *host);
5859

5960

6061
/* TCP */

src/rtmp/conn.c

+51-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <re_sa.h>
1313
#include <re_list.h>
1414
#include <re_tcp.h>
15+
#include <re_srtp.h>
16+
#include <re_tls.h>
1517
#include <re_sys.h>
1618
#include <re_odict.h>
1719
#include <re_dns.h>
@@ -38,6 +40,7 @@ static void conn_destructor(void *data)
3840
mem_deref(conn->dnsq6);
3941
mem_deref(conn->dnsq4);
4042
mem_deref(conn->dnsc);
43+
mem_deref(conn->sc);
4144
mem_deref(conn->tc);
4245
mem_deref(conn->mb);
4346
mem_deref(conn->dechunk);
@@ -358,6 +361,7 @@ static void conn_close(struct rtmp_conn *conn, int err)
358361
{
359362
rtmp_close_h *closeh;
360363

364+
conn->sc = mem_deref(conn->sc);
361365
conn->tc = mem_deref(conn->tc);
362366
conn->dnsq6 = mem_deref(conn->dnsq6);
363367
conn->dnsq4 = mem_deref(conn->dnsq4);
@@ -688,13 +692,25 @@ static int req_connect(struct rtmp_conn *conn)
688692
conn->last_ack = 0;
689693
conn->total_bytes = 0;
690694
conn->mb = mem_deref(conn->mb);
695+
conn->sc = mem_deref(conn->sc);
691696
conn->tc = mem_deref(conn->tc);
692697

693698
rtmp_dechunker_set_chunksize(conn->dechunk,
694699
RTMP_DEFAULT_CHUNKSIZE);
695700

696701
err = tcp_connect(&conn->tc, addr, tcp_estab_handler,
697702
tcp_recv_handler, tcp_close_handler, conn);
703+
704+
#ifdef USE_TLS
705+
if (conn->tls && !err) {
706+
err = tls_start_tcp(&conn->sc, conn->tls,
707+
conn->tc, 0);
708+
if (!err)
709+
err = tls_set_verify_server(conn->sc,
710+
conn->host);
711+
}
712+
#endif
713+
698714
if (!err)
699715
break;
700716
}
@@ -764,6 +780,7 @@ static void query_handler(int err, const struct dnshdr *hdr, struct list *ansl,
764780
* @param connp Pointer to allocated RTMP connection object
765781
* @param dnsc DNS Client for resolving FQDN uris
766782
* @param uri RTMP uri to connect to
783+
* @param tls TLS Context (optional)
767784
* @param estabh Established handler
768785
* @param cmdh Incoming command handler
769786
* @param closeh Close handler
@@ -777,35 +794,56 @@ static void query_handler(int err, const struct dnshdr *hdr, struct list *ansl,
777794
* rtmp://[::1]/vod/mp4:sample.mp4
778795
*/
779796
int rtmp_connect(struct rtmp_conn **connp, struct dnsc *dnsc, const char *uri,
797+
struct tls *tls,
780798
rtmp_estab_h *estabh, rtmp_command_h *cmdh,
781799
rtmp_close_h *closeh, void *arg)
782800
{
783801
struct rtmp_conn *conn;
802+
struct pl pl_scheme;
784803
struct pl pl_hostport;
785804
struct pl pl_host;
786805
struct pl pl_port;
787806
struct pl pl_app;
788807
struct pl pl_stream;
808+
uint16_t defport;
789809
int err;
790810

791811
if (!connp || !uri)
792812
return EINVAL;
793813

794-
if (re_regex(uri, strlen(uri), "rtmp://[^/]+/[^/]+/[^]+",
795-
&pl_hostport, &pl_app, &pl_stream))
814+
if (re_regex(uri, strlen(uri), "[a-z]+://[^/]+/[^/]+/[^]+",
815+
&pl_scheme, &pl_hostport, &pl_app, &pl_stream))
796816
return EINVAL;
797817

818+
if (!pl_strcasecmp(&pl_scheme, "rtmp")) {
819+
tls = NULL;
820+
defport = RTMP_PORT;
821+
}
822+
#ifdef USE_TLS
823+
else if (!pl_strcasecmp(&pl_scheme, "rtmps")) {
824+
825+
if (!tls)
826+
return EINVAL;
827+
828+
defport = 443;
829+
}
830+
#endif
831+
else
832+
return ENOTSUP;
833+
798834
if (uri_decode_hostport(&pl_hostport, &pl_host, &pl_port))
799835
return EINVAL;
800836

801837
conn = rtmp_conn_alloc(true, estabh, cmdh, closeh, arg);
802838
if (!conn)
803839
return ENOMEM;
804840

805-
conn->port = pl_isset(&pl_port) ? pl_u32(&pl_port) : RTMP_PORT;
841+
conn->port = pl_isset(&pl_port) ? pl_u32(&pl_port) : defport;
842+
conn->tls = tls;
806843

807844
err = pl_strdup(&conn->app, &pl_app);
808845
err |= pl_strdup(&conn->stream, &pl_stream);
846+
err |= pl_strdup(&conn->host, &pl_host);
809847
err |= str_dup(&conn->uri, uri);
810848
if (err)
811849
goto out;
@@ -828,10 +866,6 @@ int rtmp_connect(struct rtmp_conn **connp, struct dnsc *dnsc, const char *uri,
828866
goto out;
829867
}
830868

831-
err = pl_strdup(&conn->host, &pl_host);
832-
if (err)
833-
goto out;
834-
835869
conn->dnsc = mem_ref(dnsc);
836870

837871
err = dnsc_query(&conn->dnsq4, dnsc, conn->host, DNS_TYPE_A,
@@ -866,13 +900,15 @@ int rtmp_connect(struct rtmp_conn **connp, struct dnsc *dnsc, const char *uri,
866900
*
867901
* @param connp Pointer to allocated RTMP connection object
868902
* @param ts TCP socket with pending connection
903+
* @param tls TLS Context (optional)
869904
* @param cmdh Incoming command handler
870905
* @param closeh Close handler
871906
* @param arg Handler argument
872907
*
873908
* @return 0 if success, otherwise errorcode
874909
*/
875910
int rtmp_accept(struct rtmp_conn **connp, struct tcp_sock *ts,
911+
struct tls *tls,
876912
rtmp_command_h *cmdh, rtmp_close_h *closeh, void *arg)
877913
{
878914
struct rtmp_conn *conn;
@@ -890,6 +926,14 @@ int rtmp_accept(struct rtmp_conn **connp, struct tcp_sock *ts,
890926
if (err)
891927
goto out;
892928

929+
#ifdef USE_TLS
930+
if (tls) {
931+
err = tls_start_tcp(&conn->sc, tls, conn->tc, 0);
932+
if (err)
933+
goto out;
934+
}
935+
#endif
936+
893937
out:
894938
if (err)
895939
mem_deref(conn);

src/rtmp/rtmp.h

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct rtmp_conn {
3333
struct list streaml;
3434
struct rtmp_dechunker *dechunk;
3535
struct tcp_conn *tc;
36+
struct tls_conn *sc;
3637
struct mbuf *mb; /* TCP reassembly buffer */
3738
enum rtmp_handshake_state state;
3839
size_t total_bytes;
@@ -53,6 +54,7 @@ struct rtmp_conn {
5354
struct dns_query *dnsq6;
5455
struct list ctransl;
5556
struct sa srvv[16];
57+
struct tls *tls;
5658
unsigned srvc;
5759
uint64_t tid_counter;
5860
uint16_t port;

src/tls/openssl/tls.c

+35
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <openssl/bn.h>
1111
#include <openssl/evp.h>
1212
#include <openssl/x509.h>
13+
#include <openssl/x509v3.h>
1314
#include <re_types.h>
1415
#include <re_fmt.h>
1516
#include <re_mem.h>
@@ -876,6 +877,40 @@ int tls_set_servername(struct tls_conn *tc, const char *servername)
876877
}
877878

878879

880+
/**
881+
* Enable verification of server certificate and hostname
882+
*
883+
* @param tc TLS Connection
884+
* @param host Server hostname
885+
*
886+
* @return 0 if success, otherwise errorcode
887+
*/
888+
int tls_set_verify_server(struct tls_conn *tc, const char *host)
889+
{
890+
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
891+
!defined(LIBRESSL_VERSION_NUMBER)
892+
893+
if (!tc || !host)
894+
return EINVAL;
895+
896+
SSL_set_hostflags(tc->ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
897+
if (!SSL_set1_host(tc->ssl, host)) {
898+
ERR_clear_error();
899+
return EPROTO;
900+
}
901+
902+
SSL_set_verify(tc->ssl, SSL_VERIFY_PEER, NULL);
903+
904+
return 0;
905+
#else
906+
(void)tc;
907+
(void)host;
908+
909+
return ENOSYS;
910+
#endif
911+
}
912+
913+
879914
static int print_error(const char *str, size_t len, void *unused)
880915
{
881916
(void)unused;

0 commit comments

Comments
 (0)