Commit c03e1c45 authored by Shockfire's avatar Shockfire
Browse files

Started work on VoIP rewrite

parent 946188d1
......@@ -270,12 +270,14 @@ add_library(ElDorito SHARED
src/Utils/UPnP.hpp
src/Utils/VersionInfo.cpp
src/Utils/VersionInfo.hpp
src/VoIP/MemberList.cpp
src/VoIP/MemberList.hpp
src/VoIP/TeamspeakClient.cpp
src/VoIP/TeamspeakClient.hpp
src/VoIP/TeamspeakServer.cpp
src/VoIP/TeamspeakServer.hpp
src/Voip/Voip.cpp
src/Voip/Voip.hpp
src/Voip/VoipClient.cpp
src/Voip/VoipClient.hpp
src/Voip/VoipServer.cpp
src/Voip/VoipServer.hpp
src/Voip/VoipTokenManager.cpp
src/Voip/VoipTokenManager.hpp
src/Web/Bridge/Client/ClientFunctions.cpp
src/Web/Bridge/Client/ClientFunctions.hpp
src/Web/Bridge/WebRendererQuery.hpp
......
......@@ -4,6 +4,7 @@
#include "BlamTypes.hpp"
#include "BlamPlayers.hpp"
#include "BitStream.hpp"
#include <bitset>
namespace Blam
{
......@@ -15,6 +16,9 @@ namespace Blam
// The maximum number of players in a network session.
const int MaxPlayers = 16;
// A std::bitset of peers.
typedef std::bitset<Blam::Network::MaxPeers> PeerBitSet;
enum PeerConnectionState
{
ePeerConnectionStateNone,
......@@ -375,4 +379,4 @@ namespace Blam
// Leaves the current game.
void LeaveGame();
}
}
\ No newline at end of file
}
......@@ -10,6 +10,7 @@
#include "Server/BanList.hpp"
#include "Patches/Core.hpp"
#include "Console.hpp"
#include "Voip/Voip.hpp"
#include "Web/Ui/ScreenLayer.hpp"
#include "Web/Ui/WebChat.hpp"
#include "Web/Ui/WebConsole.hpp"
......@@ -246,6 +247,7 @@ void ElDorito::Initialize()
Server::Chat::Initialize();
Server::Voting::Init();
Server::VariableSynchronization::Initialize();
Voip::Initialize();
CreateThread(0, 0, StartRconWebSocketServer, 0, 0, 0);
if (!Blam::Cache::StringIDCache::Instance.Load("maps\\string_ids.dat"))
......
......@@ -16,7 +16,6 @@
#include "../ThirdParty/rapidjson/document.h"
#include "../ThirdParty/rapidjson/writer.h"
#include "../ThirdParty/rapidjson/stringbuffer.h"
#include "../VoIP/TeamspeakClient.hpp"
#include "../Blam/BlamNetwork.hpp"
#include "../Console.hpp"
#include "../Server/VariableSynchronization.hpp"
......@@ -430,14 +429,6 @@ namespace
Pointer::Base(0x1E40BD4).Write(xnetInfo + 0x10, 0x10);
Pointer::Base(0x1E40BE4).Write<uint32_t>(1);
// start voip
if (Modules::ModuleVoIP::Instance().VarVoIPEnabled->ValueInt == 1)
{
//Make sure teamspeak is stopped before we try to start it.
StopTeamspeakClient();
CreateThread(0, 0, StartTeamspeakClient, 0, 0, 0);
}
returnInfo = "Attempting connection to " + address + "...";
return true;
}
......@@ -899,7 +890,7 @@ namespace
membership.Update();
// Send a chat message to notify players about the shuffle
Server::Chat::PeerBitSet peers;
Blam::Network::PeerBitSet peers;
peers.set();
Server::Chat::SendServerMessage("Teams have been shuffled.", peers);
......
#include "ModuleVoIP.hpp"
#include <sstream>
#include "../ElDorito.hpp"
#include "../VoIP/TeamspeakClient.hpp"
#include "../VoIP/TeamspeakServer.hpp"
#include <teamspeak/public_definitions.h>
#include <teamspeak/public_errors.h>
#include <teamspeak/clientlib_publicdefinitions.h>
#include <teamspeak/clientlib.h>
#include "../Voip/VoipServer.hpp"
#include "../Blam/BlamNetwork.hpp"
bool VariablePushToTalkUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
unsigned int error;
/*unsigned int error;
uint64 scHandlerID = VoIPGetscHandlerID();
if (scHandlerID != NULL){
if (Modules::ModuleVoIP::Instance().VarVoIPPushToTalk->ValueInt == 0){
......@@ -49,13 +42,13 @@ bool VariablePushToTalkUpdate(const std::vector<std::string>& Arguments, std::st
}
}
}
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPPushToTalk->ValueInt ? "Enabled VoIP PushToTalk and Disabled Voice Activation Detection" : "Disabled VoIP PushToTalk and Enabled Voice Acitivation Detection.";
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPPushToTalk->ValueInt ? "Enabled VoIP PushToTalk and Disabled Voice Activation Detection" : "Disabled VoIP PushToTalk and Enabled Voice Acitivation Detection.";*/
return true;
}
bool VariableVolumeModifierUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
unsigned int error;
/*unsigned int error;
uint64 scHandlerID = VoIPGetscHandlerID();
if (scHandlerID != NULL){
if ((error = ts3client_setPlaybackConfigValue(scHandlerID, "volume_modifier", Modules::ModuleVoIP::Instance().VarVoIPVolumeModifier->ValueString.c_str())) != ERROR_ok) {
......@@ -63,12 +56,13 @@ bool VariableVolumeModifierUpdate(const std::vector<std::string>& Arguments, std
return false;
}
}
returnInfo = "Set VoIP Volume Modifier to " + Modules::ModuleVoIP::Instance().VarVoIPVolumeModifier->ValueString;
returnInfo = "Set VoIP Volume Modifier to " + Modules::ModuleVoIP::Instance().VarVoIPVolumeModifier->ValueString;*/
return true;
}
bool VariableAGCUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
unsigned int error;
/*unsigned int error;
uint64 scHandlerID = VoIPGetscHandlerID();
if (scHandlerID != NULL){
if ((error = ts3client_setPreProcessorConfigValue(scHandlerID, "agc", Modules::ModuleVoIP::Instance().VarVoIPAGC->ValueInt ? "true" : "false")) != ERROR_ok) {
......@@ -76,12 +70,13 @@ bool VariableAGCUpdate(const std::vector<std::string>& Arguments, std::string& r
return false;
}
}
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPAGC->ValueInt ? "Enabled VoIP Automatic Gain Control" : "Disabled VoIP Automatic Gain Control";
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPAGC->ValueInt ? "Enabled VoIP Automatic Gain Control" : "Disabled VoIP Automatic Gain Control";*/
return true;
}
bool VariableEchoCancellationUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
unsigned int error;
/*unsigned int error;
uint64 scHandlerID = VoIPGetscHandlerID();
if (scHandlerID != NULL){
if ((error = ts3client_setPreProcessorConfigValue(scHandlerID, "echo_canceling", Modules::ModuleVoIP::Instance().VarVoIPEchoCancellation->ValueInt ? "true" : "false")) != ERROR_ok) {
......@@ -89,12 +84,13 @@ bool VariableEchoCancellationUpdate(const std::vector<std::string>& Arguments, s
return false;
}
}
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPEchoCancellation->ValueInt ? "Enabled VoIP Echo Cancellation" : "Disabled VoIP Echo Cancellation";
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPEchoCancellation->ValueInt ? "Enabled VoIP Echo Cancellation" : "Disabled VoIP Echo Cancellation";*/
return true;
}
bool VariableVADLevelUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
unsigned int error;
/*unsigned int error;
uint64 scHandlerID = VoIPGetscHandlerID();
if (scHandlerID != NULL){
if ((error = ts3client_setPreProcessorConfigValue(scHandlerID, "voiceactivation_level", Modules::ModuleVoIP::Instance().VarVoIPVADLevel->ValueString.c_str())) != ERROR_ok) {
......@@ -102,34 +98,44 @@ bool VariableVADLevelUpdate(const std::vector<std::string>& Arguments, std::stri
return false;
}
}
returnInfo = "Set Voice Activation Level to " + Modules::ModuleVoIP::Instance().VarVoIPVADLevel->ValueString;
returnInfo = "Set Voice Activation Level to " + Modules::ModuleVoIP::Instance().VarVoIPVADLevel->ValueString;*/
return true;
}
bool VariableServerEnabledUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
//TODO: Check if host, kill client too. StopTeamspeakClient();
//TODO: Figure out why this doesn't stop the teamspeak server when setting to 0....
if (Modules::ModuleVoIP::Instance().VarVoIPServerEnabled->ValueInt == 0){
StopTeamspeakClient();
StopTeamspeakServer();
if (Modules::ModuleVoIP::Instance().VarVoIPServerEnabled->ValueInt == 1)
{
auto session = Blam::Network::GetActiveSession();
if (!session || !session->IsEstablished() || !session->IsHost())
{
returnInfo = "VoIP server enabled.";
return true;
}
Voip::Server::Start();
returnInfo = "VoIP server started. Players may not connect until the next game is started.";
}
else
{
Voip::Server::Stop();
returnInfo = "VoIP server stopped.";
}
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPServerEnabled->ValueInt ? "VoIP Server will start when a new lobby is created" : "Disabled VoIP Auto Startup.";
return true;
}
bool VariableEnabledUpdate(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
//TODO: Connect to lobby VOIP if changing to 1, for now this is fine because it will join next time they connet to a lobby
if (Modules::ModuleVoIP::Instance().VarVoIPEnabled->ValueInt == 0){
/*if (Modules::ModuleVoIP::Instance().VarVoIPEnabled->ValueInt == 0){
StopTeamspeakClient();
}
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPEnabled->ValueInt ? "VoIP client will start when joining a lobby" : "Disabled VoIP.";
returnInfo = Modules::ModuleVoIP::Instance().VarVoIPEnabled->ValueInt ? "VoIP client will start when joining a lobby" : "Disabled VoIP.";*/
return true;
}
bool CommandVoIPMutePlayer(const std::vector<std::string>& Arguments, std::string& returnInfo)
{
if (Arguments.size() <= 0)
/*if (Arguments.size() <= 0)
{
returnInfo = "Invalid arguments";
return false;
......@@ -169,7 +175,8 @@ bool CommandVoIPMutePlayer(const std::vector<std::string>& Arguments, std::strin
}
returnInfo = "Player " + mutePlayerName + " not found in game?";
return false;
return false;*/
return true;
}
namespace Modules
......
......@@ -13,11 +13,10 @@
#include "../ElDorito.hpp"
#include "../ThirdParty/rapidjson/writer.h"
#include "../ThirdParty/rapidjson/stringbuffer.h"
#include "../VoIP/TeamspeakServer.hpp"
#include "../VoIP/TeamspeakClient.hpp"
#include "../Blam/BlamNetwork.hpp"
#include "../Server/BanList.hpp"
#include "../Modules/ModulePlayer.hpp"
#include "../Voip/VoipServer.hpp"
#include "../Modules/ModuleUPnP.hpp"
#include "../Modules/ModuleVoIP.hpp"
#include "../Server/VotingSystem.hpp"
......@@ -203,7 +202,7 @@ namespace Patches
writer.Key("assassinationEnabled");
writer.String(Modules::ModuleServer::Instance().VarServerAssassinationEnabled->ValueString.c_str());
writer.Key("VoIP");
writer.Bool(IsVoIPServerRunning() ? TRUE : FALSE);
writer.Bool(Modules::ModuleVoIP::Instance().VarVoIPEnabled->ValueInt != 0);
auto session = Blam::Network::GetActiveSession();
if (session && session->IsEstablished()){
......@@ -579,27 +578,16 @@ namespace
if (isOnline == 1)
{
auto& voipvars = Modules::ModuleVoIP::Instance();
if (voipvars.VarVoIPServerEnabled->ValueInt == 1){
//Start the Teamspeak VoIP Server since this is the host
CreateThread(0, 0, StartTeamspeakServer, 0, 0, 0);
if (voipvars.VarVoIPServerEnabled->ValueInt)
Voip::Server::Start();
if (voipvars.VarVoIPEnabled->ValueInt == 1)
{
//Make sure teamspeak is stopped before we try to start it.
StopTeamspeakClient();
//Join the Teamspeak VoIP Server so the host can talk
CreateThread(0, 0, StartTeamspeakClient, 0, 0, 0);
}
}
// TODO: give output if StartInfoServer fails
Patches::Network::StartInfoServer();
}
else
{
Patches::Network::StopInfoServer();
//Stop the VoIP Server and client
StopTeamspeakClient();
StopTeamspeakServer();
Voip::Server::Stop();
}
return retval;
}
......@@ -804,8 +792,8 @@ namespace
return false;
// Boot the player from VoIP
if (playerIndex >= 0)
kickTeamspeakClient(playerName);
/*if (playerIndex >= 0)
kickTeamspeakClient(playerName);*/
return true;
}
......@@ -938,9 +926,6 @@ namespace
{
Patches::Network::StopInfoServer();
StopTeamspeakClient();
StopTeamspeakServer();
typedef char(__thiscall *Network_state_leaving_enterFunc)(void* thisPtr, int a2, int a3, int a4);
Network_state_leaving_enterFunc Network_state_leaving_enter = reinterpret_cast<Network_state_leaving_enterFunc>(0x4933E0);
return Network_state_leaving_enter(thisPtr, a2, a3, a4);
......
......@@ -113,7 +113,7 @@ namespace
}
// Broadcasts a message to a set of peers.
bool BroadcastMessage(Blam::Network::Session *session, int senderPeer, ChatMessage *message, PeerBitSet peers)
bool BroadcastMessage(Blam::Network::Session *session, int senderPeer, ChatMessage *message, Blam::Network::PeerBitSet peers)
{
if (senderPeer < 0)
return false;
......@@ -141,7 +141,7 @@ namespace
}
// Gets a bitset of peers on the same team as a peer.
bool GetTeamPeers(Blam::Network::Session *session, int senderPeer, PeerBitSet *result)
bool GetTeamPeers(Blam::Network::Session *session, int senderPeer, Blam::Network::PeerBitSet *result)
{
result->reset();
......@@ -163,7 +163,7 @@ namespace
}
// Gets a bitset of peers to send a message to.
bool GetMessagePeers(Blam::Network::Session *session, int senderPeer, const ChatMessage &message, PeerBitSet *result)
bool GetMessagePeers(Blam::Network::Session *session, int senderPeer, const ChatMessage &message, Blam::Network::PeerBitSet *result)
{
switch (message.Type)
{
......@@ -233,7 +233,7 @@ namespace
// If the IP is in a timeout state, send an error and return
if (spamIt->second.TimeoutSeconds > 0)
{
PeerBitSet targetPeers;
Blam::Network::PeerBitSet targetPeers;
targetPeers.set(peer);
SendServerMessage("You have exceeded the server's spam limit. You can chat again in " + std::to_string(spamIt->second.TimeoutSeconds) + " second(s).", targetPeers);
return true;
......@@ -305,7 +305,7 @@ namespace
LogMessage(session, peer, broadcastMessage);
PeerBitSet targetPeers;
Blam::Network::PeerBitSet targetPeers;
if (!GetMessagePeers(session, peer, message, &targetPeers))
return false;
return BroadcastMessage(session, peer, &broadcastMessage, targetPeers);
......@@ -405,7 +405,7 @@ namespace Server
return SendClientMessage(session, message);
}
bool SendServerMessage(const std::string &body, PeerBitSet peers)
bool SendServerMessage(const std::string &body, Blam::Network::PeerBitSet peers)
{
auto session = Blam::Network::GetActiveSession();
if (!session || !session->IsEstablished() || !session->IsHost())
......
#pragma once
#include <string>
#include <bitset>
#include <memory>
#include "../Blam/BlamNetwork.hpp"
......@@ -70,9 +69,6 @@ namespace Server
virtual void MessageReceived(const ChatMessage &message) = 0;
};
// A std::bitset of peers.
typedef std::bitset<Blam::Network::MaxPeers> PeerBitSet;
// Initializes the server chat system.
void Initialize();
......@@ -88,7 +84,7 @@ namespace Server
// Sends a server message to specific peers. Only works if you are
// host. Returns true if successful.
bool SendServerMessage(const std::string &body, PeerBitSet peers);
bool SendServerMessage(const std::string &body, Blam::Network::PeerBitSet peers);
// Registers a chat handler object.
void AddHandler(std::shared_ptr<ChatHandler> handler);
......
......@@ -11,6 +11,14 @@
#include <openssl\pem.h>
#include <openssl\sha.h>
#include <Windows.h>
#include <wincrypt.h>
namespace
{
HCRYPTPROV AcquireProvider();
}
namespace Utils
{
namespace Cryptography
......@@ -163,5 +171,24 @@ namespace Utils
*out = digest[0] << 24 | digest[1] << 16 | digest[2] << 8 | digest[3];
return true;
}
bool RandomBytes(int num, uint8_t *out)
{
auto provider = AcquireProvider();
if (!provider)
return false;
return CryptGenRandom(provider, num, out) == TRUE;
}
}
}
namespace
{
HCRYPTPROV AcquireProvider()
{
static HCRYPTPROV handle;
if (handle || CryptAcquireContext(&handle, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return handle;
return 0;
}
}
\ No newline at end of file
......@@ -12,5 +12,6 @@ namespace Utils
bool VerifyRSASignature(std::string pubKey, std::string signature, void* data, size_t dataSize);
bool GenerateRSAKeyPair(int numBits, std::string& privKey, std::string& pubKey);
bool Hash32(const std::string& str, uint32_t *out);
bool RandomBytes(int num, uint8_t *out);
}
}
\ No newline at end of file
......@@ -51,6 +51,7 @@ namespace Utils
case Sound: bits.push_back("Sound"); break;
case Input: bits.push_back("Input"); break;
case Debug: bits.push_back("Debug"); break;
case Voice: bits.push_back("Voice"); break;
default: bits.push_back(std::string("UnknownBit") + std::to_string(bit)); break;
}
}
......@@ -83,7 +84,7 @@ namespace Utils
{
// these will apply until the ElDorito instance is initialized (the patch stage mostly) and the config values are read
// TODO: decouple the preferences from the module system since patches need to be applied before the modules are loaded
Level = LogLevel::Warning;
Level = LogLevel::Info;
Types = All;
// spin up separate thread to periodically flush the log
......
......@@ -27,6 +27,7 @@ namespace Utils
Memory = 1 << 3,
Sound = 1 << 4,
Input = 1 << 5,
Voice = 1 << 6,
Debug = 1 << 31,
All = 0xFFFFFFFF
};
......
......@@ -163,28 +163,33 @@ namespace Utils
void HexStringToBytes(const std::string &in, void *const data, size_t length)
{
unsigned char *byteData = reinterpret_cast<unsigned char*>(data);
std::stringstream hexStringStream; hexStringStream >> std::hex;
for (size_t strIndex = 0, dataIndex = 0; strIndex < (length * 2); ++dataIndex)
unsigned char *byteData = reinterpret_cast<unsigned char*>(data);
unsigned char byte = 0;
for (auto i = 0; i < in.length() && i < length * 2; i++)
{
// Read out and convert the string two characters at a time
const char tmpStr[3] = { in[strIndex++], in[strIndex++], 0 };
// Reset and fill the string stream
hexStringStream.clear();
hexStringStream.str(tmpStr);
// Do the conversion
int tmpValue = 0;
hexStringStream >> tmpValue;
byteData[dataIndex] = static_cast<unsigned char>(tmpValue);
char ch = in[i];
unsigned char nybble = 0;
if (ch >= 'A' && ch <= 'F')
nybble = ch - 'A' + 0xA;
else if (ch >= 'a' && ch <= 'f')
nybble = ch - 'a' + 0xA;
else if (ch >= '0' && ch <= '9')
nybble = ch - '0';
if (i % 2 == 0)
{
byte = nybble << 4;
}
else
{
byte |= nybble;
byteData[i / 2] = byte;
}
}
}
void BytesToHexString(void *const data, const size_t dataLength, std::string &dest)
void BytesToHexString(const void * data, const size_t dataLength, std::string &dest)
{
unsigned char *byteData = reinterpret_cast<unsigned char*>(data);
const unsigned char *byteData = reinterpret_cast<const unsigned char*>(data);
std::stringstream hexStringStream;
hexStringStream << std::hex << std::setfill('0');
......
......@@ -15,7 +15,7 @@ namespace Utils
void RemoveCharsFromString(std::string &str, char* charsToRemove);
void HexStringToBytes(const std::string &in, void *const data, size_t length);
void BytesToHexString(void *const data, const size_t dataLength, std::string &dest);
void BytesToHexString(const void *data, const size_t dataLength, std::string &dest);
std::string ToLower(const std::string &str);
......
#include "MemberList.hpp"
void MemberList::ShowPlayerTalkEvent(std::string name)
{
memberList.push_back(name);
}
void MemberList::HidePlayerTalkEvent(std::string name)
{
for (size_t i = 0; i < memberList.size(); i++)
{
if (memberList.at(i) == name)
{
memberList.erase(memberList.begin() + i);
return;
}
}
}
\ No newline at end of file
#pragma once
#include <string>
#include <vector>
#include "..\Utils\Singleton.hpp"
class MemberList : public Utils::Singleton<MemberList>
{
public:
std::vector<std::string> memberList = std::vector<std::string>{};
void ShowPlayerTalkEvent(std::string name);
void HidePlayerTalkEvent(std::string name);
};
\ No newline at end of file
This diff is collapsed.
#pragma once
#include <Windows.h>
DWORD WINAPI StartTeamspeakClient(LPVOID);
void StopTeamspeakClient();
int muteTeamspeakClient(const std::string& name);
UINT64 VoIPGetscHandlerID();
UINT64 VoIPGetVadHandlerID();
INT VoIPGetTalkStatus();
\ No newline at end of file
/*
* TeamSpeak 3 server sample
*
* Copyright (c) 2007-2014 TeamSpeak-Systems
* https://halowiki.llf.to/ts3_sdk/server_html/index.html
*/
#ifdef _WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#else
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <stdio.h>
#include "../Console.hpp"
#include <teamspeak/public_definitions.h>
#include <teamspeak/public_errors.h>
#include <teamspeak/clientlib.h>
#include <teamspeak/serverlib.h>
#ifdef _WIN32
#define snprintf sprintf_s
#define SLEEP(x) Sleep(x)
#else
#define SLEEP(x) usleep(x*1000)
#endif
bool VoIPServerRunning = false;
bool IsVoIPServerRunning(){
return VoIPServerRunning;
}
/*
* Callback when client has connected.
*
* Parameter:
* serverID - Virtual server ID
* clientID - ID of connected client
* channelID - ID of channel the client joined
*/