diff options
Diffstat (limited to 'src/ranch_tcp.erl')
-rw-r--r-- | src/ranch_tcp.erl | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/src/ranch_tcp.erl b/src/ranch_tcp.erl index 11a0843..6bdcdd0 100644 --- a/src/ranch_tcp.erl +++ b/src/ranch_tcp.erl @@ -28,6 +28,8 @@ -export([recv/3]). -export([send/2]). -export([sendfile/2]). +-export([sendfile/4]). +-export([sendfile/5]). -export([setopts/2]). -export([controlling_process/2]). -export([peername/1]). @@ -110,21 +112,52 @@ recv(Socket, Length, Timeout) -> send(Socket, Packet) -> gen_tcp:send(Socket, Packet). -%% @doc Send a file on a socket. +%% @equiv sendfile(Socket, File, Offset, Bytes, []) +-spec sendfile(inet:socket(), file:name_all()) + -> {ok, non_neg_integer()} | {error, atom()}. +sendfile(Socket, Filename) -> + sendfile(Socket, Filename, 0, 0, []). + +%% @equiv sendfile(Socket, File, Offset, Bytes, []) +-spec sendfile(inet:socket(), file:name_all() | file:fd(), non_neg_integer(), + non_neg_integer()) + -> {ok, non_neg_integer()} | {error, atom()}. +sendfile(Socket, File, Offset, Bytes) -> + sendfile(Socket, File, Offset, Bytes, []). + +%% @doc Send part of a file on a socket. %% -%% This is the optimal way to send files using TCP. It uses a syscall -%% which means there is no context switch between opening the file -%% and writing its contents on the socket. +%% As with sendfile/2 this is the optimal way to send (parts) of files using +%% TCP. Note that unlike file:sendfile/5 this function accepts either a raw file +%% or a file name and the ordering of arguments is different. %% -%% @see file:sendfile/2 --spec sendfile(inet:socket(), file:name()) +%% @see file:sendfile/5 +-spec sendfile(inet:socket(), file:name_all() | file:fd(), non_neg_integer(), + non_neg_integer(), [{chunk_size, non_neg_integer()}]) -> {ok, non_neg_integer()} | {error, atom()}. -sendfile(Socket, Filename) -> - try file:sendfile(Filename, Socket) of +sendfile(Socket, Filename, Offset, Bytes, Opts) + when is_list(Filename) orelse is_atom(Filename) + orelse is_binary(Filename) -> + case file:open(Filename, [read, raw, binary]) of + {ok, RawFile} -> + try sendfile(Socket, RawFile, Offset, Bytes, Opts) of + Result -> Result + after + ok = file:close(RawFile) + end; + {error, _} = Error -> + Error + end; +sendfile(Socket, RawFile, Offset, Bytes, Opts) -> + Opts2 = case Opts of + [] -> [{chunk_size, 16#1FFF}]; + _ -> Opts + end, + try file:sendfile(RawFile, Socket, Offset, Bytes, Opts2) of Result -> Result catch error:{badmatch, {error, enotconn}} -> - %% file:sendfile/2 might fail by throwing a {badmatch, {error, enotconn}} + %% file:sendfile/5 might fail by throwing a {badmatch, {error, enotconn}} %% this is because its internal implementation fails with a badmatch in %% prim_file:sendfile/10 if the socket is not connected. {error, closed} |