Changeset View
Changeset View
Standalone View
Standalone View
apps/kolab_guam/src/kolab_guam_session.erl
Show First 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | case CurrentCommandSplit of | ||||
{ 0, _ } -> undefined; | { 0, _ } -> undefined; | ||||
{ Start, _ } -> | { Start, _ } -> | ||||
case binary:at(Data, Start - 1) of | case binary:at(Data, Start - 1) of | ||||
$\n -> undefined; | $\n -> undefined; | ||||
_ -> CurrentCommandSplit | _ -> CurrentCommandSplit | ||||
end | end | ||||
end | end | ||||
end; | end; | ||||
update_split_command_state(Data, #state{ command_split_reset_trigger = reset_for_next_client_command, current_command_split = CurrentCommandSplit }) -> | |||||
%If we have a currently active command (CurrentCommandSplit), then we reset only if we find a new command (and not just on any new line). | |||||
%This is relevant for multi-line commands such as APPEND, which follow up with a continuation which we want to avoid buffering. | |||||
case CurrentCommandSplit of | |||||
undefined -> undefined; | |||||
_ -> | |||||
case eimap_utils:split_command_into_components(Data) of | |||||
{ <<>>, <<>>, <<>> } -> CurrentCommandSplit; | |||||
{ _Tag, <<>>, <<>> } -> CurrentCommandSplit; | |||||
{ _Tag, Command, _Data } -> undefined | |||||
end | |||||
end; | |||||
update_split_command_state(_Data, _State) -> | update_split_command_state(_Data, _State) -> | ||||
undefined. | undefined. | ||||
accept_client(#state{ client_implicit_tls = true, tls_config = TLSConfig, listen_socket = ListenSocket, super_pid = SupervisorPID }) -> | accept_client(#state{ client_implicit_tls = true, tls_config = TLSConfig, listen_socket = ListenSocket, super_pid = SupervisorPID }) -> | ||||
AcceptSocket = accept_socket(ListenSocket, SupervisorPID), | AcceptSocket = accept_socket(ListenSocket, SupervisorPID), | ||||
%% prep for the next listen | %% prep for the next listen | ||||
{ ok, SSLSocket } = ssl:ssl_accept(AcceptSocket, TLSConfig), | { ok, SSLSocket } = ssl:ssl_accept(AcceptSocket, TLSConfig), | ||||
ok = ssl:setopts(SSLSocket, [{ active, once }, { mode, binary }]), | ok = ssl:setopts(SSLSocket, [{ active, once }, { mode, binary }]), | ||||
Show All 25 Lines | read_line(Data) -> | ||||
case binary:match(Data, <<"\r\n">>) of | case binary:match(Data, <<"\r\n">>) of | ||||
nomatch -> | nomatch -> | ||||
{Data, <<>>}; | {Data, <<>>}; | ||||
{SplitPos, SplitSize} -> | {SplitPos, SplitSize} -> | ||||
{binary:part(Data, 0, SplitPos + SplitSize), binary:part(Data, SplitPos + SplitSize, size(Data)-(SplitPos + SplitSize))} | {binary:part(Data, 0, SplitPos + SplitSize), binary:part(Data, SplitPos + SplitSize, size(Data)-(SplitPos + SplitSize))} | ||||
end. | end. | ||||
process_preprocessed_client_data(Socket, PreprocessData, #state{ command_split_reset_trigger = CurrentCommandSplitResetTrigger, current_command_split = CurrentCommandSplit } = State) -> | process_preprocessed_client_data(Socket, PreprocessData, State) -> | ||||
NewSplitCommand = case CurrentCommandSplitResetTrigger of | |||||
reset_for_next_client_command -> undefined; | |||||
_ -> CurrentCommandSplit | |||||
end, | |||||
% TODO Maybe we should prepend buffered data here instead. | |||||
{Line, Remainder} = read_line(PreprocessData), | {Line, Remainder} = read_line(PreprocessData), | ||||
NewState = process_client_line(Line, Socket, State#state{ current_command_split = NewSplitCommand }), | NewState = process_client_line(Line, Socket, State), | ||||
case Remainder of | case Remainder of | ||||
<<>> -> NewState; | <<>> -> NewState; | ||||
_ -> process_preprocessed_client_data(Socket, Remainder, NewState) | _ -> process_preprocessed_client_data(Socket, Remainder, NewState) | ||||
end. | end. | ||||
% Client data is processed as it comes in, but split up by lines if more than one line comes in at a time. | % Client data is processed as it comes in, but split up by lines if more than one line comes in at a time. | ||||
Show All 14 Lines | case check_for_transmission_change_commands(TLS, TLSConfig, Data, Deflator, Socket) of | ||||
false -> eimap:starttls(ImapSession, undefined, undefined); | false -> eimap:starttls(ImapSession, undefined, undefined); | ||||
_ -> ok | _ -> ok | ||||
end, | end, | ||||
{ true, SSLSocket, Inflator, Deflator, UndecidedRules, ActiveRules, <<>>, undefined, undefined }; | { true, SSLSocket, Inflator, Deflator, UndecidedRules, ActiveRules, <<>>, undefined, undefined }; | ||||
{ compression, NewInflator, NewDeflator } -> | { compression, NewInflator, NewDeflator } -> | ||||
eimap:compress(ImapSession), % TODO: make optional | eimap:compress(ImapSession), % TODO: make optional | ||||
{ TLS, Socket, NewInflator, NewDeflator, UndecidedRules, ActiveRules, <<>>, undefined, undefined }; | { TLS, Socket, NewInflator, NewDeflator, UndecidedRules, ActiveRules, <<>>, undefined, undefined }; | ||||
nochange -> | nochange -> | ||||
{ ModifiedData, NewSplitCommand, NewSplitResetTrigger, NewUndecidedRules, NewActiveRules, PostAction } = apply_ruleset_clientside(ImapSession, Socket, Data, CurrentCommandSplit, UndecidedRules, ActiveRules), | %We first check if we have to reset the split command before we process the new command in apply_ruleset_clientside | ||||
NewSplit = update_split_command_state(Data, State), | |||||
{ ModifiedData, NewSplitCommand, NewSplitResetTrigger, NewUndecidedRules, NewActiveRules, PostAction } = apply_ruleset_clientside(ImapSession, Socket, Data, NewSplit, UndecidedRules, ActiveRules), | |||||
BufferThisData = | BufferThisData = | ||||
case PostAction of | case PostAction of | ||||
perform_passthrough -> | perform_passthrough -> | ||||
eimap:passthrough_data(ImapSession, ModifiedData), | eimap:passthrough_data(ImapSession, ModifiedData), | ||||
<<>>; | <<>>; | ||||
buffer_data -> | buffer_data -> | ||||
Data | Data | ||||
end, | end, | ||||
▲ Show 20 Lines • Show All 211 Lines • Show Last 20 Lines |