echo daemon works well enough
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
% ANSI screen drawing macros in erlang
|
||||
%
|
||||
% Author: Peter Harpending <peterharpending@qpq.swiss>
|
||||
% Date: 2026-04-10
|
||||
%
|
||||
% Copyright (C) 2026, QPQ AG
|
||||
|
||||
% Not exhaustive, just what I need for the moment
|
||||
% ref: https://gist.github.com/ConnerWill/d4b6c776b509add763e17f9f113fd25b
|
||||
-define(ANSI_ESC, [27]).
|
||||
-define(ANSI_CRLF, "\r\n").
|
||||
-define(ANSI_FF, [12]).
|
||||
-define(ANSI_CLEAR, [12]).
|
||||
|
||||
-define(ANSI_LINE(X), [X, ?ANSI_CRLF]).
|
||||
|
||||
% MARKDOWN TIER TEXT FORMATTING
|
||||
|
||||
% resets all formatting
|
||||
-define(ANSI_RESET, [?ANSI_ESC, "[0m"]).
|
||||
|
||||
-define(ANSI_BOLD, [?ANSI_ESC, "[1m"]).
|
||||
-define(ANSI_DIM, [?ANSI_ESC, "[2m"]).
|
||||
-define(ANSI_ITALIC, [?ANSI_ESC, "[3m"]).
|
||||
-define(ANSI_ULINE, [?ANSI_ESC, "[4m"]).
|
||||
-define(ANSI_BLINK, [?ANSI_ESC, "[5m"]).
|
||||
-define(ANSI_INVERT, [?ANSI_ESC, "[7m"]).
|
||||
-define(ANSI_INVIS, [?ANSI_ESC, "[8m"]).
|
||||
-define(ANSI_STRIKE, [?ANSI_ESC, "[9m"]).
|
||||
|
||||
% > Note: Both dim and bold modes are reset with the ESC[22m sequence. The
|
||||
% > ESC[21m sequence is a non-specified sequence for double underline mode and
|
||||
% > only work in some terminals and is reset with ESC[24m.
|
||||
-define(ANSI_UNBOLD, [?ANSI_ESC, "[22m"]).
|
||||
-define(ANSI_UNDIM, [?ANSI_ESC, "[22m"]).
|
||||
-define(ANSI_UNITALIC, [?ANSI_ESC, "[23m"]).
|
||||
-define(ANSI_UNULINE, [?ANSI_ESC, "[24m"]).
|
||||
-define(ANSI_UNBLINK, [?ANSI_ESC, "[25m"]).
|
||||
-define(ANSI_UNINVERT, [?ANSI_ESC, "[27m"]).
|
||||
-define(ANSI_UNINVIS, [?ANSI_ESC, "[28m"]).
|
||||
-define(ANSI_UNSTRIKE, [?ANSI_ESC, "[29m"]).
|
||||
|
||||
-define(ANSI_BOLD(X), [?ANSI_BOLD, X, ?ANSI_UNBOLD]).
|
||||
-define(ANSI_DIM(X), [?ANSI_DIM, X, ?ANSI_UNDIM]).
|
||||
-define(ANSI_ITALIC(X), [?ANSI_ITALIC, X, ?ANSI_UNITALIC]).
|
||||
-define(ANSI_ULINE(X), [?ANSI_ULINE, X, ?ANSI_UNULINE]).
|
||||
-define(ANSI_BLINK(X), [?ANSI_BLINK, X, ?ANSI_UNBLINK]).
|
||||
-define(ANSI_INVERT(X), [?ANSI_INVERT, X, ?ANSI_UNINVERT]).
|
||||
-define(ANSI_INVIS(X), [?ANSI_INVIS, X, ?ANSI_UNINVIS]).
|
||||
-define(ANSI_STRIKE(X), [?ANSI_STRIKE, X, ?ANSI_UNSTRIKE]).
|
||||
|
||||
|
||||
% COLORS
|
||||
%
|
||||
% COLOR SetFG SetBG
|
||||
% -----------------------------
|
||||
% Black 30 40
|
||||
% Red 31 41
|
||||
% Green 32 42
|
||||
% Yellow 33 43
|
||||
% Blue 34 44
|
||||
% Magenta 35 45
|
||||
% Cyan 36 46
|
||||
% White 37 47
|
||||
% Default 39 49
|
||||
|
||||
-define(ANSI_FG_RESET, [?ANSI_ESC, "[39m"]).
|
||||
-define(ANSI_BG_RESET, [?ANSI_ESC, "[49m"]).
|
||||
|
||||
-define(ANSI_FG_BLACK, [?ANSI_ESC, "[30m"]).
|
||||
-define(ANSI_FG_RED, [?ANSI_ESC, "[31m"]).
|
||||
-define(ANSI_FG_GREEN, [?ANSI_ESC, "[32m"]).
|
||||
-define(ANSI_FG_YELLOW, [?ANSI_ESC, "[33m"]).
|
||||
-define(ANSI_FG_BLUE, [?ANSI_ESC, "[34m"]).
|
||||
-define(ANSI_FG_MAGENTA, [?ANSI_ESC, "[35m"]).
|
||||
-define(ANSI_FG_CYAN, [?ANSI_ESC, "[36m"]).
|
||||
-define(ANSI_FG_WHITE, [?ANSI_ESC, "[37m"]).
|
||||
|
||||
-define(ANSI_BG_BLACK, [?ANSI_ESC, "[40m"]).
|
||||
-define(ANSI_BG_RED, [?ANSI_ESC, "[41m"]).
|
||||
-define(ANSI_BG_GREEN, [?ANSI_ESC, "[42m"]).
|
||||
-define(ANSI_BG_YELLOW, [?ANSI_ESC, "[43m"]).
|
||||
-define(ANSI_BG_BLUE, [?ANSI_ESC, "[44m"]).
|
||||
-define(ANSI_BG_MAGENTA, [?ANSI_ESC, "[45m"]).
|
||||
-define(ANSI_BG_CYAN, [?ANSI_ESC, "[46m"]).
|
||||
-define(ANSI_BG_WHITE, [?ANSI_ESC, "[47m"]).
|
||||
|
||||
|
||||
-define(ANSI_FG_BLACK(X), [?ANSI_FG_BLACK, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_RED(X), [?ANSI_FG_RED, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_GREEN(X), [?ANSI_FG_GREEN, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_YELLOW(X), [?ANSI_FG_YELLOW, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BLUE(X), [?ANSI_FG_BLUE, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_MAGENTA(X), [?ANSI_FG_MAGENTA, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_CYAN(X), [?ANSI_FG_CYAN, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_WHITE(X), [?ANSI_FG_WHITE, X, ?ANSI_FG_RESET]).
|
||||
|
||||
-define(ANSI_BG_BLACK(X), [?ANSI_BG_BLACK, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_RED(X), [?ANSI_BG_RED, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_GREEN(X), [?ANSI_BG_GREEN, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_YELLOW(X), [?ANSI_BG_YELLOW, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BLUE(X), [?ANSI_BG_BLUE, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_MAGENTA(X), [?ANSI_BG_MAGENTA, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_CYAN(X), [?ANSI_BG_CYAN, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_WHITE(X), [?ANSI_BG_WHITE, X, ?ANSI_BG_RESET]).
|
||||
|
||||
% bright colors
|
||||
-define(ANSI_FG_BBLACK, [?ANSI_ESC, "[90m"]).
|
||||
-define(ANSI_FG_BRED, [?ANSI_ESC, "[91m"]).
|
||||
-define(ANSI_FG_BGREEN, [?ANSI_ESC, "[92m"]).
|
||||
-define(ANSI_FG_BYELLOW, [?ANSI_ESC, "[93m"]).
|
||||
-define(ANSI_FG_BBLUE, [?ANSI_ESC, "[94m"]).
|
||||
-define(ANSI_FG_BMAGENTA, [?ANSI_ESC, "[95m"]).
|
||||
-define(ANSI_FG_BCYAN, [?ANSI_ESC, "[96m"]).
|
||||
-define(ANSI_FG_BWHITE, [?ANSI_ESC, "[97m"]).
|
||||
|
||||
-define(ANSI_BG_BBLACK, [?ANSI_ESC, "[100m"]).
|
||||
-define(ANSI_BG_BRED, [?ANSI_ESC, "[101m"]).
|
||||
-define(ANSI_BG_BGREEN, [?ANSI_ESC, "[102m"]).
|
||||
-define(ANSI_BG_BYELLOW, [?ANSI_ESC, "[103m"]).
|
||||
-define(ANSI_BG_BBLUE, [?ANSI_ESC, "[104m"]).
|
||||
-define(ANSI_BG_BMAGENTA, [?ANSI_ESC, "[105m"]).
|
||||
-define(ANSI_BG_BCYAN, [?ANSI_ESC, "[106m"]).
|
||||
-define(ANSI_BG_BWHITE, [?ANSI_ESC, "[107m"]).
|
||||
|
||||
-define(ANSI_FG_BBLACK(X), [?ANSI_FG_BBLACK, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BRED(X), [?ANSI_FG_BRED, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BGREEN(X), [?ANSI_FG_BGREEN, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BYELLOW(X), [?ANSI_FG_BYELLOW, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BBLUE(X), [?ANSI_FG_BBLUE, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BMAGENTA(X), [?ANSI_FG_BMAGENTA, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BCYAN(X), [?ANSI_FG_BCYAN, X, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_FG_BWHITE(X), [?ANSI_FG_BWHITE, X, ?ANSI_FG_RESET]).
|
||||
|
||||
-define(ANSI_BG_BBLACK(X), [?ANSI_BG_BBLACK, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BRED(X), [?ANSI_BG_BRED, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BGREEN(X), [?ANSI_BG_BGREEN, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BYELLOW(X), [?ANSI_BG_BYELLOW, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BBLUE(X), [?ANSI_BG_BBLUE, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BMAGENTA(X), [?ANSI_BG_BMAGENTA, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BCYAN(X), [?ANSI_BG_BCYAN, X, ?ANSI_BG_RESET]).
|
||||
-define(ANSI_BG_BWHITE(X), [?ANSI_BG_BWHITE, X, ?ANSI_BG_RESET]).
|
||||
|
||||
-define(ANSI_FG_RGB(R,G,B),
|
||||
[?ANSI_ESC,
|
||||
"[38;2;",
|
||||
integer_to_list(R),";",
|
||||
integer_to_list(G),";",
|
||||
integer_to_list(B),"m"]
|
||||
).
|
||||
-define(ANSI_BG_RGB(R,G,B),
|
||||
[?ANSI_ESC,
|
||||
"[48;2;",
|
||||
integer_to_list(R),";",
|
||||
integer_to_list(G),";",
|
||||
integer_to_list(B),"m"]
|
||||
).
|
||||
|
||||
-define(ANSI_FG_RGB(R,G,B,Chars), [?ANSI_FG_RGB(R,G,B), Chars, ?ANSI_FG_RESET]).
|
||||
-define(ANSI_BG_RGB(R,G,B,Chars), [?ANSI_BG_RGB(R,G,B), Chars, ?ANSI_BG_RESET]).
|
||||
|
||||
|
||||
% cursor controls
|
||||
-define(ANSI_CUR_HOME, [?ANSI_ESC, "[H"]).
|
||||
|
||||
-define(ANSI_CUR_XY(X, Y), [?ANSI_ESC, "[", integer_to_list(Y), ";", integer_to_list(X), "H"]).
|
||||
-define(ANSI_CUR_UP(N), [?ANSI_ESC, "[", integer_to_list(N), "A"]).
|
||||
-define(ANSI_CUR_DOWN(N), [?ANSI_ESC, "[", integer_to_list(N), "B"]).
|
||||
-define(ANSI_CUR_RIGHT(N), [?ANSI_ESC, "[", integer_to_list(N), "C"]).
|
||||
-define(ANSI_CUR_LEFT(N), [?ANSI_ESC, "[", integer_to_list(N), "D"]).
|
||||
-define(ANSI_CUR_SAVE, [?ANSI_ESC, "7"]).
|
||||
-define(ANSI_CUR_RESTORE, [?ANSI_ESC, "8"]).
|
||||
-define(ANSI_CUR_QUERY, [?ANSI_ESC, "[6n"]).
|
||||
|
||||
-define(ANSI_CUR_UP, ?ANSI_CUR_UP(1)).
|
||||
-define(ANSI_CUR_DOWN, ?ANSI_CUR_DOWN(1)).
|
||||
-define(ANSI_CUR_RIGHT, ?ANSI_CUR_RIGHT(1)).
|
||||
-define(ANSI_CUR_LEFT, ?ANSI_CUR_LEFT(1)).
|
||||
|
||||
% aliases
|
||||
-define(ANSI_CURXY(X, Y), ?ANSI_CUR_XY(X, Y)).
|
||||
-define(ANSI_CUR_RC(R, C), ?ANSI_CUR_XY(C, R)).
|
||||
-define(ANSI_CURRC(R, C), ?ANSI_CUR_XY(C, R)).
|
||||
|
||||
|
||||
% relative movement "forward" +X=right, +Y=down
|
||||
-define(ANSI_CUR_VECT(X, Y),
|
||||
if X =< 0, Y =< 0 -> [?ANSI_CUR_LEFT(-1*X), ?ANSI_CUR_UP(-1*Y)];
|
||||
X =< 0, 0 < Y -> [?ANSI_CUR_LEFT(-1*X), ?ANSI_CUR_DOWN(Y)];
|
||||
0 < X, Y =< 0 -> [?ANSI_CUR_RIGHT(X), ?ANSI_CUR_UP(-1*Y)];
|
||||
0 < X, 0 < Y -> [?ANSI_CUR_RIGHT(X), ?ANSI_CUR_DOWN(Y)]
|
||||
end
|
||||
).
|
||||
|
||||
|
||||
-define(ANSI_ALTBUF, [?ANSI_ESC, "[?1049h"]).
|
||||
-define(ANSI_UNALTBUF, [?ANSI_ESC, "[?1049l"]).
|
||||
|
||||
-define(ANSI_CUR_INVIS, [?ANSI_ESC, "[?25l"]).
|
||||
-define(ANSI_CUR_VIS, [?ANSI_ESC, "[?25h"]).
|
||||
|
||||
-define(ANSI_WRAP, [?ANSI_ESC, "[=7h"]).
|
||||
-define(ANSI_NOWRAP, [?ANSI_ESC, "[=7l"]).
|
||||
|
||||
% XTERM control sequences.
|
||||
% References:
|
||||
% 1. `man xterm`
|
||||
% 2. Control sequences reference: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
% 3. Historical background: https://invisible-island.net/xterm/modified-keys.html
|
||||
%-define(XTERM_
|
||||
@@ -0,0 +1,20 @@
|
||||
% @doc echo server client
|
||||
-module(echoc).
|
||||
|
||||
-export([main/0]).
|
||||
|
||||
main() ->
|
||||
{ok, Socket} = gen_tcp:connect("localhost", 6969, [binary, {packet, 0}]),
|
||||
loop(Socket).
|
||||
|
||||
|
||||
loop(Socket) ->
|
||||
ok = inet:setopts(Socket, [{active, once}]),
|
||||
receive
|
||||
{tcp, Socket, Bytes} ->
|
||||
ok = io:format("< ~tp~n", [Bytes]),
|
||||
loop(Socket);
|
||||
{tcp_closed, Socket} ->
|
||||
ok = io:format("connection terminated~n", []),
|
||||
exit(normal)
|
||||
end.
|
||||
@@ -0,0 +1,249 @@
|
||||
%% @doc
|
||||
%% super simple telnet echo server daemon
|
||||
%%
|
||||
%% no noise yet
|
||||
%%
|
||||
%% pimps and hos model (from trash talk template):
|
||||
%%
|
||||
%% ```
|
||||
%% t_sup
|
||||
%% |
|
||||
%% t_clients
|
||||
%% |
|
||||
%% +--- t_client_man pimp
|
||||
%% |
|
||||
%% +--- t_client_sup bottom bitch
|
||||
%% |
|
||||
%% +--- <0.1.0> (t_client) ho
|
||||
%% +--- <0.2.0> (t_client) ho
|
||||
%% +--- <0.3.0> (t_client) ho
|
||||
%% '''
|
||||
%%
|
||||
%% each ho:
|
||||
%%
|
||||
%% <ul>
|
||||
%% <li>Takes listen socket as arg</li>
|
||||
%% <li>spawns next ho</li>
|
||||
%% </ul>
|
||||
%%
|
||||
%% ```
|
||||
%% start(ListenSocket) ->
|
||||
%% t_client_sup:start_acceptor(ListenSocket).
|
||||
%%
|
||||
%% start_link(ListenSocket) ->
|
||||
%% proc_lib:start_link(?MODULE, init, [self(), ListenSocket]).
|
||||
%%
|
||||
%% init(Parent, ListenSocket) ->
|
||||
%% ok = io:format("~p Listening.~n", [self()]),
|
||||
%% Debug = sys:debug_options([]),
|
||||
%% ok = proc_lib:init_ack(Parent, {ok, self()}),
|
||||
%% listen(Parent, Debug, ListenSocket).
|
||||
%%
|
||||
%% listen(Parent, Debug, ListenSocket) ->
|
||||
%% case gen_tcp:accept(ListenSocket) of
|
||||
%% {ok, Socket} ->
|
||||
%% {ok, _} = start(ListenSocket),
|
||||
%% {ok, Peer} = inet:peername(Socket),
|
||||
%% ok = io:format("~p Connection accepted from: ~p~n", [self(), Peer]),
|
||||
%% ok = t_client_man:enroll(),
|
||||
%% State = #s{socket = Socket},
|
||||
%% loop(Parent, Debug, State);
|
||||
%% {error, closed} ->
|
||||
%% ok = io:format("~p Retiring: Listen socket closed.~n", [self()]),
|
||||
%% exit(normal)
|
||||
%% end.
|
||||
%% '''
|
||||
%%
|
||||
%% @end
|
||||
-module(echod).
|
||||
|
||||
-include("./ansi.hrl").
|
||||
-export([main/0]).
|
||||
|
||||
|
||||
% ho from pimp pov
|
||||
-record(pho,
|
||||
{pid :: pid(),
|
||||
ref :: reference(),
|
||||
name :: string()}).
|
||||
|
||||
%% pimp state
|
||||
-record(ps,
|
||||
{lsock = none :: gen_tcp:socket(),
|
||||
hos = [] :: [#pho{}],
|
||||
ho_names = init_ho_names() :: [string()]}).
|
||||
|
||||
|
||||
%% ho state
|
||||
-record(hs,
|
||||
{name = none :: string(),
|
||||
daddy = none :: pid(),
|
||||
asock = none :: gen_tcp:socket()}).
|
||||
|
||||
|
||||
main() ->
|
||||
io:format("RBX example 2 telnet echo server daemon~n"
|
||||
"`one' part of the many-to-one relationship~n",
|
||||
[]),
|
||||
p_init().
|
||||
|
||||
|
||||
|
||||
% pimp process startup
|
||||
p_init() ->
|
||||
p_logln("pimp startup (p_init)"),
|
||||
Port = 6969,
|
||||
Opts = [binary, {packet, line}, {active, once}],
|
||||
case gen_tcp:listen(Port, Opts) of
|
||||
{ok, LSock} ->
|
||||
ok = p_logfln("pimp starting: ~tp", [self()]),
|
||||
PS_I = #ps{lsock = LSock},
|
||||
PS_II = p_spawn_ho(PS_I),
|
||||
p_loop(PS_II);
|
||||
{error, closed} ->
|
||||
%% dont be pimp
|
||||
p_logln("listen socket closed")
|
||||
end.
|
||||
|
||||
p_loop(PS = #ps{hos = Hos}) ->
|
||||
receive
|
||||
{ho, _HoPid, taken} ->
|
||||
NewPS = p_spawn_ho(PS),
|
||||
p_loop(NewPS);
|
||||
{ho, HoPid, sent, Data} ->
|
||||
HoName = p_ho_name(HoPid, PS),
|
||||
SendMessage = io_lib:format("~ts :: ~ts\r\n", [HoName, Data]),
|
||||
ok = p_echo_except(HoPid, HoName, SendMessage, Hos),
|
||||
p_loop(PS);
|
||||
Down = {'DOWN', _, _, _, _} ->
|
||||
NewPS = p_ho_down(Down, PS),
|
||||
p_loop(NewPS);
|
||||
Unknown ->
|
||||
ok = p_logfln("unknown message: ~tw", [Unknown]),
|
||||
p_loop(PS)
|
||||
end.
|
||||
|
||||
% given pid of ho, get her name
|
||||
p_ho_name(HoPid, #ps{hos = Hos}) ->
|
||||
case lists:keyfind(HoPid, #pho.pid, Hos) of
|
||||
#pho{name = Name} -> Name;
|
||||
false -> "JaneDoe"
|
||||
end.
|
||||
|
||||
% pimp spawns new ho
|
||||
p_spawn_ho(PS = #ps{lsock = LSock, hos = Hos, ho_names = Names}) ->
|
||||
% new name for ho, initial ho state
|
||||
{N, NewNames} = recycle(Names),
|
||||
InitHS = #hs{name = N, daddy = self()},
|
||||
% spawn the new ho
|
||||
ok = p_logfln("spawning new ho: ~ts", [N]),
|
||||
SpawnHo = fun() -> h_init(LSock, InitHS) end,
|
||||
{HPid, HRef} = erlang:spawn_monitor(SpawnHo),
|
||||
% new ho record from Pimp POV
|
||||
NewHo = #pho{pid = HPid, ref = HRef, name = N},
|
||||
ok = p_logfln("spawned new ho: ~tw", [NewHo]),
|
||||
NewPS = PS#ps{hos = [NewHo | Hos], ho_names = NewNames},
|
||||
NewPS.
|
||||
|
||||
% ho down, remove her from roster
|
||||
p_ho_down({'DOWN', _Ref, process, Pid, Info}, PS = #ps{hos = Hos}) ->
|
||||
ok = p_logfln("ho down: ~tp; reason: ~tw", [Pid, Info]),
|
||||
NewHos = lists:keydelete(Pid, #pho.pid, Hos),
|
||||
NewPS = PS#ps{hos = NewHos},
|
||||
NewPS.
|
||||
|
||||
|
||||
% echo message from one ho to all the rest
|
||||
% skip if equal
|
||||
p_echo_except(SrcPid, SrcName, Data, [#pho{pid = SrcPid} | Rest]) ->
|
||||
p_echo_except(SrcPid, SrcName, Data, Rest);
|
||||
p_echo_except(SrcPid, SrcName, Data, [#pho{pid = DstPid} | Rest]) ->
|
||||
DstPid ! {pimp, send, Data},
|
||||
p_echo_except(SrcPid, SrcName, Data, Rest);
|
||||
p_echo_except(_, _, _, []) ->
|
||||
ok.
|
||||
|
||||
%% runs in ho context
|
||||
h_init(LSock, HS = #hs{name = Name, daddy = Daddy, asock = none}) ->
|
||||
h_logln(Name, "h_init"),
|
||||
% this is key: accept needs to run in ho context, otherwise she
|
||||
% doesn't own the acceptor socket
|
||||
%
|
||||
% blocks until client connects
|
||||
case gen_tcp:accept(LSock) of
|
||||
{ok, ASock} ->
|
||||
h_logln(Name, "taken"),
|
||||
% tell daddy to spawn the next ho
|
||||
Daddy ! {ho, self(), taken},
|
||||
Welcome = io_lib:format("HI! I'm ~ts. What's your name?\r\n",
|
||||
[Name]),
|
||||
ok = h_send(Name, ASock, Welcome),
|
||||
HS_II = HS#hs{asock = ASock},
|
||||
h_loop(HS_II);
|
||||
{error, closed} ->
|
||||
h_logln(Name, "didn't get taken")
|
||||
end.
|
||||
|
||||
|
||||
h_loop(HS = #hs{name = Name, daddy = Daddy, asock = ASock}) ->
|
||||
ok = inet:setopts(ASock, [{active, once}]),
|
||||
receive
|
||||
{tcp, ASock, Data} ->
|
||||
Data_II = string:chomp(Data),
|
||||
ok = h_rcvd(Name, Data_II),
|
||||
Daddy ! {ho, self(), sent, Data_II},
|
||||
h_loop(HS);
|
||||
{pimp, send, Data} ->
|
||||
ok = h_send(Name, ASock, Data),
|
||||
h_loop(HS);
|
||||
{tcp_closed, ASock} ->
|
||||
exit(its_fine);
|
||||
Unknown ->
|
||||
ok = h_logfln(Name, "unknown message: ~tw", [Unknown]),
|
||||
h_loop(HS)
|
||||
end.
|
||||
|
||||
|
||||
% pimp log in bold
|
||||
p_logln(LogStr) ->
|
||||
Msg = io_lib:format("!! Daddy :: ~ts~n", [LogStr]),
|
||||
PimpChars = ?ANSI_BOLD([Msg]),
|
||||
io:put_chars(PimpChars).
|
||||
|
||||
p_logfln(LogStr, Args) ->
|
||||
p_logln(io_lib:format(LogStr, Args)).
|
||||
|
||||
|
||||
% ho log dimmed
|
||||
h_logln(HoName, LogStr) ->
|
||||
FMsg = io_lib:format("!! ~ts :: ~ts~n", [HoName, LogStr]),
|
||||
HoChars = ?ANSI_DIM([FMsg]),
|
||||
io:put_chars(HoChars).
|
||||
|
||||
h_logfln(HoName, MsgStr, Args) ->
|
||||
h_logln(HoName, io_lib:format(MsgStr, Args)).
|
||||
|
||||
% normal: john messages
|
||||
h_rcvd(Name, MsgStr) ->
|
||||
Msg = io_lib:format("<< ~ts :: ~ts~n", [Name, MsgStr]),
|
||||
io:put_chars(Msg).
|
||||
|
||||
h_send(Name, Socket, Msg) ->
|
||||
ok = io:format(">> ~ts :: ~ts~n", [Name, Msg]),
|
||||
gen_tcp:send(Socket, Msg).
|
||||
|
||||
|
||||
init_ho_names() ->
|
||||
["Crystal", "Tiffany", "Amber", "Brandy", "Lola", "Angel",
|
||||
"Ginger", "Candy", "Charity", "Anastasia", "Cherry", "Kitty",
|
||||
"Jade", "Destiny", "Devon", "Chastity", "Raven", "Scarlett",
|
||||
"Bambi", "Star", "Paris", "Dallas", "Diamond", "Skye",
|
||||
"Trinity", "Tawny", "Layla", "Lexie", "Roxy", "Porsche",
|
||||
"Nevaeh", "Ashlynn", "Aspen", "Chyna", "Lexus", "Unique",
|
||||
"Chardonnay", "Houston", "London", "Coco", "Luscious",
|
||||
"Delight", "Capri", "Trixie", "Cinnamon"].
|
||||
|
||||
|
||||
|
||||
recycle([N | Ns]) ->
|
||||
{N, Ns ++ [N]}.
|
||||
@@ -0,0 +1,86 @@
|
||||
1. Liam
|
||||
2. Noah
|
||||
3. Oliver
|
||||
4. Theodore
|
||||
5. Henry
|
||||
6. James
|
||||
7. Elijah
|
||||
8. Mateo
|
||||
9. William
|
||||
10. Lucas
|
||||
11. Benjamin
|
||||
12. Levi
|
||||
13. Elias
|
||||
14. Luca
|
||||
15. Jack
|
||||
16. Sebastian
|
||||
17. Hudson
|
||||
18. Samuel
|
||||
19. Leo
|
||||
20. Ezra
|
||||
21. Michael
|
||||
22. Daniel
|
||||
23. John
|
||||
24. Ethan
|
||||
25. Julian
|
||||
26. Santiago
|
||||
27. Cooper
|
||||
28. Asher
|
||||
29. Joseph
|
||||
30. Alexander
|
||||
31. Owen
|
||||
32. Matthew
|
||||
33. Luke
|
||||
34. Thomas
|
||||
35. David
|
||||
|
||||
36. Jackson
|
||||
|
||||
37. Gabriel
|
||||
|
||||
38. Wyatt
|
||||
|
||||
39. Mason
|
||||
|
||||
40. Bennett
|
||||
|
||||
41. Dylan
|
||||
|
||||
42. Roman
|
||||
|
||||
43. Jacob
|
||||
|
||||
44. Miles
|
||||
|
||||
45. Carter
|
||||
|
||||
46. Anthony
|
||||
|
||||
47. Isaac
|
||||
|
||||
48. Charles
|
||||
|
||||
49. Maverick
|
||||
|
||||
50. Thiago
|
||||
|
||||
51. Grayson
|
||||
|
||||
52. Wesley
|
||||
|
||||
53. Logan
|
||||
|
||||
54. Josiah
|
||||
|
||||
55. Weston
|
||||
|
||||
56. Waylon
|
||||
|
||||
57. Isaiah
|
||||
|
||||
58. Caleb
|
||||
|
||||
59. Rowan
|
||||
|
||||
60. Beau
|
||||
61. Ezekiel
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
Alexander
|
||||
Anthony
|
||||
Asher
|
||||
Beau
|
||||
Benjamin
|
||||
Bennett
|
||||
Caleb
|
||||
Carter
|
||||
Charles
|
||||
Cooper
|
||||
Daniel
|
||||
David
|
||||
Dylan
|
||||
Elias
|
||||
Elijah
|
||||
Ethan
|
||||
Ezekiel
|
||||
Ezra
|
||||
Gabriel
|
||||
Grayson
|
||||
Henry
|
||||
Hudson
|
||||
Isaac
|
||||
Isaiah
|
||||
Jack
|
||||
Jackson
|
||||
Jacob
|
||||
James
|
||||
John
|
||||
Joseph
|
||||
Josiah
|
||||
Julian
|
||||
Leo
|
||||
Levi
|
||||
Liam
|
||||
Logan
|
||||
Luca
|
||||
Lucas
|
||||
Luke
|
||||
Mason
|
||||
Mateo
|
||||
Matthew
|
||||
Maverick
|
||||
Michael
|
||||
Miles
|
||||
Noah
|
||||
Oliver
|
||||
Owen
|
||||
Roman
|
||||
Rowan
|
||||
Samuel
|
||||
Santiago
|
||||
Sebastian
|
||||
Theodore
|
||||
Thiago
|
||||
Thomas
|
||||
Waylon
|
||||
Wesley
|
||||
Weston
|
||||
William
|
||||
Wyatt
|
||||
@@ -0,0 +1,126 @@
|
||||
#1: Crystal
|
||||
#2: Tiffany
|
||||
#3: Amber
|
||||
#4: Brandy
|
||||
#5: Lola
|
||||
#6: Angel
|
||||
#7: Ginger
|
||||
#8: Candy
|
||||
#9: Charity
|
||||
#10: Anastasia
|
||||
#11: Cherry
|
||||
#12: Kitty
|
||||
#13: Jade
|
||||
#14: Destiny
|
||||
#15: Devon
|
||||
#16: Chastity
|
||||
#17: Raven
|
||||
|
||||
Raven means "black-haired," and propelled to popularity in 1980, sitting among the top 600 most favored names for girls. It reached its peak in 1997 in the top 200, but dropped back to the top 600 most-liked names for girls by 2012.Ranked 1,358 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#18: Scarlett
|
||||
|
||||
It has been said that Scarlett, which means "red," was popularized as a name because of the relentless Southern belle protagonist in Margaret Mitchell's "Gone With the Wind." In 1993, it breached the top 1000 most popular names for girls, and as of 2012, it's among the top 50 most popular names. Ranked 1,496 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#19: Bambi
|
||||
|
||||
In 1942, Disney released its classic animated flick about a precious deer name Bambi. During that time, Bambi-- of Italian origin--ranked among the top 900 names for females, and later fell out of favor in the 1980s.Ranked 1,554 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#20: Star
|
||||
|
||||
From 1997-1998, Star skyrocketed in popularity for girls names, ranking among the top 900 most common. Ranked 1,890 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#21: ParisParis, popular as name for both girls and boys, became in vogue in US in the 1980s. It peaked in 2004--a year after Paris Hilton's "The Simple Life" made the sex tape star and socialite a household name-and ranked among the top 200 most popular names for girls.Ranked 2,006 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#22: Dallas
|
||||
|
||||
Meaning "from the dales, the valley meadows," in 1996 the name Dallas ranked among the top 500 most common names for girls. By 2000 it grew out of favor and ranked in the top 900, eventually dropping off the top 1000 most common names for girls until 2012 when it reclaimed its same spot from nearly 14 years ago. Ranked 2,167 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#23: Diamond
|
||||
|
||||
Meaning "of high value or brilliant," the name Diamond reached its height of popularity in 1998, ranking among the top 200 most popular names for females, but it steadily declined, barreling to the top 800 most popular names in 2012.Ranked 2,283 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#24: Skye
|
||||
|
||||
In 1981 Skye catapulted into the top 700 most popular names for girls. It later reached its height in 2004 when it skyrocketed among the top 400 most common names for girls. Ranked 2,353 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#25: Trinity
|
||||
|
||||
Trinity, meaning "union of three," started becoming a popular name for girls in the 1990s, where it started among the top 900 and climbed to the top 25 in 2004. In 2012 it ranked in the top 100 most common names.Ranked 2,406 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#26: Tawny
|
||||
|
||||
Meaning "a green field; golden brown," of English origin, the name hit its peak in popularity during the 1980s but has since gone out of fashion. Ranked 2,438 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#27: Layla
|
||||
|
||||
In Arabic, Layla means "night beauty" and in Hebrew, short for Delilah, it means "seductive." In 2012, Layla ranked among the top 50 most popular names for girls.Ranked 2,609 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#28: Lexie
|
||||
|
||||
Lexie, diminutive of Alexandra, means "man's defender." It became a mainstream name in 1890 amid the 900 most popular names for girls. In 1910 it fell out of favor, but it saw resurgence in 1994. In 2012 it was among the top 600 most popular names for girls.Ranked 3,029 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#29: Roxy
|
||||
|
||||
Roxy is short for Roxanne, and means "dawn." It catapulted to popularity in the 1880s among the top 900 most popular names for girls, but hasn't been mainstream since that time.Ranked 3,061 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
|
||||
#30: PorschePorsche (variations include Portia and Porsha) never quite took off in popularity as a girl's name as fast as the pricey car. Ranked 3,776 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
|
||||
#31: Nevaeh
|
||||
|
||||
Nevaeh, which is "Heaven" spelled backward, became popular in 2000 and has skyrocketed to one of the top 50 most popular names for girls in 2012.Source
|
||||
|
||||
#32: Ashlynn
|
||||
|
||||
A combination of Ashley and Lynn, in the past 20 years, Ashlynn has been a favorite name for girls and now ranks among the top 300 most common names, according to US Census 2000 data. The name means "dream."Ranked lower than 4,276 of the most popular names for all girls (1880-2012). Source
|
||||
|
||||
#33: Aspen
|
||||
|
||||
Aspen, named after the cheap drugstore cologne and the beautiful, hip resort town in Colorado, grew in popularity as a female name in 1994, ranking among the top 700. In 2012 it was one of the top 500 names for girls.Ranked lower than 4,276 of the most popular names for all girls (1880-2012). Source
|
||||
|
||||
#34: Chyna
|
||||
|
||||
Chyna, referring to the country China, became popular in 1994 and peaked in1999 as one of the top 500 most popular names for girls. Three years later, it dwindled off the top 1000 chart. Ranked lower than 4,276 of the most popular names for all girls (1880-2012).Source
|
||||
|
||||
#35: Lexus
|
||||
|
||||
Lexus, a variation of Alexis and Alexandra, means "man's defender." It reached the top 500 most popular names for girls in the mid-1990s, but grew out of favor by 2000, eventually dropping off the top 1000 chart in 2004.Ranked lower than 4,276 of the most popular names for all girls (1880-2012). Source
|
||||
|
||||
#36: Unique
|
||||
|
||||
In Latin, Unique means "only one" and began to rise in popularity in 1994, reaching its peak a year later as one of the top 800 most popular names for girls. Ranked lower than 4,276 of the most popular names for all girls (1880-2012).Source
|
||||
|
||||
#37: Chardonnay
|
||||
|
||||
Although not particularly a common name in the US, Chardonnay--which is a type of wine--rose to popularity as a girl's name from 2001-2003 in the UK based on the character Chardonnay Lane-Pascoe from the hit TV series "Footballers' Wives."Ranked lower than 4,276 of the most popular names for all girls (1880-2012). Source
|
||||
|
||||
#38: Houston
|
||||
|
||||
In 1836, the US's now-fourth largest city was settled and named after Texan General Sam Houston. Houston has been a popular first name for boys since 1880, but has never been a hit name for girls. Ranked lower than 4,276 of the most popular names for all girls (1880-2012).
|
||||
|
||||
#39: London
|
||||
|
||||
London, named after England's capital, has recently surged as a popular nom de guerre for strippers.Ranked lower than 4,276 of the most popular names for all girls (1880-2012).
|
||||
|
||||
#40: Coco
|
||||
|
||||
You'll probably hear of only three Cocos in your life: Coco Chanel, Coco Puffs, and Coco at the Cheetah Club. Short for Nicolette, the name is of French origin and has not been a popular American name.Ranked lower than 4,276 of the most popular names for all girls (1880-2012). Source
|
||||
|
||||
#41: Luscious
|
||||
|
||||
According to Dictionary.com, one of the definitions of the name means "arousing physical, or sexual, desire; voluptuous." It is not a common name for girls, but a popular alias in the adult industry. Ranked lower than 4,276 of the most popular names for all girls (1880-2012).
|
||||
|
||||
#42: Delight
|
||||
|
||||
Never a common name for girls, Delight is of French origin and means "something that gives great pleasure," according to Dictionary.com.Ranked lower than 4,276 of the most popular names for all girls (1880-2012). Source
|
||||
|
||||
#43: Capri
|
||||
|
||||
Named after the pristine Italian island, the name isn't common in the US. Capri is also short for Caprice, who, if you know anything about the international glamour model Caprice Bourret, is as close to a stripper as you can get. Ranked lower than 4,276 of the most popular names for all girls (1880-2012).Source
|
||||
|
||||
#44: Trixie
|
||||
|
||||
A variation of the name Beatrix, which means "voyager" (through life) or "blessed" in Latin, Trixie has never been a popular name but has surged as an alias in the adult industry.Ranked lower than 4,276 of the most popular names for all girls (1880-2012).Source
|
||||
|
||||
#45: Cinnamon
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#1: Crystal
|
||||
#2: Tiffany
|
||||
#3: Amber
|
||||
#4: Brandy
|
||||
#5: Lola
|
||||
#6: Angel
|
||||
#7: Ginger
|
||||
#8: Candy
|
||||
#9: Charity
|
||||
#10: Anastasia
|
||||
#11: Cherry
|
||||
#12: Kitty
|
||||
#13: Jade
|
||||
#14: Destiny
|
||||
#15: Devon
|
||||
#16: Chastity
|
||||
#17: Raven
|
||||
#18: Scarlett
|
||||
#19: Bambi
|
||||
#20: Star
|
||||
#21: ParisParis, popular as name for both girls and boys, became in vogue in US in the 1980s. It peaked in 2004--a year after Paris Hilton's "The Simple Life" made the sex tape star and socialite a household name-and ranked among the top 200 most popular names for girls.Ranked 2,006 out of 4,276 most popular names for all girls (1880-2012). Source
|
||||
#22: Dallas
|
||||
#23: Diamond
|
||||
#24: Skye
|
||||
#25: Trinity
|
||||
#26: Tawny
|
||||
#27: Layla
|
||||
#28: Lexie
|
||||
#29: Roxy
|
||||
#30: PorschePorsche (variations include Portia and Porsha) never quite took off in popularity as a girl's name as fast as the pricey car. Ranked 3,776 out of 4,276 most popular names for all girls (1880-2012).Source
|
||||
#31: Nevaeh
|
||||
#32: Ashlynn
|
||||
#33: Aspen
|
||||
#34: Chyna
|
||||
#35: Lexus
|
||||
#36: Unique
|
||||
#37: Chardonnay
|
||||
#38: Houston
|
||||
#39: London
|
||||
#40: Coco
|
||||
#41: Luscious
|
||||
#42: Delight
|
||||
#43: Capri
|
||||
#44: Trixie
|
||||
#45: Cinnamon
|
||||
@@ -0,0 +1,45 @@
|
||||
Crystal
|
||||
Tiffany
|
||||
Amber
|
||||
Brandy
|
||||
Lola
|
||||
Angel
|
||||
Ginger
|
||||
Candy
|
||||
Charity
|
||||
Anastasia
|
||||
Cherry
|
||||
Kitty
|
||||
Jade
|
||||
Destiny
|
||||
Devon
|
||||
Chastity
|
||||
Raven
|
||||
Scarlett
|
||||
Bambi
|
||||
Star
|
||||
ParisParis,
|
||||
Dallas
|
||||
Diamond
|
||||
Skye
|
||||
Trinity
|
||||
Tawny
|
||||
Layla
|
||||
Lexie
|
||||
Roxy
|
||||
PorschePorsche
|
||||
Nevaeh
|
||||
Ashlynn
|
||||
Aspen
|
||||
Chyna
|
||||
Lexus
|
||||
Unique
|
||||
Chardonnay
|
||||
Houston
|
||||
London
|
||||
Coco
|
||||
Luscious
|
||||
Delight
|
||||
Capri
|
||||
Trixie
|
||||
Cinnamon
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
liquidate_hos([{HoPid, _HoRef} | Hos]) ->
|
||||
p_logfln("liquidating ~tp", [HoPid]),
|
||||
exit(HoPid, kill),
|
||||
liquidate_hos(Hos);
|
||||
liquidate_hos([]) ->
|
||||
p_logln("it's done").
|
||||
|
||||
|
||||
Reference in New Issue
Block a user