<commit_before>﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;
using MsgPack;
using MsgPack.Serialization;

namespace CoolRanch
{
    public class InfoResponseEventArgs : EventArgs
    {
        public IPEndPoint EndPoint;
        public byte[] Challenge;
        public Dictionary<string, object> Info;

        public InfoResponseEventArgs(IPEndPoint endpoint, byte[] challenge, Dictionary<string, object> info)
        {
            EndPoint = endpoint;
            Challenge = challenge;
            Info = info;
        }
    }

    public class SessionInfoExchanger
    {
        UdpClient _udp;
        ElDorado _game;
        HMAC _challengeHmac;

        private IPEndPoint _masterServer;
        private IPEndPoint _joinTarget;
        private Dictionary<IPEndPoint, byte[]> _challengeCache; // oh god what 

        public bool AllowJoins, Announcing;

        public event EventHandler<InfoResponseEventArgs> InfoResponseReceived;

        public SessionInfoExchanger(ElDorado game)
        {
            _game = game;
            _udp = new UdpClient(new IPEndPoint(IPAddress.Any, 11770));
            _udp.Client.IOControl(-1744830452, new byte[] { 0, 0, 0, 0 }, null);
            _challengeHmac = new HMACMD5();

            _masterServer =
                new IPEndPoint(Array.Find(Dns.GetHostAddresses("coolranch.ax.lt"),
                    a => a.AddressFamily == AddressFamily.InterNetwork), 8080);
            _challengeCache = new Dictionary<IPEndPoint, byte[]>();
        }

        public void ReceiveLoop()
        {
            var peer = new IPEndPoint(IPAddress.Any, 0);

            while (true)
            {
                var data = _udp.Receive(ref peer);
                Console.WriteLine("{0} -> {1}", peer, BitConverter.ToString(data));

                var reader = new BinaryReader(new MemoryStream(data));
                var magic = new string(reader.ReadChars(4));

                if (magic != "SIXP")
                    continue;

                var version = reader.ReadByte();
                var flags = reader.ReadByte();

                byte[] msg;

                if ((flags & 0x1) != 0)
                    throw new NotImplementedException();
                else
                    msg = reader.ReadBytes(1024);

                ProcessMessage(msg, peer);
            }
        }

        public void AnnounceLoop()
        {
            Console.WriteLine("Announcement loop started.");

            while (Announcing)
            {
                SendAssociationRequest(_masterServer);
                Thread.Sleep(120000);
            }

            Console.WriteLine("Announcement loop stopped.");
        }

        enum SixpMessageType : byte
        {
            ChallengeRequest,
            ChallengeResponse,
            AssociationRequest,
            InfoRequest,
            InfoResponse,
            JoinRequest,
            JoinResponse
        };

        void ProcessMessage(byte[] msg, IPEndPoint peer)
        {
            var ms = new MemoryStream(msg);
            var reader = new BinaryReader(ms);

            var type = (SixpMessageType)reader.ReadByte();
            switch (type)
            {
                case SixpMessageType.ChallengeRequest:
                {
                    var clientChallenge = reader.ReadBytes(4);
                    SendChallengeResponse(peer, clientChallenge);
                }
                    break;
                case SixpMessageType.ChallengeResponse:
                {
                    var clientChallenge = reader.ReadBytes(4);
                    var hostChallenge = reader.ReadBytes(4);

                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!clientChallenge.SequenceEqual(verify))
                        return;

                    _challengeCache[peer] = hostChallenge;

                    if (Equals(peer, _joinTarget))
                        SendJoinRequest(peer, hostChallenge);
                    else
                        SendInfoRequest(peer, hostChallenge);
                }
                    break;
                case SixpMessageType.InfoRequest:
                {
                    var hostChallenge = reader.ReadBytes(4);
                    var clientChallenge = reader.ReadBytes(4);

                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!hostChallenge.SequenceEqual(verify))
                        return;

                    if (Announcing)
                        SendInfoReponse(peer, clientChallenge);
                }
                    break;
                case SixpMessageType.InfoResponse:
                {
                    var clientChallenge = reader.ReadBytes(4);
                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!clientChallenge.SequenceEqual(verify))
                        return;

                    var serializer = MessagePackSerializer.Get<Dictionary<string, object>>();
                    var info = serializer.Unpack(ms);
                    if (InfoResponseReceived != null)
                        InfoResponseReceived(this, new InfoResponseEventArgs(peer, _challengeCache[peer], info));
                    _challengeCache.Remove(peer);
                }
                    break;
                case SixpMessageType.JoinRequest:
                {
                    var hostChallenge = reader.ReadBytes(4);
                    var clientChallenge = reader.ReadBytes(4);

                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!hostChallenge.SequenceEqual(verify))
                        return;

