Author: bdonlan
Date: 2005-12-09 17:24:04 -0500 (Fri, 09 Dec 2005)
New Revision: 947
Modified:
trunk/erlang/server/haver_worker.erl
trunk/erlang/server/schema.hrl
trunk/erlang/server/server.erl
Log:
ghost support - be sure to remake your schema
Modified: trunk/erlang/server/haver_worker.erl
===================================================================
--- trunk/erlang/server/haver_worker.erl 2005-12-09 21:42:22 UTC (rev
946)
+++ trunk/erlang/server/haver_worker.erl 2005-12-09 22:24:04 UTC (rev
947)
@@ -11,6 +11,8 @@
entry(Parent, Socket) ->
link(Parent),
put(socket, Socket),
+ { ok, { Address, RemotePort } } = inet:peername(Socket),
+ put(address, Address),
receive
{ line, [ "HAVER", Vers | _ ] } ->
haver_sendline(["HAVER", "localhost", "Erver/0.0"]),
@@ -21,7 +23,7 @@
Foo -> io:format("haver_entry unknown msg ~p~n", [Foo])
end.
-handle_ident(Uid) ->
+try_ident(Uid) ->
F = fun() ->
Q = query
[ E || E <- table(users), E.name = Uid ]
@@ -29,28 +31,91 @@
R = mnemosyne:eval(Q),
io:format("~p~n", [R]),
case R of
- [] -> mnesia:write(#users{name = Uid, pid = self()}),
+ [] -> mnesia:write(#users{name = Uid, pid = self(), ip =
get(address)}),
ok;
_ -> collision
end
end,
R = mnesia:transaction(F),
case R of
- { atomic, ok } ->
+ { atomic, ok } -> ok;
+ { atomic, collision } -> collision;
+ V -> exit(V)
+ end.
+
+handle_ident(Uid) ->
+ case try_ident(Uid) of
+ ok ->
haver_sendline(["HELLO", Uid]),
put(uid, Uid),
haver_mainloop();
- { atomic, collision } ->
+ collision ->
haver_sendline(["FAIL", "IDENT", "exists.user", Uid]),
+ haver_login()
+ end.
+
+handle_ghost(Uid) ->
+ Myip = get(address),
+ F = fun() ->
+ Q = query [ U || U <- table(users), U.name = Uid ] end,
+ R = mnemosyne:eval(Q),
+ case R of
+ [] -> try_ident;
+ [U] ->
+ Theirip = U#users.ip,
+ case Theirip of
+ Myip -> U;
+ _ -> wrongip
+ end end end,
+ R = mnesia:transaction(F),
+ io:format("hg, R=~p, myip=~p~n", [R, Myip]),
+ case R of
+ { atomic, try_ident } ->
+ case try_ident(Uid) of
+ ok ->
+ haver_sendline(["HELLO", Uid]),
+ put(uid, Uid),
+ haver_mainloop();
+ collision ->
+ haver_sendline(["FAIL", "GHOST", "race", Uid]),
+ haver_login()
+ end;
+ { atomic, wrongip } ->
+ haver_sendline(["FAIL", "GHOST", "ip.mismatch", Uid]),
haver_login();
- Wtf -> io:format("wtf: ~p~n", [Wtf])
+ { atomic, U } -> perform_ghost(U)
end.
+perform_ghost(U) ->
+ io:format("p_g: U=~p~n", [U]),
+ Uid = U#users.name,
+ Pid = U#users.pid,
+ erlang:monitor(process, U#users.pid),
+ U#users.pid ! { quit, "ghost", ghost },
+ receive
+ {'DOWN', _, _, Pid, _} ->
+ server:reap_child(U#users.pid, ghost),
+ case try_ident(U#users.name) of
+ collision ->
+ haver_sendline(["FAIL", "GHOST", "race"]),
+ haver_login();
+ ok ->
+ haver_sendline(["HELLO", Uid]),
+ put(uid, Uid),
+ haver_mainloop()
+ end
+ after
+ 5000 ->
+ haver_sendline(["FAIL", "GHOST", "timeout", Uid]),
+ haver_login()
+ end.
+
haver_login() ->
receive
{ line, [ "IDENT", Uid ] } -> handle_ident(Uid);
+ { line, [ "GHOST", Uid ] } -> handle_ghost(Uid);
{ line, _ } ->
- haver_sendline(["DIE", "ihateyou"]),
+ haver_sendline(["DIE", "wrong.command"]),
gen_tcp:close(get(socket)),
exit(rudepeer);
M -> exit({unexpected, M})
@@ -237,6 +302,7 @@
haver_sendline(["BYE", Detail]),
gen_tcp:close(get(socket)),
exit({ quit, "bye", Detail});
+ { line, [ "BYE" ] } -> self() ! { line, [ "BYE", "bye" ] }
{ line, [ L | T ] } ->
io:format("unmatched line: ~p~n", [L|T]),
haver_sendline(["FAIL", L, "unknown.cmd"]),
@@ -247,6 +313,10 @@
{ privmsg, From, Message } ->
haver_sendline(["FROM", From | Message]),
ok;
- Other -> io:format("unknown msg: ~p~n", Other), exit(Other)
+ { quit, Message, Exitcode } ->
+ haver_sendline(["BYE", Message]),
+ gen_tcp:close(get(socket)),
+ exit(Exitcode);
+ Other -> io:format("unknown msg: ~p~n", [Other]), exit(Other)
end,
haver_mainloop().
Modified: trunk/erlang/server/schema.hrl
===================================================================
--- trunk/erlang/server/schema.hrl 2005-12-09 21:42:22 UTC (rev 946)
+++ trunk/erlang/server/schema.hrl 2005-12-09 22:24:04 UTC (rev 947)
@@ -1,4 +1,4 @@
--record(users, {name,
- pid}).
+% vim: set ft=erlang :
+-record(users, {name, pid, ip}).
-record(channels, {name, notused}).
-record(chanjoin, {channel, user}).
Modified: trunk/erlang/server/server.erl
===================================================================
--- trunk/erlang/server/server.erl 2005-12-09 21:42:22 UTC (rev 946)
+++ trunk/erlang/server/server.erl 2005-12-09 22:24:04 UTC (rev 947)
@@ -1,6 +1,6 @@
-module(server).
-export([cstart/1, start/1, stop/0, worker/2, setup_schema/0,
- clear_transients/0]).
+ clear_transients/0, reap_child/2]).
-import(haver_worker, []).
-import(haver_protocol, [encode/1, decode/1]).
-include_lib("mnemosyne/include/mnemosyne.hrl").
@@ -57,10 +57,13 @@
ok -> { ok, spawn(?MODULE, cstart, [Port]) };
Err -> { nok, Err }
end.
-stop() -> haver ! shutdown.
+stop() ->
+ haver ! shutdown.
+
match_reason({quit, Type, Detail}) -> {Type, Detail};
match_reason({socket_closed, _}) -> {"closed", ""};
+match_reason(ghost) -> {"ghost", ""};
match_reason(R) ->
io:format("Unknown quit-reason: ~p~n", [R]),
{ "error", io_lib:format("~w", [R]) }.