Development · Downloadables · Tutorial

Chattr

Back at it again with more coding and projects.

This is a chatting application that is inspired by WhatsApp and Discord. It uses simple Sockets and managed to catch all lost packets when their size is over the limited one, so I never get packet-loss errors for the content.

BasePacket

I send data using by BasePacket which is serialized to Json and then converted to bytes, then sent over the internet.

using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using RaulSSorban.Chattr.Data.Packets;
using System;
using System.IO;

namespace RaulSSorban.Chattr.Data.Base
{
    [System.Serializable]
    public class BasePacket
    {
        public string HookMethod;
        public ConnectionInfo ConnectionInfo;

        public BasePacket () { }
        public BasePacket ( ConnectionInfo connectionInfo, string hookMethod )
        {
            HookMethod = hookMethod;
            ConnectionInfo = connectionInfo;
        }

        public static Random random = new Random ();

        public string Serialize ()
        {
            var output = JsonConvert.SerializeObject ( this, Formatting.Indented );
            output += SocketPacket.END_SEPARATOR;

            return output;
        }

        public static T Deserialize ( string input )
        {
            input = input.CorrectString ();

            var output = JsonConvert.DeserializeObject ( input );
            return output;
        }

        [JsonIgnore] public string Header { get { return HookMethod.Split ( ':' ) [ 0 ]; } }
        [JsonIgnore] public string Method { get { return HookMethod.Split ( ':' ) [ 1 ]; } }
    }
}

It carries basic data, like who sent the packet, from what ip:port and uses a technique that I just thought about and implemented, never heard of it – hook methods. Which are pretty much commands but not really.

A real example of using BasePacket.

using RaulSSorban.Chattr.Data.Base;

namespace RaulSSorban.Chattr.Data.Packets
{
    [System.Serializable]
    public class MessagePacket : BasePacket
    {
        public string ID;
        public User User;
        public string Message;

        public MessagePacket ()
        {
            ID = $"{Humanlights.Extensions.RandomEx.GetRandomString ( 30 )}";
        }

        public static byte [] Send ( User user, string message )
        {
            var msg = new MessagePacket ();

            msg.ConnectionInfo = user.ConnectionInfo;
            msg.HookMethod = HookMethods.MESSAGE_SEND;
            msg.User = user;
            msg.Message = message;

            return msg.Serialize ().FromStringToBytes ();
        }
    }
}

And results this:

{
  "ID": "M2ghGNyi2VUWnwPxhxXZWPFiB1eiWA",
  "User": {
    "ID": "45667319",
    "UserType": 0,
    "ConnectionInfo": {
      "IP": "10.0.0.68",
      "Port": 4200
    },
    "Credentials": {
      "Username": "localhost",
      "Password": "admin"
    },
    "Status": {
      "ConnectionStatus": 1,
      "UserStatus": 0,
      "StatusMessage": null
    },
    "IsTyping": false
  },
  "Message": "raulssorban just logged in.",
  "HookMethod": "message:send",
  "ConnectionInfo": {
    "IP": "10.0.0.68",
    "Port": 4200
  }
}

---------------- END OF THIS FUCKING PACKET ----------------

The “—————- END OF THIS FUCKING PACKET —————-” is a separator, to can separate combined bytes sent/received at once, so all code sent over is being used.

The first file has all the combined bytes (json sources), and the next enumerated packets are the splitted sources. And those splitted ones are being handled (ran).

Bandwidth Optimization

Since the limited send/receive server and client byte size is ( 1024 * 1000 ) * 2, which is 2 megabytes per-packet (crazily), I send a lot of data. Full user information to the client, with the tokens and passwords, which is not normal, but soon after finishing writing this, I’ll write a specific ClientUser class which holds just the ip:port, ID and few states (if logged in, what user type, etc), so everyone’s happy.