Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion include/mumlib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
#include "mumlib/Callback.hpp"

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/noncopyable.hpp>


#include <string>
#include <mumlib/enums.hpp>

Expand All @@ -15,14 +17,28 @@ namespace mumlib {
using namespace std;
using namespace boost::asio;

#ifdef MUMLIB_USE_EXCEPTIONS
class MumlibException : public runtime_error {
public:
MumlibException(string message) : runtime_error(message) { }
};
#endif
struct MumlibConfigurationSSLOptions
{
std::string ssl_cert, ssl_key, ssl_rsa_key;
};
struct MumlibConfigurationVersionOptions
{
string os_version = "Not set", os_build = "Not set", mumble_version = "Not set";
int mumble_version_int = 0x010300;

};

struct MumlibConfiguration {
int opusEncoderBitrate = DEFAULT_OPUS_ENCODER_BITRATE;
// additional fields will be added in the future
MumlibConfigurationVersionOptions version;
MumlibConfigurationSSLOptions ssl;

};

struct _Mumlib_Private;
Expand Down
13 changes: 8 additions & 5 deletions include/mumlib/Audio.hpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
#pragma once

#include "Transport.hpp"
#include <mumlib/Transport.hpp>

#include <opus.h>
#include <opus/opus.h>

#include <chrono>

namespace mumlib {

constexpr int SAMPLE_RATE = 48000;

#ifdef MUMLIB_USE_EXCEPTIONS
class MumlibException;

class AudioException : public MumlibException {
public:
AudioException(string message) : MumlibException(message) { }
};
#endif

struct IncomingAudioPacket {
AudioPacketType type;
Expand Down Expand Up @@ -53,7 +54,9 @@ namespace mumlib {
void resetEncoder();

private:
log4cpp::Category &logger;
#ifdef MUMLIB_USE_LOG4CPP
MUMLIB_USE_LOG4CPP::Category &logger;
#endif

OpusDecoder *opusDecoder;
OpusEncoder *opusEncoder;
Expand All @@ -62,4 +65,4 @@ namespace mumlib {

std::chrono::time_point<std::chrono::system_clock> lastEncodedAudioPacketTimestamp;
};
}
}
4 changes: 3 additions & 1 deletion include/mumlib/Callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ namespace mumlib {
uint32_t version,
uint32_t positional,
uint32_t push_to_talk) { };
virtual void disconnected () {};

};

Expand Down Expand Up @@ -285,8 +286,9 @@ namespace mumlib {
uint32_t version,
uint32_t positional,
uint32_t push_to_talk) override;
virtual void disconnected() override;

private:
_BasicCallback_Private *impl;
};
}
}
40 changes: 28 additions & 12 deletions include/mumlib/Transport.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#pragma once

#include "mumlib/CryptState.hpp"
#include "mumlib/VarInt.hpp"
#include "enums.hpp"
#include <mumlib/CryptState.hpp>
#include <mumlib/VarInt.hpp>
#include <mumlib/enums.hpp>

#include <boost/noncopyable.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/pool/pool.hpp>

#include <log4cpp/Category.hh>
#ifdef MUMLIB_USE_LOG4CPP
#include <MUMLIB_USE_LOG4CPP/Category.hh>
#endif
#include <google/protobuf/message.h>

#include <chrono>
Expand All @@ -27,18 +26,20 @@ namespace mumlib {
typedef function<bool(MessageType, uint8_t *, int)> ProcessControlMessageFunction;

typedef function<bool(AudioPacketType, uint8_t *, int)> ProcessEncodedAudioPacketFunction;

#ifdef MUMLIB_USE_EXCEPTIONS
class TransportException : public MumlibException {
public:
TransportException(string message) : MumlibException(message) { }
};
#endif

class Transport : boost::noncopyable {
public:
Transport(io_service &ioService,
ProcessControlMessageFunction processControlMessageFunc,
ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction,
bool noUdp = false);
MumlibConfiguration MumblConfig,
bool noUdp = true);

~Transport();

Expand All @@ -59,8 +60,15 @@ namespace mumlib {

void sendEncodedAudioPacket(uint8_t *buffer, int length);

void set_callback(Callback *cb)
{
this->cb = cb;
}

private:
log4cpp::Category &logger;
#ifdef MUMLIB_USE_LOG4CPP
MUMLIB_USE_LOG4CPP::Category &logger;
#endif

io_service &ioService;

Expand All @@ -84,14 +92,21 @@ namespace mumlib {
CryptState cryptState;

ssl::context sslContext;
ssl::stream<tcp::socket> sslSocket;
ssl::stream<tcp::socket> *sslSocket; //must be created after context already configured
uint8_t *sslIncomingBuffer;

deadline_timer pingTimer;
std::chrono::time_point<std::chrono::system_clock> lastReceivedUdpPacketTimestamp;

boost::pool<> asyncBufferPool;

MumlibConfiguration MumbleConfig;
//session related data
std::string name;
uint32_t session;
//
Callback *cb = nullptr;

void pingTimerTick(const boost::system::error_code &e);

void sslConnectHandler(const boost::system::error_code &error);
Expand Down Expand Up @@ -119,8 +134,9 @@ namespace mumlib {
void sendUdpAsync(uint8_t *buff, int length);

void sendUdpPing();

#ifdef MUMLIB_USE_EXCEPTIONS
void throwTransportException(string message);
#endif

void processAudioPacket(uint8_t *buff, int length);
};
Expand Down
4 changes: 3 additions & 1 deletion include/mumlib/VarInt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#include <string>

namespace mumlib {
#ifdef MUMLIB_USE_EXCEPTIONS
class VarIntException : public MumlibException {
public:
VarIntException(std::string message) : MumlibException(message) { }
};
#endif

class VarInt {
public:
Expand All @@ -31,4 +33,4 @@ namespace mumlib {

int64_t parseVariant(uint8_t *buffer);
};
}
}
37 changes: 31 additions & 6 deletions src/Audio.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
#include "mumlib/Audio.hpp"
#include "mumlib/include/mumlib/Audio.hpp"

#include <boost/format.hpp>

static boost::posix_time::seconds RESET_SEQUENCE_NUMBER_INTERVAL(5);

mumlib::Audio::Audio(int opusEncoderBitrate)
: logger(log4cpp::Category::getInstance("mumlib.Audio")),
:
#ifdef MUMLIB_USE_LOG4CPP
logger(MUMLIB_USE_LOG4CPP::Category::getInstance("mumlib.Audio")),
#endif
opusDecoder(nullptr),
opusEncoder(nullptr),
outgoingSequenceNumber(0) {
outgoingSequenceNumber(0)
{

int error;

opusDecoder = opus_decoder_create(SAMPLE_RATE, 1, &error);
if (error != OPUS_OK) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to initialize OPUS decoder: %s") % opus_strerror(error)).str());
#endif
}

opusEncoder = opus_encoder_create(SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &error);
if (error != OPUS_OK) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to initialize OPUS encoder: %s") % opus_strerror(error)).str());
#endif
}

opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(0));
Expand All @@ -42,16 +49,20 @@ mumlib::Audio::~Audio() {
void mumlib::Audio::setOpusEncoderBitrate(int bitrate) {
int error = opus_encoder_ctl(opusEncoder, OPUS_SET_BITRATE(bitrate));
if (error != OPUS_OK) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to initialize transmission bitrate to %d B/s: %s")
% bitrate % opus_strerror(error)).str());
#endif
}
}

