Merge branch 'rtc'
This commit is contained in:
commit
f46ca1c341
40
.gitignore
vendored
40
.gitignore
vendored
@ -104,4 +104,42 @@ typings/
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Compiled TypeScript code
|
# Compiled TypeScript code
|
||||||
dist/
|
dist/
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.o
|
||||||
|
|
||||||
|
# Protobuffer builds
|
||||||
|
*.pb.cc
|
||||||
|
*.pb.h
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
build/
|
||||||
|
.vscode/
|
||||||
|
16
CMakeLists.txt
Normal file
16
CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
project(fosscord-media)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
find_package(mongocxx REQUIRED)
|
||||||
|
find_package(Boost REQUIRED)
|
||||||
|
|
||||||
|
|
||||||
|
file(GLOB SourceFiles ${PROJECT_SOURCE_DIR}/src/*.cpp)
|
||||||
|
#include_directories("bsoncxx/v_noabi/bsoncxx/")
|
||||||
|
add_executable(${CMAKE_PROJECT_NAME} ${SourceFiles})
|
||||||
|
|
||||||
|
target_link_libraries(${CMAKE_PROJECT_NAME} datachannel mongo::mongocxx_shared Boost::boost)
|
35
README.md
35
README.md
@ -1,29 +1,18 @@
|
|||||||
<p align="center">
|
# Fosscord-media
|
||||||
<img width="100" src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets/logo_big_transparent.png" />
|
|
||||||
</p>
|
|
||||||
<h1 align="center">Fosscord server util</h1>
|
|
||||||
|
|
||||||
<p>
|
A Fosscord media (voice and video) server
|
||||||
<a href="https://discord.gg/ZrnGQP6p3d">
|
|
||||||
<img src="https://img.shields.io/discord/806142446094385153?color=7489d5&logo=discord&logoColor=ffffff" />
|
|
||||||
</a>
|
|
||||||
<img src="https://img.shields.io/static/v1?label=Status&message=Development&color=blue">
|
|
||||||
<a title="Crowdin" target="_blank" href="https://translate.fosscord.com/"><img src="https://badges.crowdin.net/fosscord/localized.svg"></a>
|
|
||||||
<a href="https://opencollective.com/fosscord">
|
|
||||||
<img src="https://opencollective.com/fosscord/tiers/badge.svg">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## [About](https://fosscord.com)
|
|
||||||
|
|
||||||
Fosscord is a free open source selfhostable chat, voice and video discord-compatible platform.
|
|
||||||
|
|
||||||
Fosscord server util contains all necessary logic that is shared between the [api](https://github.com/fosscord/fosscord-api), [gateway](https://github.com/fosscord/fosscord-gateway) and [cdn](https://github.com/fosscord/fosscord-cdn).
|
|
||||||
|
|
||||||
It contains all mongoose database models and utility functions.
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Install the [libdatachannel](https://github.com/paullouisageneau/libdatachannel) library
|
||||||
|
- Install the [libmongocxx](http://mongocxx.org/mongocxx-v3/installation/) driver and its requirements
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @fosscord/server-util
|
$ cmake
|
||||||
|
$ cd build
|
||||||
|
$ make
|
||||||
```
|
```
|
||||||
|
1
config.json
Normal file
1
config.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
47
src/main.cpp
Normal file
47
src/main.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// $$$$$$\ $$\
|
||||||
|
// $$ __$$\ $$ |
|
||||||
|
// $$ / \__|$$$$$$\ $$$$$$$\ $$$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$$ |
|
||||||
|
// $$$$\ $$ __$$\ $$ _____|$$ _____|$$ _____|$$ __$$\ $$ __$$\ $$ __$$ |
|
||||||
|
// $$ _| $$ / $$ |\$$$$$$\ \$$$$$$\ $$ / $$ / $$ |$$ | \__|$$ / $$ |
|
||||||
|
// $$ | $$ | $$ | \____$$\ \____$$\ $$ | $$ | $$ |$$ | $$ | $$ |
|
||||||
|
// $$ | \$$$$$$ |$$$$$$$ |$$$$$$$ |\$$$$$$$\ \$$$$$$ |$$ | \$$$$$$$ |
|
||||||
|
// \__| \______/ \_______/ \_______/ \_______| \______/ \__| \_______|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// $$\ $$$$$$\
|
||||||
|
// \__| $$ __$$\
|
||||||
|
// $$\ $$\ $$$$$$\ $$\ $$$$$$$\ $$$$$$\ $$ / \__| $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$\ $$$$$$\
|
||||||
|
// \$$\ $$ |$$ __$$\ $$ |$$ _____|$$ __$$\ \$$$$$$\ $$ __$$\ $$ __$$\\$$\ $$ |$$ __$$\ $$ __$$\
|
||||||
|
// \$$\$$ / $$ / $$ |$$ |$$ / $$$$$$$$ | \____$$\ $$$$$$$$ |$$ | \__|\$$\$$ / $$$$$$$$ |$$ | \__|
|
||||||
|
// \$$$ / $$ | $$ |$$ |$$ | $$ ____|$$\ $$ |$$ ____|$$ | \$$$ / $$ ____|$$ |
|
||||||
|
// \$ / \$$$$$$ |$$ |\$$$$$$$\ \$$$$$$$\ \$$$$$$ |\$$$$$$$\ $$ | \$ / \$$$$$$$\ $$ |
|
||||||
|
// \_/ \______/ \__| \_______| \_______| \______/ \_______|\__| \_/ \_______|\__|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "rtcPeerHandler.hpp" //Handle peer connection requests
|
||||||
|
#include "mongoStub.hpp" //Handle communication with the MongoDB server
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
|
||||||
|
auto commsHandler = std::make_shared<rtcPeerHandler>();
|
||||||
|
auto mongoHandler = std::make_unique<mongoStub>();
|
||||||
|
|
||||||
|
mongocxx::options::change_stream options;
|
||||||
|
//voiceEvents collection watcher
|
||||||
|
mongocxx::change_stream colCs = mongoHandler->getCol().watch(options);
|
||||||
|
|
||||||
|
std::cout << "Server created and listening for events" << std::endl;
|
||||||
|
|
||||||
|
//Check for new messages in the collection
|
||||||
|
for (;;){
|
||||||
|
std::vector<mongoStub::mongoMessage> t = mongoHandler->getNewMessages(&colCs);
|
||||||
|
for(auto &i : t){
|
||||||
|
std::cout << "[" << i.eventName << "] " << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
84
src/mongoStub.cpp
Normal file
84
src/mongoStub.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "mongoStub.hpp"
|
||||||
|
|
||||||
|
mongoStub::mongoStub() {
|
||||||
|
if (this->client) {
|
||||||
|
this->db = client["fosscord"];
|
||||||
|
|
||||||
|
if (this->db) {
|
||||||
|
this->col = db["events"];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::cout << "db not found";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Client couldn't be initialized";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too slow for my liking
|
||||||
|
std::vector<mongoStub::mongoMessage> mongoStub::getNewMessages(
|
||||||
|
mongocxx::change_stream* colCs) {
|
||||||
|
std::vector<mongoStub::mongoMessage> retVec;
|
||||||
|
|
||||||
|
for (auto&& event : *colCs) {
|
||||||
|
mongoStub::mongoMessage returnValue;
|
||||||
|
|
||||||
|
std::cout << bsoncxx::to_json(event) << std::endl;
|
||||||
|
|
||||||
|
// Only listen to insert events (to avoid "precondition failed: data"
|
||||||
|
// exception)
|
||||||
|
if (event["operationType"].get_utf8().value.to_string() != "insert") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string evName = event["fullDocument"]["event"].get_utf8().value.to_string();
|
||||||
|
|
||||||
|
if(evName.substr(0, 7)=="VSERVER"){ continue; } //Ignore the event if it's been emited by a voice server
|
||||||
|
|
||||||
|
if (evName == "UDP_CONNECTION") {
|
||||||
|
handleUdpRequest(
|
||||||
|
event["fullDocument"]["data"]["d"]["address"].get_utf8().value.to_string(),
|
||||||
|
event["fullDocument"]["data"]["d"]["port"].get_int32().value,
|
||||||
|
event["fullDocument"]["data"]["d"]["mode"].get_utf8().value.to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
} else if (evName == "VOICE_REQUEST") {
|
||||||
|
//TODO
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue.eventName = evName;
|
||||||
|
retVec.push_back(returnValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mongoStub::handleUdpRequest(std::string address, int port, std::string mode) {
|
||||||
|
using bsoncxx::builder::basic::kvp;
|
||||||
|
using bsoncxx::builder::basic::sub_array;
|
||||||
|
using bsoncxx::builder::basic::sub_document;
|
||||||
|
|
||||||
|
auto builder = bsoncxx::builder::basic::document{};
|
||||||
|
|
||||||
|
//Handle UDP socket stuff (later tho)
|
||||||
|
|
||||||
|
builder.append(kvp("event", "VSERVER_UDP_RESPONSE"));
|
||||||
|
builder.append(kvp("op", "4"));
|
||||||
|
builder.append(kvp("d", [](sub_document subdoc) {
|
||||||
|
subdoc.append(kvp("mode", "CRYPT_MODE")),
|
||||||
|
subdoc.append(kvp("secret_key", [](sub_array subarr) {
|
||||||
|
subarr.append(1, 2, 3, 5); // HOW DO I GEN A SKEY?
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
bsoncxx::stdx::optional<mongocxx::result::insert_one> r= col.insert_one(builder.view());
|
||||||
|
}
|
||||||
|
|
||||||
|
void mongoStub::handleVoiceRequest() {
|
||||||
|
//Is this really needed? idk
|
||||||
|
}
|
41
src/mongoStub.hpp
Normal file
41
src/mongoStub.hpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef MONGOSTUB_HPP
|
||||||
|
#define MONGOSTUB_HPP
|
||||||
|
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <mongocxx/client.hpp>
|
||||||
|
#include <mongocxx/instance.hpp>
|
||||||
|
#include <mongocxx/change_stream.hpp>
|
||||||
|
#include <bsoncxx/json.hpp>
|
||||||
|
#include <bsoncxx/document/element.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
class mongoStub{
|
||||||
|
public:
|
||||||
|
mongoStub();
|
||||||
|
|
||||||
|
struct mongoMessage{
|
||||||
|
std::string eventName;
|
||||||
|
std::vector<std::string> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<mongoMessage> getNewMessages(mongocxx::change_stream* colCs);
|
||||||
|
|
||||||
|
mongocxx::collection getCol() const { return col; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
mongocxx::instance instance;
|
||||||
|
mongocxx::client client{mongocxx::uri{}};
|
||||||
|
mongocxx::database db;
|
||||||
|
mongocxx::collection col;
|
||||||
|
mongocxx::change_stream* colCs = nullptr;
|
||||||
|
|
||||||
|
void handleUdpRequest(std::string address, int port, std::string mode);
|
||||||
|
void handleVoiceRequest();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
83
src/rtcPeerHandler.cpp
Normal file
83
src/rtcPeerHandler.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "rtcPeerHandler.hpp"
|
||||||
|
|
||||||
|
rtcPeerHandler::rtcPeerHandler() {
|
||||||
|
rtc::InitLogger(rtc::LogLevel::Verbose, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtcPeerHandler::initiateConnection(std::string peerIP, int peerPort) {
|
||||||
|
// Socket connection between client and server
|
||||||
|
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
sockaddr_in addr;
|
||||||
|
addr.sin_addr.s_addr = inet_addr(peerIP.c_str());
|
||||||
|
addr.sin_port = htons(peerPort);
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
|
||||||
|
rtc::Configuration conf;
|
||||||
|
conf.enableIceTcp = false;
|
||||||
|
conf.disableAutoNegotiation = false;
|
||||||
|
|
||||||
|
auto pc = std::make_shared<rtc::PeerConnection>(conf);
|
||||||
|
|
||||||
|
rtc::Description::Audio media("audio",
|
||||||
|
rtc::Description::Direction::SendRecv);
|
||||||
|
media.addOpusCodec(96);
|
||||||
|
media.setBitrate(64);
|
||||||
|
|
||||||
|
auto track = pc->addTrack(media);
|
||||||
|
|
||||||
|
// auto session = std::make_shared<rtc::MediaHandler>();
|
||||||
|
|
||||||
|
// track->setMediaHandler(session);
|
||||||
|
|
||||||
|
rtc::Reliability rtcRel;
|
||||||
|
rtcRel.unordered = true;
|
||||||
|
rtcRel.type = rtc::Reliability::Type::Timed;
|
||||||
|
rtcRel.rexmit = 500;
|
||||||
|
|
||||||
|
rtc::DataChannelInit rtcConf;
|
||||||
|
rtcConf.reliability = rtcRel;
|
||||||
|
rtcConf.negotiated = false;
|
||||||
|
|
||||||
|
pc->onStateChange([](rtc::PeerConnection::State state) {
|
||||||
|
std::cout << "State: " << state << std::endl;
|
||||||
|
if (state == rtc::PeerConnection::State::Disconnected ||
|
||||||
|
state == rtc::PeerConnection::State::Failed ||
|
||||||
|
state == rtc::PeerConnection::State::Closed) {
|
||||||
|
// remove disconnected client
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pc->onGatheringStateChange([](rtc::PeerConnection::GatheringState state) {
|
||||||
|
std::cout << "Gathering State: " << state << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*std::tuple<rtc::Track*, rtc::RtcpSrReporter*> addAudio(
|
||||||
|
|
||||||
|
const std::shared_ptr<rtc::PeerConnection> pc,
|
||||||
|
const uint8_t payloadType, const uint32_t ssrc, const std::string cname,
|
||||||
|
const std::string msid, const std::function<void(void)> onOpen) {
|
||||||
|
auto audio = Description::Audio(cname);
|
||||||
|
audio.addOpusCodec(payloadType);
|
||||||
|
audio.addSSRC(ssrc, cname, msid, cname);
|
||||||
|
auto track = pc->addTrack(audio);
|
||||||
|
// create RTP configuration
|
||||||
|
auto rtpConfig = make_shared<RtpPacketizationConfig>(
|
||||||
|
ssrc, cname, payloadType, OpusRtpPacketizer::defaultClockRate);
|
||||||
|
// create packetizer
|
||||||
|
auto packetizer = make_shared<OpusRtpPacketizer>(rtpConfig);
|
||||||
|
// create opus handler
|
||||||
|
auto opusHandler = make_shared<OpusPacketizationHandler>(packetizer);
|
||||||
|
|
||||||
|
// add RTCP SR handler
|
||||||
|
auto srReporter = make_shared<RtcpSrReporter>(rtpConfig);
|
||||||
|
opusHandler->addToChain(srReporter);
|
||||||
|
|
||||||
|
// set handler
|
||||||
|
track->setMediaHandler(opusHandler);
|
||||||
|
track->onOpen(onOpen);
|
||||||
|
auto trackData = make_shared<ClientTrackData>(track, srReporter);
|
||||||
|
return trackData;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pc->createDataChannel("Fosscord voice connection", rtcConf);
|
||||||
|
}
|
32
src/rtcPeerHandler.hpp
Normal file
32
src/rtcPeerHandler.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "libdatachannel/rtc.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
typedef int SOCKET;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
#ifndef RTCPEERHANDLER
|
||||||
|
#define RTCPEERHANDLER
|
||||||
|
class rtcPeerHandler{
|
||||||
|
public:
|
||||||
|
rtcPeerHandler();
|
||||||
|
void initiateConnection(std::string peerIP, int peerPort);
|
||||||
|
|
||||||
|
struct client
|
||||||
|
{
|
||||||
|
std::shared_ptr<rtc::PeerConnection> pc;
|
||||||
|
std::shared_ptr<rtc::DataChannel> dc;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<SOCKET, client> clients;
|
||||||
|
};
|
||||||
|
#endif
|
0
src/rtcServer.hpp
Normal file
0
src/rtcServer.hpp
Normal file
Loading…
x
Reference in New Issue
Block a user