Erlang - Lista 4.

Zadanie 2.

#!/usr/bin/env escript
 
main(_) ->
    case io:get_line("") of
        eof -> {error, read_error};
        {error, Reason} -> {error, read_error, Reason};
        Input -> analyze(hd_to_binary(Input))
    end.
 
hd_to_binary(HD) -> hd_to_binary(HD, []).
 
hd_to_binary("\n", Acc) ->
    list_to_binary(lists:reverse(Acc));
hd_to_binary([X,Y|HD], Acc) ->
    {ok, [V], []} = io_lib:fread("~16u", [X,Y]),
    hd_to_binary(HD, [V | Acc]).
 
binary_to_hd(Bin) ->
    lists:flatten([io_lib:format("~2.16.0B", [X]) ||
        X <- binary_to_list(Bin)]).
 
icmp(Payload) ->
	case Payload of
		<< ToM: 8, Code: 8, Checksum: 16, Quench: 32, Data/binary>> ->
		Sum = chksum(<< ToM:8, Code:8, 0:16, Quench: 32, Data/binary>>),
		io:format("\nICMP:\n\nType of message:\t0x~.16B (~s)\nCode:\t\t\t0x~.16B\nChecksum:\t\t0x~.16B (calculated: 0x~.16B)\nQuench:\t\t\t~.16B\nData:\t\t\t~s\n", [ToM, icmp_type(ToM), Code, Checksum, Sum, Quench, binary_to_hd(Data)]);
		_ -> {error}
	end.
 
udp(DGram, IP) ->
	case DGram of
		<< SPort: 16, DPort: 16, Len: 16, Checksum:16, Data/binary>> ->
			Sum = chksum(<< IP/binary, SPort:16, DPort:16, Len:16, 0:16, Data/binary>>),
			io:format("\nUDP:\n\nSource port:\t\t0x~.16B (~B)\nDestination port:\t0x~.16B (~B)\nLen:\t\t\t~B\nChecksum:\t\t0x~.16B (calculated: 0x~.16B)\nData:\t\t\t~s\n", [SPort, SPort, DPort, DPort, Len, Checksum, Sum, binary_to_hd(Data)]);
		_ -> {error}
	end.
 
tcp(Segment, SAddr, DAddr) ->
	case Segment of
		<< SPort: 16, DPort: 16, Seq: 32, Ack: 32, DataOff: 4, Reserved: 4, CWR:1, ECE:1, URG:1, ACK:1, PSH:1, RST:1, SYN:1, FIN:1, WindowSize: 16, Checksum: 16, UrgentPointer: 16, Data/binary>> ->
		SegSize = byte_size(Segment),
		Sum = chksum(<< SAddr:32, DAddr:32, 0:8, 6:8, SegSize:16, SPort: 16, DPort: 16, Seq: 32, Ack: 32, DataOff: 4, Reserved: 4, CWR:1, ECE:1, URG:1, ACK:1, PSH:1, RST:1, SYN:1, FIN:1, WindowSize: 16, 0:16, UrgentPointer:16, Data/binary>>),
		io:format("\nTCP:\n\nSource port:\t\t0x~.16B (~B)\nDestination port:\t0x~.16B (~B)\nSequence number:\t~B\nAck number:\t\t~B\nData offset:\t\t0x~.16B\nFlags:\t\t\tCWR: ~B ECE: ~B URG: ~B ACK: ~B PSH: ~B RST: ~B SYN: ~B FIN: ~B\nWindow size:\t\t0x~.16B\nChecksum:\t\t0x~.16B (calculated: 0x~.16B)\nUrgent pointer:\t\t~.16B\nData:\t\t\t~s\n", [SPort, SPort, DPort, DPort, Seq, Ack, DataOff, CWR, ECE, URG, ACK, PSH, RST, SYN, FIN, WindowSize, Checksum, Sum, UrgentPointer, binary_to_hd(Data)]);
		_ -> {error}
	end.
analyze(Dgram) ->
    DgramSize = byte_size(Dgram),
    case Dgram of
        << 4:4, HLen:4, SrvcType:8, TotLen:16,
        ID:16, Flgs:3, FragOff:13, TTL:8,
        Proto:8, HdrChkSum:16, SrcIP:32, DestIP:32,
        RestDgram/binary>>