int mumlib::Audio::getOpusEncoderBitrate() {
opus_int32 bitrate;
int error = opus_encoder_ctl(opusEncoder, OPUS_GET_BITRATE(&bitrate));
if (error != OPUS_OK) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to read Opus bitrate: %s") % opus_strerror(error)).str());
#endif
}
return bitrate;
}
Expand All @@ -71,8 +82,10 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
opusDataLength = opusDataLength & 0x1fff;

if (inputLength < opusDataLength + dataPointer) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("invalid Opus payload (%d B): header %d B, expected Opus data length %d B")
% inputLength % dataPointer % opusDataLength).str());
#endif
}

int outputSize = opus_decode(opusDecoder,
Expand All @@ -83,12 +96,15 @@ std::pair<int, bool> mumlib::Audio::decodeOpusPayload(uint8_t *inputBuffer,
0);

if (outputSize <= 0) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to decode %d B of OPUS data: %s") % inputLength %
opus_strerror(outputSize)).str());
#endif
}

#ifdef MUMLIB_USE_LOG4CPP
logger.debug("%d B of Opus data decoded to %d PCM samples, last packet: %d.",
opusDataLength, outputSize, lastPacket);
#endif

return std::make_pair(outputSize, lastPacket);
}
Expand All @@ -102,7 +118,9 @@ int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int in
system_clock::now() - lastEncodedAudioPacketTimestamp).count();

if (lastAudioPacketSentInterval > RESET_SEQUENCE_NUMBER_INTERVAL.total_milliseconds() + 1000) {
#ifdef MUMLIB_USE_LOG4CPP
logger.debug("Last audio packet was sent %d ms ago, resetting encoder.", lastAudioPacketSentInterval);
#endif
resetEncoder();
}

Expand All @@ -122,8 +140,10 @@ int mumlib::Audio::encodeAudioPacket(int target, int16_t *inputPcmBuffer, int in
);

if (outputSize <= 0) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to encode %d B of PCM data: %s") % inputLength %
opus_strerror(outputSize)).str());
#endif
}

auto outputSizeEnc = VarInt(outputSize).getEncoded();
Expand All @@ -145,7 +165,9 @@ void mumlib::Audio::resetEncoder() {
int status = opus_encoder_ctl(opusEncoder, OPUS_RESET_STATE, nullptr);

if (status != OPUS_OK) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("failed to reset encoder: %s") % opus_strerror(status)).str());
#endif
}

outgoingSequenceNumber = 0;
Expand All @@ -170,10 +192,12 @@ mumlib::IncomingAudioPacket mumlib::Audio::decodeIncomingAudioPacket(uint8_t *in
incomingAudioPacket.audioPayloadLength = inputBufferLength - dataPointer;

if (dataPointer >= inputBufferLength) {
#ifdef MUMLIB_USE_EXCEPTIONS
throw AudioException((boost::format("invalid incoming audio packet (%d B): header %d B") % inputBufferLength %
dataPointer).str());
#endif
}

#ifdef MUMLIB_USE_LOG4CPP
logger.debug(
"Received %d B of audio packet, %d B header, %d B payload (target: %d, sessionID: %ld, seq num: %ld).",
inputBufferLength,
Expand All @@ -182,6 +206,7 @@ mumlib::IncomingAudioPacket mumlib::Audio::decodeIncomingAudioPacket(uint8_t *in
incomingAudioPacket.target,
incomingAudioPacket.sessionId,
incomingAudioPacket.sequenceNumber);
#endif

return incomingAudioPacket;
}
Expand Down
Loading