aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tls/tls.erl33
-rw-r--r--src/tls/tls_drv.c13
-rw-r--r--src/web/ejabberd_http.erl52
3 files changed, 50 insertions, 48 deletions
diff --git a/src/tls/tls.erl b/src/tls/tls.erl
index dfb9d2306..e4184a09a 100644
--- a/src/tls/tls.erl
+++ b/src/tls/tls.erl
@@ -32,7 +32,7 @@
-export([start/0, start_link/0,
tcp_to_tls/2, tls_to_tcp/1,
send/2,
- recv/2, recv/3, recv_data/2,
+ recv/2, recv/3,
setopts/2,
sockname/1, peername/1,
controlling_process/2,
@@ -160,29 +160,34 @@ tls_to_tcp(#tlssock{tcpsock = TCPSocket, tlsport = Port}) ->
recv(Socket, Length) ->
recv(Socket, Length, infinity).
-recv(#tlssock{tcpsock = TCPSocket} = TLSSock,
- _Length, Timeout) ->
- %% The Length argument cannot be used for gen_tcp:recv/3, because the
- %% compressed size does not equal the desired uncompressed one.
- case gen_tcp:recv(TCPSocket, 0, Timeout) of
- {ok, Packet} ->
- recv_data(TLSSock, Packet);
- {error, _Reason} = Error ->
- Error
+recv(#tlssock{tcpsock = TCPSocket, tlsport = Port} = TLSSock,
+ Length, Timeout) ->
+ case port_control(Port, ?GET_DECRYPTED_INPUT, <<Length:32>>) of
+ <<0>> ->
+ case gen_tcp:recv(TCPSocket, 0, Timeout) of
+ {ok, Packet} ->
+ recv_data(TLSSock, Packet, Length);
+ {error, _Reason} = Error ->
+ Error
+ end;
+ <<0, In/binary>> ->
+ {ok, In};
+ <<1, Error/binary>> ->
+ {error, binary_to_list(Error)}
end.
-recv_data(TLSSock, Packet) ->
- case catch recv_data1(TLSSock, Packet) of
+recv_data(TLSSock, Packet, Length) ->
+ case catch recv_data1(TLSSock, Packet, Length) of
{'EXIT', Reason} ->
{error, Reason};
Res ->
Res
end.
-recv_data1(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
+recv_data1(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet, Length) ->
case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of
<<0>> ->
- case port_control(Port, ?GET_DECRYPTED_INPUT, []) of
+ case port_control(Port, ?GET_DECRYPTED_INPUT, <<Length:32>>) of
<<0, In/binary>> ->
case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
<<0, Out/binary>> ->
diff --git a/src/tls/tls_drv.c b/src/tls/tls_drv.c
index 40295d7a3..60a51174d 100644
--- a/src/tls/tls_drv.c
+++ b/src/tls/tls_drv.c
@@ -434,13 +434,22 @@ static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
"SSL_do_handshake failed");
}
if (SSL_is_init_finished(d->ssl)) {
+ size_t req_size = 0;
+ if (len == 4)
+ {
+ req_size =
+ (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ }
size = BUF_SIZE + 1;
rlen = 1;
b = driver_alloc_binary(size);
b->orig_bytes[0] = 0;
- while ((res = SSL_read(d->ssl,
- b->orig_bytes + rlen, BUF_SIZE)) > 0)
+ while ((req_size == 0 || rlen < req_size + 1) &&
+ (res = SSL_read(d->ssl,
+ b->orig_bytes + rlen,
+ (req_size == 0 || req_size + 1 >= size) ?
+ size - rlen : req_size + 1 - rlen)) > 0)
{
//printf("%d bytes of decrypted data read from state machine\r\n",res);
rlen += res;
diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl
index aff928f72..fab09782a 100644
--- a/src/web/ejabberd_http.erl
+++ b/src/web/ejabberd_http.erl
@@ -192,38 +192,30 @@ receive_headers(State) ->
_ ->
case Data of
{ok, Binary} ->
- process_requests(State, binary_to_list(Binary));
+ {Request, Trail} = parse_request(
+ State,
+ State#state.trail ++ binary_to_list(Binary)),
+ State1 = State#state{trail = Trail},
+ NewState = lists:foldl(
+ fun(D, S) ->
+ case S#state.end_of_request of
+ true ->
+ S;
+ _ ->
+ process_header(S, D)
+ end
+ end, State1, Request),
+ case NewState#state.end_of_request of
+ true ->
+ ok;
+ _ ->
+ receive_headers(NewState)
+ end;
_ ->
ok
end
end.
-process_requests(State, Data) ->
- {Request, Trail} = parse_request(
- State,
- State#state.trail ++ Data),
- State1 = State#state{trail = Trail},
- NewState = lists:foldl(
- fun(D, S) ->
- case S#state.end_of_request of
- true ->
- S;
- _ ->
- process_header(S, D)
- end
- end, State1, Request),
- case State1#state.trail of
- [] ->
- case NewState#state.end_of_request of
- true ->
- ok;
- _ ->
- receive_headers(NewState)
- end;
- _ ->
- process_requests(State1, "")
- end.
-
process_header(State, Data) ->
SockMod = State#state.sockmod,
Socket = State#state.socket,
@@ -599,11 +591,7 @@ recv_data(_State, 0, Acc) ->
recv_data(State, Len, Acc) ->
case State#state.trail of
[] ->
- Len2 = case State#state.sockmod of
- gen_tcp -> Len;
- _ -> 0
- end,
- case (State#state.sockmod):recv(State#state.socket, Len2, 300000) of
+ case (State#state.sockmod):recv(State#state.socket, Len, 300000) of
{ok, Data} ->
recv_data(State, Len - size(Data), [Acc | [Data]]);
_ ->