% when HLen >= 5, 4*HLen=<DgramSize
        ->
            OptsLen = 4*(HLen - 5),
            <<Opts:OptsLen/binary, Data/binary>> = RestDgram,
            CRC = chksum(<< 4:4, HLen:4, SrvcType:8, TotLen:16, ID:16, Flgs:3, FragOff:13, TTL:8, Proto:8, 0:16, SrcIP:32, DestIP:32, Opts:OptsLen>>),
            io:format("IP version:\t\t4\nHeader length:\t\t~B\nService type:\t\t~B\nTotal length:\t\t~B (calculated: ~B)\nID:\t\t\t0x~.16B\nFlags:\t\t\t0x~.16B\nFragment offset:\t~B\nTTL:\t\t\t~B\nProtocol:\t\t0x~.16B (~s)\nHeader checksum:\t0x~.16B (calculated: 0x~.16B)\nSource address:\t\t0x~.16B (~s)\nDestination address:\t0x~.16B (~s)\nData:\t\t\t~s\n", [HLen, SrvcType, TotLen, DgramSize, ID, Flgs, FragOff, TTL, Proto, proto(Proto), HdrChkSum, CRC, SrcIP, hex_to_ip(SrcIP), DestIP, hex_to_ip(DestIP), binary_to_hd(Data)]),
			if
				Proto == 1 -> icmp(Data);
				Proto == 6 -> tcp(Data, SrcIP, DestIP);
				Proto == 17 -> DSize = byte_size(Data), udp(Data, <<SrcIP:32, DestIP:32, 0:8, 17:8, DSize:16>>);
				true -> io:format("")
			end;
 
 
    _ -> io:format("Not an IP packet\n")
    end.
 
hex_to_ip(H) ->
    X = << H:32 >>,
    << A:8, B:8, C:8, D:8 >> = X,
    io_lib:format("~B.~B.~B.~B", [A,B,C,D]).
 
proto(P) ->
    Protos = [
        {1, "ICMP"},
        {3, "GGP"},
        {6, "TCP"},
        {17, "UDP"}
    ],
    case lists:keyfind(P, 1, Protos) of
        false -> "Unknown";
        {_, Proto} -> Proto
    end.
icmp_type(P) ->
    Types = [
        {0, "Echo reply"},
        {1, "Reserved"},
        {3, "Destination unreachable"},
        {8, "Echo request"}
    ],
    case lists:keyfind(P, 1, Types) of
        false -> "Unknown";
        {_, Proto} -> Proto
    end.
 
chksum(H) -> chksum(H, 0).
chksum(<<>>, Acc) -> (bnot (Acc + (Acc bsr 16)) band 65535);
chksum(<<A:8>>, Acc) -> chksum(<<A:8, 0:8>>, Acc);
chksum(<<A:8, B:8, C/binary>>, Acc) ->
    chksum(C, Acc+B+(A bsl 8)).

Zadanie 3.

-module(zad3).
-export([create/1, insert/2, select/2, select/3, delete/2, update/3, update/4]).
 
-record(db, {recordname, fields, auto_id, data}).
 
% test:
% rd(x, {y,z}).     
%{db,a, [y,z], 4, [{1,#x{y = 1,z = 2}}, {2,#x{y = undefined,z = undefined}}, {3,#x{y = 5,z = 5}}]}
 
create({RecordName, Fields}) ->
    {ok, #db{recordname=RecordName, fields=Fields, auto_id=1, data=[]}}.
 
insert(Db, Record) ->
    Id = Db#db.auto_id,
    NewData = [{Id,Record}|Db#db.data],
    {ok, Id, Db#db{auto_id=Id+1, data=NewData}}.
 
select(Db, Pred) ->
    try
        Result = lists:filter(fun ({_,Record}) -> Pred(Record) end, Db#db.data),
        {ok, Result}
    catch
        _:_ -> {error, bad_query}
    end.
 
select(Db, Pred, Field) ->
    try
        N = field(Field, Db#db.fields),
        Result = lists:filter(fun ({_,Record}) -> Pred(element(N,Record)) end, Db#db.data),
        {ok, Result}
    catch
        _:_ -> {error, bad_query}
    end.
 
field(Field, Fields) ->
    field(Field, Fields, 2).
 
field(_, [], _) -> {error, not_found};
field(Field, [H|L], N) ->
    if
        Field == H -> N;
        true -> field(Field, L, N+1)
    end.
 
delete(Db, Pred) ->
try
    {Sat, NSat} = lists:partition(fun ({_,Record}) -> Pred(Record) end, Db#db.data),
    {ok, Db#db{data=NSat}, Sat}
catch
    _:_ -> {error, bad_query}
end.
 
update(Db, Pred, F) ->
    try
        {Sat, NSat} = lists:partition(fun ({_,Record}) -> Pred(Record) end, Db#db.data),
        try
            ModSat = lists:map(fun ({Id, Record}) -> {Id, F(Record)} end, Sat),
            {ok, Db#db{data=ModSat++NSat}, ModSat}
        catch
            _:_ -> {error, bad_updater}
        end
    catch
        _:_ -> {error, bad_query}
    end.
update(Db, Pred, F, Field) -> 
    N = field(Field, Db#db.fields),
    update(Db,
        fun(P) -> Pred(element(N, P)) end,
        fun(P) -> setelement(N, P, F(element(N, P))) end
    ).
 
kurs_jezyka_erlang/10.lista04.txt · ostatnio zmienione: 2010/03/30 21:41 przez drx
 
Wszystkie treści w tym wiki, którym nie przyporządkowano licencji, podlegają licencji:MIT License
Recent changes RSS feed