anchor.diff:  %%----------------------------------------------------------------------
   
   -dialyzer({nowarn_function, ssl_connect/3}).
  --spec ssl_connect(Address, Port, Options) ->
  +-spec ssl_connect(Address, ClientPid, Options) ->
   		{ok, SslSocket} | {error, Reason} when
   	Address :: inet:ip_address(),
  -	Port :: inet:port_number(),
  +	ClientPid :: pid(),
   	Options :: [term()],
   	SslSocket :: pid(),
   	Reason :: term().
   %% @doc Open an SSL connection to Host, Port.
  -ssl_connect(Address, Port, Options) ->
  -	ssl:connect(Address, Port, [?cb_info | Options]).
  +ssl_connect(Address, ClientPid, Options) ->
  +	{ok , SslSocket} = ssl:connect(Address, ClientPid, [?cb_info | Options]),
  +	ClientPid ! {ssl_socket, SslSocket}.
   
  --spec deliver(Data) ->
  +-spec deliver(SslPid, ClientPid, Data) ->
   	ok when
  -		Data :: binary().
  +		SslPid :: pid(),
  +		ClientPid :: pid(),
  +		Data :: iodata().
   %% @doc Deliver received EAP-TTLS payload to SSL.
  -deliver(Data) ->
  -	self() ! {eap_ttls, self(), Data},
  +deliver(SslPid, ClientPid, Data) when is_pid(SslPid), is_pid(ClientPid) ->
  +	SslPid ! {eap_ttls, ClientPid, iolist_to_binary(Data)},
   	ok.
   
   %%----------------------------------------------------------------------
  -%%  ocs_eap_ttls_transport callbacks
  +%%  peer_ttls_transport callbacks
   %%----------------------------------------------------------------------
  -connect(Address, Port, SocketOpts, Timeout) ->
  -	{ok, self()}.
  +-spec connect(Address, ClientPid, SocketOpts, Timeout) ->
  +		{ok, ClinetPid} when
  +	Address :: inet:socket_address() | inet:hostname(),
  +	ClientPid :: pid(),
  +	SocketOpts :: [trems()],
  +	Timeout :: timeout().
  +%% @doc Connects to the EAP session
  +connect(Address, ClientPid, SocketOpts, Timeout) ->
  +	{ok, ClientPid}.
   
   -spec setopts(ClientPid, Options) ->
   	ok | {error, Reason} when
  
