Add natives to get client ip and connect password

The hltv server doesn't provide a nice IPlayerInfo interface to get
stuff. Have to grab it and hold on to it while we can!
This commit is contained in:
Peace-Maker 2016-03-03 02:47:06 +01:00
parent 10f7fa56a1
commit c0eb6eb75f
9 changed files with 243 additions and 29 deletions

View File

@ -8,7 +8,8 @@ sourceFiles = [
'extension.cpp',
'natives.cpp',
'forwards.cpp',
'hltvdirectorwrapper.cpp'
'hltvdirectorwrapper.cpp',
'hltvclientwrapper.cpp'
]
###############

View File

@ -41,6 +41,7 @@
#include <IBinTools.h>
#include <ISDKTools.h>
#include "hltvdirectorwrapper.h"
#include "hltvclientwrapper.h"
#include "ihltvdirector.h"
#include "ihltv.h"
#include "iserver.h"

View File

@ -97,14 +97,18 @@ void CForwardManager::HookServer(IServer *server)
return;
SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false);
SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect_Post), true);
// Hook all already connected clients as well for late loading
for (int i = 0; i < server->GetClientCount(); i++)
{
IClient *client = server->GetClient(i);
if (client->IsConnected())
{
HookClient(client);
// Ip and password unknown :(
// Could add more gamedata to fetch it if people really lateload the extension and expect it to work :B
g_HLTVClientManager.GetClient(i + 1)->Initialize("", "", client);
}
}
}
@ -114,7 +118,6 @@ void CForwardManager::UnhookServer(IServer *server)
return;
SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false);
SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect_Post), true);
// Unhook all connected clients as well.
for (int i = 0; i < server->GetClientCount(); i++)
@ -296,9 +299,9 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol,
cell_t retVal = 1;
m_SpectatorPreConnectFwd->Execute(&retVal);
IServer *server = META_IFACEPTR(IServer);
if (retVal == 0)
{
IServer *server = META_IFACEPTR(IServer);
#if SOURCE_ENGINE == SE_CSGO
RejectConnection(server, address, rejectReason);
#else
@ -307,30 +310,26 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol,
RETURN_META_VALUE(MRES_SUPERCEDE, nullptr);
}
pchPassword = passwordBuffer;
// Call the original function.
#if SOURCE_ENGINE == SE_CSGO
RETURN_META_VALUE_MNEWPARAMS(MRES_IGNORED, nullptr, CHLTVServer_ConnectClient, (address, nProtocol, iChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie, pSplitPlayerConnectVector, bUnknown, platform, pUnknown, iUnknown));
IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie, pSplitPlayerConnectVector, bUnknown, platform, pUnknown, iUnknown);
#else
RETURN_META_VALUE_MNEWPARAMS(MRES_IGNORED, nullptr, CHLTVServer_ConnectClient, (address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie));
IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie);
#endif
}
#if SOURCE_ENGINE == SE_CSGO
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char * pUnknown, int iUnknown)
#else
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_t & address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie)
#endif
{
IClient *client = META_RESULT_ORIG_RET(IClient *);
if (!client)
RETURN_META_VALUE(MRES_IGNORED, nullptr);
RETURN_META_VALUE(MRES_SUPERCEDE, nullptr);
HookClient(client);
m_SpectatorConnectedFwd->PushCell(client->GetPlayerSlot()+1);
HLTVClientWrapper *wrapper = g_HLTVClientManager.GetClient(client->GetPlayerSlot() + 1);
wrapper->Initialize(ipString, pchPassword, client);
m_SpectatorConnectedFwd->PushCell(client->GetPlayerSlot() + 1);
m_SpectatorConnectedFwd->Execute();
RETURN_META_VALUE(MRES_IGNORED, nullptr);
// Don't call the hooked function again, just return its value.
RETURN_META_VALUE(MRES_SUPERCEDE, client);
}
void CForwardManager::OnSpectatorDisconnect(const char *reason)

View File

@ -72,11 +72,9 @@ private:
#if SOURCE_ENGINE == SE_CSGO
void OnStopRecording_Post(CGameInfo const *info);
IClient *OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
IClient *OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
#else
void OnStopRecording_Post();
IClient *OnSpectatorConnect(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie);
IClient *OnSpectatorConnect_Post(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie);
#endif
void OnSpectatorDisconnect(const char *reason);

69
hltvclientwrapper.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "hltvclientwrapper.h"
HLTVClientWrapper::HLTVClientWrapper()
{
m_Client = nullptr;
}
void HLTVClientWrapper::Initialize(const char *ip, const char *password, IClient *client)
{
m_Ip = ip;
m_Password = password;
m_Client = client;
}
const char *HLTVClientWrapper::Name()
{
return m_Client->GetClientName();
}
const char *HLTVClientWrapper::Ip()
{
return m_Ip.chars();
}
const char *HLTVClientWrapper::Password()
{
return m_Password.chars();
}
bool HLTVClientWrapper::IsConnected()
{
return m_Client && m_Client->IsConnected();
}
IClient *HLTVClientWrapper::BaseClient()
{
return m_Client;
}
void HLTVClientWrapper::Kick(const char *reason)
{
// Go this route due to different IClient::Disconnect signatures in games..
m_Client->GetServer()->DisconnectClient(m_Client, reason);
}
HLTVClientWrapper *HLTVClientManager::GetClient(int index)
{
// Grow the vector with null pointers
// There might have been clients with lower indexes before we were loaded.
if (m_Clients.length() < (size_t)index)
{
int start = m_Clients.length();
m_Clients.resize(index);
for (int i = start; i < index; i++)
{
m_Clients[i] = nullptr;
}
}
if (!m_Clients[index - 1])
{
m_Clients[index - 1] = new HLTVClientWrapper();
}
return m_Clients[index - 1];
}
// FIXME: ClientManager instance for each hltvserver instance in csgo!
HLTVClientManager g_HLTVClientManager;

71
hltvclientwrapper.h Normal file
View File

@ -0,0 +1,71 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod SourceTV Manager Extension
* Copyright (C) 2004-2016 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_HLTVCLIENT_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_HLTVCLIENT_H_
#include "extension.h"
#include "amtl/am-string.h"
#include "amtl/am-vector.h"
#include "amtl/am-utility.h"
class HLTVClientWrapper {
public:
HLTVClientWrapper();
void Initialize(const char *ip, const char *password, IClient *client);
public:
const char *Name();
const char *Ip();
const char *Password();
bool IsConnected();
IClient *BaseClient();
void Kick(const char *reason);
private:
ke::AString m_Ip;
ke::AString m_Password;
IClient *m_Client;
};
class HLTVClientManager {
public:
HLTVClientWrapper *GetClient(int index);
private:
ke::Vector<ke::AutoPtr<HLTVClientWrapper>> m_Clients;
};
extern HLTVClientManager g_HLTVClientManager;
#endif // _INCLUDE_SOURCEMOD_EXTENSION_HLTVCLIENT_H_

View File

