diff --git a/.gitignore b/.gitignore
index d7fc3f74..f14b4548 100644
--- a/.gitignore
+++ b/.gitignore
@@ -104,4 +104,42 @@ typings/
.DS_Store
# Compiled TypeScript code
-dist/
\ No newline at end of file
+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/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..2cf5c0a6
--- /dev/null
+++ b/CMakeLists.txt
@@ -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)
\ No newline at end of file
diff --git a/README.md b/README.md
index 9c983acd..ee452adf 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,18 @@
-<p align="center">
- <img width="100" src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets/logo_big_transparent.png" />
-</p>
-<h1 align="center">Fosscord server util</h1>
+# Fosscord-media
-<p>
- <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>
+A Fosscord media (voice and video) server
-## [About](https://fosscord.com)
-
-Fosscord is a free open source selfhostable chat, voice and video discord-compatible platform.
+## Installation
-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).
+### Prerequisites
-It contains all mongoose database models and utility functions.
+- Install the [libdatachannel](https://github.com/paullouisageneau/libdatachannel) library
+- Install the [libmongocxx](http://mongocxx.org/mongocxx-v3/installation/) driver and its requirements
-## Installation
+### Building
```bash
-npm install @fosscord/server-util
+$ cmake
+$ cd build
+$ make
```
diff --git a/config.json b/config.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/config.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 00000000..372eaa00
--- /dev/null
+++ b/src/main.cpp
@@ -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;
+}
\ No newline at end of file
diff --git a/src/mongoStub.cpp b/src/mongoStub.cpp
new file mode 100644
index 00000000..ccd2abda
--- /dev/null
+++ b/src/mongoStub.cpp
@@ -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
+}
\ No newline at end of file
diff --git a/src/mongoStub.hpp b/src/mongoStub.hpp
new file mode 100644
index 00000000..2809142f
--- /dev/null
+++ b/src/mongoStub.hpp
@@ -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
diff --git a/src/rtcPeerHandler.cpp b/src/rtcPeerHandler.cpp
new file mode 100644
index 00000000..9bfc6466
--- /dev/null
+++ b/src/rtcPeerHandler.cpp
@@ -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);
+}
diff --git a/src/rtcPeerHandler.hpp b/src/rtcPeerHandler.hpp
new file mode 100644
index 00000000..3ba32a83
--- /dev/null
+++ b/src/rtcPeerHandler.hpp
@@ -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
\ No newline at end of file
diff --git a/src/rtcServer.hpp b/src/rtcServer.hpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/rtcServer.hpp
|