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 + -
显示快捷键?