diff options
| author | Mishio595 <[email protected]> | 2018-10-21 18:20:01 -0600 |
|---|---|---|
| committer | Mishio595 <[email protected]> | 2018-10-21 18:20:01 -0600 |
| commit | b47f0a22c5bcba1e2570dcf95d820399e9627ec2 (patch) | |
| tree | 23a850e882ac2dd9d625b052d17148a610e8d2b6 /lib/client | |
| parent | Add HTTP routes (diff) | |
| download | disml-b47f0a22c5bcba1e2570dcf95d820399e9627ec2.tar.xz disml-b47f0a22c5bcba1e2570dcf95d820399e9627ec2.zip | |
Basic sharding
Diffstat (limited to 'lib/client')
| -rw-r--r-- | lib/client/client.ml | 0 | ||||
| -rw-r--r-- | lib/client/shardManager.ml | 127 |
2 files changed, 127 insertions, 0 deletions
diff --git a/lib/client/client.ml b/lib/client/client.ml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/client/client.ml diff --git a/lib/client/shardManager.ml b/lib/client/shardManager.ml new file mode 100644 index 0000000..16aa531 --- /dev/null +++ b/lib/client/shardManager.ml @@ -0,0 +1,127 @@ +open Lwt.Infix +open Websocket + +module Opcode = struct + type t = + | DISPATCH + | HEARTBEAT + | IDENTIFY + | STATUS_UPDATE + | VOICE_STATE_UPDATE + | RESUME + | RECONNECT + | REQUEST_GUILD_MEMBERS + | INVALID_SESSION + | HELLO + | HEARTBEAT_ACK + + let to_int = function + | DISPATCH -> 0 + | HEARTBEAT -> 1 + | IDENTIFY -> 2 + | STATUS_UPDATE -> 3 + | VOICE_STATE_UPDATE -> 4 + | RESUME -> 6 + | RECONNECT -> 7 + | REQUEST_GUILD_MEMBERS -> 8 + | INVALID_SESSION -> 9 + | HELLO -> 10 + | HEARTBEAT_ACK -> 11 + + let to_string = function + | DISPATCH -> "DISPATCH" + | HEARTBEAT -> "HEARTBEAT" + | IDENTIFY -> "IDENTIFY" + | STATUS_UPDATE -> "STATUS_UPDATE" + | VOICE_STATE_UPDATE -> "VOICE_STATE_UPDATE" + | RESUME -> "RESUME" + | RECONNECT -> "RECONNECT" + | REQUEST_GUILD_MEMBERS -> "REQUEST_GUILD_MEMBER" + | INVALID_SESSION -> "INVALID_SESSION" + | HELLO -> "HELLO" + | HEARTBEAT_ACK -> "HEARTBEAT_ACK" +end + +module Shard = struct + type t = { + send: (Frame.t -> unit Lwt.t); + recv: (unit -> Frame.t Lwt. t); + hb_interval: int; + session_id: string; + seq: int; + } + + let connect uri = + let url = Uri.to_string uri in + let ip = Ipaddr.V4 Ipaddr.V4.any in + Websocket_lwt.with_connection (`TLS (`Hostname url, `IP ip, `Port 443)) uri + >|= fun (recv, send) -> + (* Start heartbeat sequencing *) + { send; recv; hb_interval = 42500; session_id = ""; seq = 0; } + + let send payload shard = + payload + |> shard.send + |> ignore + + let wrap_payload d op = + `Assoc [ + ("op", `Int op); + ("d", d) + ] + + let identify ?(threshold=250) shard id total token = + let p = wrap_payload(`Assoc [ + ("token", `String token); + ("properties", `Assoc [ + ("$os", `String Sys.os_type); + ("$browser", `String "animus"); + ("$device", `String "animus"); + ]); + ("large_threshold", `Int threshold); + ("shard", `List [`Int id; `Int total]); + ]) (Opcode.to_int IDENTIFY) in + let p = Frame.create ~content:(Yojson.Basic.to_string p) () in + send p shard + + let resume shard token = + let p = wrap_payload (`Assoc [ + ("token", `String token); + ("session_id", `String shard.session_id); + ("seq", `Int shard.seq); + ]) (Opcode.to_int RESUME) in + let p = Frame.create ~content:(Yojson.Basic.to_string p) () in + send p shard + + let heartbeat shard = + let p = Frame.create () in + send p shard +end + +module ShardMap = Map.Make( + struct + type t = int + let compare: int -> int -> int = Pervasives.compare + end +) + +type t = { + shards: Shard.t ShardMap.t; + gateway_url: Uri.t; + token: string; +} + +let create_shard manager = + Shard.connect manager.gateway_url + >|= fun shard -> + let id = (ShardMap.cardinal manager.shards) + 1 in + ShardMap.add id shard manager.shards + +let identify manager id = + let total = ShardMap.cardinal manager.shards in + let shard = ShardMap.find id manager.shards in + Shard.identify shard id total manager.token + +let resume manager id = + let shard = ShardMap.find id manager.shards in + Shard.resume shard manager.token
\ No newline at end of file |