📄 main.pas
字号:
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, FTKernelAPI, StdCtrls, ComCtrls, WinSock, ExtCtrls, Files,
MakeTorrent, InputPwd, StrUtils;
const
sIP = '222.77.186.53';
WM_REMOTE_CALL = WM_USER + 108;
type
TRemoteCallInfo = class(TObject)
pPeerID: array[0..19] of byte;
pInfoHash: array[0..19] of byte;
end;
TMainFrm = class(TForm)
GroupBox1: TGroupBox;
Edit1: TEdit;
Button1: TButton;
OpenDialog1: TOpenDialog;
GroupBox2: TGroupBox;
ProgressBar1: TProgressBar;
Button2: TButton;
Button3: TButton;
Memo1: TMemo;
Timer1: TTimer;
Memo2: TMemo;
Button4: TButton;
Button5: TButton;
Button6: TButton;
Timer2: TTimer;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Timer2Timer(Sender: TObject);
procedure WMRemoteCallMsg(var msg: TMessage); message WM_REMOTE_CALL;
private
{ Private declarations }
sStartupPath: string;
sTorrentFile: string;
nTotalFileSize: QWORD;
nPieceCount: DWord;
hDownloader: HDownloader;
sHexHashKey: string;
bSetSeq: Boolean;
function StartContext(): boolean;
function StopContext(): boolean;
function StartDownload(): boolean;
function StopDownload(): boolean;
public
{ Public declarations }
end;
//外部设置内网连接通知回调函数的指针
//Define callback function for Nat PEER notification
function ftk_nat_peer_cb(pInfoHash: PByte; lpszIP: PChar; nPort: Short; pPeerID: PByte): Boolean; stdcall;
var
MainFrm: TMainFrm;
WSAData: TWSAData;
function IFormatByte(nSize: Int64): string;
function FFormatByte(fSize: Double): string;
implementation
function Startup(): boolean;
var
ErrorCode: Integer;
begin
ErrorCode := WSAStartup($0202, WSAData);
if ErrorCode <> 0 then
result := False;
end;
function Cleanup: boolean;
var
ErrorCode: Integer;
begin
ErrorCode := WSACleanup;
if ErrorCode <> 0 then
Result := False;
end;
function TMainFrm.StartContext(): boolean;
var
sConfigFileName: string;
xhConfigIni: HConfigIni;
sLicenseKey: string;
begin
Result := False;
sLicenseKey := '851554BEA3F29D1EC3658672F131E48837C15A1F567E5C7CCC9E8EA94C023E';
sLicenseKey := sLicenseKey + '9C0B0FF2FFA4BA74303AF02CCC217FB83F9129D8A8883ECDCB2AF2B6236F33BDC0E8E05901635351D9ADBCA17774A8E112DB94941F0F74A7E6C8C6F60C78FA54C64BE134A41D863AFB8C13F027B3C44243AD9E8E926B68C09B95FFCC42DBC13BF1';
FTK_License_Set(PChar(sLicenseKey));
if FTK_Context_IsInit() then
begin
Memo1.lines.Add('FTK_Context_IsInit:: success!');
Exit;
end;
sConfigFileName := sStartupPath;
sConfigFileName := sConfigFileName + 'Config.ini';
Memo1.lines.Add('Config File: ' + sConfigFileName);
if not FTK_Context_Init(PChar(sConfigFileName), True) then
begin
Memo1.lines.Add('FTK_Context_Init:: failed!');
Exit;
end;
//如果想不使用配置文件更改绑定的端口
{xhConfigIni := FTK_Config_Open();
FTK_Config_SetInt(xhConfigIni, PChar('fix_port'), 1);
FTK_Config_SetInt(xhConfigIni, PChar('port'), 27800);
if not FTK_Context_Init2(xhConfigIni, True) then
begin
Memo1.lines.Add('FTK_Context_Init:: failed!');
FTK_Config_Close(xhConfigIni);
Exit;
end;
FTK_Config_Close(xhConfigIni);}
if FTK_Context_IsRunning() then
begin
Memo1.lines.Add('FTK_Context_IsRunning:: success!');
Exit;
end;
FTK_Context_Run();
if (not FTK_Context_IsRunning()) then
begin
Exit;
end;
//////////////////////////////////////////////////////////////////////////
//初始化内网穿透部分API
//预先设置是否需要输出日志,以及输出日志的级别( -1, 不输出日志 )
FTK_UDPT_PreInitLog(4);
//预先设置远程呼叫的回掉函数
FTK_UDPT_PreInitPeerCallCB(nil);
//设置穿透服务器的地址和端口
FTK_UDPT_SetTunnelInfo(PChar(sIP), 9911);
//初始化UDP穿透的环境(返回FALSE表示失败), 动态加载穿透需要的辅助动态库
//此处的IP和Port表示,当启用了,代理时, 通过此tcp方式登陆服务器
if (not FTK_UDPT_Init('FTKUDPxAPI.dll', 'FTKTCPxAPI.dll', PChar(sIP), 8199)) then
begin
MessageBox(Handle, '初始化内网穿透服务器环境失败, 请检测代理设置是否正确!', '', MB_OK);
Exit;
end;
//连接登陆服务器
//IP和Port表示, UDP登陆服务器的地址和端口
if (not FTK_UDPT_Connect(PChar(sIP), 9999)) then
begin
MessageBox(Handle, '登陆内网穿透服务器失败, 请检测代理设置是否正确!', '', MB_OK);
Exit;
end;
//设置时间事件函数
Timer2.Enabled := True;
Result := True;
end;
function TMainFrm.StopContext(): boolean;
begin
result := true;
//停止UDP穿透的内核
FTK_UDPT_Disconnect();
FTK_UDPT_Release();
if FTK_Context_IsInit() then
begin
FTK_Context_Release();
end;
end;
function TMainFrm.StartDownload(): boolean;
var
sValue: string;
xhTorrentFile: HTorrentFile;
aPreAllocFile: ArrayByte;
aPrePrioFile: array of char;
nFilesCount: Integer;
sTorrentPath: string;
sDestFileName: string;
i: Integer;
bRet: Boolean;
bCipher: Boolean;
nlengthStr: Integer;
begin
if FTK_Torrent_IsCipherTorrent(PAnsiChar(sTorrentFile)) then
begin
PwdForm := TPwdForm.Create(self);
if mrOK = PwdForm.ShowModal() then
begin
bCipher := True;
xhTorrentFile := FTK_Torrent_Open(PAnsiChar(sTorrentFile), CP_ACP, PChar(PwdForm.Edit1.Text));
end;
end
else
begin
xhTorrentFile := FTK_Torrent_Open(PAnsiChar(sTorrentFile));
end;
if not assigned(xhTorrentFile) then
begin
Memo1.lines.Add('StartDownload::Failed to open torrent file: !' + sTorrentFile);
Exit;
end;
Memo1.lines.Add('StartDownload::Success to open torrent file: !' + sTorrentFile);
nFilesCount := FTK_Torrent_GetFilesCount(xhTorrentFile);
SetLength(aPreAllocFile, nFilesCount);
for i := 0 to nFilesCount - 1 do
begin
aPreAllocFile[i] := 0;
end;
sTorrentPath := ExtractFilePath(sTorrentFile);
sDestFileName := sTorrentPath + FTK_Torrent_GetTorrentName(xhTorrentFile);
Memo1.lines.Add('StartDownload::Destination file: !' + sDestFileName);
sValue := FTK_Torrent_GetHexInfoHash(xhTorrentFile);
{ nLengthStr := length( sValue );
sHexHashKey := '';
for i := 1 to nlengthStr do
begin
if sValue[ i ] <> '%' then
begin
sHexHashKey := sHexHashKey + sValue[ i ];
end;
end; }
sHexHashkey := AnsiReplaceStr(sValue, '%', '');
hDownloader := FTK_Downloader_Open();
//SetLength(aPrePrioFile, nFilesCount);
//for i := 0 to nFilesCount - 1 do
//begin
// aPrePrioFile[i] := #254;
//end;
//aPrePrioFile[nFilesCount -1] := #0;
//FTK_Downloader_PreInitFilePriority(hDownloader, PChar(aPrePrioFile), nFilesCount);
FTK_Downloader_SetNatPeerCB( hDownloader, ftk_nat_peer_cb );
if bCipher = True then
begin
bRet := FTK_Downloader_Init(
hDownloader,
PAnsiChar(sTorrentFile),
PByte(aPreAllocFile), //*****
nFilesCount,
False,
PChar(sDestFileName),
PChar(sStartupPath + 'Config.ini'),
//If you want to don't output log file and status file ,input nil
//Ohterwise input a absolute log filename and status filename.
nil, //PChar( sStartupPath + 'Log\Downloader.log' ),
nil, //PChar( sStartupPath + sHexHashKey + '.status' ),
false, //如果想快速做种子,将这里设置为True,但是指向的目的路径一定要正确,后果自负
PChar(PwdForm.Edit1.Text), //password
CP_ACP);
end
else
begin
bRet := FTK_Downloader_Init(
hDownloader,
PAnsiChar(sTorrentFile),
PByte(aPreAllocFile), //*****
nFilesCount,
False,
PChar(sDestFileName),
PChar(sStartupPath + 'Config.ini'),
//If you want to don't output log file and status file ,input nil
//Ohterwise input a absolute log filename and status filename.
PChar(sStartupPath + 'Log\Downloader.log'),
PChar(sStartupPath + sHexHashKey + '.status'),
false, //如果想快速做种子,将这里设置为True,但是指向的目的路径一定要正确,后果自负
nil, //password
CP_ACP);
end;
if not bRet then
begin
Memo1.lines.Add('StartDownload::FTK_Downloader_Init failed!');
Exit;
end;
bRet := FTK_Downloader_Execute(hDownloader);
if not bRet then
begin
Memo1.lines.Add('StartDownload::FTK_Downloader_Execute failed!');
FTK_Downloader_Close(hDownloader);
hDownloader := nil;
Exit;
end;
FTK_GlobalVar_AddTorrentSHA1(PChar(sHexHashKey), hDownloader);
nTotalFileSize := FTK_Torrent_GetFileSize(xhTorrentFile);
nPieceCount := FTK_Torrent_GetPieceCount(xhTorrentFile);
FTK_Torrent_Close(xhTorrentFile);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -