anchor.diff:          Window:16/big,
           Csum:16/big, UrgPointer:16/big,
           Data/binary>> = Pkt,
  -       [IPH = #ipv4_pseudo_hdr{} | DecodeOpts]) ->
  -    HeaderLen = 4*DataOffset,
  +       [IPH = #ipv4_pseudo_hdr{} | _DecodeOpts]) ->
  +    HeaderLen = ?TCP_OPTS_ALIGNMENT*DataOffset,
       OptsLen = HeaderLen - ?TCP_HEADER_MIN_LEN,
  -    << _Header:20/binary,
  -     Options:OptsLen/binary,
  -     TcpData/binary>> = Pkt,
  -    Tcp = #tcp{src_port=decode_port(Src)
  -               ,dst_port=decode_port(Dst)
  -               ,seq_no=Sequence
  -               ,ack_no=Ack
  -               ,data_offset=DataOffset
  -               ,reserved=Reserved
  -               ,urg=decode_flag(Urg), ack=decode_flag(Ack), psh=decode_flag(Psh)
  -               ,rst=decode_flag(Rst), syn=decode_flag(Syn), fin=decode_flag(Fin)
  -               ,window=Window
  -               ,csum=check_sum(Csum, IPH, byte_size(Pkt), Pkt)
  -               ,urg_pointer=UrgPointer
  -               ,options=decode_options(Options)
  -               ,data=TcpData
  -              };
  +    <<Options:OptsLen/binary,
  +      TcpData/binary>> = Data,
  +    #tcp{src_port=decode_port(Src)
  +         ,dst_port=decode_port(Dst)
  +         ,seq_no=Sequence
  +         ,ack_no=Ack
  +         ,data_offset=DataOffset
  +         ,reserved=Reserved
  +         ,urg=decode_flag(Urg), ack=decode_flag(Ack), psh=decode_flag(Psh)
  +         ,rst=decode_flag(Rst), syn=decode_flag(Syn), fin=decode_flag(Fin)
  +         ,window=Window
  +         ,csum=check_sum(Csum, IPH, byte_size(Pkt), Pkt)
  +         ,urg_pointer=UrgPointer
  +         ,options=decode_options(Options)
  +         ,data=TcpData
  +        };
   decode(_Packet, _DecodeOpts) ->
       {error, bad_packet}.
   
   decode_port(Port) ->
       enet_services:decode_port(tcp, Port).
   
  +encode(#tcp{src_port=Src
  +            ,dst_port=Dst
  +            ,seq_no=SeqNo
  +            ,ack_no=AckNo
  +            ,data_offset=DataOffset
  +            ,reserved=Reserved
  +            ,urg=Urg, ack=Ack, psh=Psh
  +            ,rst=Rst, syn=Syn, fin=Fin
  +            ,window=Window
  +            ,csum=Csum
  +            ,urg_pointer=UrgPointer
  +            ,options=Options
  +            ,data=TcpData
  +           }, _)
  +  when is_binary(Src), is_binary(Dst),
  +       is_integer(SeqNo),
  +       is_integer(AckNo),
  +       is_integer(DataOffset),
  +       is_integer(Reserved),
  +       is_integer(Urg), is_integer(Ack), is_integer(Psh),
  +       is_integer(Rst), is_integer(Syn), is_integer(Fin),
  +       is_integer(Window),
  +       is_integer(Csum),
  +       is_integer(UrgPointer),
  +       is_binary(Options),
  +       is_binary(TcpData) ->
  +    OptSize = byte_size(Options),
  +    PadLen = ?TCP_OPTS_ALIGNMENT - ((?TCP_HEADER_MIN_LEN + OptSize) rem ?TCP_OPTS_ALIGNMENT),
  +    Padding = case PadLen of
  +                  0 -> <<>>;
  +                  _N -> <<0:(PadLen*8)>>
  +              end,
  +    MyDataOffset = (?TCP_HEADER_MIN_LEN + OptSize + PadLen) div ?TCP_OPTS_ALIGNMENT,
  +    DataOffset = MyDataOffset,
  +    <<Src:2/binary, Dst:2/binary,
  +      SeqNo:32/big, AckNo:32/big,
  +      DataOffset:4, Reserved:6,
  +      Urg:1, Ack:1, Psh:1, Rst:1, Syn:1, Fin:1,
  +      Window:16/big,
  +      Csum:16/big, UrgPointer:16/big,
  +      Options/binary,
  +      Padding/binary,
  +      TcpData/binary>>;
  +encode(TcpPacket = #tcp{}, EncodeOptions) ->
  +    encode(expand(TcpPacket, EncodeOptions), EncodeOptions).
  +
  +expand(#tcp{data=Data}, _) when not is_binary(Data) ->
  +    erlang:error({tcp_payload_not_encoded, Data});
  +expand(Pkt = #tcp{src_port=Src}, O) when not is_binary(Src);
  +                                         is_binary(Src), byte_size(Src) =/= 2 ->
  +    Port = encode_port(Src),
  +    expand(Pkt#tcp{src_port= <<Port:16/big>>}, O);
  +expand(Pkt = #tcp{dst_port=Dst}, O) when not is_binary(Dst);
  +                                         is_binary(Dst), byte_size(Dst) =/= 2 ->
  +    Port = encode_port(Dst),
  +    expand(Pkt#tcp{dst_port= <<Port:16/big>>}, O);
  +
  +expand(Pkt = #tcp{options=OptList}, O) when is_list(OptList) ->
  +    EncodedOptions = encode_options(OptList),
  +    expand(Pkt#tcp{options=EncodedOptions}, O);
  +
  +expand(Pkt = #tcp{urg=Flag}, O) when is_atom(Flag) ->
  +    expand(Pkt#tcp{urg=encode_flag(Flag)}, O);
  +expand(Pkt = #tcp{ack=Flag}, O) when is_atom(Flag) ->
  +    expand(Pkt#tcp{ack=encode_flag(Flag)}, O);
  +expand(Pkt = #tcp{psh=Flag}, O) when is_atom(Flag) ->
  +    expand(Pkt#tcp{psh=encode_flag(Flag)}, O);
  +expand(Pkt = #tcp{rst=Flag}, O) when is_atom(Flag) ->
  +    expand(Pkt#tcp{rst=encode_flag(Flag)}, O);
  +expand(Pkt = #tcp{syn=Flag}, O) when is_atom(Flag) ->
  +    expand(Pkt#tcp{syn=encode_flag(Flag)}, O);
  +expand(Pkt = #tcp{fin=Flag}, O) when is_atom(Flag) ->
  +    expand(Pkt#tcp{fin=encode_flag(Flag)}, O);
  +
  +expand(Pkt = #tcp{csum={incorrect, Value}}, O) ->
  +    expand(Pkt#tcp{csum=Value}, O);
  +
  +expand(#tcp{src_port=Src
  +            ,dst_port=Dst
  +            ,seq_no=SeqNo
  +            ,ack_no=AckNo
  +            ,data_offset=DataOffset
  +            ,reserved=Reserved
  +            ,urg=Urg, ack=Ack, psh=Psh
  +            ,rst=Rst, syn=Syn, fin=Fin
  +            ,window=Window
  +            ,csum=correct
  +            ,urg_pointer=UrgPointer
  +            ,options=Options
  +            ,data=TcpData
  +           } = Pkt, O)
  +  when is_binary(Src), is_binary(Dst),
  +       is_integer(SeqNo),
  +       is_integer(AckNo),
  +       is_integer(DataOffset),
  +       is_integer(Reserved),
  +       is_integer(Urg), is_integer(Ack), is_integer(Psh),
  +       is_integer(Rst), is_integer(Syn), is_integer(Fin),
  +       is_integer(Window),
  +       is_integer(UrgPointer),
  +       is_binary(Options),
  +       is_binary(TcpData) ->
  +    PseudoPkt = encode(Pkt#tcp{csum=0}, O),
  +    NewCsum = sum(PseudoPkt, byte_size(PseudoPkt), O),
  +    expand(Pkt#tcp{csum=NewCsum}, O);
  +
  +expand(#tcp{src_port=Src
  +            ,dst_port=Dst
  +            ,seq_no=SeqNo
  +            ,ack_no=AckNo
  +            ,data_offset=DataOffset
  +            ,reserved=Reserved
  +            ,urg=Urg, ack=Ack, psh=Psh
  +            ,rst=Rst, syn=Syn, fin=Fin
  +            ,window=Window
  +            ,csum=Csum
  +            ,urg_pointer=UrgPointer
  +            ,options=Options
  +            ,data=TcpData
  +           } = ExpandedPkt, _)
  +  when is_binary(Src), is_binary(Dst),
  +       is_integer(SeqNo),
  +       is_integer(AckNo),
  +       is_integer(DataOffset),
  +       is_integer(Reserved),
  +       is_integer(Urg), is_integer(Ack), is_integer(Psh),
  +       is_integer(Rst), is_integer(Syn), is_integer(Fin),
  +       is_integer(Window),
  +       is_integer(Csum),
  +       is_integer(UrgPointer),
  +       is_binary(Options),
  +       is_binary(TcpData) ->
  +    ExpandedPkt.
  +
   encode_port(Port) ->
       enet_services:encode_port(tcp, Port).
   
  
positive.code: decode_options(<<OptionData/binary>>, Acc) ->
      [{error, {unknown_opt_data, OptionData}} | Acc].
  
  check_sum(16#FFFF, _IPH, _Length, _Data) ->
      no_checksum;
  check_sum(Csum, #ipv4_pseudo_hdr{src=Src, dst=Dst, proto=Proto},
  
negative.code: %% End of Options List (padding?)
  decode_options(<<0, Rest/binary>>, Acc) -> decode_options(Rest, Acc);
  %% Nop
  decode_options(<<1, Rest/binary>>, Acc) -> decode_options(Rest, [nop | Acc]);
  %% MSS
  decode_options(<<2, 4, MSS:16/big, Rest/binary>>, Acc) ->
      decode_options(Rest, [{mss, MSS} | Acc]);
  %% Window Size Shift
  decode_options(<<3, 3, Shift:8, Rest/binary>>, Acc) ->
      decode_options(Rest, [{window_size_shift, Shift} | Acc]);
  %% SACK Permitted
  decode_options(<<4, 2, Rest/binary>>, Acc) ->
  