@ -544,7 +544,7 @@ static cell_t Native_IsClientConnected(IPluginContext *pContext, const cell_t *p
return 0;
}
IClient *pClient = hltvserver->GetBaseServer()->GetClient(client - 1);
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
return pClient->IsConnected();
}
@ -561,14 +561,62 @@ static cell_t Native_GetSpectatorName(IPluginContext *pContext, const cell_t *pa
return 0;
}
IClient *pClient = hltvserver->GetBaseServer()->GetClient(client - 1);
if (!pClient || !pClient->IsConnected())
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
if (!pClient->IsConnected())
{
pContext->ReportError("Client %d is not connected.", client);
return 0;
}
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->GetClientName(), NULL);
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->Name(), NULL);
return 0;
}
// native SourceTV_GetSpectatorIP(client, String:ip[], maxlen);
static cell_t Native_GetSpectatorIP(IPluginContext *pContext, const cell_t *params)
{
if (hltvserver == nullptr)
return 0;
cell_t client = params[1];
if (client < 1 || client > hltvserver->GetBaseServer()->GetClientCount())
{
pContext->ReportError("Invalid spectator client index %d.", client);
return 0;
}
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
if (!pClient->IsConnected())
{
pContext->ReportError("Client %d is not connected.", client);
return 0;
}
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->Ip(), NULL);
return 0;
}
// native SourceTV_GetSpectatorPassword(client, String:password[], maxlen);
static cell_t Native_GetSpectatorPassword(IPluginContext *pContext, const cell_t *params)
{
if (hltvserver == nullptr)
return 0;
cell_t client = params[1];
if (client < 1 || client > hltvserver->GetBaseServer()->GetClientCount())
{
pContext->ReportError("Invalid spectator client index %d.", client);
return 0;
}
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
if (!pClient->IsConnected())
{
pContext->ReportError("Client %d is not connected.", client);
return 0;
}
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->Password(), NULL);
return 0;
}
@ -585,8 +633,8 @@ static cell_t Native_KickClient(IPluginContext *pContext, const cell_t *params)
return 0;
}
IClient *pClient = hltvserver->GetBaseServer()->GetClient(client - 1);
if (!pClient || !pClient->IsConnected())
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
if (!pClient->IsConnected())
{
pContext->ReportError("Client %d is not connected.", client);
return 0;
@ -595,7 +643,7 @@ static cell_t Native_KickClient(IPluginContext *pContext, const cell_t *params)
char *pReason;
pContext->LocalToString(params[2], &pReason);
hltvserver->GetBaseServer()->DisconnectClient(pClient, pReason);
pClient->Kick(pReason);
return 0;
}
@ -626,6 +674,8 @@ const sp_nativeinfo_t sourcetv_natives[] =
{ "SourceTV_GetClientCount", Native_GetClientCount },
{ "SourceTV_IsClientConnected", Native_IsClientConnected },
{ "SourceTV_GetSpectatorName", Native_GetSpectatorName },
{ "SourceTV_GetSpectatorIP", Native_GetSpectatorIP },
{ "SourceTV_GetSpectatorPassword", Native_GetSpectatorPassword },
{ "SourceTV_KickClient", Native_KickClient },
{ NULL, NULL },
};

View File

@ -141,14 +141,15 @@ public Action:Cmd_GetDelay(client, args)
public Action:Cmd_Spectators(client, args)
{
ReplyToCommand(client, "SourceTV spectator count: %d/%d", SourceTV_GetSpectatorCount(), SourceTV_GetClientCount());
new String:sName[64];
new String:sName[64], String:sIP[16];
for (new i=1;i<=SourceTV_GetClientCount();i++)
{
if (!SourceTV_IsClientConnected(i))
continue;
SourceTV_GetSpectatorName(i, sName, sizeof(sName));
ReplyToCommand(client, "Client %d: %s", i, sName);
SourceTV_GetSpectatorIP(i, sIP, sizeof(sIP));
ReplyToCommand(client, "Client %d: %s - %s", i, sName, sIP);
}
return Plugin_Handled;
}

View File

@ -287,6 +287,30 @@ native bool:SourceTV_IsClientConnected(client);
*/
native SourceTV_GetSpectatorName(client, String:name[], maxlen);
/**
* Get the IP of a SourceTV spectator client.
*
* @param client The spectator client index.
* @param name Buffer for the client ip.
* @param maxlen Maximal length of the buffer.
* @noreturn
* @error Invalid client index or not connected.
*/
native SourceTV_GetSpectatorIP(client, String:ip[], maxlen);
/**
* Get the password of a SourceTV spectator client.
* The password the client tried to connect with.
* Ignores changes from the SourceTV_OnSpectatorPreConnect forward.
*
* @param client The spectator client index.
* @param name Buffer for the client ip.
* @param maxlen Maximal length of the buffer.
* @noreturn
* @error Invalid client index or not connected.
*/
native SourceTV_GetSpectatorPassword(client, String:password[], maxlen);
/**
* Kick a SourceTV spectator client.
*