anchor.diff:      end.
   
   %%--------------------------------------------------------------------
  -%% Function: do_recv(DataIn, State)
  -%%           State  = state record()
  -%%           DataIn = list()
  -%% Descrip.: Read data from our socket and add it to whatever data was
  -%%           supplied in DataIn until a SIP message header/body
  -%%           separator ("\r\n\r\n") is seen. It is possible that we
  -%%           also get part or a whole body of the message, but as soon
  -%%           as we have the header we use tcp_read_sip_message()
  -%%           instead.
  -%% Returns : DataOut             |
  -%%           {connection_closed} |
  -%%           {close}
  -%%           {error, Reason}
  -%%           DataOut = list(), whatever we have left in our buffer
  -%%                     when we have processed all SIP messages in it.
  -%%                     Will get passed to us as DataIn on the next
  -%%                     itteration.
  -%%           Reason = string()
  -%%--------------------------------------------------------------------
  -do_recv(DataIn, State) ->
  -    SocketModule = State#state.socketmodule,
  -    Socket = State#state.socket,
  -    case SocketModule:recv(Socket, 0) of
  -	{ok, B} ->
  -	    L = binary_to_list(B),
  -	    logger:log(debug, "TCP receiver: Received ~p bytes of data, adding it to my buffer which contained ~p bytes of data",
  -		       [length(L), length(DataIn)]),
  -	    %% remove_separator() removes any leading CR or LF
  -	    SoFar = remove_separator(lists:append(DataIn, L)),
  -	    case has_header_body_separator(SoFar) of
  -		false ->
  -		    %% No Header Body separator yet, read more data
  -		    do_recv(SoFar, State);
  -		true ->
  -		    case header_received(SoFar, State) of
  -			Rest when is_list(Rest) ->
  -			    logger:log(debug, "TCP receiver: My buffer now contains ~p bytes of data", [length(Rest)]),
  -			    Rest;
  -			Rest2 ->
  -			    Rest2
  -		    end
  -	    end;
  -	{error, closed} ->
  -	    logger:log(debug, "TCP receiver: Extra debug: ~p recv() returned 'closed' in do_recv() (Socket: ~p)",
  -		       [SocketModule, Socket]),
  -	    {connection_closed};
  -	{error, E} ->
  -	    logger:log(error, "TCP receiver: Error when reading data : ~s (~p)", [inet:format_error(E), E]),
  -	    {error, E}
  +%% Function: handle_received_data(Data, Recv, State)
  +%%           Data  = binary(), the data we have just received
  +%%           Recv  = recv record(), receive state
  +%%           State = state record()
  +%% Descrip.: Handle data just received from the network. Calls
  +%%           handle_received_data2/2 and then looks at the msg_stack
  +%%           in the returned recv record() to see if we now have one
  +%%           or more messages to pass to our parent.
  +%% Returns : NewRecv = recv record() |
  +%%           close
  +%%--------------------------------------------------------------------
  +handle_received_data(Data, Recv, State) when is_binary(Data), is_record(Recv, recv) ->
  +    try handle_received_data2(Data, Recv) of
  +	#recv{msg_stack=[]} = NewRecv ->
  +	    %% No messages on the stack
  +	    NewRecv;
  +	#recv{msg_stack=ReverseMsgs} = NewRecv ->
  +	    Msgs = lists:reverse(ReverseMsgs),
  +	    ok = send_messages_to_parent(Msgs, State#state.parent),
  +	    NewRecv#recv{msg_stack=[]}
  +    catch
  +	throw:
  +	  {error, parse_failed, E} ->
  +	    {IP, Port} = State#state.remote,
  +	    Msg = binary_to_list( list_to_binary([Recv#recv.frame, Data]) ),
  +	    ProtoStr = case State#state.socketmodule of
  +			   ssl -> "tls";
  +			   gen_tcp -> "tcp"
  +		       end,
  +	    logger:log(error, "TCP receiver: Failed parsing data received from ~s:~s:~p, ",
  +		       "discarding and closing socket.", [ProtoStr, IP, Port]),
  +	    logger:log(debug, "TCP receiver: Data : ~n~p~nError : ~p", [Msg, E]),
  +	    close
  +
       end.
   
  -%% Look for header-body separator, return true | false
  -has_header_body_separator(Data) ->
  -    case string:str(Data, "\r\n\r\n") of
  -	0 ->
  -	    false;
  -	N when is_integer(N) ->
  -	    true
  +%%--------------------------------------------------------------------
  +%% Function: handle_received_data2(Data, Recv)
  +%%           Data = binary(), the data we have just received
  +%%           Recv = recv record(), receive state
  +%% Descrip.: Look at received data to see if it should be added to our
  +%%           current recv.frame, or if it is CRLF's between requests.
  +%%
  +%%           These first three instances of handle_received_data2/2 is
  +%%           just for ignoring CRLF's (and LF's) between requests, as
  +%%           specified by RFC3261 #7.5.
  +%% Returns : NewRecv = recv record()
  +%%--------------------------------------------------------------------
  +handle_received_data2(<<?CR, ?LF, Rest/binary>>, #recv{frame = <<>>}=Recv) ->
  +    %% Ignore CRLF received when current recv.frame is empty.
  +    handle_received_data2(Rest, Recv);
  +
  +handle_received_data2(<<?LF, Rest/binary>>, #recv{frame = <<>>}=Recv) ->
  +    %% Ignore LF received when current recv.frame is empty.
  +    handle_received_data2(Rest, Recv);
  +
  +handle_received_data2(<<?LF, Rest/binary>>, #recv{frame = <<?CR>>}=Recv) ->
  +    %% LF received when current recv.frame was a CR - ignore it and clear recv.frame.
  +    handle_received_data2(Rest, Recv#recv{frame = <<>>});
  +
  +%%--------------------------------------------------------------------
  +%% Function: handle_received_data2(Data, Recv)
  +%%           Data = binary(), the data we have just received
  +%%           Recv = recv record(), receive state
  +%% Descrip.: Look at received data to see if we should attempt to
  +%%           parse message headers now (because we've just spotted the
  +%%           header-body separator). init_frame() might find that we
  +%%           have received the complete frame by the way, in which
  +%%           case it will place the received frame in recv.msg_stack
  +%%           and start on a new frame.
  +%% Returns : NewRecv = recv record()
  +%%--------------------------------------------------------------------
  +handle_received_data2(Data, #recv{body_offset = undefined}=Recv) when is_binary(Data) ->
  +    %% No body_offset information - means we haven't parsed the headers yet
  +    OldLen = size(Recv#recv.frame),
  +    NewFrame = list_to_binary([Recv#recv.frame, Data]),
  +    %% Now look for header-body separator in NewFrame - we only have to look from position
  +    %% (OldLen - 3) since worst case is that we have CRLFCR in the previously received data
  +    %% and Data begins with LF.
  +    case has_header_body_separator(NewFrame, OldLen - 3) of
  +	{true, BodyOffset} ->
  +	    %% Ok, we found the header-body separator. We might now have a complete message,
  +	    %% or we might still be waiting for more data to add to the body.
  +	    init_frame(NewFrame, BodyOffset, Recv);
  +	false ->
  +	    %% Header-body separator not found
  +	    Recv#recv{frame=NewFrame}
  +    end;
  +
  +%%--------------------------------------------------------------------
  +%% Function: handle_received_data2(Data, Recv)
  +%%           Data = binary(), the data we have just received
  +%%           Recv = recv record(), receive state
  +%% Descrip.: recv.body_offset is set, meaning we have recevied all the
  +%%           headers but (at least previously) not the whole body. Add
  +%%           the received data to our current frame, and call
  +%%           decode_frame() to see if we have a complete frame now.
  +%% Returns : NewRecv = recv record()
  +%%--------------------------------------------------------------------
  +handle_received_data2(Data, Recv) when is_binary(Data), is_record(Recv, recv) ->
  +    %% bytes_left is set, means we have already received the headers and are now just
  +    %% adding to the body. Note that we might just have received the rest of the frame
  +    %% we were working on, and parts of (or whole) the next frame.
  +    NewFrame = list_to_binary([Recv#recv.frame, Data]),
  +    BL = Recv#recv.bytes_left - size(Data),
  +    decode_frame(NewFrame, Recv#recv{bytes_left=BL}).
  +
  +
  +%%--------------------------------------------------------------------
  +%% Function: init_frame(Frame, BodyOffset, Recv)
  +%%           Frame      = binary(), our frame with the newly arrived
  +%%                        data appended
  +%%           BodyOffset = integer(), where the body starts
  +%%           Recv       = recv record(), receive state
  +%% Descrip.: When we see the header-body separator, we let this
  +%%           function call sippacket:parse() on the data we have this
  +%%           far, so that we can calculate the total frame length (we
  +%%           must parse the headers for that - to find the Content-
  +%%           Length header). This function caches the parse results
  +%%           in recv.parsed to avoid having to do that again later.
  +%% Returns : NewRecv = recv record() |
  +%%           throw(...)
  +%%--------------------------------------------------------------------
  +init_frame(Frame, BodyOffset, Recv) when is_binary(Frame), is_integer(BodyOffset), is_record(Recv, recv) ->
  +    case catch sippacket:parse(Frame, none) of
  +	Request when is_record(Request, request) ->
  +	    CL = get_content_length(request, Request#request.header),
  +	    Left = (BodyOffset + CL) - size(Frame),
  +	    decode_frame(Frame, Recv#recv{parsed=Request, body_offset=BodyOffset, body_length=CL, bytes_left=Left});
  +	Response when is_record(Response, response) ->
  +	    CL = get_content_length(response, Response#response.header),
  +	    Left = (BodyOffset + CL) - size(Frame),
  +	    decode_frame(Frame, Recv#recv{parsed=Response, body_offset=BodyOffset, body_length=CL, bytes_left=Left});
  +	Unknown ->
  +	    throw({error, parse_failed, Unknown})
       end.
   
   %%--------------------------------------------------------------------
  -%% Function: header_received(Data, State)
  -%%           Data  = list()
  -%%           State = state record()
  -%% Descrip.: Data contains at least one SIP messages complete header.
  -%%           Parse it and hand it over to tcp_read_sip_message().
  -%%           If we aren't given a parseable header as input, we return
  -%%           a instruction to close this socket.
  -%%           When tcp_read_sip_message() has received a complete SIP
  -%%           message (and handled it), it might have received more
  -%%           data (part or whole of the next request/response sent to
  -%%           us on this socket). If that is the case we invoke
  -%%           ourselves again on this data in case it contains a
  -%%           header/body separator, or we return the extra bytes to
  -%%           our caller in case it does not.
  -%% Returns : DataOut             |
  -%%           {connection_closed} |
  -%%           {close}
  -%%           DataOut = list(), whatever we have left in our buffer
  -%%           when we have processed all SIP messages in it. Will get
  -%%           passed to us as DataIn on the next itteration.
  -%%--------------------------------------------------------------------
  -header_received(Data, State) when list(Data), record(State, state) ->
  -    Rest = case catch sippacket:parse(Data, none) of
  -	       Request when record(Request, request) ->
  -		   tcp_read_sip_message(request, Request#request.header, Request#request.body, Data, State);
  -	       Response when record(Response, response) ->
  -		   tcp_read_sip_message(response, Response#response.header, Response#response.body, Data, State);
  -	       _ ->
  -		   %% Data did not parse, close connection.
  -		   Socket = State#state.socket,
  -		   logger:log(debug, "TCP receiver: Received unparseable data - closing socket (~p) :~n~p",
  -			      [Socket, Data]),
  -		   {close}
  -	   end,
  -    case Rest of
  -	{connection_closed} ->
  -	    {connection_closed};
  -	{close} ->
  -	    {close};
  -	_ when list(Rest) ->
  -	    %% We received more data than the Content-Length indicated, might be pipelined requests?
  -	    %% Remove any CRLF sequences before (or between) requests, RFC3261 #7.5
  -	    NewData = remove_separator(lists:flatten(Rest)),
  -	    %% Check if there is already a complete request/response in NewData -
  -	    %% recurse on ourselves until that is not the case
  -	    case has_header_body_separator(NewData) of
  -		true  -> header_received(NewData, State);
  -		false -> NewData
  -	    end;
  +%% Function: decode_frame(Frame, Recv)
  +%%           Frame = binary(), our frame with the newly arrived data
  +%%                   appended
  +%%           Recv  = recv record(), receive state
  +%% Descrip.: Check bytes_left inside Recv to see if we have now
  +%%           received enough data, or if we should just set frame in
  +%%           Recv to Frame. The caller is responsible for updating
  +%%           bytes_left in Recv. If we have enough data, split out
  +%%           this frame and push it onto the msg_stack in Recv. Then
  +%%           check any remaining data to see if there are more data
  +%%           we can process there at this time.
  +%% Returns : NewRecv = recv record()
  +%%--------------------------------------------------------------------
  +decode_frame(Frame, #recv{bytes_left=BL} = Recv) when is_binary(Frame), is_integer(BL), BL =< 0 ->
  +    %% Bytes left is zero or less, we have a full frame
  +    BodyOffset = Recv#recv.body_offset,
  +    BodyLen = Recv#recv.body_length,
  +    %% Extract the complete body from Frame, put it into the request/response record
  +    %% we have already parsed and insert the results first in the msg_stack.
  +    <<_:BodyOffset/binary, Body:BodyLen/binary, NewFrame/binary>> = Frame,
  +    %% Don't use siprequest:set_{request,response}_body since it potentially alters the record
  +    %% in more ways than just setting the body element. We don't want the socket code to alter
  +    %% what is received.
  +    Msg =
  +	if
  +	    is_record(Recv#recv.parsed, request) ->
  +		(Recv#recv.parsed)#request{body = Body};
  +	    is_record(Recv#recv.parsed, response) ->
  +		(Recv#recv.parsed)#response{body = Body}
  +	end,
  +    NewStack = [Msg | Recv#recv.msg_stack],
  +    OriginStr = Recv#recv.origin_str,
  +    logger:log_iolist(debug, [<<"Frame received (from ">>, OriginStr, <<") :", 10>>, Frame, 10]),
  +    %% Check if there is already a header-body separator in NewFrame
  +    case has_header_body_separator(NewFrame, 0) of
  +	{true, NewFrameBO} ->
  +	    init_frame(NewFrame, NewFrameBO, Recv#recv{msg_stack=NewStack});
  +	false ->
  +	    %% create new recv record to get correct defaults, then just set msg_stack and frame (and origin_str)
  +	    #recv{msg_stack=NewStack, frame=NewFrame, origin_str=OriginStr}
  +    end;
  +decode_frame(Frame, Recv) when is_binary(Frame), is_record(Recv, recv) ->
  +    %% bytes_left is > 0, we can't decode a frame right now. Save it in recv.
  +    Recv#recv{frame=Frame}.
  +
  +%%--------------------------------------------------------------------
  +%% Function: has_header_body_separator(Data, Offset)
  +%%           Data   = binary(), our current frame
  +%%           Offset = integer(), start offset for search
  +%% Descrip.: Look for header-body separator (CRLFCRLF or LFLF).
  +%% Returns : {true, BodyOffset} |
  +%%           false
  +%%--------------------------------------------------------------------
  +%%
  +has_header_body_separator(Data, Offset) when is_integer(Offset), Offset >= 0 ->
  +    has_header_body_separator2(Data, Offset);
  +has_header_body_separator(Data, Offset) when is_integer(Offset) ->
  +    %% Offset < 0
  +    has_header_body_separator2(Data, 0).
  +
  +has_header_body_separator2(Data, Offset) when is_binary(Data), is_integer(Offset) ->
  +    case Data of
  +	<<_:Offset/binary, ?CR, ?LF, ?CR, ?LF, _/binary>> ->
  +	    {true, Offset + 4};
  +	<<_:Offset/binary, ?LF, ?LF, _/binary>> ->
  +	    {true, Offset + 2};
  +	<<_:Offset/binary, _:8, _/binary>> ->
  +	    has_header_body_separator2(Data, Offset + 1);
   	_ ->
  -	    logger:log(error, "TCP receiver: Unknown result from sippacket:parse() or tcp_read_sip_message() :~n~p~n" ++
  -		       "Closing socket.", [Rest]),
  -	    {close}
  +	    false
       end.
   
  -
  -%%--------------------------------------------------------------------
  -%% Function: tcp_read_sip_message(MessageType, Header, BodyIn, DataIn,
  -%%                                State)
  -%%           MessageType = request | response
  -%%           Header      = keylist record()
  -%%           BodyIn      = list(), whatever part of the body that was
  -%%                         received before we were invoked
  -%%           DataIn      = list(), the data we have received yet, in
  -%%                         unparsed form
  -%%           State       = state record()
  -%% Descrip.: A parseable header of a SIP message has been received
  -%%           (and possibly also parts of or the whole body). Calculate
  -%%           how much more data (if any) we must read to have the
  -%%           whole message (through the Content-Length header), and
  -%%           wait until we have received it all. Then send this SIP
  -%%           message to our parent.
  -%% Returns : DataOut             |
  -%%           {connection_closed} |
  -%%           {close}
  -%%           DataOut = list(), whatever we have left in our buffer
  -%%           when we have one (1) SIP messages in it.
  -%%--------------------------------------------------------------------
  -tcp_read_sip_message(MessageType, Header, BodyIn, DataIn, State) when record(State, state) ->
  -    {IP, Port} = State#state.remote,
  -    Parent = State#state.parent,
  -    Socket = State#state.socket,
  -    case get_content_length(Header) of
  -	CLen when integer(CLen) ->
  -	    Remaining = CLen - length(BodyIn),
  -	    case tcp_read_more_data(State#state.socketmodule, Socket, Remaining, DataIn) of
  -		Data when list(Data) ->
  -		    ThisMessage = string:substr(Data, 1, length(DataIn) + Remaining),
  -		    Rest = string:substr(Data, 1 + length(DataIn) + Remaining),
  -		    gen_server:cast(Parent, {recv, ThisMessage}),
  -		    %% We have received more data than just this request/response, like a pipelined request
  -		    Rest;
  -		{connection_closed} ->
  -		    logger:log(debug, "TCP receiver: Connection closed by foreign host when expecting ~p bytes more data", [CLen]),
  -		    {connection_closed};
  -		Res ->
  -		    logger:log(debug, "TCP receiver: Failed reading ~p bytes more data : ~p", [CLen, Res]),
  -		    []
  -	    end;
  -	Unknown ->
  -	    logger:log(debug, "TCP receiver: Non-integer Content-Length spotted : ~p", [Unknown]),
  -	    case MessageType of
  -		request ->
  -		    logger:log(debug, "TCP receiver: Non-existing or invalid Content-Length in request from ~s:~p, " ++
  -			       "(socket ~p), discarding message :~n~p", [IP, Port, Socket, DataIn]),
  -		    logger:log(error, "TCP receiver: Non-existing or invalid Content-Length in request from ~s:~p, " ++
  -			       "answering 400 Bad Request and closing socket", [IP, Port]),
  -		    SipSocket = State#state.sipsocket,
  -		    transportlayer:send_result(Header, SipSocket, "", 400, "Bad Request",
  -					       [{"Reason", ["Non-existing or invalid Content-Length"]}]);
  -		response ->
  -		    logger:log(debug, "TCP receiver: Non-existing or invalid Content-Length in response from ~s:~p " ++
  -			       "(socket ~p), discarding message :~n~p", [IP, Port, Socket, DataIn]),
  -		    logger:log(error, "TCP receiver: Non-existing or invalid Content-Length in response from ~s:~p, " ++
  -			       "discarding and closing socket.", [IP, Port])
  -	    end,
  -	    logger:log(debug, "TCP receiver: Closing socket ~p since there is no way to know we are synchronized with remote end", [Socket]),
  -	    {close}
  -    end.
  -
  -%%--------------------------------------------------------------------
  -%% Function: get_content_length(Header)
  +%%--------------------------------------------------------------------
  +%% Function: send_messages_to_parent(MsgList, Parent)
  +%%           MsgList = list() of request or response record()
  +%%           Parent  = term(), pid() or atom()
  +%% Descrip.: Send received frames to parent (tcp_connection pid).
  +%% Returns : ok
  +%%--------------------------------------------------------------------
  +send_messages_to_parent([H | T], Parent) ->
  +    gen_server:cast(Parent, {recv_sipmsg, H}),
  +    send_messages_to_parent(T, Parent);
  +send_messages_to_parent([], _Parent) ->
  +    ok.
  +
  +%%--------------------------------------------------------------------
  +%% Function: get_content_length(Type, Header)
  +%%           Type   = request | response
   %%           Header = keylist record()
   %% Descrip.: Get Content-Length and return it as an integer value.
  -%% Returns : Length  |
  -%%           invalid
  -%%           Length = integer()
  -%%--------------------------------------------------------------------
  -get_content_length(Header) ->
  +%% Returns : Length = integer() |
  +%%           throw(...)
  +%%--------------------------------------------------------------------
  +get_content_length(Type, Header) ->
       case keylist:fetch('content-length', Header) of
   	[CLenStr] ->
  -	    case util:isnumeric(CLenStr) of
  -		true ->
  -		    %% Be extra careful and check for numeric value.
  -		    %% We don't have to worry about partially received Content-Length
  -		    %% header here since this function doesn't get invoked until
  -		    %% the header-body separator has been seen.
  -		    list_to_integer(CLenStr);
  -		false ->
  -		    invalid
  -	    end;
  +	    %% sippacket will fail if Content-Length is bad before we get here.
  +	    %% if it doesn't - let it crash here.
  +	    list_to_integer(CLenStr);
   	_ ->
  -	    invalid
  +	    throw({error, Type, invalid_content_length, Header})
       end.
   
  -%%--------------------------------------------------------------------
  -%% Function: tcp_read_more_data(SocketModule, Socket, Len, DataIn)
  -%%           SocketModule = atom(), socket module to use
  -%%           Socket       = term(), the socket
  -%%           Len          = integer(), how much more data to wait for
  -%%           DataIn       = list()
  -%% Descrip.: SSL version: Wait for a pre-determined ammount of more
  -%%           data from a socket.
  -%% Returns : DataOut             |
  -%%           {connection_closed} |
  -%%           {error, Reason}
  -%%           Reason = string()
  -%%--------------------------------------------------------------------
  -tcp_read_more_data(SocketModule, Socket, Len, DataIn) when Len > 0, SocketModule == ssl ->
  -    receive
  -	{ssl, Socket, B} ->
  -	    Data = binary_to_list(B),
  -	    L = length(Data),
  -	    logger:log(debug, "TCP receiver: Extra debug: Received ~p bytes of data (~p more expected)",
  -		       [L, Len - L]),
  -	    SoFar = lists:append(DataIn, Data),
  -	    SocketModule:setopts(Socket, [{active, once}]),
  -	    tcp_read_more_data(SocketModule, Socket, Len - length(Data), SoFar);
  -
  -	{ssl_closed, Socket} ->
  -	    logger:log(debug, "TCP receiver: Extra debug: Got message that socket ~p was closed tcp_read_more_data()",
  -		       [Socket]),
  -	    {connection_closed};
  -
  -	{ssl_error, Socket, E} ->
  -	    logger:log(error, "TCP receiver: Error when reading ~p bytes of data : ~s (~p)",
  -		       [Len, SocketModule:format_error(E), E]),
  -	    {error, E}
  -    end;
  -
  -%%--------------------------------------------------------------------
  -%% Function: tcp_read_more_data(SocketModule, Socket, Len, DataIn)
  -%%           SocketModule = atom(), socket module to use
  -%%           Socket       = term(), the socket
  -%%           Len          = integer(), how much more data to read
  -%%           DataIn       = list()
  -%% Descrip.: Read a pre-determined ammount of more data from a socket.
  -%% Returns : DataOut             |
  -%%           {connection_closed} |
  -%%           {error, Reason}
  -%%           Reason = string()
  -%%--------------------------------------------------------------------
  -tcp_read_more_data(SocketModule, Socket, Len, DataIn) when Len > 0 ->
  -    case SocketModule:recv(Socket, 0) of
  -	{ok, B} ->
  -	    Data = binary_to_list(B),
  -	    L = length(Data),
  -	    logger:log(debug, "TCP receiver: Extra debug: Received ~p bytes of data (~p more expected)",
  -		       [L, Len - L]),
  -	    SoFar = lists:append(DataIn, Data),
  -	    tcp_read_more_data(SocketModule, Socket, Len - length(Data), SoFar);
  -	{error, closed} ->
  -	    logger:log(debug, "TCP receiver: Extra debug: ~p recv() returned 'closed' in tcp_read_more_data() (Socket: ~p)",
  -		       [SocketModule, Socket]),
  -	    {connection_closed};
  -	{error, E} ->
  -	    logger:log(error, "TCP receiver: Error when reading ~p bytes of data : ~s (~p)",
  -		       [Len, inet:format_error(E), E]),
  -	    {error, E}
  -    end;
  -
  -tcp_read_more_data(_SocketModule, _Socket, _Len, In) ->
  -    In.
  -
  -%%--------------------------------------------------------------------
  -%% Function: remove_separator(Data)
  -%%           Data = list()
  -%% Descrip.: RFC3261 7.5. Remove linefeeds between messages (often
  -%%           used as keepalive messages).
  -%% Returns : DataOut
  -%%           DataOut = list()
  -%%--------------------------------------------------------------------
  -remove_separator([H|T]) when H == $\r;H == $\n ->
  -    remove_separator(T);
  -remove_separator(L) ->
  -    L.
  +%%====================================================================
  +%% Test functions
  +%%====================================================================
  +
  +%%--------------------------------------------------------------------
  +%% Function: test()
  +%% Descrip.: autotest callback
  +%% Returns : ok
  +%%--------------------------------------------------------------------
  +test() ->
  +    %% handle_received_data2/2
  +    %%--------------------------------------------------------------------
  +    EmptyRecv = #recv{},
  +
  +    io:format("test: handle_received_data2/2 - 1~n"),
  +    %% check that we properly ignore leading CRLF's
  +    EmptyRecv = handle_received_data2(<<?CR, ?LF>>, EmptyRecv),
  +
  +    io:format("test: handle_received_data2/2 - 2~n"),
  +    %% check that we properly ignore leading LF's
  +    EmptyRecv = handle_received_data2(<<?LF>>, EmptyRecv),
  +
  +    io:format("test: handle_received_data2/2 - 3~n"),
  +    %% one CR is stored in recv.frame
  +    #recv{frame = <<?CR>>} = HRD_2_Recv = handle_received_data2(<<?CR>>, EmptyRecv),
  +
  +    io:format("test: handle_received_data2/2 - 4~n"),
  +    %% but when it is followed by a LF recv.frame is emptied
  +    EmptyRecv = handle_received_data2(<<?LF>>, HRD_2_Recv),
  +
  +    io:format("test: handle_received_data2/2 - 5~n"),
  +    %% check that we properly ignore a bundle of leading CRLF's and LF's
  +    EmptyRecv = handle_received_data2(<<?CR, ?LF, ?LF, ?LF, ?CR, ?LF, ?CR, ?LF, ?LF>>, EmptyRecv),
  +
  +    io:format("test: handle_received_data2/2 - 7.1~n"),
  +    HRD_7_Data = <<
  +		  "INVITE sip:ft@example.org SIP/2.0", ?CR, ?LF,
  +		  "Foo: bar", ?CR, ?LF,
  +		  "Content-Length: 0", ?CR, ?LF,
  +		  ?CR, ?LF
  +		  >>,
  +    HRD7_URI = sipurl:parse("sip:ft@example.org"),
  +    %% receive a complete request at once, result should be like EmptyRecv but with
  +    %% the request parsed and ready in msg_stack
  +    HRD_7_Recv = handle_received_data2(HRD_7_Data, EmptyRecv),
  +    %% verify msg_stack
  +    [HRD_7_Req] = HRD_7_Recv#recv.msg_stack,
  +    %% verify that msg_stack was the only thing set in HRD_7_Recv
  +    EmptyRecv = HRD_7_Recv#recv{msg_stack=[]},
  +
  +    io:format("test: handle_received_data2/2 - 7.2~n"),
  +    %% verify results
  +    true = is_record(HRD_7_Req, request),
  +    "INVITE" = HRD_7_Req#request.method,
  +    HRD7_URI = HRD_7_Req#request.uri,
  +    ["bar"] = keylist:fetch("foo", HRD_7_Req#request.header),
  +    ["0"] = keylist:fetch('content-length', HRD_7_Req#request.header),
  +    <<>> = HRD_7_Req#request.body,
  +
  +    io:format("test: handle_received_data2/2 - 8~n"),
  +    %% test two requests in the same packet (use the requests from test 7 above)
  +    HRD_8_Recv = handle_received_data2(list_to_binary([HRD_7_Data, HRD_7_Data]), EmptyRecv),
  +    %% verify msg_stack
  +    [HRD_7_Req, HRD_7_Req] = HRD_8_Recv#recv.msg_stack,
  +    %% verify that msg_stack was the only thing set in HRD_8_Recv
  +    EmptyRecv = HRD_8_Recv#recv{msg_stack=[]},
  +
  +    io:format("test: handle_received_data2/2 - 9~n"),
  +    %% start receiving a request
  +    HRD_9_Recv = handle_received_data2(<<?LF, ?CR, ?LF, "INVITE sip:ft@example.org ">>, EmptyRecv),
  +    HRD_9_Recv = EmptyRecv#recv{frame = <<"INVITE sip:ft@example.org ">>},
  +
  +    io:format("test: handle_received_data2/2 - 10~n"),
  +    HRD_10_Data = <<"INVITE sip:ft@example.org SIP/2.0", ?CR, ?LF>>,
  +    %% receive more
  +    HRD_10_Recv = handle_received_data2(<<"SIP/2.0", ?CR, ?LF>>, HRD_9_Recv),
  +    HRD_10_Recv = EmptyRecv#recv{frame = HRD_10_Data},
  +
  +    io:format("test: handle_received_data2/2 - 11~n"),
  +    HRD_11_Data = <<
  +		   "Foo: ", ?LF,
  +		   "  bar", ?CR, ?LF,
  +		   "Content-Length: 0004", ?CR, ?LF,
  +		   ?CR
  +		   >>,
  +    %% some headers (mixed line endings), and half the header-body separator
  +    HRD_11_Recv = handle_received_data2(HRD_11_Data, HRD_10_Recv),
  +    %% quickly verify the results
  +    HRD_11_Frame = list_to_binary([HRD_10_Data, HRD_11_Data]),
  +    HRD_11_Frame = HRD_11_Recv#recv.frame,
  +
  +    io:format("test: handle_received_data2/2 - 12.1~n"),
  +    %% now receive a single LF which means we now are exactly at the header-body
  +    %% separator and are just waiting for four bytes of body
  +    HRD_12_Recv = handle_received_data2(<<?LF>>, HRD_11_Recv),
  +    io:format("test: handle_received_data2/2 - 12.2~n"),
  +    %% quickly verify the results (body length)
  +    4 = HRD_12_Recv#recv.body_length,
  +    io:format("test: handle_received_data2/2 - 12.3~n"),
  +    %% quickly verify the results (body offset)
  +    HRD_12_Right_Body_Offset = size(HRD_11_Frame) + 1,
  +    HRD_12_Right_Body_Offset = HRD_12_Recv#recv.body_offset,
  +    io:format("test: handle_received_data2/2 - 12.4~n"),
  +    4 = HRD_12_Recv#recv.bytes_left,
  +
  +    io:format("test: handle_received_data2/2 - 13.1~n"),
  +    %% receive the four body bytes plus some chars from the next request
  +    HRD_13_Recv = handle_received_data2(<<"testINV">>, HRD_12_Recv),
  +
  +    io:format("test: handle_received_data2/2 - 13.2~n"),
  +    %% verify the results
  +    [HRD_13_Req] = HRD_13_Recv#recv.msg_stack,
  +    true = is_record(HRD_13_Req, request),
  +
  +    io:format("test: handle_received_data2/2 - 13.3~n"),
  +    %% verify headers
  +    ["bar"] = keylist:fetch("foo", HRD_13_Req#request.header),
  +    io:format("test: handle_received_data2/2 - 13.4~n"),
  +    ["0004"] = keylist:fetch('content-length', HRD_13_Req#request.header),
  +
  +    io:format("test: handle_received_data2/2 - 13.5~n"),
  +    %% verify body
  +    <<"test">> = HRD_13_Req#request.body,
  +
  +    io:format("test: handle_received_data2/2 - 13.6~n"),
  +    %% verify next frame data
  +    <<"INV">> = HRD_13_Recv#recv.frame,
  +
  +    io:format("test: handle_received_data2/2 - 14.1~n"),
  +    %% Make a data entry with a request, two responses and then the same request again.
  +    %% We then feed this to handle_received_data2/2 one byte at a time, and then verify
  +    %% the results
  +    HRD_14_Req_Data =
  +	"INVITE sip:ft@example.org SIP/2.0\n"
  +	"Foo: bar\n"
  +	"Content-Length: 3\n"
  +	"\n"
  +	"one",
  +    %% Short form of header Content-Length
  +    HRD_14_Res1_Data =
  +	"SIP/2.0 100 Trying\r\n"
  +	"Foo: bar\r\n"
  +	"l:0\r\n"
  +	"\r\n",
  +    %% A bunch of CR/LFs between requests (should be ignored)
  +    HRD_14_Ignore = "\r\n\r\n\n\n\r\n",
  +    %% Another request, with a binary body
  +    HRD_14_Res2_Data =
  +	"SIP/2.0 404 Not Found\r\n"
  +	"Foo: bar\r\n"
  +	"Content-Length: 8\r\n"
  +	"\r\n" ++
  +	[1,2,3,4,5,6,7,8],
  +
  +    HRD_14_Data = HRD_14_Req_Data ++ HRD_14_Res1_Data ++ HRD_14_Ignore ++
  +	HRD_14_Res2_Data ++ HRD_14_Ignore ++ HRD_14_Req_Data,
  +
  +    io:format("test: handle_received_data2/2 - 14.2~n"),
  +    HRD_14_Recv =
  +	lists:foldl(fun(H, Recv) when is_record(Recv, recv) ->
  +			    B = list_to_binary([H]),
  +			    handle_received_data2(B, Recv)
  +		    end, EmptyRecv, HRD_14_Data),
  +
  +    io:format("test: handle_received_data2/2 - 14.3~n"),
  +    %% verify the results (msg_stack and record types)
  +    [HRD_14_Req, HRD_14_Res1, HRD_14_Res2, HRD_14_Req] = lists:reverse(HRD_14_Recv#recv.msg_stack),
  +    true = is_record(HRD_14_Req, request),
  +    true = is_record(HRD_14_Res1, response),
  +    true = is_record(HRD_14_Res2, response),
  +
  +    io:format("test: handle_received_data2/2 - 14.4~n"),
  +    %% verify the results (bodys)
  +    <<"one">> = HRD_14_Req#request.body,
  +    <<>> = HRD_14_Res1#response.body,
  +    <<1,2,3,4,5,6,7,8>> = HRD_14_Res2#response.body,
  +
  +
  +    %% test invalid content-length
  +
  +    io:format("test: handle_received_data2/2 - 15~n"),
  +    %% invalid Content-Length in request
  +    HRD_15_Data = <<
  +		   "INVITE sip:ft@example.org SIP/2.0", ?CR, ?LF,
  +		   "Foo: bar", ?CR, ?LF,
  +		   "Content-Length: broken", ?CR, ?LF,
  +		   ?CR, ?LF
  +		   >>,
  +    {error, parse_failed, _} =
  +	(catch handle_received_data2(HRD_15_Data, EmptyRecv)),
  +
  +    io:format("test: handle_received_data2/2 - 16~n"),
  +    %% invalid (double) Content-Length in response
  +    HRD_16_Data = <<
  +		   "SIP/2.0 100 Trying", ?CR, ?LF,
  +		   "Foo: bar", ?CR, ?LF,
  +		   "Content-Length: 1, 2", ?CR, ?LF,
  +		   ?CR, ?LF
  +		   >>,
  +    {error, parse_failed, _} =
  +	(catch handle_received_data2(HRD_16_Data, EmptyRecv)),
  +
  +    ok.
  
positive.code: 	  linked=no
  	 }).
  
  %%====================================================================
  %% External functions
  %%====================================================================
  
negative.code: %% Returns : void()
  %%--------------------------------------------------------------------
  start_link(SocketModule, Socket, Local, Remote, SipSocket) ->
      State = #state{socketmodule=SocketModule, socket=Socket, parent=self(),
  		   local=Local, remote=Remote, sipsocket=SipSocket},
  
      %% Create origin string for logging the source of received frames
      {IP, Port} = State#state.remote,
      Origin = #siporigin{proto=SipSocket#sipsocket.proto, addr=IP, port=Port, receiver=self(), sipsocket=SipSocket},
      OriginStr = sipserver:origin2str(Origin),
  
      Recv = #recv{origin_str=OriginStr},
      Pid = spawn_link(?MODULE, recv_loop, [State, Recv]),
      Pid.
  
  %%====================================================================
  