Fix a crash in packet_split. Packets don't always arrive full.
This commit is contained in:
parent
a870dc618f
commit
09e585b549
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
-module(egs_game).
|
-module(egs_game).
|
||||||
-export([start/0]). % external
|
-export([start/0]). % external
|
||||||
-export([listen/0, accept/1, process/2, char_select/3, lobby_load/4, loop/3]). % internal
|
-export([listen/0, accept/1, process/2, char_select/3, lobby_load/4, loop/3, loop/4]). % internal
|
||||||
|
|
||||||
-include("include/records.hrl").
|
-include("include/records.hrl").
|
||||||
-include("include/network.hrl").
|
-include("include/network.hrl").
|
||||||
@ -215,11 +215,16 @@ lobby_load(CSocket, GID, Map, Entry) ->
|
|||||||
log(GID, "send error, closing")
|
log(GID, "send error, closing")
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% @doc Alias for the game main's loop when the buffer is empty.
|
||||||
|
|
||||||
|
loop(CSocket, GID, Version) ->
|
||||||
|
loop(CSocket, GID, Version, << >>).
|
||||||
|
|
||||||
%% @doc Game's main loop.
|
%% @doc Game's main loop.
|
||||||
%% @todo Have some kind of clock process for keepalive packets.
|
%% @todo Have some kind of clock process for keepalive packets.
|
||||||
%% @todo Handle 0102 and 0503 broadcasts correctly.
|
%% @todo Handle 0102 and 0503 broadcasts correctly.
|
||||||
|
|
||||||
loop(CSocket, GID, Version) ->
|
loop(CSocket, GID, Version, SoFar) ->
|
||||||
receive
|
receive
|
||||||
{psu_broadcast_0102, Data} ->
|
{psu_broadcast_0102, Data} ->
|
||||||
<< _:96, SrcGID:32/little-unsigned-integer, _:256, After/bits >> = Data,
|
<< _:96, SrcGID:32/little-unsigned-integer, _:256, After/bits >> = Data,
|
||||||
@ -234,7 +239,7 @@ loop(CSocket, GID, Version) ->
|
|||||||
LID:32/little-unsigned-integer, After/binary >>,
|
LID:32/little-unsigned-integer, After/binary >>,
|
||||||
egs_proto:packet_send(CSocket, Send)
|
egs_proto:packet_send(CSocket, Send)
|
||||||
end,
|
end,
|
||||||
?MODULE:loop(CSocket, GID, Version);
|
?MODULE:loop(CSocket, GID, Version, SoFar);
|
||||||
{psu_broadcast_010f, Data} ->
|
{psu_broadcast_010f, Data} ->
|
||||||
<< _:96, SrcGID:32/little-unsigned-integer, _:256, After/bits >> = Data,
|
<< _:96, SrcGID:32/little-unsigned-integer, _:256, After/bits >> = Data,
|
||||||
% TODO: assign the LID correctly when sending the character info for the player's character, not when broadcasting
|
% TODO: assign the LID correctly when sending the character info for the player's character, not when broadcasting
|
||||||
@ -248,7 +253,7 @@ loop(CSocket, GID, Version) ->
|
|||||||
LID:32/little-unsigned-integer, After/binary >>,
|
LID:32/little-unsigned-integer, After/binary >>,
|
||||||
egs_proto:packet_send(CSocket, Send)
|
egs_proto:packet_send(CSocket, Send)
|
||||||
end,
|
end,
|
||||||
?MODULE:loop(CSocket, GID, Version);
|
?MODULE:loop(CSocket, GID, Version, SoFar);
|
||||||
{psu_broadcast_0503, Data} ->
|
{psu_broadcast_0503, Data} ->
|
||||||
<< _:96, SrcGID:32/little-unsigned-integer, _:256, After/bits >> = Data,
|
<< _:96, SrcGID:32/little-unsigned-integer, _:256, After/bits >> = Data,
|
||||||
% TODO: assign the LID correctly when sending the character info for the player's character, not when broadcasting
|
% TODO: assign the LID correctly when sending the character info for the player's character, not when broadcasting
|
||||||
@ -262,17 +267,17 @@ loop(CSocket, GID, Version) ->
|
|||||||
LID:32/little-unsigned-integer, After/binary >>,
|
LID:32/little-unsigned-integer, After/binary >>,
|
||||||
egs_proto:packet_send(CSocket, Send)
|
egs_proto:packet_send(CSocket, Send)
|
||||||
end,
|
end,
|
||||||
?MODULE:loop(CSocket, GID, Version);
|
?MODULE:loop(CSocket, GID, Version, SoFar);
|
||||||
{psu_chat, ChatGID, ChatName, ChatModifiers, ChatMessage} ->
|
{psu_chat, ChatGID, ChatName, ChatModifiers, ChatMessage} ->
|
||||||
egs_proto:send_chat(CSocket, Version, ChatGID, ChatName, ChatModifiers, ChatMessage),
|
egs_proto:send_chat(CSocket, Version, ChatGID, ChatName, ChatModifiers, ChatMessage),
|
||||||
?MODULE:loop(CSocket, GID, Version);
|
?MODULE:loop(CSocket, GID, Version, SoFar);
|
||||||
{psu_player_spawn, SpawnPlayer} ->
|
{psu_player_spawn, SpawnPlayer} ->
|
||||||
send_spawn(CSocket, GID, SpawnPlayer),
|
send_spawn(CSocket, GID, SpawnPlayer),
|
||||||
?MODULE:loop(CSocket, GID, Version);
|
?MODULE:loop(CSocket, GID, Version, SoFar);
|
||||||
{ssl, _, Data} ->
|
{ssl, _, Data} ->
|
||||||
Packets = egs_proto:packet_split(Data),
|
{Packets, Rest} = egs_proto:packet_split(<< SoFar/bits, Data/bits >>),
|
||||||
[dispatch(CSocket, GID, Version, P) || P <- Packets],
|
[dispatch(CSocket, GID, Version, P) || P <- Packets],
|
||||||
?MODULE:loop(CSocket, GID, Version);
|
?MODULE:loop(CSocket, GID, Version, Rest);
|
||||||
{ssl_closed, _} ->
|
{ssl_closed, _} ->
|
||||||
log(GID, "ssl closed~n"),
|
log(GID, "ssl closed~n"),
|
||||||
egs_db:users_delete(GID),
|
egs_db:users_delete(GID),
|
||||||
@ -282,11 +287,11 @@ loop(CSocket, GID, Version) ->
|
|||||||
egs_db:users_delete(GID),
|
egs_db:users_delete(GID),
|
||||||
ssl:close(CSocket);
|
ssl:close(CSocket);
|
||||||
_ ->
|
_ ->
|
||||||
?MODULE:loop(CSocket, GID, Version)
|
?MODULE:loop(CSocket, GID, Version, SoFar)
|
||||||
after 1000 ->
|
after 1000 ->
|
||||||
egs_proto:send_keepalive(CSocket, GID),
|
egs_proto:send_keepalive(CSocket, GID),
|
||||||
reload,
|
reload,
|
||||||
?MODULE:loop(CSocket, GID, Version)
|
?MODULE:loop(CSocket, GID, Version, SoFar)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Dispatch the command to the right handler.
|
%% @doc Dispatch the command to the right handler.
|
||||||
|
@ -101,14 +101,22 @@ packet_fragment_send(CSocket, Packet, Size, Current) ->
|
|||||||
%% @doc Split a packet received into commands. This is only needed when receiving packets in active mode.
|
%% @doc Split a packet received into commands. This is only needed when receiving packets in active mode.
|
||||||
|
|
||||||
packet_split(Packet) ->
|
packet_split(Packet) ->
|
||||||
|
packet_split(Packet, []).
|
||||||
|
|
||||||
|
packet_split(Packet, Result) ->
|
||||||
<< Size:32/little-unsigned-integer, _/bits >> = Packet,
|
<< Size:32/little-unsigned-integer, _/bits >> = Packet,
|
||||||
|
case Size > byte_size(Packet) of
|
||||||
|
true ->
|
||||||
|
{Result, Packet};
|
||||||
|
false ->
|
||||||
BitSize = Size * 8,
|
BitSize = Size * 8,
|
||||||
<< Split:BitSize/bits, Rest/bits >> = Packet,
|
<< Split:BitSize/bits, Rest/bits >> = Packet,
|
||||||
case Rest of
|
case Rest of
|
||||||
<< >> ->
|
<< >> ->
|
||||||
[ Split ];
|
{Result ++ [Split], << >>};
|
||||||
_ ->
|
_ ->
|
||||||
[ Split | packet_split(Rest) ]
|
packet_split(Rest, Result ++ [Split])
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Parse a login authentication command. Return the username and password.
|
%% @doc Parse a login authentication command. Return the username and password.
|
||||||
|
Loading…
Reference in New Issue
Block a user