📄 proxy.erl.svn-base
字号:
-module(proxy).-export([inicio/3, inicio/6]).%%-----------------------------------------------------------------------------%% proxy maldito que pierde o retrasa paquetes%%-----------------------------------------------------------------------------%%%% uso:%% erl -eval ' proxy2:inicio(Puerto, Forwards, Rangos). '%%%% donde:%%%% Forwars: lista de pares de host donde redirigir%% ejemplo: [{host1, host2, puerto}, {host2, host1, puerto}]%% redirigir desde host1 a host2, y de host 2 a host1%% host pueden ser: nombre de maquina o ip entre ""%% %% Rangos: lista de pares de {Porcentaje, Tiempo}%% ejemplo: [{0.1, 100}, {0.2, 10}, {0.1, inf}]%% significa:%% 10% de los paquetes se retrasa 100 msec%% 20% de los paquetes se retrasa 10 msec%% 10% de los paquetes se retrasa inf-initamente, o sea se botan%% el resto se entrega directamente%% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!%% uso para solo drop:%%%% proxy2:inicio(PuertoEscuchando, Host1, Port1, Host2, Port2, TasaDrop).%%%% asi los paquetes que reciba desde Host1 los pasa a Host2:Port2%% y los de Host2 a Host1:Port1, TasaDrop es la tasa de paquetes botados%%%%-----------------------------------------------------------------------------%%-----------------------------------------------------------------------------%% mecanismo:%%%% los Rangos, formados por {Porcentaje, Tiempo} se deben transformar en%% Retardos (no supe como llamarlos) que son {Cota_inferior, Tiempo}.%%%% cuando llega un paquete, el sistema sortea un numero de 1 a 100, y empieza%% a revisar esta tabla de {Cota_inferior, Tiempo}:%%%% si el numero es >= que Cota_inferior ->%% el paquete es reenviado con Tiempo msec de retraso%%%% si el numero es menor que todas las Cota_inferior ->%% el paquete se descarta%%-----------------------------------------------------------------------------%%-----------------------------------------------------------------------------%% el MAIN%%-----------------------------------------------------------------------------inicio(Puerto, Forwards, Rangos) -> %% primero convertir los hosts de Forwards a IP canonicas %% 127.0.0.1 -> {127, 0, 0, 1} ForwardsArreglados = lists:map(fun ({IP_from, IP_to, Port}) -> {ok, IP1} = inet:getaddr(IP_from, inet), {ok, IP2} = inet:getaddr(IP_to, inet), {IP1, IP2, Port} end, Forwards), Retardos = rangos_a_retardos(Rangos), imprime_datos(Puerto, ForwardsArreglados, Retardos), {ok, Socket} = gen_udp:open(Puerto, [binary]), [R1, R2, R3 | _] = os:cmd("dd if=/dev/random count=1"), random:seed(R1, R2, R3), ciclo(Socket, ForwardsArreglados, Retardos).inicio(_, _, _, _, _, TasaDrop) when TasaDrop > 1; TasaDrop < 0 -> io:format("Error, TasaDrop debe estar entre 0 y 1~n"), error;inicio(Puerto_escuchando, Host1, Port1, Host2, Port2, Tasa_Drop) -> Fwd = [{Host1, Host2, Port2} ,{Host2, Host1, Port1}], Rangos = [{Tasa_Drop, inf}], inicio(Puerto_escuchando, Fwd, Rangos).%------------------------------------------------------------------------------%------------------------------------------------------------------------------% porcentaje minimo:% busca en Rangos el procentaje asociado a 'inf' (paquetes que son descartados)% este porcentaje sirve para armar la tabla de Retardos, % es la Cota_inferior minima (queda al final de la tabla)%------------------------------------------------------------------------------p_minimo([]) -> 0;p_minimo([{Porcentaje , inf} | _]) -> Porcentaje;p_minimo([_ | Resto]) -> p_minimo(Resto).% %% otra forma:%%p_minimo(L) ->% case lists:keysearch(inf, 2, L) of% {value {Porcentaje, _}} ->% Porcentaje;% false ->% 0% end.%------------------------------------------------------------------------------%-------------------------------------------------------------------------------% convertir Rangos a Retardos% se parte con el procentaje de paquetes descartados como base% en cada iteracion se suma el procentaje%-------------------------------------------------------------------------------% si Rangos esta vacio, la cota inferior es 0% o sea desde 1 al 100 -> 0 retardorangos_a_retardos([]) -> [{0, 0}];% para partir:% RetardosListos = []% cita-inferior = porcentaje minimorangos_a_retardos(Rangos) -> rangos_a_retardos(Rangos, [], 100 * p_minimo(Rangos)).rangos_a_retardos([], RetardosListos, Cota_inferior) -> [{Cota_inferior, 0}] ++ RetardosListos;% nos saltamos el porcentaje asociado a inf (ya lo usamos en p_minimo())rangos_a_retardos([{_, inf}| Resto] , RetardosListos, Cota_inferior) -> rangos_a_retardos(Resto, RetardosListos, Cota_inferior);rangos_a_retardos([{Porcentaje, Tiempo} | Resto], RetardosListos, Cota_inferior) -> rangos_a_retardos(Resto, [{Cota_inferior, Tiempo}] ++ RetardosListos, Cota_inferior + (100 * Porcentaje)).%-------------------------------------------------------------------------------%-------------------------------------------------------------------------------% Busca en Retardos el Tiempo que corresponde al numero N%-------------------------------------------------------------------------------ver_retardo(_, []) -> drop;ver_retardo(N, [{Cota_minima, Retardo} | _]) when N >= Cota_minima -> Retardo; ver_retardo(N, [_ | Resto]) -> ver_retardo(N, Resto).%-------------------------------------------------------------------------------%-------------------------------------------------------------------------------% enviar un paquete con Data hacia IP:Puerto, tras Retardo msec% para retardos > 0, se lanza un proceso que espera el tiempo, manda el paquete% y termina.%-------------------------------------------------------------------------------enviar_retardado(Socket, Puerto, IP_destino, Data, 0) -> gen_udp:send(Socket, IP_destino, Puerto, Data);enviar_retardado(Socket, Puerto, IP_destino, Data, Retardo) -> spawn(fun() -> receive after Retardo -> gen_udp:send(Socket, IP_destino, Puerto, Data) end end).%-------------------------------------------------------------------------------%-------------------------------------------------------------------------------% ciclo principal de recibir y despachar paquetes%-------------------------------------------------------------------------------ciclo(Socket, Forwards, Retardos) -> receive {udp, Socket, IP_from, _, Data} -> io:format("~p ", [IP_from]), N = random:uniform(100), case ver_retardo(N, Retardos) of drop -> io:format(" drop~n"), ciclo(Socket, Forwards, Retardos); R -> case lists:keysearch(IP_from, 1, Forwards) of {value, {IP_from, IP_to, Puerto}} -> io:format(" --> ~p:~p retardo: ~p~n", [IP_to, Puerto, R]), enviar_retardado(Socket, Puerto, IP_to, Data, R), ciclo(Socket, Forwards, Retardos); _ -> io:format(" discard~n"), ciclo(Socket, Forwards, Retardos) end end; _ -> ciclo(Socket, Forwards, Retardos) end.%--------------------------------------------------------------------------------%--------------------------------------------------------------------------------% funcion para imprimir los datos de entrada%--------------------------------------------------------------------------------imprime_datos(Puerto, Forwards, Retardos) -> io:format("puerto escuhando: ~p~n", [Puerto]), io:format("forwards:~n"), lists:foreach(fun({IP_from, IP_to, Port}) -> io:format(" ~p -> ~p:~p~n", [IP_from, IP_to, Port]) end, Forwards), io:format("retardos:~n"), N = lists:foldl(fun({Numero, Retardo}, NumeroAnterior) -> Porcentaje = NumeroAnterior - Numero, io:format("~p...~p | ~p msec --> ~p%~n", [NumeroAnterior, Numero, Retardo, Porcentaje]), Numero end, 100, Retardos), io:format("\tn < ~p --> drop~n", [N]).%---------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -