Skip to content

Instantly share code, notes, and snippets.

@nikita-petko
Last active March 28, 2022 16:56
Show Gist options
  • Select an option

  • Save nikita-petko/58ad6a781f755d09c9fe33b49f615eee to your computer and use it in GitHub Desktop.

Select an option

Save nikita-petko/58ad6a781f755d09c9fe33b49f615eee to your computer and use it in GitHub Desktop.
automod.fx
/* BA Client FxV103 Migrations, this is quite volatile right now, it won't be shipped until everyting is finalized. */
// written by: cj_7 because I'm lazy
// date: 05/11/2021
// TODO: fix something with mutables
// moved from https://git.mfdlabs.local/mfdlabs/ba/blob/master/src/lib/players/automod.fx
// nothing much has changed, but it's a lot of work to make it work with the new system.
#use FX 103
// set file's namespace
namespace com.mfdlabs.ba.client.lib.players.moderation;
// new include syntax, slow moving back to it being preprocessors
#using <"com.consider">
#using <"com.mfdlabs.series_ten.moderation">
#using <"com.networking.replication">
#using <"com.gc">
#using <"com.io">
#using <"com.mfdlabs.l22.packagesv2">
#using <"com.mfdlabs.l22.diagnosticsv2">
using namespace com::mfdlabs::series_ten::moderation;
enum AUTOMOD_PACKET_TYPE
{
REQUEST_INITIAL_DATA = 2613,
REQUEST_AUDIT_DATA,
BAD_PACKET_DATA,
SEND_AUDIT_DATA = 6152
}
NETWORKING_REPLICATION_PACKET_TYPE(AUTOMOD_PACKET_TYPE);
IMMUTABLE_PACKAGE_V2 class AutoModerator
: public com::mfdlabs::l22::packages::package
, public com::networking::replication::reciever
{
private:
void disconnect_deferred(com::networking::replication::connection_peer* peer, com::networking::replication::disconnect_reason reason = com::networking::replication::disconnect_bad_data);
{
// calls for disconnection but sends a log dump and metrics to the server
peer->call_for_disconnect(reason);
disconnect_cleanup(peer);
}
void disconnect(com::networking::replication::connection_peer* peer, com::networking::replication::disconnect_reason reason = com::networking::replication::disconnect_bad_data);
{
peer->immediate_disconnect(reason);
disconnect_cleanup(peer);
}
void disconnect_cleanup(com::networking::replication::connection_peer* peer);
{
SYSTEM_CALL_FOR_FATALITY(com::string::format("AutoModerator: Peer '%s' disconnected", peer->get_machine_address()));
peer->dispose();
URGENT_GC_NOW(this);
}
void send_audit(com::networking::replication::connection_peer* peer)
{
// safe here because it's possibly unreadable due to permissions (we should be allow to read it by default because we own the folder)
const com::io::file_stream initial_data = auditing::fetch_bad_actor_detections_safe(peer);
if (initial_data == NULL) { this->disconnect(peer, com::networking::replication::disconnect_permissions_conflict); return; }
com::networking::replication::data_stream stream;
stream << AUTOMOD_PACKET_TYPE::SEND_AUDIT_DATA << initial_data.to_buffer();
// TODO: clean up the enum references
peer->send_replication_packet(
stream,
com::networking::replication::replication_packet_type::data_packet,
com::networking::replication::replication_packet_reliability::reliable_packet,
com::networking::replication::replication_packet_cacheability::no_cache,
com::networking::replication::replication_packet_priority::high_priority,
com::networking::replication::replication_packet_order::sequenced_packet,
com::networking::replication::replication_packet_order_index::any
);
return true;
}
public:
// inferable parameter types based on the base class or symbol's type
/*override*/ virtual void on_replication_packet(^packet)
{
// why would the packet be null?
if (packet == NULL) { return; }
if (!packet->is_data_packet()) { packet->next(); return; }
com::networking::replication::data_stream stream(&packet->encrypted_buffer);
// read the first byte, which is the type of the packet
// we only want the type of the packet to be any of the following:
// AUTOMOD_PACKET_TYPE::REQUEST_INITIAL_DATA -> server requests client information from the client's file system directly
// AUTOMOD_PACKET_TYPE::REQUEST_AUDIT_DATA -> server requests client information for an ongoing server investigation on a possible bad actor
// AUTOMOD_PACKET_TYPE::BAD_PACKET_DATA -> client sends the server a bad packet,
// possibly corrupted or lost in on the upstream network,
// if this happens the server will send the client a packet to tell it to repeat a resend,
// if it fails to do so, the server will disconnect the client and add it's network address to a "bad actor list"
// if you want to read the data, you can use the stream, but you can also use the packet directly
// packet->read(count) => char[]; decrypts the buffer and returns the count of data while shifting it off the buffer
char pkt_type;
stream >> pkt_type;
// we want to lock the source so no other processor can execute until we're done (this will exclude the metrics processors,
// because they only read the data, they don't actually call any of the next processors)
consider::hold_global_lock<consider::lock_kind_write>(&packet->source)
.allow_read_on_components(packet->source->get_known_metrics_components());
const auto* const peer = packet->source->get_peer(this);
switch (pkt_type)
{
case AUTOMOD_PACKET_TYPE::REQUEST_INITIAL_DATA:
send_audit(peer);
packet->next();
break;
case AUTOMOD_PACKET_TYPE::REQUEST_AUDIT_DATA:
send_audit(peer);
packet->next();
break;
case AUTOMOD_PACKET_TYPE::BAD_PACKET_DATA:
char bad_packet_id;
char bad_packet_sequence_id;
bool is_call_for_disconnect;
stream >> bad_packet_id >> bad_packet_sequence_id >> is_call_for_disconnect;
if (is_call_for_disconnect) { this->disconnect(peer); break; } // if the server is requesting a disconnect, disconnect the client immediately
com::networking::replication::packet last_auto_mod_packet;
this->packet_cache.sent.try_get_last_packet_of_id_and_at_sequence(bad_packet_id, bad_packet_sequence_id, &last_auto_mod_packet);
if (last_auto_mod_packet == NULL) { this->disconnect_deferred(peer); break; } // there was no packet of this id, so we can't do anything
if (last_auto_mod_packet.is_unknown_packet()) { this->disconnect_deferred(peer); break; } // the packet id was unknown, so we can't do anything
// we have a packet of this id and sequence, so we can send it back to the server with reattempt metrics
peer->send_with_reattempt_metrics(&last_auto_mod_packet);
// we assume that the packet was sent successfully, so we can call the next processor
packet->next();
break;
default:
packet->next();
break;
}
// release it just in case
consider::release_global_lock<consider::lock_kind_write>(&packet->source);
GC_CLEAN_UNUSED_SCOPED_MEMORY();
}
}
// register the processor, this will automatically register the processor with the global network manager
NETWORKING_REPLICATION_PACKET_PROCESSOR_DECLARE(
AutoModerator,
com::networking::replication::processor_priority::high,
com::networking::replication::processor_order::high,
com::networking::replication::processor_order_index::any,
com::networking::replication::processor_flags::allow_block_on_recieve |
com::networking::replication::processor_flags::allow_block_on_send |
com::networking::replication::processor_flags::allow_kill_on_disconnect |
com::networking::replication::processor_flags::allow_filesystem_read |
com::networking::replication::processor_flags::allow_metrics_injection |
com::networking::replication::processor_flags::allow_metrics_read |
com::networking::replication::processor_flags::allow_metrics_read_on_components,
com::networking::replication::processor_metrics::all,
com::networking::replication::processor_metrics_components::all
);
// register the package into the global scope
PACKAGES_V2_REGISTER_PACKAGE(AutoModerator, "AutoModerator", com::mfdlabs::l22::packages::scope_global, com::mfdlabs::l22::packages::package_type::package_type_replication_reciever | com::mfdlabs::l22::packages::package_type::package_type_replication_sender);
// this will gc the package on shutdown, because it's a global package, and doesn't want to be auto-gc'd for some reason
DIAGNOSTICS_EVENT_BASED_DEALLOCATION($autoModeratorSingleton, com::gc::event_on_app_released);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment