Added RTMPS listening port support
This commit is contained in:
parent
8fd4f29b06
commit
78a30e212e
4 changed files with 156 additions and 0 deletions
|
@ -807,6 +807,51 @@ static void my_debug(void *ctx, int level, const char *file, int line, const cha
|
||||||
fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str);
|
fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str);
|
||||||
fflush((FILE *)ctx);
|
fflush((FILE *)ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a just-accepted socket and SSL-ifies it.
|
||||||
|
bool Socket::Connection::sslAccept(mbedtls_ssl_config * sslConf, mbedtls_ctr_drbg_context * dbgCtx){
|
||||||
|
int ret;
|
||||||
|
server_fd = new mbedtls_net_context;
|
||||||
|
mbedtls_net_init(server_fd);
|
||||||
|
server_fd->fd = getSocket();
|
||||||
|
|
||||||
|
ssl = new mbedtls_ssl_context;
|
||||||
|
mbedtls_ssl_init(ssl);
|
||||||
|
if ((ret = mbedtls_ctr_drbg_reseed(dbgCtx, (const unsigned char *)"child", 5)) != 0){
|
||||||
|
FAIL_MSG("Could not reseed");
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the SSL connection
|
||||||
|
if ((ret = mbedtls_ssl_setup(ssl, sslConf)) != 0){
|
||||||
|
FAIL_MSG("Could not set up SSL connection");
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inform mbedtls how we'd like to use the connection (uses default bio handlers)
|
||||||
|
// We tell it to use non-blocking IO here
|
||||||
|
mbedtls_net_set_nonblock(server_fd);
|
||||||
|
Blocking = false;
|
||||||
|
mbedtls_ssl_set_bio(ssl, server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||||
|
// do the SSL handshake
|
||||||
|
while ((ret = mbedtls_ssl_handshake(ssl)) != 0){
|
||||||
|
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE){
|
||||||
|
char error_buf[200];
|
||||||
|
mbedtls_strerror(ret, error_buf, 200);
|
||||||
|
WARN_MSG("Could not handshake, SSL error: %s (%d)", error_buf, ret);
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
Util::sleep(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sslConnected = true;
|
||||||
|
HIGH_MSG("Started SSL connection handler");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Create a new TCP Socket. This socket will (try to) connect to the given host/port right away.
|
/// Create a new TCP Socket. This socket will (try to) connect to the given host/port right away.
|
||||||
|
|
|
@ -144,6 +144,9 @@ namespace Socket{
|
||||||
void open(std::string hostname, int port, bool nonblock, bool with_ssl = false); // Open TCP connection.
|
void open(std::string hostname, int port, bool nonblock, bool with_ssl = false); // Open TCP connection.
|
||||||
void open(std::string adres, bool nonblock = false); // Open Unix connection.
|
void open(std::string adres, bool nonblock = false); // Open Unix connection.
|
||||||
void open(int write, int read); // Open from two existing file descriptors.
|
void open(int write, int read); // Open from two existing file descriptors.
|
||||||
|
#ifdef SSL
|
||||||
|
bool sslAccept(mbedtls_ssl_config * sslConf, mbedtls_ctr_drbg_context * dbgCtx);
|
||||||
|
#endif
|
||||||
void close(); ///< Close connection.
|
void close(); ///< Close connection.
|
||||||
void drop(); ///< Close connection without shutdown.
|
void drop(); ///< Close connection without shutdown.
|
||||||
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
|
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
|
||||||
|
|
|
@ -21,7 +21,19 @@ const char * trackType(char ID){
|
||||||
|
|
||||||
|
|
||||||
namespace Mist{
|
namespace Mist{
|
||||||
|
#ifdef SSL
|
||||||
|
bool sslEnabled = false;
|
||||||
|
mbedtls_entropy_context OutRTMP::entropy;
|
||||||
|
mbedtls_ctr_drbg_context OutRTMP::ctr_drbg;
|
||||||
|
mbedtls_ssl_config OutRTMP::sslConf;
|
||||||
|
mbedtls_x509_crt OutRTMP::srvcert;
|
||||||
|
mbedtls_pk_context OutRTMP::pkey;
|
||||||
|
#endif
|
||||||
|
|
||||||
OutRTMP::OutRTMP(Socket::Connection &conn) : Output(conn){
|
OutRTMP::OutRTMP(Socket::Connection &conn) : Output(conn){
|
||||||
|
#ifdef SSL
|
||||||
|
if (sslEnabled){myConn.sslAccept(&sslConf, &ctr_drbg);}
|
||||||
|
#endif
|
||||||
lastSilence = 0;
|
lastSilence = 0;
|
||||||
hasSilence = false;
|
hasSilence = false;
|
||||||
lastAudioInserted = 0;
|
lastAudioInserted = 0;
|
||||||
|
@ -90,6 +102,74 @@ namespace Mist{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SSL
|
||||||
|
/// Listens for HTTPS requests, accepting them and connecting them to a HTTP socket
|
||||||
|
void OutRTMP::listener(Util::Config &conf, int (*callback)(Socket::Connection &S)){
|
||||||
|
// No cert or key? Non-SSL mode.
|
||||||
|
if (config->getOption("cert", true).size() < 2 || config->getOption("key", true).size() < 2){
|
||||||
|
INFO_MSG("No cert or key set, regular RTMP mode");
|
||||||
|
Output::listener(conf, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO_MSG("Cert and key set, RTMPS mode");
|
||||||
|
sslEnabled = true;
|
||||||
|
|
||||||
|
// Declare and set up all required mbedtls structures
|
||||||
|
int ret;
|
||||||
|
mbedtls_ssl_config_init(&sslConf);
|
||||||
|
mbedtls_entropy_init(&entropy);
|
||||||
|
mbedtls_pk_init(&pkey);
|
||||||
|
mbedtls_x509_crt_init(&srvcert);
|
||||||
|
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||||
|
|
||||||
|
// seed the rng
|
||||||
|
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||||
|
(const unsigned char *)APPNAME, strlen(APPNAME))) != 0){
|
||||||
|
FAIL_MSG("Could not seed the random number generator!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read certificate chain(s) from cmdline option(s)
|
||||||
|
JSON::Value certs = config->getOption("cert", true);
|
||||||
|
jsonForEach(certs, it){
|
||||||
|
if (it->asStringRef().size()){// Ignore empty entries (default is empty)
|
||||||
|
ret = mbedtls_x509_crt_parse_file(&srvcert, it->asStringRef().c_str());
|
||||||
|
if (ret != 0){
|
||||||
|
WARN_MSG("Could not load any certificates from file: %s", it->asStringRef().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read key from cmdline option
|
||||||
|
ret = mbedtls_pk_parse_keyfile(&pkey, config->getString("key").c_str(), 0);
|
||||||
|
if (ret != 0){
|
||||||
|
FAIL_MSG("Could not load any keys from file: %s", config->getString("key").c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = mbedtls_ssl_config_defaults(&sslConf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_DEFAULT)) != 0){
|
||||||
|
FAIL_MSG("SSL config defaults failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mbedtls_ssl_conf_rng(&sslConf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||||
|
mbedtls_ssl_conf_ca_chain(&sslConf, srvcert.next, NULL);
|
||||||
|
if ((ret = mbedtls_ssl_conf_own_cert(&sslConf, &srvcert, &pkey)) != 0){
|
||||||
|
FAIL_MSG("SSL config own certificate failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::listener(conf, callback);
|
||||||
|
|
||||||
|
// Free all the mbedtls structures
|
||||||
|
mbedtls_x509_crt_free(&srvcert);
|
||||||
|
mbedtls_pk_free(&pkey);
|
||||||
|
mbedtls_ssl_config_free(&sslConf);
|
||||||
|
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||||
|
mbedtls_entropy_free(&entropy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void OutRTMP::startPushOut(const char *args){
|
void OutRTMP::startPushOut(const char *args){
|
||||||
|
|
||||||
myConn.close();
|
myConn.close();
|
||||||
|
@ -277,6 +357,22 @@ namespace Mist{
|
||||||
capa["optional"]["maxkbps"]["short"] = "K";
|
capa["optional"]["maxkbps"]["short"] = "K";
|
||||||
capa["optional"]["maxkbps"]["default"] = 0;
|
capa["optional"]["maxkbps"]["default"] = 0;
|
||||||
capa["optional"]["maxkbps"]["type"] = "uint";
|
capa["optional"]["maxkbps"]["type"] = "uint";
|
||||||
|
|
||||||
|
#ifdef SSL
|
||||||
|
capa["optional"]["cert"]["name"] = "Certificate";
|
||||||
|
capa["optional"]["cert"]["help"] = "(Root) certificate(s) file(s) to append to chain";
|
||||||
|
capa["optional"]["cert"]["option"] = "--cert";
|
||||||
|
capa["optional"]["cert"]["short"] = "C";
|
||||||
|
capa["optional"]["cert"]["default"] = "";
|
||||||
|
capa["optional"]["cert"]["type"] = "str";
|
||||||
|
capa["optional"]["key"]["name"] = "Key";
|
||||||
|
capa["optional"]["key"]["help"] = "Private key for SSL";
|
||||||
|
capa["optional"]["key"]["option"] = "--key";
|
||||||
|
capa["optional"]["key"]["short"] = "k";
|
||||||
|
capa["optional"]["key"]["default"] = "";
|
||||||
|
capa["optional"]["key"]["type"] = "str";
|
||||||
|
#endif
|
||||||
|
|
||||||
cfg->addConnectorOptions(1935, capa);
|
cfg->addConnectorOptions(1935, capa);
|
||||||
config = cfg;
|
config = cfg;
|
||||||
config->addStandardPushCapabilities(capa);
|
config->addStandardPushCapabilities(capa);
|
||||||
|
|
|
@ -19,6 +19,9 @@ namespace Mist{
|
||||||
static bool listenMode();
|
static bool listenMode();
|
||||||
void requestHandler();
|
void requestHandler();
|
||||||
bool onFinish();
|
bool onFinish();
|
||||||
|
#ifdef SSL
|
||||||
|
static void listener(Util::Config &conf, int (*callback)(Socket::Connection &S));
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string streamOut; ///< When pushing out, the output stream name
|
std::string streamOut; ///< When pushing out, the output stream name
|
||||||
|
@ -52,6 +55,15 @@ namespace Mist{
|
||||||
void sendLoopedAudio(uint64_t untilTimestamp);
|
void sendLoopedAudio(uint64_t untilTimestamp);
|
||||||
// Gets the next ADTS frame in AAC file. Loops if EOF reached
|
// Gets the next ADTS frame in AAC file. Loops if EOF reached
|
||||||
void calcNextFrameInfo();
|
void calcNextFrameInfo();
|
||||||
|
|
||||||
|
#ifdef SSL
|
||||||
|
// TLS-related
|
||||||
|
static mbedtls_entropy_context entropy;
|
||||||
|
static mbedtls_ctr_drbg_context ctr_drbg;
|
||||||
|
static mbedtls_ssl_config sslConf;
|
||||||
|
static mbedtls_x509_crt srvcert;
|
||||||
|
static mbedtls_pk_context pkey;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}// namespace Mist
|
}// namespace Mist
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue