EnableExplicit Procedure UDP_Tracker_GetInfo(Connect, *Size.Unicode, Bytes, *Err.String) Protected *mem, Len, MemPos, Count Protected ErrS.s, ErrP.i MemPos=0 Count = 400 ErrP=0 ErrS="" *Err\s="" *mem=AllocateMemory(4048) If *mem FillMemory(*mem, 4048, 0) Repeat If NetworkClientEvent(Connect)=#PB_NetworkEvent_Data Len=ReceiveNetworkData(Connect, *mem+MemPos, 2048) If Len>0 MemPos+Len If Bytes>0 And MemPos>=Bytes If *Size : *Size\u = MemPos : EndIf Break ElseIf MemPos>4048 FreeMemory(*mem) *mem=0 If *Size : *Size\u = 0 : EndIf Break EndIf Count=20 EndIf Else If Count<380 ErrS=TestBadConnect(Connect, @ErrP, #True) If ErrP<>0 And ErrS<>"" If MemPos<=0 *Err\s=ErrS FreeMemory(*mem) *mem=0 EndIf Break EndIf EndIf Delay(16) Count - 1 If Count<=0 If *Size : *Size\u = MemPos : EndIf If MemPos=0 *Err\s="Трекер не ответил на запрос." FreeMemory(*mem) *mem=0 EndIf Break EndIf EndIf ForEver EndIf ProcedureReturn *mem EndProcedure Procedure.s UDP_Tracker_GetError(*Point, Size, Transaction_ID.l) ; Получение строки с ошибкой трекера. Protected Result.s, Err.UDP_Tracker_Error_Response If Size >= SizeOf(UDP_Tracker_Error_Response) CopyMemory(*Point, @Err, SizeOf(UDP_Tracker_Error_Response)) If Err\transaction_id = Transaction_ID And ReverseLong(Err\action) = 3 Result = PeekS(*Point+SizeOf(UDP_Tracker_Error_Response), Size-SizeOf(UDP_Tracker_Error_Response)-1, #PB_Ascii) ElseIf Err\transaction_id = Transaction_ID ;Size = SizeOf(UDP_Tracker_Error_Response) Result = "Ошибка формата данных." Else Result = "Ошибка UDP пакета." EndIf Else Result = "Ошибка UDP пакета." EndIf ProcedureReturn Result EndProcedure Procedure.a UDP_Tracker_PeerInfo(*Response, Size, *PeerInfo.UDP_Tracker_Announce, *Tracker_Info.Tracker_Bencode_Info) ; Разбор ответа и вытаскивание информации об сидах, пирах и др. данные. Protected i *Tracker_Info\Complete = ReverseLong(*PeerInfo\Seeders) *Tracker_Info\Incomplete = ReverseLong(*PeerInfo\Leechers) *Tracker_Info\Interval = ReverseLong(*PeerInfo\Interval) Size-1 For i=20 To Size Step 6 If AddElement(*Tracker_Info\Peersld()) *Tracker_Info\Peersld()\IP = IPString(PeekL(*Response+i)) *Tracker_Info\Peersld()\Port = ReverseWord(PeekW(*Response+i+4)) *Tracker_Info\Peersld()\Peer_id = "" EndIf Next i EndProcedure Procedure.a UDP_Tracker_Announce(Connect, *ConnectRequest.UDP_Tracker_ConnectResponse, *Info.Tracker_SetTracker, *Tracker_Info.Tracker_Bencode_Info, *ErrString.String) ; Получение анонаса от UDP трекера. Protected Announce.UDP_Tracker_AnnounceRequest, Event.l Protected ErrS.s, *Response, ErrState.a Protected Size.Unicode, PeerInfo.UDP_Tracker_Announce ErrState = 0 Announce\Connection_ID = *ConnectRequest\Connection_ID Announce\Action = ReverseLong(1) Announce\Transaction_ID = *ConnectRequest\Transaction_ID CopyMemory(@*Info\info_hash, @Announce\Info_Hash, 20) CopyMemory(@G_ProgramMiscInfo\Network\peer_id_bin, @Announce\Peer_ID, 20) Announce\Downloaded = ReverseQuad(*Info\downloaded) Announce\Left = ReverseQuad(*Info\left) Announce\Uploaded = ReverseQuad(*Info\uploaded) Select *Info\event Case #Tracker_Completed Event = 1 Case #Tracker_Started Event = 2 Case #Tracker_Stopped Event = 3 Default EndSelect Announce\Event = ReverseLong(Event) Announce\IP_Address = 0 Announce\Key = ReverseLong(G_ProgramMiscInfo\Network\Key) Announce\Num_Want = ReverseLong(*Info\numwant) Announce\Port = ReverseWord(*Info\port) If SendNetworkData(Connect, @Announce, SizeOf(UDP_Tracker_AnnounceRequest)) = SizeOf(UDP_Tracker_AnnounceRequest) ErrS=TestBadConnect(Connect, 0, #False) If ErrS="" ; Нет ошибки передачи Delay(800) *Response = UDP_Tracker_GetInfo(Connect, @Size, 20, *ErrString) ; Запрос идентификатра связи. If *Response If Size\u>=20 CopyMemory(*Response, @PeerInfo, 20) If *ConnectRequest\Transaction_ID = PeerInfo\Transaction_ID And ReverseLong(PeerInfo\Action) = 1 ; Пакет целый и все ОК. UDP_Tracker_PeerInfo(*Response, Size\u, @PeerInfo, *Tracker_Info) Else ShowMemoryViewer(*Response, Size\u) *ErrString\s = UDP_Tracker_GetError(*Response, Size\u, *ConnectRequest\Transaction_ID) ErrState = 1 EndIf Else *ErrString\s = UDP_Tracker_GetError(*Response, Size\u, *ConnectRequest\Transaction_ID) ErrState = 1 EndIf FreeMemory(*Response) Else ErrState = 1 EndIf Else *ErrString\s = ErrS ErrState = 1 EndIf Else *ErrString\s = "Ошибка передачи данных." ErrState = 1 EndIf ProcedureReturn ErrState EndProcedure Procedure UDP_Tracker_Request(Connect, *Info.Tracker_SetTracker, *Tracker_Info.Tracker_Bencode_Info, *ErrString.String) ; Запрос UDP трекеру. Protected ConnectRequest.UDP_Tracker_ConnectRequest Protected Transaction_ID.l, ErrState, ErrS.s Protected Size.Unicode, *Response Protected ConnectResponse.UDP_Tracker_ConnectResponse Transaction_ID = Random($7FFFFFFF) ErrState = 0 *ErrString\s="" ClearStructure(*Tracker_Info, Tracker_Bencode_Info) InitializeStructure(*Tracker_Info, Tracker_Bencode_Info) ConnectRequest\Connection_ID = ReverseQuad($41727101980) ConnectRequest\Action = 0 ConnectRequest\Transaction_ID = Transaction_ID If SendNetworkData(Connect, @ConnectRequest, SizeOf(UDP_Tracker_ConnectRequest)) = SizeOf(UDP_Tracker_ConnectRequest) ErrS=TestBadConnect(Connect, 0, #False) If ErrS="" ; Нет ошибки передачи Delay(800) *Response = UDP_Tracker_GetInfo(Connect, @Size, 16, *ErrString) ; Запрос идентификатра связи. If *Response If Size\u>0 CopyMemory(*Response, @ConnectResponse, SizeOf(UDP_Tracker_ConnectResponse)) If Size\u>=SizeOf(UDP_Tracker_ConnectResponse) If ConnectResponse\Transaction_ID = Transaction_ID And ConnectResponse\Action = 0 ErrState = UDP_Tracker_Announce(Connect, @ConnectResponse, *Info, *Tracker_Info, *ErrString) ; Получение анонаса от UDP трекера. Else *ErrString\s = UDP_Tracker_GetError(*Response, Size\u, Transaction_ID) ErrState = 1 EndIf Else *ErrString\s = UDP_Tracker_GetError(*Response, Size\u, Transaction_ID) ErrState = 1 EndIf EndIf FreeMemory(*Response) Else ErrState = 1 EndIf Else *ErrString\s = ErrS ErrState = 1 EndIf Else *ErrString\s = "Ошибка передачи данных." ErrState = 1 EndIf ProcedureReturn ErrState EndProcedure DisableExplicit ; IDE Options = PureBasic 5.20 beta 15 LTS (Windows - x86) ; Folding = - ; EnableXP