nullschritt Posted February 3, 2014 Posted February 3, 2014 (edited) Hello, I am re-releasing hyperzap's Event Driven P2P UDF with some modifications. Thanks to hyperzap for the original UDF. New Features Dynamic RegEx Headers/Footers Supports Messages of Any Length (Including file transfers) [automatically] Allows use of all symbols/letters in messages* Pre-Modification Features Relays messages over P2P network Delivers messages to client only machines [that cannot port forward] BootStrapping (optional) [Automatically connect to more peers] Even Driven LAN or WAN Mode FAST (Takes 5-50ms per hop) Known Limitations Does not relay messages when emulated on linux with WINE. (still receives and sends messages) * = You CANNOT use the "`" symbol in long range messages. To support this symbol, please replace it with it's html entity, urlencode, or use the INCLUDED _base64encode function on data you want to send long range. How it works:##################When you start the UDF, it will start listening and accepting incoming connections. The UDF will, in the backround, continue to manage all your connections and initiate any new ones should you use the _P2P_Connect( IP) function. It will also manage the recieving and sending of data.As a P2P node should, it will route data destined for others, and it will also maintain a healthy number of connections (the number which you define when you start the node).This entire system is event driven, so you will register your functions with the UDF and the function will get called when the corresponding event happens. See the comments in the UDF for more information.This works in the same way as Kip's TCP UDF.Structure:##################The first thing you must do is start the Node:_P2P_Start_Node( Node Identifier, Port, Max peers, Bootstrap mode, Bootstrap max, local/global, IP)All the Parameters are pretty self expanatory. The Node identifier is the name of your computer in the network. It must not change across sessions and it must be unique. It is used to identify you in your network.Bootstrapping means autoconnecting. if Bootstrap mode is 1, It will autoconnect you to others until you reach your Bootstrap Max.Local/Global - Put 0 if working on a LAN, 1 if over internet.IP - (Optional). You shouldn't need to change this. It is the IP of the listening port.The second thing is declare your functions. This tells the UDF which functions to call when something happens. EG:_P2P_Register_Event($P2P_RECEIVE, "my_recieve_function")So, this will call the function my_recieve_function when data from a peer is recieved. See the comments at the beginning of the UDF for a complete list of Event values, and the parameters for your functions.Then fire away!_P2P_Send( $socket, "MY DATA!!)_P2P_Connect( "127.0.0.1")_P2P_Broadcast( "My data")When your done,_P2P_Stop_Node() The UDF: expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.0.0 Author: Hyperzap. Modified By: NullSchritt (Stormageddon) Design concepts were first coined by Kip in his "Event driven TCP UDF" Zatorg's Asynchronous Sockets UDF is also used. Script Function: This UDF is a re-write of Kip's 'Event driven TCP UDF'. Thx Kip. It aims to generate simple TCP, event driven functionality for P2P programs, As opposed to client-server oriented communication as in Kip's UDF. Evidently, this functionality is not possible in Kips original releases. Apart from the obvious conponents of such a code, like Recv, Send, Connect, Listen, other important P2P routines have been coded. These include things like; Universal identifiers, bootstrapping mechanisms, peers discovery, and message routing. MINOR DRAWBACKS: You must replace "`" in messages with it's html entity or some other symbol during long range message routing. #ce ---------------------------------------------------------------------------- $UDF_Version = "1.33 STABLE" $console_out = False $STANDARD_MESSAGE_LIFE = 200 #cs Functions: _P2P_Start_Node( Node Identifier, Port, Max peers, Bootstrap mode, Boostrap max, local/global, IP) _P2P_Stop_Node() _P2P_Connect( IP) _P2P_Send( Socket, Data) _P2P_Disconnect_Peer( Socket) _P2P_Send_Message( Address, Data) _P2P_Register_Event($iEvent, $sFunction) Register event values: $P2P_AUX_DATA ; Function ($hSocket, $DataType, $Data);When things like IP and Node identifier are discovered. $P2P_MESSAGE ; Function ($hSocket, $message, $iError) ;When long distance messages are recieved. $P2P_RECEIVE ; Function ($hSocket, $sReceived, $iError) $P2P_CONNECT ; Function ($hSocket, $iError) $P2P_DISCONNECT ; Function ($hSocket, $iError) $P2P_NEWCONNECTION ; Function ($hSocket, $iError) Also, please call the function peer_broadcast() periodically in your program. Failing to do this will Seriously cripple the bootstrapping mechanism (unless you program is ALWAYS recieving data at least once every 40 seconds, In which case the mechanism will trigger automatically). #ce Global Const $fd_read = 1 Global Const $fd_write = 2 Global Const $fd_oob = 4 Global Const $fd_accept = 8 Global Const $fd_connect = 16 Global Const $fd_close = 32 Global $hws2_32 = -1 Global Const $tcp_send = 1 Global Const $tcp_receive = 2 Global Const $tcp_connect = 4 Global Const $tcp_disconnect = 8 Global Const $tcp_newclient = 16 Global Const $iploc_local = 64 Global Const $iploc_global = 128 Global Const $p2p_message = 256 Global Const $p2p_receive = 512 Global Const $p2p_connect = 1024 Global Const $p2p_disconnect = 2048 Global Const $p2p_newconnection = 4096 Global Const $p2p_aux_data = 8192 Global $total_connected = 0 Global $max_connections Global $listening_socket Global $node_ip Global $node_port Global $node_identifier Global $node_ext_ip Global $bootstrap_mode Global $bootstrap_max Global $peer_timer Global $total_id_known = 0 Global $known_id[200] Global $connectfunc = "" Global $recievefunc = "" Global $disconnectfunc = "" Global $newconnectionfunc = "" Global $messagefunc = "" Global $auxfunc = "" Global $main_socket_address = "" TCPStartup() Global Const $__tcp_window = GUICreate("Async Sockets UDF") Func _p2p_start_node($node_id, $port, $max_peers, $bootstrapmode, $bootstrapmax, $location, $ip = "0.0.0.0") Local $startuptimer = TimerInit() $listening_socket = ___asocket() $main_socket_address = $listening_socket ___asockselect($listening_socket, $__tcp_window, 1024, $fd_accept) GUIRegisterMsg(1024, "Listensocket_data_") ___asocklisten($listening_socket, $ip, $port) If $bootstrapmode = 0 Then $bootstrap_mode = $iploc_local If $bootstrapmode = 1 Then $bootstrap_mode = $iploc_global $bootstrap_max = $bootstrapmax $max_connections = $max_peers $node_ip = $ip $node_port = $port $node_identifier = $node_id $peer_timer = TimerInit() If $location = 1 Then $node_ext_ip = _get_ip() If $location = 0 Then $node_ext_ip = @IPAddress1 Global $socket_handle_array[$max_peers + 1] Global $node_identifier_array[$max_peers + 1] Global $node_ip_array[$max_peers + 1] Global $node_peer_reachable_list[$max_peers + 1] For $x = 0 To $max_peers Step 1 $socket_handle_array[$x] = -1 $node_identifier_array[$x] = -1 $node_ip_array[$x] = -1 $node_peer_reachable_list[$x] = -1 Next If $console_out = True Then ConsoleWrite(@CRLF & @CRLF & "P2P_: Node started") If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Port: " & $node_port) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Ext IP: " & $node_ext_ip) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Max peers: " & $max_connections) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Identifier: " & $node_identifier) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Engine Version: " & $udf_version) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Startup time: " & TimerDiff($startuptimer) & "ms" & @CRLF) EndFunc Func _p2p_stop_node() ___asockshutdown($listening_socket) TCPCloseSocket($listening_socket) $socket_handle_array= -1 $node_identifier_array= -1 $node_ip_array= -1 $node_peer_reachable_list= -1 $max_connections = 0 $listening_socket = "" $node_ip = "" $node_port = "" $node_identifier = -1 $node_ext_ip = "" $bootstrap_mode = "" $bootstrap_max = 0 $connectfunc = "" $recievefunc = "" $disconnectfunc = "" $newconnectionfunc = "" $messagefunc = "" $auxfunc = "" If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Engine shutdown successful.") EndFunc Func listensocket_data_($hwnd, $imsgid, $wparam, $lparam) Local $socketinquestion = $wparam Local $ierror = ___hiword($lparam) Local $ievent = ___loword($lparam) Abs($hwnd) If $imsgid = 1024 Then If $ievent = $fd_accept Then If NOT $ierror Then $arrayslot = findfreearrayslot() If $arrayslot = "error" Then $newsocket = TCPAccept($socketinquestion) TCPSend($newsocket, "`" & _generateheader(2) & "`NOSLOT`" & _generateheader(1)) TCPCloseSocket($newsocket) EndIf $newsocket = TCPAccept($socketinquestion) ___asockselect($newsocket, $__tcp_window, 1024 + $arrayslot, BitOR($fd_read, $fd_connect, $fd_close)) GUIRegisterMsg(1024 + $arrayslot, "Opensocket_data_") $socket_handle_array[$arrayslot] = $newsocket $node_identifier_array[$arrayslot] = -1 $node_ip_array[$arrayslot] = -1 TCPSend($newsocket, "`" & "`IP`" & $node_ext_ip & _generateheader(1)) TCPSend($newsocket, "`" & "`ID`" & $node_identifier & _generateheader(1)) peer_broadcast_to_peer($newsocket) $total_connected += 1 Call($newconnectionfunc, $newsocket, $ierror) Else Call($newconnectionfunc, 0, $ierror) EndIf ElseIf $ievent = $fd_connect Then Call($connectfunc, $newsocket, $ierror) EndIf EndIf EndFunc Func _generateheader($type = 1) $alpha = StringSplit("PRODY", "", 3) $str = "" If $type = 1 Then $str = "--P2P:" For $i = 1 To 5 $str &= Random(0, 9, 1) & $alpha[Random(0, 4, 1)] Next Return $str EndIf If $type = 2 Then $str = "--P2P:" For $i = 1 To 5 $str &= $alpha[Random(0, 4, 1)] & Random(0, 9, 1) Next Return $str EndIf EndFunc Func findfreearrayslot() $newconnnum = -1 For $x = 1 To $max_connections If $socket_handle_array[$x] = -1 Then $newconnnum = $x ExitLoop EndIf Next If $newconnnum = -1 Then Return "error" Return $newconnnum EndFunc Func opensocket_data_($hwnd, $imsgid, $wparam, $lparam) Local $ierror = ___hiword($lparam) Local $ievent = ___loword($lparam) Abs($hwnd) Local $array_slot = $imsgid - 1024 Local $socketid = $socket_handle_array[$array_slot] If $socketid = -1 Then Return 0 Switch $ievent Case $fd_read $rawrecv = TCPRecv($socketid, 2048) If $rawrecv <> "" Then $regex = StringRegExp($rawrecv, "--P2P:([0-9](.*?)[PRODY]){5}", 2) If IsArray($regex) Then $rawrecv = StringReplace($rawrecv, $regex[0], "") recvprocess($rawrecv, $socketid, $array_slot, $ierror) Else $dre = 0 Do $recvtmp = TCPRecv($socketid, 2048) If $recvtmp = "" Then ExitLoop EndIf $rawrecv &= $recvtmp $regex = StringRegExp($rawrecv, "--P2P:([0-9](.*?)[PRODY]){5}", 2) Sleep(1) Until IsArray($regex) If IsArray($regex) Then $rawrecv = StringReplace($rawrecv, $regex[0], "") recvprocess($rawrecv, $socketid, $array_slot, $ierror) EndIf EndIf EndIf Case $fd_close ___asockshutdown($socketid) TCPCloseSocket($socketid) Call($disconnectfunc, $socketid, $ierror) $socket_handle_array[$array_slot] = -1 $node_identifier_array[$array_slot] = -1 $node_ip_array[$array_slot] = -1 $node_peer_reachable_list[$array_slot] = -1 $total_connected -= 1 If TimerDiff($peer_timer) > 40000 Then peer_broadcast() EndIf Case $fd_connect If $ierror Then If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Connection failed: " & $socketid) $socket_handle_array[$array_slot] = -1 $node_identifier_array[$array_slot] = -1 $node_ip_array[$array_slot] = -1 $node_peer_reachable_list[$array_slot] = -1 $total_connected -= 1 Call($connectfunc, $socketid, $ierror) Else Call($connectfunc, $socketid, $ierror) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Connection established: " & $socketid) TCPSend($socket_handle_array[$array_slot], "`" & "`IP`" & $node_ext_ip & _generateheader(1)) TCPSend($socket_handle_array[$array_slot], "`" & "`ID`" & $node_identifier & _generateheader(1)) peer_broadcast_to_peer($socket_handle_array[$array_slot]) EndIf If TimerDiff($peer_timer) > 40000 Then peer_broadcast() EndIf EndSwitch EndFunc Func recvprocess($rawrecv, $socketid, $array_slot, $ierror) If StringLen($rawrecv) < 1 Then Return 0 $regex = StringRegExp($rawrecv, "--P2P:([0-9](.*?)[PRODY]){5}", 2) If IsArray($regex) Then Local $single_data = StringSplit($rawrecv, $regex[0], 1) Else Local $single_data = $rawrecv EndIf If UBound($single_data) < 1 Then Return For $k = 1 To $single_data[0] Step 1 If $single_data[$k] = "" Then ContinueLoop If $single_data[$k] = " " Then ContinueLoop If StringRegExp($single_data[$k], "--P2P:([PRODY](.*?)[0-9]){5}") Then node_data_process($socketid, $single_data[$k], $array_slot, $ierror) Else Call($recievefunc, $socketid, $single_data[$k], $ierror) EndIf Next If TimerDiff($peer_timer) > 40000 Then peer_broadcast() EndIf EndFunc Func node_data_process($socketid, $data, $array_slot, $ierror) Local $split = StringSplit($data, "`") If $split[3] = "IP" Then $node_ip_array[$array_slot] = $split[4] Call($auxfunc, $socketid, "IP", $split[4]) EndIf If $split[3] = "ID" Then $node_identifier_array[$array_slot] = $split[4] Call($auxfunc, $socketid, "ID", $split[4]) EndIf If $split[3] = "PEER" Then bootstrap($socketid, $split[4], $array_slot, $ierror) If $split[3] = "IDLIST" Then $node_peer_reachable_list[$array_slot] = $split[4] Call($auxfunc, $socketid, "NODE-REACHABLE", $split[4]) EndIf If $split[3] = "MESSAGE" Then route_message($socketid, $data, $array_slot) EndIf EndFunc Func bootstrap($socketid, $split, $array_slot, $ierror) If $bootstrap_mode = $iploc_local Then Return 9 If $total_connected >= $bootstrap_max Then Return 8 Local $connectpeers = Round(($bootstrap_max / $total_connected / 2), 0) If $connectpeers < $bootstrap_max AND $connectpeers = 0 Then $connectpeers = 1 If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Bootstrap stats: " & $connectpeers & ":" & $total_connected & "/" & $bootstrap_max) $peers = StringSplit($split, ";") For $d = 1 To $connectpeers Step 1 $error = False $rndarray = Random(1, $peers[0], 1) If $peers[$rndarray] = "" OR $peers[$rndarray] = " " Then ContinueLoop For $u = 0 To $max_connections Step 1 If $peers[$rndarray] = $node_ip_array[$u] Then If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Bootstrap: connectee already connected! reselecting...") $error = True ExitLoop EndIf Next If $error = True Then ContinueLoop _p2p_connect($peers[$rndarray]) Next EndFunc Func peer_broadcast() $peer_timer = TimerInit() Local $peers = "" Local $idlist = "" For $a = 0 To $max_connections Step 1 If $node_ip_array[$a] <> -1 Then $peers &= $node_ip_array[$a] & ";" If $node_identifier_array[$a] <> -1 Then $idlist &= $node_identifier_array[$a] & ";" Next _p2p_broadcast("`" & _generateheader(2) & "`PEER`" & $peers) _p2p_broadcast("`" & _generateheader(2) & "`IDLIST`" & $idlist) EndFunc Func peer_broadcast_to_peer($socket) Local $peers = "" Local $idlist = "" For $a = 0 To $max_connections Step 1 If $node_ip_array[$a] <> -1 Then $peers &= $node_ip_array[$a] & ";" If $node_identifier_array[$a] <> -1 Then $idlist &= $node_identifier_array[$a] & ";" Next TCPSend($socket, "`" & _generateheader(2) & "`PEER`" & $peers & _generateheader(1)) TCPSend($socket, "`" & _generateheader(2) & "`IDLIST`" & $idlist & _generateheader(1)) EndFunc Func route_message($socket, $message, $array_slot) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: MessageRouting started") Local $timer = TimerInit() Local $split = StringSplit($message, "`") If $split[0] < 6 Then Return 1 Local $ttl = $split[4] Local $from = $split[5] Local $address = $split[6] Local $identifier = $split[7] Local $begin = "`" & _generateheader(2) & "`MESSAGE`" & $ttl & "`" & $from & "`" & $address & "`" & $identifier & "`" Local $cutlen = StringLen($message) - StringLen($begin) If idknown($split[7]) = True Then If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message-ID known.") If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) Return 1 EndIf If $address = $node_identifier Then Local $messagetrim = StringRight($message, $cutlen) Local $messagetrim = StringRight($message, $cutlen) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message-Inbound") If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) Call($messagefunc, $socket, $messagetrim, $from, 0) Return 1 EndIf If $ttl = 0 Then If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message-TTL Exceeded.") If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) Return 1 EndIf $messagefull = "`" & _generateheader(2) & "`MESSAGE`" & ($ttl - 1) & "`" & $from & "`" & $address & "`" & $identifier & "`" & StringRight($message, $cutlen) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Starting First level Routing: " & $total_connected) For $qwe = 0 To $max_connections Step 1 If $address = $node_identifier_array[$qwe] Then _p2p_send($socket_handle_array[$qwe], $messagefull) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message-Destination located.") If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) Return 1 EndIf Next If $socket = -1 Then _p2p_broadcast($messagefull) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) Return 1 Else For $qwe = 0 To $max_connections Step 1 If $socket_handle_array[$qwe] = -1 Then ContinueLoop If StringInStr($node_peer_reachable_list[$qwe], $address) > 0 Then _p2p_send($socket_handle_array[$qwe], $messagefull) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message-2nd Level destination located. ") If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) Return 1 EndIf Next EndIf For $qwe = 0 To $max_connections Step 1 If $socket_handle_array[$qwe] = -1 Then ContinueLoop If $node_identifier_array[$qwe] = $node_identifier_array[$array_slot] Then ContinueLoop If StringInStr($node_peer_reachable_list[$array_slot], $node_identifier_array[$qwe]) > 0 Then ContinueLoop _p2p_send($socket_handle_array[$qwe], $messagefull) Next If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message Routing Finished: " & Round(TimerDiff($timer), 1)) EndFunc Func _p2p_send_message($idaddress, $indata, $from = "Null") Local $messageid = Round(((Random(0, 99999999999, 1) * @YDAY) / @MIN) * (Random(5, 1376, 1) / (@SEC * 100)), 0) Local $ttl = $standard_message_life Local $fullmessage = "`" & _generateheader(2) & "`MESSAGE`" & $ttl & "`" & $from & "`" & $idaddress & "`" & $messageid & "`" & $indata & _generateheader(1) If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Message generated: " & $messageid) route_message(-1, $fullmessage, -1) EndFunc Func idknown($id) For $idcount = 0 To $total_id_known Step 1 If $known_id[$idcount] = $id Then Return True Next $total_id_known += 1 If $total_id_known > 198 Then $total_id_known = 0 $known_id[$total_id_known] = $id Return False EndFunc Func _p2p_send($socket, $data) TCPSend($socket, $data & _generateheader(1)) EndFunc Func _p2p_disconnect_peer($socket) Local $it_socket = "" Local $array_slot = "" For $count = 0 To $max_connections Step 1 If $socket_handle_array[$count] = $socket Then $it_socket = $socket $array_slot = $count ExitLoop EndIf Next If $it_socket = "" Then Return False ___asockshutdown($it_socket) TCPCloseSocket($it_socket) $socket_handle_array[$array_slot] = -1 $node_identifier_array[$array_slot] = -1 $node_ip_array[$array_slot] = -1 $node_peer_reachable_list[$array_slot] = -1 If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Peer " & $it_socket & " closed.") Return True EndFunc Func _p2p_connect($conn_ip) For $u = 0 To $max_connections Step 1 If $conn_ip = $node_ip_array[$u] Then If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Unable to connect-IP is already connected!") Return 1 EndIf Next If $conn_ip = "" Then Return 0 If $conn_ip = " " Then Return 0 If $conn_ip = "0" Then Return 0 If $conn_ip = ";" Then Return 0 If $conn_ip = @CRLF Then Return 0 $arrayslot = findfreearrayslot() If $arrayslot = "error" Then If $listening_socket = "" Then If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Unable to connect-node services offline!") Return 3 EndIf If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Unable to connect-peer limit reached!") Return 2 EndIf If $console_out = True Then ConsoleWrite(@CRLF & "P2P_: Attempting Connection: " & $conn_ip) Local $socketid = ___asocket() ___asockselect($socketid, $__tcp_window, 1024 + $arrayslot, BitOR($fd_connect, $fd_read, $fd_close)) GUIRegisterMsg(1024 + $arrayslot, "Opensocket_data_") $socket_handle_array[$arrayslot] = $socketid $node_identifier_array[$arrayslot] = -1 $node_ip_array[$arrayslot] = $conn_ip $return = ___asockconnect($socketid, $conn_ip, $node_port) $total_connected += 1 If @extended Then If $console_out = True Then ConsoleWrite(@CRLF & "_P2P: Connection Established.") Call($connectfunc, $socketid, 0) EndIf EndFunc Func _p2p_broadcast($data) Local $i For $i = 0 To $max_connections Step 1 If $socket_handle_array[$i] <> -1 Then TCPSend($socket_handle_array[$i], $data & _generateheader(1)) Next Return True EndFunc Func _p2p_peerlist() Local $alist[$max_connections + 1][3], $alist_count = 1 For $i = 1 To $max_connections If $socket_handle_array[$i] <> -1 Then $alist[$alist_count][0] = $socket_handle_array[$i] $alist[$alist_count][1] = $node_identifier_array[$i] $alist[$alist_count][2] = $node_ip_array[$i] $alist_count += 1 EndIf Next $alist[0][0] = $alist_count Return $alist EndFunc Func _p2p_register_event($ievent, $sfunction) If $ievent = $p2p_aux_data Then $auxfunc = $sfunction If $ievent = $p2p_receive Then $recievefunc = $sfunction If $ievent = $p2p_connect Then $connectfunc = $sfunction If $ievent = $p2p_disconnect Then $disconnectfunc = $sfunction If $ievent = $p2p_newconnection Then $newconnectionfunc = $sfunction If $ievent = $p2p_message Then $messagefunc = $sfunction EndFunc Func ___asocket($iaddressfamily = 2, $itype = 1, $iprotocol = 6) If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") Local $hsocket = DllCall($hws2_32, "uint", "socket", "int", $iaddressfamily, "int", $itype, "int", $iprotocol) If @error Then SetError(1, @error) Return -1 EndIf If $hsocket[0] = -1 Then SetError(2, ___wsagetlasterror()) Return -1 EndIf Return $hsocket[0] EndFunc Func ___asockshutdown($hsocket) If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") Local $iret = DllCall($hws2_32, "int", "shutdown", "uint", $hsocket, "int", 2) If @error Then SetError(1, @error) Return False EndIf If $iret[0] <> 0 Then SetError(2, ___wsagetlasterror()) Return False EndIf Return True EndFunc Func ___asockclose($hsocket) If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") Local $iret = DllCall($hws2_32, "int", "closesocket", "uint", $hsocket) If @error Then SetError(1, @error) Return False EndIf If $iret[0] <> 0 Then SetError(2, ___wsagetlasterror()) Return False EndIf Return True EndFunc Func ___asockselect($hsocket, $hwnd, $uimsg, $ievent) If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") Local $iret = DllCall($hws2_32, "int", "WSAAsyncSelect", "uint", $hsocket, "hwnd", $hwnd, "uint", $uimsg, "int", $ievent) If @error Then SetError(1, @error) Return False EndIf If $iret[0] <> 0 Then SetError(2, ___wsagetlasterror()) Return False EndIf Return True EndFunc Func ___asocklisten($hsocket, $sip, $uiport, $imaxpending = 5) Local $iret Local $staddress If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") $staddress = ___sockaddr($sip, $uiport) If @error Then SetError(@error, @extended) Return False EndIf $iret = DllCall($hws2_32, "int", "bind", "uint", $hsocket, "ptr", DllStructGetPtr($staddress), "int", DllStructGetSize($staddress)) If @error Then SetError(3, @error) Return False EndIf If $iret[0] <> 0 Then $staddress = 0 SetError(4, ___wsagetlasterror()) Return False EndIf $iret = DllCall($hws2_32, "int", "listen", "uint", $hsocket, "int", $imaxpending) If @error Then SetError(5, @error) Return False EndIf If $iret[0] <> 0 Then $staddress = 0 SetError(6, ___wsagetlasterror()) Return False EndIf Return True EndFunc Func ___asockconnect($hsocket, $sip, $uiport) Local $iret Local $staddress If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") $staddress = ___sockaddr($sip, $uiport) If @error Then SetError(@error, @extended) Return False EndIf $iret = DllCall($hws2_32, "int", "connect", "uint", $hsocket, "ptr", DllStructGetPtr($staddress), "int", DllStructGetSize($staddress)) If @error Then SetError(3, @error) Return False EndIf $iret = ___wsagetlasterror() If $iret = 10035 Then Return True EndIf SetExtended(1) Return True EndFunc Func ___sockaddr($sip, $iport, $iaddressfamily = 2) Local $iret Local $staddress If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") $staddress = DllStructCreate("short; ushort; uint; char[8]") If @error Then SetError(1, @error) Return False EndIf DllStructSetData($staddress, 1, $iaddressfamily) $iret = DllCall($hws2_32, "ushort", "htons", "ushort", $iport) DllStructSetData($staddress, 2, $iret[0]) $iret = DllCall($hws2_32, "uint", "inet_addr", "str", $sip) If $iret[0] = -1 Then $staddress = 0 SetError(2, ___wsagetlasterror()) Return False EndIf DllStructSetData($staddress, 3, $iret[0]) Return $staddress EndFunc Func ___wsagetlasterror() If $hws2_32 = -1 Then $hws2_32 = DllOpen("Ws2_32.dll") Local $iret = DllCall($hws2_32, "int", "WSAGetLastError") If @error Then SetExtended(1) Return 0 EndIf Return $iret[0] EndFunc Func ___makelong($loword, $hiword) Return BitOR($hiword * 65536, BitAND($loword, 65535)) EndFunc Func ___hiword($long) Return BitShift($long, 16) EndFunc Func ___loword($long) Return BitAND($long, 65535) EndFunc Func _get_ip() Local $ip, $t_ip If InetGet("http://checkip.dyndns.org/?rnd1=" & Random(1, 65536) & "&rnd2=" & Random(1, 65536), @TempDir & "\~ip.tmp") Then $ip = FileRead(@TempDir & "\~ip.tmp", FileGetSize(@TempDir & "\~ip.tmp")) FileDelete(@TempDir & "\~ip.tmp") $ip = StringTrimLeft($ip, StringInStr($ip, ":") + 1) $ip = StringTrimRight($ip, StringLen($ip) - StringInStr($ip, "/") + 2) $t_ip = StringSplit($ip, ".") If $t_ip[0] = 4 AND StringIsDigit($t_ip[1]) AND StringIsDigit($t_ip[2]) AND StringIsDigit($t_ip[3]) AND StringIsDigit($t_ip[4]) Then Return $ip EndIf EndIf If InetGet("http://www.whatismyip.com/?rnd1=" & Random(1, 65536) & "&rnd2=" & Random(1, 65536), @TempDir & "\~ip.tmp") Then $ip = FileRead(@TempDir & "\~ip.tmp", FileGetSize(@TempDir & "\~ip.tmp")) FileDelete(@TempDir & "\~ip.tmp") $ip = StringTrimLeft($ip, StringInStr($ip, "Your ip is") + 10) $ip = StringLeft($ip, StringInStr($ip, " ") - 1) $ip = StringStripWS($ip, 8) $t_ip = StringSplit($ip, ".") If $t_ip[0] = 4 AND StringIsDigit($t_ip[1]) AND StringIsDigit($t_ip[2]) AND StringIsDigit($t_ip[3]) AND StringIsDigit($t_ip[4]) Then Return $ip EndIf EndIf SetError(1) Return -1 EndFunc Func _base64decode($data) Local $opcode = "0xC81000005356578365F800E8500000003EFFFFFF3F3435363738393A3B3C3DFFFFFF00FFFFFF000102030405060708090A0B0C0D0E0F10111213141516171819FFFFFFFFFFFF1A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132338F45F08B7D0C8B5D0831D2E9910000008365FC00837DFC047D548A034384C0750383EA033C3D75094A803B3D75014AB00084C0751A837DFC047D0D8B75FCC64435F400FF45FCEBED6A018F45F8EB1F3C2B72193C7A77150FB6F083EE2B0375F08A068B75FC884435F4FF45FCEBA68D75F4668B06C0E002C0EC0408E08807668B4601C0E004C0EC0208E08847018A4602C0E00624C00A46038847028D7F038D5203837DF8000F8465FFFFFF89D05F5E5BC9C21000" Local $codebuffer = DllStructCreate("byte[" & BinaryLen($opcode) & "]") DllStructSetData($codebuffer, 1, $opcode) Local $ouput = DllStructCreate("byte[" & BinaryLen($data) & "]") Local $ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr($codebuffer), "str", $data, "ptr", DllStructGetPtr($ouput), "int", 0, "int", 0) Return BinaryMid(DllStructGetData($ouput, 1), 1, $ret[0]) EndFunc Func _base64encode($data, $linebreak = 76) Local $opcode = "0x5589E5FF7514535657E8410000004142434445464748494A4B4C4D4E4F505152535455565758595A6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435363738392B2F005A8B5D088B7D108B4D0CE98F0000000FB633C1EE0201D68A06880731C083F901760C0FB6430125F0000000C1E8040FB63383E603C1E60409C601D68A0688470183F90176210FB6430225C0000000C1E8060FB6730183E60FC1E60209C601D68A06884702EB04C647023D83F90276100FB6730283E63F01D68A06884703EB04C647033D8D5B038D7F0483E903836DFC04750C8B45148945FC66B80D0A66AB85C90F8F69FFFFFFC607005F5E5BC9C21000" Local $codebuffer = DllStructCreate("byte[" & BinaryLen($opcode) & "]") DllStructSetData($codebuffer, 1, $opcode) $data = Binary($data) Local $input = DllStructCreate("byte[" & BinaryLen($data) & "]") DllStructSetData($input, 1, $data) $linebreak = Floor($linebreak / 4) * 4 Local $oputputsize = Ceiling(BinaryLen($data) * 4 / 3) $oputputsize = $oputputsize + Ceiling($oputputsize / $linebreak) * 2 + 4 Local $ouput = DllStructCreate("char[" & $oputputsize & "]") DllCall("user32.dll", "none", "CallWindowProc", "ptr", DllStructGetPtr($codebuffer), "ptr", DllStructGetPtr($input), "int", BinaryLen($data), "ptr", DllStructGetPtr($ouput), "uint", $linebreak) Return DllStructGetData($ouput, 1) EndFunc Usage Example:P2Ptest.au3 Edited February 5, 2014 by nullschritt
nullschritt Posted February 7, 2014 Author Posted February 7, 2014 Hi this looks interesting. Can you aid me a boost in the right direction? Is lets say I develop a app for voting (poll) Do I setup my client as the destination and then give out my WAN and PORT to the peers and this way they build a list of peers? Also I plan on using SQLite for the voting so I guess the peers need to build a voting list? ? All nodes act as both a server and a client. You can easily build a simple server node though. The server node needs to simply be running on the same port as the node in your program. In your program enable bootstrapping. Whenever a new pc connects to this server, it will notify all connected clients of the new peer, and they will all try to connect. You can always resolve a hostname to an ip address, and attempt to connect to it automatically with your code. You could also ask the user for an ip if that fails, or try a pre-generated list of other ip addresses. If you want to make a pure peer-to-peer voting system, and want each node to store the votes in a sqlite file you will need to do two things. 1)Make a way to verify votes. This is to ensure a user doesnt send false votes into the network, or edit it into the file. 2)Make an update system for clients who have not been online. (Allow these clients to ask any other clients for any vote info they dont already have)
TLOTS Posted May 7, 2014 Posted May 7, 2014 Hi! i have a problem :/ if i try to run P2PTest.au3, it throws me "Problem connection attempt: " and a number, every time i connect (press d) if i turn on the debug on the UDF, it says: "P2P_: Connection failed: " and the same number. The twitchyliquid64's udf works fine in my computer. What can i do to fix the problem?
nullschritt Posted August 16, 2014 Author Posted August 16, 2014 (edited) Hi! i have a problem :/ if i try to run P2PTest.au3, it throws me "Problem connection attempt: " and a number, every time i connect (press d) if i turn on the debug on the UDF, it says: "P2P_: Connection failed: " and the same number. The twitchyliquid64's udf works fine in my computer. What can i do to fix the problem? It's probably because the bootstrapper has already connected you in this case. Try pressing e to send some data. (with console out on) Edited August 16, 2014 by nullschritt
MikahS Posted August 25, 2014 Posted August 25, 2014 Just for the general public, I would put the bug you are having into the first post of this UDF -- >link "I am having this same problem with the Event Driven P2P script based off this script, it's not sendign the data as packets, it's simply cutting off the string when it's send over a network connection, locally there is no limit for TCPSend, but it seems that over a network connection, only so many bytes can be transferred at once." As I'm seeing people looking for the same thing, this could save someone a lot of time testing your code.. Snips & Scripts My Snips: graphCPUTemp ~ getENVvarsMy Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4 Feel free to use any of my code for your own use. Forum FAQ
zelles Posted October 29, 2014 Posted October 29, 2014 Can you use _P2P_Connect($ip) to connect to some peers also? If so would you call it for each one or can you only call the _P2P_Connect($ip) function 1 time? Thanks in advance for any informatin on this.
MikahS Posted October 31, 2014 Posted October 31, 2014 Can you use _P2P_Connect($ip) to connect to some peers also? If so would you call it for each one or can you only call the _P2P_Connect($ip) function 1 time? Thanks in advance for any informatin on this. Every time you are trying to make a connection you call the connect function. But, please see the below quote as this could create errors; This whole library is based off a library that the author said not to use, just FYI >link "I am having this same problem with the Event Driven P2P script based off this script, it's not sendign the data as packets, it's simply cutting off the string when it's send over a network connection, locally there is no limit for TCPSend, but it seems that over a network connection, only so many bytes can be transferred at once." Snips & Scripts My Snips: graphCPUTemp ~ getENVvarsMy Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4 Feel free to use any of my code for your own use. Forum FAQ
zelles Posted October 31, 2014 Posted October 31, 2014 Thank you MikahS, for the information. Looks like I'll have to stick with what I had before looking at this...
MikahS Posted October 31, 2014 Posted October 31, 2014 My pleasure What were you doing before? Snips & Scripts My Snips: graphCPUTemp ~ getENVvarsMy Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4 Feel free to use any of my code for your own use. Forum FAQ
zelles Posted November 1, 2014 Posted November 1, 2014 Using two central servers. I'd like to learn about setting up p2p connections though.
MikahS Posted November 3, 2014 Posted November 3, 2014 Have you had a look at Kealper's TCP server example by chance? >link very nice way of doing a TCP server. Snips & Scripts My Snips: graphCPUTemp ~ getENVvarsMy Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4 Feel free to use any of my code for your own use. Forum FAQ
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now