positive.code: %%----------------------------------------------------------------------
  %%  internal functions
  %%----------------------------------------------------------------------
  client_hello(Socket, Address, Port, ReqAuth, RadId, EapId, Secret, NasId,
  			MAC, AnonymousName, Data) ->
  	TtlsData = iolist_to_binary(Data),
  	Ttls = ocs_eap_codec:eap_ttls(#eap_ttls{version = 1,data = TtlsData}),
  	EapRecord = #eap_packet{code = response, type = ?TTLS,
  			identifier = EapId, data = Ttls},
  	EapMsg = ocs_eap_codec:eap_packet(EapRecord),
  	EapMessages = eap_fragment(EapMsg, []),
  	access_request(Socket, Address, Port, NasId,
  			AnonymousName, Secret, MAC, ReqAuth,RadId, EapMessages).
  
  server_hello(ClientPid, Socket, Address, Port, ReqAuth, RadId, Secret) ->
  	EapMsg = access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?TTLS,
  			identifier = 4, data = TtlsMsg} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_ttls{data = TtlsData} = ocs_eap_codec:eap_ttls(TtlsMsg),
  	deliver(TtlsData).
  
  client_cipher(Socket, Address, Port, ReqAuth,
  		RadId, EapId, Secret, NasId, MAC, UserName, Data) ->
  	TtlsData = iolist_to_binary(Data),
  	Ttls = ocs_eap_codec:eap_ttls(#eap_ttls{version = 1,data = TtlsData}),
  	EapRecord = #eap_packet{code = response, type = ?TTLS,
  			identifier = EapId, data = Ttls},
  	EapMsg = ocs_eap_codec:eap_packet(EapRecord),
  	EapMessages = eap_fragment(EapMsg, []),
  	access_request(Socket, Address, Port, NasId,
  			UserName, Secret, MAC, ReqAuth,RadId, EapMessages).
  
  server_cipher(ClientPid, Socket, Address, Port, ReqAuth, RadId, Secret) ->
  	EapMsg = access_challenge(Socket, Address, Port,
  			Secret, RadId, ReqAuth),
  	#eap_packet{code = request, type = ?TTLS,
  			identifier = 5, data = TtlsMsg} = ocs_eap_codec:eap_packet(EapMsg),
  	#eap_ttls{data = TtlsData} = ocs_eap_codec:eap_ttls(TtlsMsg),
  	deliver(TtlsData).
  
  eap_fragment(<<Chunk:253/binary, Rest/binary>>, RadiusAttributes) ->
  	AttributList = radius_attributes:add(?EAPMessage, Chunk,
  			RadiusAttributes),
  	eap_fragment(Rest, AttributList);
  eap_fragment(<<>>, RadiusAttributes) ->
  	RadiusAttributes;
  eap_fragment(Chunk, RadiusAttributes) ->
  	radius_attributes:add(?EAPMessage, Chunk,
  			RadiusAttributes).
  
  access_request(Socket, Address, Port, NasId,
  		UserName, Secret, MAC, ReqAuth,  RadId, RadiusAttributes) ->
  	A1 = radius_attributes:add(?FramedMtu, 65536, RadiusAttributes),
  	A2 = radius_attributes:add(?UserName, UserName, A1),
  	A3 = radius_attributes:add(?NasPort, 0, A2),
  	A4 = radius_attributes:add(?NasIdentifier, NasId, A3),
  	A5 = radius_attributes:add(?CallingStationId, MAC, A4),
  	A6 = radius_attributes:add(?MessageAuthenticator,
  			list_to_binary(lists:duplicate(16,0)), A5),
  	Request1 = #radius{code = ?AccessRequest, id = RadId,
  		authenticator = ReqAuth, attributes = A6},
  	ReqPacket1 = radius:codec(Request1),
  	MsgAuth1 = crypto:hmac(md5, Secret, ReqPacket1),
  	A7 = radius_attributes:store(?MessageAuthenticator, MsgAuth1, A6),
  	Request2 = Request1#radius{attributes = A7},
  	ReqPacket2 = radius:codec(Request2),
  	ok = gen_udp:send(Socket, Address, Port, ReqPacket2).
  
  access_challenge(Socket, Address, Port, Secret, RadId, ReqAuth) ->
  	receive_radius(?AccessChallenge, Socket, Address, Port, Secret, RadId, ReqAuth).
  
  receive_radius(Code, Socket, Address, Port, Secret, RadId, ReqAuth) ->
  	{ok, {Address, Port, RespPacket1}} = gen_udp:recv(Socket, 0),
  	Resp1 = radius:codec(RespPacket1),
  	#radius{code = Code, id = RadId, authenticator = RespAuth,
  		attributes = BinRespAttr1} = Resp1,
  	Resp2 = Resp1#radius{authenticator = ReqAuth},
  	RespPacket2 = radius:codec(Resp2),
  	RespAuth = binary_to_list(crypto:hash(md5, [RespPacket2, Secret])),
  	RespAttr1 = radius_attributes:codec(BinRespAttr1),
  	{ok, MsgAuth} = radius_attributes:find(?MessageAuthenticator, RespAttr1),
  	RespAttr2 = radius_attributes:store(?MessageAuthenticator,
  			list_to_binary(lists:duplicate(16, 0)), RespAttr1),
  	Resp3 = Resp2#radius{attributes = RespAttr2},
  	RespPacket3 = radius:codec(Resp3),
  	MsgAuth = crypto:hmac(md5, Secret, RespPacket3),
  	EapMsg = radius_attributes:get_all(?EAPMessage, RespAttr1),
  	iolist_to_binary(EapMsg).
  
  
negative.code: -export([send/2, controlling_process/2,
  		shutdown/2, close/1, connect/4]).
  %% export public API
  -export([ssl_connect/3, deliver/3]).
  
  -export_type([listen_option/0, eap_option/0]).
  
  