cosfiletransfer_filetransfersession_impl.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,040 行 · 第 1/3 页
ERL
1,040 行
{active, false}|Options]), {ok, Port} = ssl:port(Socket), {Socket, [#'CosFileTransfer_ProtocolSupport'{protocol_name="SSL", addresses = [local_address(Port)]}]}.local_address(Port) -> {ok, Hostname} = inet:gethostname(), {ok, {A1, A2, A3, A4}} = inet:getaddr(Hostname, inet), integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3) ++ "." ++ integer_to_list(A4)++":"++integer_to_list(Port).ssl_server_cacertfile_option() -> case cosFileTransferApp:ssl_server_cacertfile() of [] -> []; X when list(X) -> [{cacertfile, X}]; _ -> [] end.%%----------------------------------------------------------------------%% Function : source_file_operation%% Arguments : %% Returns : %% Description: %%----------------------------------------------------------------------source_FTS_operation(State, SrcFile, DestFile, Op, Offset, FTS) -> Mod = ?get_Module(State), %% The source FTS is supposed to be the active one, set up a connection. Protocols = 'CosFileTransfer_FileTransferSession':'_get_protocols_supported'(FTS), SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile), TempName = cosFileTransferApp:create_name("TemporarySrcFile"), case Mod:recv(?get_Server(State), filename:join(SrcName), TempName) of ok when Op == insert -> %% Downloaded the File, we are now ready to transmit. Pid = spawn(?MODULE, invoke_call, [self(), insert, [FTS, SrcFile, DestFile, Offset]]), send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), TempName), %% Delete the temporary local copy. delete_tmp_file(TempName, "Transfer completed but failed to remove temporary local copy."), check_reply(Pid), {reply, ok, State}; ok -> %% Downloaded the File, we are now ready to transmit. Pid = spawn(?MODULE, invoke_call, [self(), Op, [FTS, SrcFile, DestFile]]), send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), TempName), %% Delete the temporary local copy. delete_tmp_file(TempName, "Transfer completed but failed to remove temporary local copy."), check_reply(Pid), {reply, ok, State}; {error, epath} -> corba:raise(#'CosFileTransfer_FileNotFoundException' {reason="File not found."}); {error, elogin} -> corba:raise(#'CosFileTransfer_SessionException' {reason="User not loggen in."}); {error, econn} -> corba:raise(#'CosFileTransfer_RequestFailureException' {reason="Premature connection ending."}) end. %%----------------------------------------------------------------------%% Function : target_file_operation%% Arguments : %% Returns : %% Description: %%----------------------------------------------------------------------target_FTS_operation(State, _SrcFile, DestFile, Op, Offset) -> Mod = ?get_Module(State), DestName = 'CosFileTransfer_File':'_get_complete_file_name'(DestFile), TempName = cosFileTransferApp:create_name("TemporaryDestFile"), receive_file(?get_MyType(State), ?get_Connection(State), ?get_ConnectionTimeout(State), TempName, write), Result = if Op == insert -> Mod:insert(?get_Server(State), TempName, filename:join(DestName), Offset); true -> Mod:Op(?get_Server(State), TempName, filename:join(DestName)) end, case Result of ok -> %% Delete the temporary local copy. delete_tmp_file(TempName, "Transfer completed but failed to remove temporary local copy."), %% Completed the transfer succesfully. {reply, ok, State}; {error, epath} -> delete_tmp_file(TempName, "IllegalOperationException and not able to remove temporary local copy."), corba:raise(#'CosFileTransfer_IllegalOperationException' {reason="Not allowed by destination."}); {error, elogin} -> delete_tmp_file(TempName, "SessionException and not able to remove temporary local copy."), corba:raise(#'CosFileTransfer_SessionException' {reason="User not logged in."}); {error, econn} -> delete_tmp_file(TempName, "TransferException and not able to remove temporary local copy."), corba:raise(#'CosFileTransfer_TransferException' {reason="Premature connection ending."}); {error, etnospc} -> delete_tmp_file(TempName, "RequestFailureException and not able to remove temporary local copy."), corba:raise(#'CosFileTransfer_RequestFailureException' {reason="Premature connection ending."}); {error, efnamena} -> delete_tmp_file(TempName, "IllegalOperationException and not able to remove temporary local copy."), corba:raise(#'CosFileTransfer_IllegalOperationException' {reason="Not allowed by destination."}) end.%%----------------------------------------------------------------------%% Function : receive_file%% Arguments : Driver - currently only gen_tcp supported.%% LSocket - which socket to use.%% FileName - an absolute file name representing the%% file we want to create or append to.%% Type - 'read', 'write', 'append'.%% Returns : %% Description: %%----------------------------------------------------------------------receive_file(tcp, LSock, Timeout, FileName, Type) -> %% The Type can be the ones allowed by the file-module, i.e., %% 'read', 'write' or 'append' FD = file_open(FileName, Type), case gen_tcp:accept(LSock, Timeout) of {ok, Sock} -> receive_file_helper(gen_tcp, Sock, FD); {error, timeout} -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file();gen_tcp:accept(~p) timed out", [?LINE, Timeout], ?DEBUG_LEVEL), corba:raise(#'CosFileTransfer_RequestFailureException' {reason="TCP accept timed out.."}); {error, Why} -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file();gen_tcp:accept(~p) failed: ~p", [?LINE, Timeout, Why], ?DEBUG_LEVEL), corba:raise(#'CosFileTransfer_RequestFailureException' {reason="TCP accept failed."}) end;receive_file(ssl, LSock, Timeout, FileName, Type) -> %% The Type can be the ones allowed by the file-module, i.e., %% 'read', 'write' or 'append' FD = file_open(FileName, Type), case ssl:accept(LSock, Timeout) of {ok, Sock} -> receive_file_helper(ssl, Sock, FD); {error, timeout} -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file();ssl:accept(~p) timed out", [?LINE, Timeout], ?DEBUG_LEVEL), corba:raise(#'CosFileTransfer_RequestFailureException' {reason="TCP accept timed out.."}); {error, Why} -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file();ssl:accept(~p) failed: ~p", [?LINE, Timeout, Why], ?DEBUG_LEVEL), corba:raise(#'CosFileTransfer_RequestFailureException' {reason="TCP accept failed."}) end.receive_file_helper(Driver, Sock, FD) -> case Driver:recv(Sock, 0) of {ok, Bin} -> file:write(FD, Bin), receive_file_helper(Driver, Sock, FD); {error, closed} -> file:close(FD); What -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file(~p);Error occured when receiving data: ~p", [?LINE, Driver, What], ?DEBUG_LEVEL), corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) end.%%----------------------------------------------------------------------%% Function : send_file%% Arguments : Driver - currently only gen_tcp supported.%% Sock - which socket to use.%% FileName - an absolute file name representing the%% file we want to send.%% Returns : %% Description: %%----------------------------------------------------------------------send_file(Protocols, Type, Timeout, FileName) -> {Driver, Sock} = setup_connection(Protocols, Type, Timeout), FD = file_open(FileName, read), BuffSize = cosFileTransferApp:get_buffert_size(), send_file_helper(Driver, Sock, FD, BuffSize).send_file_helper(Driver, Sock, FD, BuffSize) -> case file:read(FD, BuffSize) of eof -> file:close(FD), Driver:close(Sock); {ok, Bin} -> case Driver:send(Sock, Bin) of ok -> send_file_helper(Driver, Sock, FD, BuffSize); What -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:send_file_helper(~p);Error occured when sending data: ~p", [?LINE, Driver, What], ?DEBUG_LEVEL), corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) end end.file_open(File, Type) -> case file:open(File, [raw, binary, Type]) of {ok, FD} -> FD; {error, What} -> orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:file_open(~p);Failed to open the file due to: ~p", [?LINE, File, What], ?DEBUG_LEVEL), corba:raise(#'CosFileTransfer_RequestFailureException' {reason="Unable to open given file."}) end.%%----------------------------------------------------------------------%% Function : check_type%% Arguments : FullName - an absolute file name representing the%% file or directory we want to evaluate.%% Returns : %% Description: %% When communcating with FTP-servers on different platforms a variety of%% answers can be returned. A few examples:%%%% ### ftp:nlist on an empty directory ###%% {ok, ""}, {error, epath}%% %% ### ftp:nlist on a non-existing directory or file ###%% {ok, "XXX: No such file or directory}, {error, epath}%%%% ### ftp:nlist on an existing directory with one contained item ###%% {ok, "Item"}%%%% Comparing the above we see that it's virtually impossible to tell apart%% {ok, "XXX: No such file or directory} and {ok, "Item"}.%% Hence, it's easier to test if it's possible to do ftp:cd instead.%% Ugly, but rather effective. If we look at the bright side, it's only%% necessary when we try to lookup:%% * non-existing item%% * A directory with one member only.%% * An empty directory.%% %% Furthermore, no need for traversing Listings etc.%%----------------------------------------------------------------------check_type(_OE_This, State, FullName) when ?is_FTP(State); ?is_NATIVE(State) -> Mod = ?get_Module(State), Result = case Mod:nlist(?get_Server(State), FullName) of {ok, Listing} when length(Listing) > 0-> case string:tokens(Listing, ?SEPARATOR) of [FullName] -> nfile; Members when length(Members) > 1 -> %% Must test if more than one member since sometimes %% this operation returns for example: %% {ok, "XXX No such file or drectory"} {ndirectory, Members}; Member -> case Mod:cd(?get_Server(State), FullName) of ok -> case Mod:cd(?get_Server(State), ?get_CurrentDir(State)) of ok -> {ndirectory, Member}; _ -> %% Failed, we cannot continue since the %% FTS now pointso an incorrect Directory. %% Hence, we must terminate. {stop, normal, {'EXCEPTION', #'CosFileTransfer_RequestFailureException' {reason="Unknown error."}}, State} end; {error, E} -> {error, E}; _ -> nfile end end; {error, epath} -> %% Might be a file. DirName = filename:dirname(FullName), case Mod:nlist(?get_Server(State), DirName) of {ok, Listing} when length(Listing) > 0-> Members = string:tokens(Listing, ?SEPARATOR), case lists:member(FullName, Members) of true -> nfile; _ -> BName = filename:basename(FullName), case lists:member(BName, Members) of true -> nfile; _ -> {error, epath} end end; _ -> {error, epath} end; _ -> case Mod:cd(?get_Server(State), FullName) of ok -> case Mod:cd(?get_Server(State), ?get_CurrentDir(State)) of ok -> {ndirectory, []}; _ -> %% Failed, we cannot continue since the %% FTS now pointso an incorrect Directory. %% Hence, we must terminate. {stop, normal, {'EXCEPTION', #'CosFileTransfer_RequestFailureException' {reason="Unknown error."}}, State} end; _ -> {error, epath} end end, case Result of {error, epath} -> corba:raise(#'CosFileTransfer_FileNotFoundException' {reason="File or Directory not found."}); {error, elogin} -> corba:raise(#'CosFileTransfer_SessionException' {reason="User not logged in."}); {error, econn} -> corba:raise(#'CosFileTransfer_RequestFailureException' {reason="Premature connection ending."}); Other -> Other end.%%======================================================================%% END OF MODULE%%======================================================================
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?