Created
July 17, 2014 00:32
-
-
Save trapped/de3704881d8eeb6a3eaf to your computer and use it in GitHub Desktop.
RotMG proof-of-concept server in Erlang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% RotMG game module | |
-module(rotmgs). | |
-export([start/0, read/1, processpacket/2, send/2]). | |
-define(PORT, 2050). | |
-define(TCP_OPTIONS, [binary, | |
{packet, 0}, | |
{active, false}, | |
{backlog, 1024}, | |
{reuseaddr, true}]). | |
-define(RC4R, [16#31, 16#1f, 16#80, 16#69, 16#14, 16#51, 16#c7, 16#1d, 16#09, 16#a1, 16#3a, 16#2a, 16#6e]). | |
-define(RC4S, [16#72, 16#c5, 16#58, 16#3c, 16#af, 16#b6, 16#81, 16#89, 16#95, 16#cd, 16#d7, 16#4b, 16#80]). | |
start() -> | |
io:format("Starting~n"), | |
crypto:start(), | |
listen(). | |
listen() -> | |
{ok, Listener} = gen_tcp:listen(?PORT, ?TCP_OPTIONS), | |
io:format("Listening on ~b~n", [?PORT]), | |
accept(Listener). | |
accept(Listener) -> | |
{ok, Client} = gen_tcp:accept(Listener), | |
io:format("Accepted client~n"), | |
spawn(?MODULE, read, [Client]), | |
accept(Listener). | |
read(Client) -> | |
case gen_tcp:recv(Client, 4) of | |
{ok, Data} -> | |
<<Length:32/big-unsigned-integer>> = Data, | |
readpacket(Client, Length); | |
{error, _} -> | |
ok | |
end. | |
readpacket(Client, Length) -> | |
io:format("Packet length: ~b~n", [Length]), | |
case gen_tcp:recv(Client, Length - 4) of | |
{ok, Data} -> | |
spawn_link(?MODULE, processpacket, [Client, Data]); | |
{error, _} -> | |
ok | |
end, | |
read(Client). | |
processpacket(Client, Packet) -> | |
<<Ty, EData/binary>> = Packet, | |
io:format("Packet type: ~b~n", [Ty]), | |
Type = | |
case Ty of | |
13 -> | |
hello | |
end, | |
Data = crypto:rc4_encrypt(?RC4R, EData), | |
processpacket(Type, Client, Data). | |
processpacket(hello, Client, Data) -> | |
<<BVLn:16/big-unsigned-integer, BuildVersion:BVLn/binary, | |
GmId:32/big-unsigned-integer, | |
GLen:16/big-unsigned-integer, Guid:GLen/binary, | |
Rnd1:32/big-unsigned-integer, | |
PLen:16/big-unsigned-integer, Password:PLen/binary, | |
Rnd2:32/big-unsigned-integer, | |
SLen:16/big-unsigned-integer, Secret:SLen/binary, | |
KTim:32/big-unsigned-integer, | |
KLen:16/big-unsigned-integer, Key:KLen/binary, | |
MLen:32/big-unsigned-integer, MapInfo:MLen/binary, | |
OLn1:16/big-unsigned-integer, Obf1:OLn1/binary, | |
OLn2:16/big-unsigned-integer, Obf2:OLn2/binary, | |
OLn3:16/big-unsigned-integer, Obf3:OLn3/binary, | |
OLn4:16/big-unsigned-integer, Obf4:OLn4/binary, | |
OLn5:16/big-unsigned-integer, Obf5:OLn5/binary>> = Data, | |
io:format("Received HELLO: ~s~n", [BuildVersion]), | |
%failure(Client, 55, "Test error") | |
mapinfo(Client, 10, 10, "Nexus", "Nexuss", 0, 0, 1, true, true). | |
failure(Client, Id, LMessage) -> | |
Message = list_to_binary(LMessage), | |
MsgSize = byte_size(Message), | |
Base = <<0, MsgSize:16/big-unsigned-integer, Message/binary>>, | |
BaseSize = byte_size(Base) + 4, | |
Packet = <<BaseSize:32/big-unsigned-integer, Base/binary>>, | |
spawn_link(?MODULE, send, [Client, Packet]). | |
mapinfo(Client, Width, Height, Name, WorldName, Fp, Background, Difficulty, AllowTeleport, ShowDisplays) -> | |
LName = list_to_binary(Name), | |
LWorldName = list_to_binary(WorldName), | |
NLen = byte_size(LName), | |
WNLen = byte_size(LWorldName), | |
AllowTeleportB = | |
case AllowTeleport of | |
true -> | |
16#1; | |
false -> | |
16#0 | |
end, | |
ShowDisplaysB = | |
case ShowDisplays of | |
true -> | |
16#1; | |
false -> | |
16#0 | |
end, | |
Base = <<16#62, | |
Width:32/big-unsigned-integer, | |
Height:32/big-unsigned-integer, | |
NLen:16/big-unsigned-integer, LName:NLen/binary, | |
WNLen:16/big-unsigned-integer, LWorldName:WNLen/binary, | |
Fp:32/big-unsigned-integer, | |
Background:32/big-unsigned-integer, | |
Difficulty:32/big-unsigned-integer, | |
AllowTeleportB, ShowDisplaysB, 0:16, 0:16>>, | |
%CXLen:16/big-unsigned-integer, ClientXML:CXLen/binary, | |
%EXLen:16/big-unsigned-integer, ExtraXML:EXLen/binary>>, | |
BaseSize = byte_size(Base) + 4, | |
Packet = <<BaseSize:32/big-unsigned-integer, Base/binary>>, | |
spawn_link(?MODULE, send, [Client, Packet]). | |
send(Client, Data) -> | |
case gen_tcp:send(Client, Data) of | |
ok -> | |
ok; | |
{error, _} -> | |
ok | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment