Fix Cygwin compilation:

- Fix various incompatibilities and differences between Linux and Cygwin builds
- Make usrsctp an optional dependency
- Fix building without SSL
- Add new secure random bytes function, use it for websockets
- Switch to libsrtp2 v2.6.0 (currently latest release)
- Add patch that makes latest libsrtp2 build in latest Cygwin
- Add patch that makes srt build in latest Cygwin
- Correctly allow linking libsrtp2 and srt to local mbedtls version
This commit is contained in:
Thulinma 2024-03-26 12:04:53 +01:00
parent db30be38c5
commit dbafa808b8
23 changed files with 131 additions and 23 deletions

View file

@ -927,7 +927,9 @@ void Util::getMyExec(std::deque<std::string> &execs){
WIN32_FIND_DATA FindFileData;
HANDLE hdl = FindFirstFile(path.c_str(), &FindFileData);
while (hdl != INVALID_HANDLE_VALUE){
execs.push_back(FindFileData.cFileName);
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
execs.push_back(FindFileData.cFileName);
}
if (!FindNextFile(hdl, &FindFileData)){
FindClose(hdl);
hdl = INVALID_HANDLE_VALUE;

View file

@ -13,7 +13,6 @@ headers = [
'config.h',
'defines.h',
'dtsc.h',
'encryption.h',
'flv_tag.h',
'h264.h',
'h265.h',
@ -63,14 +62,15 @@ if have_srt
headers += 'socket_srt.h'
endif
install_headers(headers, subdir: 'mist')
extra_code = []
if usessl
headers += 'encryption.h'
extra_code += ['stun.cpp', 'certificate.cpp', 'encryption.cpp',]
endif
install_headers(headers, subdir: 'mist')
libmist = library('mist',
'adts.cpp',
'amf.cpp',

View file

@ -592,7 +592,7 @@ namespace IPC{
unmap();
if (handle > 0){
::close(handle);
if (master && name != ""){unlink(name.c_str());}
if (master && name != ""){unlink(std::string(Util::getTmpFolder() + name).c_str());}
handle = 0;
}
}

View file

@ -1605,6 +1605,7 @@ int Socket::Server::getSocket(){
}
#ifdef SSL
static int dTLS_recv(void *s, unsigned char *buf, size_t len){
return ((Socket::UDPConnection*)s)->dTLSRead(buf, len);
}
@ -1612,6 +1613,7 @@ static int dTLS_recv(void *s, unsigned char *buf, size_t len){
static int dTLS_send(void *s, const unsigned char *buf, size_t len){
return ((Socket::UDPConnection*)s)->dTLSWrite(buf, len);
}
#endif
/// Create a new UDP Socket.
@ -1680,6 +1682,7 @@ static int dtlsExtractKeyData( void *user, const unsigned char *ms, const unsign
}
#endif
#ifdef SSL
void Socket::UDPConnection::initDTLS(mbedtls_x509_crt *cert, mbedtls_pk_context *key){
hasDTLS = true;
nextDTLSRead = 0;
@ -1825,6 +1828,7 @@ void Socket::UDPConnection::dTLSReset(){
WARN_MSG("dTLS could not set transport ID: %s", mbedtls_msg);
}
}
#endif //if SSL
///Checks if the UDP receive buffer is at least 1 mbyte, attempts to increase and warns user through log message on failure.
void Socket::UDPConnection::checkRecvBuf(){
@ -1913,7 +1917,9 @@ Socket::UDPConnection::~UDPConnection(){
free(recvAddr);
recvAddr = 0;
}
#ifdef SSL
deinitDTLS();
#endif
}
@ -2175,6 +2181,7 @@ void Socket::UDPConnection::SendNow(const char *sdata, size_t len, sockaddr * dA
}
return;
}
#if !defined(__CYGWIN__) && !defined(_WIN32)
if (hasReceiveData && recvAddr){
msghdr mHdr;
char msg_control[0x100];
@ -2209,13 +2216,16 @@ void Socket::UDPConnection::SendNow(const char *sdata, size_t len, sockaddr * dA
}
return;
}else{
#endif
int r = sendto(sock, sdata, len, 0, dAddr, dAddrLen);
if (r > 0){
up += r;
}else{
FAIL_MSG("Could not send UDP data through %d: %s", sock, strerror(errno));
}
#if !defined(__CYGWIN__) && !defined(_WIN32)
}
#endif
}
/// Queues sdata, len for sending over this socket.
@ -2223,6 +2233,7 @@ void Socket::UDPConnection::SendNow(const char *sdata, size_t len, sockaddr * dA
/// Warning: never call sendPaced for the same socket from a different thread!
/// Note: Only actually encrypts if initDTLS was called in the past.
void Socket::UDPConnection::sendPaced(const char *sdata, size_t len, bool encrypt){
#ifdef SSL
if (hasDTLS && encrypt){
#if MBEDTLS_VERSION_MAJOR > 2
if (!mbedtls_ssl_is_handshake_over(&ssl_ctx)){
@ -2235,6 +2246,7 @@ void Socket::UDPConnection::sendPaced(const char *sdata, size_t len, bool encryp
int write = mbedtls_ssl_write(&ssl_ctx, (unsigned char*)sdata, len);
if (write <= 0){WARN_MSG("Could not write DTLS packet!");}
}else{
#endif
if (!paceQueue.size() && (!lastPace || Util::getMicros(lastPace) > 10000)){
SendNow(sdata, len);
lastPace = Util::getMicros();
@ -2244,7 +2256,9 @@ void Socket::UDPConnection::sendPaced(const char *sdata, size_t len, bool encryp
// Try to send a packet, if time allows
//sendPaced(0);
}
#ifdef SSL
}
#endif
}
// Gets time in microseconds until next sendPaced call would send something
@ -2621,6 +2635,7 @@ bool Socket::UDPConnection::Receive(){
return false;
}
if (destAddr && destsize && destAddr_size >= destsize){memcpy(destAddr, &addr, destsize);}
#if !defined(__CYGWIN__) && !defined(_WIN32)
if (recvAddr){
for ( struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mHdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mHdr, cmsg)){
if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO){continue;}
@ -2633,6 +2648,7 @@ bool Socket::UDPConnection::Receive(){
hasReceiveData = true;
}
}
#endif
data.append(0, r);
down += r;
//Handle UDP packets that are too large
@ -2646,8 +2662,9 @@ bool Socket::UDPConnection::Receive(){
bool Socket::UDPConnection::onData(){
wasEncrypted = false;
if (!data.size()){return false;}
uint8_t fb = 0;
int r = data.size();
#ifdef SSL
uint8_t fb = 0;
if (r){fb = (uint8_t)data[0];}
if (r && hasDTLS && fb > 19 && fb < 64){
if (nextDTLSReadLen){
@ -2761,6 +2778,7 @@ bool Socket::UDPConnection::onData(){
return true;
}
}
#endif
return r > 0;
}

View file

@ -237,12 +237,14 @@ namespace Socket{
bool hasDTLS; ///< True if dTLS is enabled
void * nextDTLSRead;
size_t nextDTLSReadLen;
#ifdef SSL
mbedtls_entropy_context entropy_ctx;
mbedtls_ctr_drbg_context rand_ctx;
mbedtls_ssl_context ssl_ctx;
mbedtls_ssl_config ssl_conf;
mbedtls_ssl_cookie_ctx cookie_ctx;
mbedtls_timing_delay_context timer_ctx;
#endif
public:
Util::ResizeablePointer data;
@ -251,11 +253,13 @@ namespace Socket{
~UDPConnection();
bool operator==(const UDPConnection& b) const;
operator bool() const;
#ifdef SSL
void initDTLS(mbedtls_x509_crt *cert, mbedtls_pk_context *key);
void deinitDTLS();
int dTLSRead(unsigned char *buf, size_t len);
int dTLSWrite(const unsigned char *buf, size_t len);
void dTLSReset();
#endif
bool wasEncrypted;
void close();
int getSock();
@ -281,12 +285,15 @@ namespace Socket{
size_t timeToNextPace(uint64_t uTime = 0);
void setSocketFamily(int AF_TYPE);
#ifdef SSL
// dTLS-related public members
std::string cipher, remote_key, local_key, remote_salt, local_salt;
#if HAVE_UPSTREAM_MBEDTLS_SRTP
unsigned char master_secret[48];
unsigned char randbytes[64];
mbedtls_tls_prf_types tls_prf_type;
#endif
#endif
};
}// namespace Socket

View file

@ -1,6 +1,6 @@
/// \file timing.cpp
/// Utilities for handling time and timestamps.
#define _XOPEN_SOURCE // Ensures strptime works in Cygwin
#include "timing.h"
#include <cstdio>
#include <cstring>

View file

@ -302,6 +302,16 @@ namespace Util{
DONTEVEN_MSG("Waiting %" PRId64 " ms out of %" PRId64 " for iteration %zu/%zu", w, maxWait, currIter, maxIter);
return w;
}
/// Secure random bytes generator
/// Uses /dev/urandom internally
void getRandomBytes(void * dest, size_t len){
static FILE * randSource = fopen("/dev/urandom", "rb");
if (fread((void *)dest, len, 1, randSource) != 1){
WARN_MSG("Reading random data failed - generating using rand() as backup");
for (size_t i = 0; i < len; ++i){((char*)dest)[i] = rand() % 255;}
}
}
/// 64-bits version of ftell
uint64_t ftell(FILE *stream){
@ -374,7 +384,12 @@ namespace Util{
bool ResizeablePointer::allocate(uint32_t l){
if (l > maxSize){
void *tmp = realloc(ptr, l);
void *tmp = 0;
if (!ptr){
tmp = malloc(l);
}else{
tmp = realloc(ptr, l);
}
if (!tmp){
FAIL_MSG("Could not allocate %" PRIu32 " bytes of memory", l);
return false;

View file

@ -20,6 +20,8 @@ namespace Util{
int64_t expBackoffMs(const size_t currIter, const size_t maxIter, const int64_t maxWait);
void getRandomBytes(void * dest, size_t len);
uint64_t ftell(FILE *stream);
uint64_t fseek(FILE *stream, uint64_t offset, int whence);

View file

@ -8,6 +8,7 @@
#include "mbedtls/sha1.h"
#endif
#ifdef SSL
// Takes the data from a Sec-WebSocket-Key header, and returns the corresponding data for a Sec-WebSocket-Accept header
static std::string calculateKeyAccept(std::string client_key){
client_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@ -18,6 +19,7 @@ static std::string calculateKeyAccept(std::string client_key){
mbedtls_sha1_finish(&ctx, outdata);
return Encodings::Base64::encode(std::string((const char *)outdata, 20));
}
#endif
namespace HTTP{
@ -33,12 +35,9 @@ namespace HTTP{
//Ensure our passed socket gets used by the downloader class
d.setSocket(&C);
//Generate a random nonce based on the current process ID
//Note: This is not cryptographically secure, nor intended to be.
//It does make it possible to trace which stream came from which PID, if needed.
//Generate a random nonce
char nonce[16];
unsigned int state = getpid();
for (size_t i = 0; i < 16; ++i){nonce[i] = rand_r(&state) % 255;}
Util::getRandomBytes(nonce, 16);
std::string handshakeKey = Encodings::Base64::encode(std::string(nonce, 16));
//Prepare the headers