                    if (_game.IsRunning && _game.IsHostingOnlineSession())
                        SendJoinResponse(peer, clientChallenge);
                }
                    break;
                case SixpMessageType.JoinResponse:
                {
                    var clientChallenge = reader.ReadBytes(4);<commit_msg>Perhaps I should read my own code<commit_after>﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;
using MsgPack;
using MsgPack.Serialization;

namespace CoolRanch
{
    public class InfoResponseEventArgs : EventArgs
    {
        public IPEndPoint EndPoint;
        public byte[] Challenge;
        public Dictionary<string, object> Info;

        public InfoResponseEventArgs(IPEndPoint endpoint, byte[] challenge, Dictionary<string, object> info)
        {
            EndPoint = endpoint;
            Challenge = challenge;
            Info = info;
        }
    }

    public class SessionInfoExchanger
    {
        UdpClient _udp;
        ElDorado _game;
        HMAC _challengeHmac;

        private IPEndPoint _masterServer;
        private IPEndPoint _joinTarget;
        private Dictionary<IPEndPoint, byte[]> _challengeCache; // oh god what 

        public bool AllowJoins, Announcing;

        public event EventHandler<InfoResponseEventArgs> InfoResponseReceived;

        public SessionInfoExchanger(ElDorado game)
        {
            _game = game;
            _udp = new UdpClient(new IPEndPoint(IPAddress.Any, 11770));
            _udp.Client.IOControl(-1744830452, new byte[] { 0, 0, 0, 0 }, null);
            _challengeHmac = new HMACMD5();

            _masterServer =
                new IPEndPoint(Array.Find(Dns.GetHostAddresses("coolranch.ax.lt"),
                    a => a.AddressFamily == AddressFamily.InterNetwork), 8080);
            _challengeCache = new Dictionary<IPEndPoint, byte[]>();
        }

        public void ReceiveLoop()
        {
            var peer = new IPEndPoint(IPAddress.Any, 0);

            while (true)
            {
                var data = _udp.Receive(ref peer);
                Console.WriteLine("{0} -> {1}", peer, BitConverter.ToString(data));

                var reader = new BinaryReader(new MemoryStream(data));
                var magic = new string(reader.ReadChars(4));

                if (magic != "SIXP")
                    continue;

                var version = reader.ReadByte();
                var flags = reader.ReadByte();

                byte[] msg;

                if ((flags & 0x1) != 0)
                    throw new NotImplementedException();
                else
                    msg = reader.ReadBytes(1024);

                ProcessMessage(msg, peer);
            }
        }

        public void AnnounceLoop()
        {
            Console.WriteLine("Announcement loop started.");

            while (Announcing)
            {
                SendAssociationRequest(_masterServer);
                Thread.Sleep(120000);
            }

            Console.WriteLine("Announcement loop stopped.");
        }

        enum SixpMessageType : byte
        {
            ChallengeRequest,
            ChallengeResponse,
            AssociationRequest,
            InfoRequest,
            InfoResponse,
            JoinRequest,
            JoinResponse
        };

        void ProcessMessage(byte[] msg, IPEndPoint peer)
        {
            var ms = new MemoryStream(msg);
            var reader = new BinaryReader(ms);

            var type = (SixpMessageType)reader.ReadByte();
            switch (type)
            {
                case SixpMessageType.ChallengeRequest:
                {
                    var clientChallenge = reader.ReadBytes(4);
                    SendChallengeResponse(peer, clientChallenge);
                }
                    break;
                case SixpMessageType.ChallengeResponse:
                {
                    var clientChallenge = reader.ReadBytes(4);
                    var hostChallenge = reader.ReadBytes(4);

                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!clientChallenge.SequenceEqual(verify))
                        return;

                    _challengeCache[peer] = hostChallenge;

                    if (Equals(peer, _joinTarget))
                        SendJoinRequest(peer, hostChallenge);
                    else
                        SendInfoRequest(peer, hostChallenge);
                }
                    break;
                case SixpMessageType.InfoRequest:
                {
                    var hostChallenge = reader.ReadBytes(4);
                    var clientChallenge = reader.ReadBytes(4);

                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!hostChallenge.SequenceEqual(verify))
                        return;

                    if (Announcing)
                        SendInfoReponse(peer, clientChallenge);
                }
                    break;
                case SixpMessageType.InfoResponse:
                {
                    var clientChallenge = reader.ReadBytes(4);
                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!clientChallenge.SequenceEqual(verify))
                        return;

                    var serializer = MessagePackSerializer.Get<Dictionary<string, object>>();
                    var info = serializer.Unpack(ms);
                    if (InfoResponseReceived != null)
                        InfoResponseReceived(this, new InfoResponseEventArgs(peer, _challengeCache[peer], info));
                    _challengeCache.Remove(peer);
                }
                    break;
                case SixpMessageType.JoinRequest:
                {
                    var hostChallenge = reader.ReadBytes(4);
                    var clientChallenge = reader.ReadBytes(4);

                    var verify = _challengeHmac.ComputeHash(peer.Address.GetAddressBytes()).Take(4);
                    if (!hostChallenge.SequenceEqual(verify))
                        return;

                    SendJoinResponse(peer, clientChallenge);
                }
                    break;
                case SixpMessageType.JoinResponse:
                {
                    var clientChallenge = reader.ReadBytes(4);
{'fraction_non_alphanumeric': 0.08128020280440466, 'fraction_numerical': 0.008555810821516279, 'mean_word_length': 1.4943687018375815, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '775780', 'n_tokens_mistral': 3288, 'n_tokens_neox': 2914, 'n_words': 632}