Fix race conditions when querying user information. Probably.

This commit is contained in:
Loïc Hoguin 2010-05-15 16:12:00 +02:00
parent 9ad0e2d771
commit c8c167c556
2 changed files with 50 additions and 29 deletions

View File

@ -48,8 +48,12 @@ next(Type) ->
%% @doc Select exactly one user by its GID. Return an #users record. %% @doc Select exactly one user by its GID. Return an #users record.
users_select(GID) -> users_select(GID) ->
{atomic, [Val]} = mnesia:transaction(fun() -> mnesia:read({users, GID}) end), case mnesia:transaction(fun() -> mnesia:read({users, GID}) end) of
Val. {atomic, []} ->
error;
{atomic, [Val]} ->
Val
end.
%% @doc Select all users. Return a list of #users records. %% @doc Select all users. Return a list of #users records.

View File

@ -70,18 +70,23 @@ process(CSocket, Version) ->
process_handle(16#020d, CSocket, Version, Packet) -> process_handle(16#020d, CSocket, Version, Packet) ->
[{gid, GID}, {auth, Auth}] = egs_proto:parse_game_auth(Packet), [{gid, GID}, {auth, Auth}] = egs_proto:parse_game_auth(Packet),
User = egs_db:users_select(GID), case egs_db:users_select(GID) of
case User#users.auth of error ->
Auth -> log(GID, "can't find user, closing"),
log(GID, "good auth, proceed"), ssl:close(CSocket);
LID = egs_db:next(lobby), User ->
egs_db:users_insert(#users{gid=GID, pid=self(), socket=CSocket, auth= << 0:32 >>, folder=User#users.folder, lid=LID}), case User#users.auth of
egs_proto:send_flags(CSocket, GID), Auth ->
?MODULE:char_select(CSocket, GID, Version); log(GID, "good auth, proceed"),
_ -> LID = egs_db:next(lobby),
log(GID, "bad auth, closing"), egs_db:users_insert(#users{gid=GID, pid=self(), socket=CSocket, auth= << 0:32 >>, folder=User#users.folder, lid=LID}),
egs_db:users_delete(GID), egs_proto:send_flags(CSocket, GID),
ssl:close(CSocket) ?MODULE:char_select(CSocket, GID, Version);
_ ->
log(GID, "bad auth, closing"),
egs_db:users_delete(GID),
ssl:close(CSocket)
end
end; end;
%% @doc Platform information handler. Obtain the game version. %% @doc Platform information handler. Obtain the game version.
@ -219,22 +224,30 @@ loop(CSocket, GID, Version) ->
{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,
% 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
User = egs_db:users_select(SrcGID), case egs_db:users_select(SrcGID) of
LID = User#users.lid, error ->
Send = << 16#01020101:32, 0:32, 16#00011300:32, SrcGID:32/little-unsigned-integer, 0:64, ignore;
16#00011300:32, GID:32/little-unsigned-integer, 0:64, SrcGID:32/little-unsigned-integer, User ->
LID:32/little-unsigned-integer, After/binary >>, LID = User#users.lid,
egs_proto:packet_send(CSocket, Send), Send = << 16#01020101:32, 0:32, 16#00011300:32, SrcGID:32/little-unsigned-integer, 0:64,
16#00011300:32, GID:32/little-unsigned-integer, 0:64, SrcGID:32/little-unsigned-integer,
LID:32/little-unsigned-integer, After/binary >>,
egs_proto:packet_send(CSocket, Send)
end,
?MODULE:loop(CSocket, GID, Version); ?MODULE:loop(CSocket, GID, Version);
{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
User = egs_db:users_select(SrcGID), case egs_db:users_select(SrcGID) of
LID = User#users.lid, error ->
Send = << 16#05030101:32, 0:32, 16#00011300:32, SrcGID:32/little-unsigned-integer, 0:64, ignore;
16#00011300:32, GID:32/little-unsigned-integer, 0:64, SrcGID:32/little-unsigned-integer, User ->
LID:32/little-unsigned-integer, After/binary >>, LID = User#users.lid,
egs_proto:packet_send(CSocket, Send), Send = << 16#05030101:32, 0:32, 16#00011300:32, SrcGID:32/little-unsigned-integer, 0:64,
16#00011300:32, GID:32/little-unsigned-integer, 0:64, SrcGID:32/little-unsigned-integer,
LID:32/little-unsigned-integer, After/binary >>,
egs_proto:packet_send(CSocket, Send)
end,
?MODULE:loop(CSocket, GID, Version); ?MODULE:loop(CSocket, GID, Version);
{psu_chat, ChatGID, ChatName, ChatMessage} -> {psu_chat, ChatGID, ChatName, ChatMessage} ->
egs_proto:send_chat(CSocket, Version, ChatGID, ChatName, ChatMessage), egs_proto:send_chat(CSocket, Version, ChatGID, ChatName, ChatMessage),
@ -292,7 +305,7 @@ handle(16#021f, CSocket, GID, _, Packet) ->
log(GID, "uni selection (my room)"), log(GID, "uni selection (my room)"),
% 0230 0220 % 0230 0220
% myroom_load(CSocket, GID, Version, 16#a701, 16#0100); % myroom_load(CSocket, GID, Version, 16#a701, 16#0100);
lobby_load(CSocket, GID, 16#0100, 16#0100); lobby_load(CSocket, GID, 16#6700, 16#0100);
_ -> _ ->
log(GID, "uni selection (reload)"), log(GID, "uni selection (reload)"),
% 0230 0220 % 0230 0220
@ -314,8 +327,12 @@ handle(16#0304, _, GID, Version, Packet) ->
[{gid, _}, {name, ChatName}, {message, ChatMessage}] = egs_proto:parse_chat(Version, Packet), [{gid, _}, {name, ChatName}, {message, ChatMessage}] = egs_proto:parse_chat(Version, Packet),
case ChatName of case ChatName of
missing -> missing ->
User = egs_db:users_select(GID), case egs_db:users_select(GID) of
ActualName = User#users.charname; error ->
ActualName = ChatName;
User ->
ActualName = User#users.charname
end;
_ -> _ ->
ActualName = ChatName ActualName = ChatName
end, end,