#define MS_CLASS "mediasoup-worker"
#include "common.hpp"
#include "DepLibSRTP.hpp"
#include "DepLibUV.hpp"
#include "DepLibWebRTC.hpp"
#include "DepOpenSSL.hpp"
#include "DepUsrSCTP.hpp"
#include "Logger.hpp"
#include "MediaSoupErrors.hpp"
#include "Settings.hpp"
#include "Utils.hpp"
#include "Worker.hpp"
#include "Channel/ChannelSocket.hpp"
#include "PayloadChannel/PayloadChannelSocket.hpp"
#include "RTC/DtlsTransport.hpp"
#include "RTC/SrtpSession.hpp"
#include <uv.h>
#include <absl/container/flat_hash_map.h>
#include <cerrno>
#include <csignal>
#include <string>
void IgnoreSignals();
extern "C" int mediasoup_worker_run(
int argc,
char* argv[],
const char* version,
int consumerChannelFd,
int producerChannelFd,
int payloadConsumeChannelFd,
int payloadProduceChannelFd,
ChannelReadFn channelReadFn,
ChannelReadCtx channelReadCtx,
ChannelWriteFn channelWriteFn,
ChannelWriteCtx channelWriteCtx,
PayloadChannelReadFn payloadChannelReadFn,
PayloadChannelReadCtx payloadChannelReadCtx,
PayloadChannelWriteFn payloadChannelWriteFn,
PayloadChannelWriteCtx payloadChannelWriteCtx)
{
DepLibUV::ClassInit();
std::unique_ptr<Channel::ChannelSocket> channel{ nullptr };
std::unique_ptr<PayloadChannel::PayloadChannelSocket> payloadChannel{ nullptr };
try
{
if (channelReadFn)
{
channel.reset(
new Channel::ChannelSocket(channelReadFn, channelReadCtx, channelWriteFn, channelWriteCtx));
}
else
{
channel.reset(new Channel::ChannelSocket(consumerChannelFd, producerChannelFd));
}
}
catch (const MediaSoupError& error)
{
MS_ERROR_STD("error creating the Channel: %s", error.what());
DepLibUV::RunLoop();
DepLibUV::ClassDestroy();
return 40;
}
try
{
if (payloadChannelReadFn)
{
payloadChannel.reset(new PayloadChannel::PayloadChannelSocket(
payloadChannelReadFn, payloadChannelReadCtx, payloadChannelWriteFn, payloadChannelWriteCtx));
}
else
{
payloadChannel.reset(
new PayloadChannel::PayloadChannelSocket(payloadConsumeChannelFd, payloadProduceChannelFd));
}
}
catch (const MediaSoupError& error)
{
MS_ERROR_STD("error creating the PayloadChannel: %s", error.what());
channel->Close();
DepLibUV::RunLoop();
DepLibUV::ClassDestroy();
return 40;
}
Logger::ClassInit(channel.get());
try
{
Settings::SetConfiguration(argc, argv);
}
catch (const MediaSoupTypeError& error)
{
MS_ERROR_STD("settings error: %s", error.what());
channel->Close();
payloadChannel->Close();
DepLibUV::RunLoop();
DepLibUV::ClassDestroy();
return 42;
}
catch (const MediaSoupError& error)
{
MS_ERROR_STD("unexpected settings error: %s", error.what());
channel->Close();
payloadChannel->Close();
DepLibUV::RunLoop();
DepLibUV::ClassDestroy();
return 40;
}
MS_DEBUG_TAG(info, "starting mediasoup-worker process [version:%s]", version);
#if defined(MS_LITTLE_ENDIAN)
MS_DEBUG_TAG(info, "little-endian CPU detected");
#elif defined(MS_BIG_ENDIAN)
MS_DEBUG_TAG(info, "big-endian CPU detected");
#else
MS_WARN_TAG(info, "cannot determine whether little-endian or big-endian");
#endif
#if defined(INTPTR_MAX) && defined(INT32_MAX) && (INTPTR_MAX == INT32_MAX)
MS_DEBUG_TAG(info, "32 bits architecture detected");
#elif defined(INTPTR_MAX) && defined(INT64_MAX) && (INTPTR_MAX == INT64_MAX)
MS_DEBUG_TAG(info, "64 bits architecture detected");
#else
MS_WARN_TAG(info, "cannot determine 32 or 64 bits architecture");
#endif
Settings::PrintConfiguration();
DepLibUV::PrintVersion();
try
{
DepOpenSSL::ClassInit();
DepLibSRTP::ClassInit();
DepUsrSCTP::ClassInit();
DepLibWebRTC::ClassInit();
Utils::Crypto::ClassInit();
RTC::DtlsTransport::ClassInit();
RTC::SrtpSession::ClassInit();
#ifdef MS_EXECUTABLE
IgnoreSignals();
#endif
Worker worker(channel.get(), payloadChannel.get());
DepLibSRTP::ClassDestroy();
Utils::Crypto::ClassDestroy();
DepLibWebRTC::ClassDestroy();
RTC::DtlsTransport::ClassDestroy();
DepUsrSCTP::ClassDestroy();
DepLibUV::ClassDestroy();
#ifdef MS_EXECUTABLE
uv_sleep(200);
#endif
return 0;
}
catch (const MediaSoupError& error)
{
MS_ERROR_STD("failure exit: %s", error.what());
return 40;
}
}
void IgnoreSignals()
{
#ifndef _WIN32
MS_TRACE();
int err;
struct sigaction act;
absl::flat_hash_map<std::string, int> ignoredSignals =
{
{ "PIPE", SIGPIPE },
{ "HUP", SIGHUP },
{ "ALRM", SIGALRM },
{ "USR1", SIGUSR1 },
{ "USR2", SIGUSR2 }
};
act.sa_handler = SIG_IGN; act.sa_flags = 0;
err = sigfillset(&act.sa_mask);
if (err != 0)
{
MS_THROW_ERROR("sigfillset() failed: %s", std::strerror(errno));
}
for (auto& kv : ignoredSignals)
{
const auto& sigName = kv.first;
int sigId = kv.second;
err = sigaction(sigId, &act, nullptr);
if (err != 0)
{
MS_THROW_ERROR("sigaction() failed for signal %s: %s", sigName.c_str(), std::strerror(errno));
}
}
#endif
}