Search the Community
Showing results for tags 'winsock'.
-
Hi guys, some time ago I tried to deal with client\server application using native winsock functions, but I encountered some difficult because their limitations, so I decided to write a new UDF based on winsock library. Some functions are simply wrappers of native function, but some other are completely renewed and there are a lot of improvements. Check it out! Each function has a detailed description and I attached 5 simple example script ; #INDEX# ======================================================================================================================= ; Title .........: Winsock ; AutoIt Version : 3.3.14.2 ; Language ......: English ; Description ...: Functions that assist with Winsock library management. ; Author(s) .....: j0kky ; =============================================================================================================================== ; #CONSTANTS# =================================================================================================================== Global Const $TCP_DATA_EOT = 2 ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ; _TCPStartup ; _TCPListen ; _TCPAccept ; _TCPRecv ; _TCPConnect ; _TCPSend ; _TCPNameToIP ; _TCPCloseSocket ; _TCPShutdown ; _GetIps ; _UDPStartup ; _UDPBind ; _UDPSendTo ; _UDPRecvFrom ; _UDPCloseSocket ; _UDPShutdown ; =============================================================================================================================== ; #WRAPPER# ===================================================================================================================== Func _TCPStartup() $iResult = TCPStartup() Return SetError(@error, 0, $iResult) EndFunc ;==>_TCPStartup ; #WRAPPER# ===================================================================================================================== Func _TCPListen($iIPAddr, $iPort, $iMaxPendingConnection = 0) If Not $iMaxPendingConnection Then $iResult = TCPListen($iIPAddr, $iPort) Else $iResult = TCPListen($iIPAddr, $iPort, $iMaxPendingConnection) EndIf Return SetError(@error, 0, $iResult) EndFunc ;==>_TCPListen ; #FUNCTION# ==================================================================================================================== ; Name...........: _TCPAccept ; Description ...: Permits an incoming connection attempt on a socket. ; Syntax.........: _TCPAccept($iMainsocket) ; Parameters ....: $iMainsocket - The main socket identifier (SocketID) as returned by _TCPListen function. ; Return values .: On success it returns an array: ; |[0] - The connected socket identifier. ; |[1] - The external address of the client ; |[2] - The external port which the client are communicating on ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter (not used in this function) ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: accept: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737526(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _TCPAccept($iMainsocket) $iMainsocket = Number($iMainsocket) If $iMainsocket < 0 Then Return SetError(-4, 0, -1) ; invalid parameter Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0, $hSock = 0 Local $tagSockAddr = "short sin_family; ushort sin_port; " & _ "STRUCT; ulong S_addr; ENDSTRUCT; " & _ ;sin_addr "char sin_zero[8]" If Not $bError Then $aRet = DllCall($hWs2, "int", "ioctlsocket", "uint", $iMainsocket, "long", 0x8004667e, "ulong*", 1) ;FIONBIO If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf EndIf If Not $bError Then $tSockAddr = DllStructCreate($tagSockAddr) $aRet = DllCall($hWs2, "uint", "accept", "uint", $iMainsocket, "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf ($aRet[0] = 4294967295) Or ($aRet[0] = -1) Then ;INVALID_SOCKET $bError = 1 $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $bError = -1 ElseIf ($aRet[0] = 0) Or ($aRet[0] = 10035) Then ;WSAEWOULDBLOCK $nCode = -10 ;internal function value, it means no error EndIf Else $hSock = $aRet[0] $aRet = DllCall($hWs2, "ptr", "inet_ntoa", "ulong", DllStructGetData($tSockAddr, "S_addr")) If @error Then $bError = -1 ElseIf $aRet[0] = Null Then $bError = 1 Else $sIPAddr = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", DllStructGetData($tSockAddr, "sin_port")) If @error Then $bError = -1 Else $nPort = $aRet[0] Local $aResult[3] = [$hSock, $sIPAddr, $nPort] EndIf EndIf EndIf EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure If $hSock Then TCPCloseSocket($hSock) ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf If $nCode = -10 Then $nCode = 0 $nReturn = -1 If $hSock Then TCPCloseSocket($hSock) Else $nReturn = $aResult EndIf DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_TCPAccept ; #FUNCTION# ==================================================================================================================== ; Name...........: _TCPRecv ; Description ...: Receives data from a connected socket. ; Syntax.........: _TCPRecv($iMainsocket, $iMaxLen, $iFlag = 0) ; Parameters ....: $iMainsocket - The array as returned by _TCPAccept ; or the connected socket identifier (SocketID) as returned by _TCPConnect. ; $iMaxLen - max # of characters to receive (usually 2048). ; $iFlag - values can be added together ; |$TCP_DATA_DEFAULT (0) - Text data. [Default] ; |$TCP_DATA_BINARY (1) - Binary data. ; |$TCP_DATA_EOT (2) - Returns data received and ; set @error to -6 when it reaches the End of Text ASCII character (Chr(3)) ; Return values .: On success it returns the binary/string sent by the connected socket. ; On failure it returns "" and sets the @error or @extended flag to non-zero: ; @error values: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; @extended values: ; |1 - connection closed ; |2 - End of Text reached ; Author ........: j0kky ; Modified ......: 1.0.0 ; Remarks .......: If Unicode strings need to be transmitted they must be encoded/decoded with StringToBinary()/BinaryToString(). ; $iFlag = 2 must be set in couple with _TCPSend ; You must check for both @error and @extended, @extended could be set with @error set to zero ; Links .........: recv: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _TCPRecv($iMainsocket, $iMaxLen, $iFlag = 0) If IsArray($iMainsocket) And (UBound($iMainsocket, 0) = 1) And (UBound($iMainsocket) > 0) Then $iMainsocket = $iMainsocket[0] If $iFlag = Default Then $iFlag = 0 $iMainsocket = Number($iMainsocket) $iMaxLen = Number($iMaxLen) $iFlag = Number($iFlag) If $iMainsocket < 0 Or _ $iMaxLen < 1 Or _ Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(-4, 0, -1) ; invalid parameter Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0, $nExtended = 0 If Not $bError Then $aRet = DllCall($hWs2, "int", "ioctlsocket", "uint", $iMainsocket, "long", 0x8004667e, "ulong*", 1) ;FIONBIO If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf EndIf Local $tBuf If $iFlag Then $tBuf = DllStructCreate("byte[" & $iMaxLen & "]") Else $tBuf = DllStructCreate("char[" & $iMaxLen & "]") EndIf $aRet = DllCall($hWs2, "int", "recv", "uint", $iMainsocket, "ptr", DllStructGetPtr($tBuf), "int", $iMaxLen, "int", 0) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Then ;SOCKET_ERROR $bError = 1 $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $bError = -1 ElseIf $aRet[0] = 0 Or $aRet[0] = 10035 Then ;WSAEWOULDBLOCK $nCode = -10 ;internal function value, it means no error EndIf ElseIf $aRet[0] = 0 Then $bError = 1 $nCode = -10 $nExtended = 1 ;connection closed Else Local $sResult = DllStructGetData($tBuf, 1) ;data If BitAND($iFlag, 2) = 2 Then ;EOT If StringRight($sResult, 1) = Chr(3) Then $sResult = StringTrimRight($sResult, 1) $nExtended = 2 ;End of Text reached EndIf EndIf EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = "" ;failure ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf If $nCode = -10 Then $nCode = 0 $nReturn = "" Else $nReturn = $sResult EndIf DllClose($hWs2) Return SetError($nCode, $nExtended, $nReturn) EndFunc ;==>_TCPRecv ; #FUNCTION# ==================================================================================================================== ; Name...........: _TCPConnect ; Description ...: Create a socket connected to an existing server. ; Syntax.........: _TCPConnect($sIPAddr, $iDestPort, $sSourceAddr = "", $iSourcePort = 0, $iTimeOut = 0) ; Parameters ....: $sIPAddr - Destination IP. ; |Internet Protocol dotted address(IpV4) as "192.162.1.1". ; $iDestPort - Destination port. ; |1 : 65534 - port on which the created socket will be connected. ; $sSourceAddr - Source IP ; |Internet Protocol dotted address(IpV4) as "192.162.1.1". [Default = ""] ; $iSourcePort - Source port. ; |1 : 65534 - port on which the created socket will be bind (on the local PC). [Default = 0] ; $iTimeOut - The maximum time in milliseconds for _TCPConnect to wait for connection. ; |Any value > 0 [Default = 0 and it will be equal to Opt("TCPTimeout")]. ; Return values .: On success it returns the main socket identifier. ; |Any value > 0 ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter ; |-5 - not connected ; |-6 - timed out ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Remarks .......: This function is used by a client to communicate with the server and it allows to choose a source IP, ; a source port and to set a timeout for the connection. ; Links .........: bind: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx ; connect: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737625(v=vs.85).aspx ; select: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _TCPConnect($sIPAddr, $iDestPort, $sSourceAddr = "", $iSourcePort = 0, $iTimeOut = 0) If $sSourceAddr = Default Then $sSourceAddr = "" If $iSourcePort = Default Then $iSourcePort = 0 If $iTimeOut = Default Then $iTimeOut = 0 $sIPAddr = String($sIPAddr) $iDestPort = Number($iDestPort) $sSourceAddr = String($sSourceAddr) $iSourcePort = Number($iSourcePort) $iTimeOut = Number($iTimeOut) If Not ($iDestPort > 0 And $iDestPort < 65535) Or _ Not ($iSourcePort >= 0 And $iSourcePort < 65535) Or _ Not ($iTimeOut >= 0) Then Return SetError(-4, 0, -1) ; invalid parameter StringRegExp($sIPAddr, "((?:\d{1,3}\.){3}\d{1,3})", 3) ;$STR_REGEXPARRAYGLOBALMATCH If @error Then Return SetError(-4, 0, -1) If $sSourceAddr <> "" Then StringRegExp($sSourceAddr, "((?:\d{1,3}\.){3}\d{1,3})", 3) ;$STR_REGEXPARRAYGLOBALMATCH If @error Then Return SetError(-4, 0, -1) EndIf Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0 Local $tagSockAddr = "short sin_family; ushort sin_port; " & _ "STRUCT; ulong S_addr; ENDSTRUCT; " & _ ;sin_addr "char sin_zero[8]" Local $hSock = DllCall($hWs2, "uint", "socket", "int", 2, "int", 1, "int", 6); AF_INET, SOCK_STREAM, IPPROTO_TCP If @error Then $bError = -1 ElseIf ($hSock[0] = 4294967295) Or ($hSock[0] = -1) Then ;INVALID_SOCKET $bError = 1 Else $hSock = $hSock[0] EndIf If Not $bError Then $aRet = DllCall($hWs2, "ulong", "inet_addr", "str", $sIPAddr) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Or ($aRet[0] = 0) Then ;INADDR_NONE or INADDR_ANY $bError = 1 Else $sIPAddr = $aRet[0] EndIf EndIf If Not $bError Then $aRet = DllCall($hWs2, "ushort", "htons", "ushort", $iDestPort) If @error Then $bError = -1 Else $iDestPort = $aRet[0] EndIf EndIf If (Not $bError) And ($sSourceAddr <> "") Then $aRet = DllCall($hWs2, "ulong", "inet_addr", "str", $sSourceAddr) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Or ($aRet[0] = 0) Then ;INADDR_NONE or INADDR_ANY $bError = 1 Else $sSourceAddr = $aRet[0] EndIf EndIf If (Not $bError) And $iSourcePort Then $aRet = DllCall($hWs2, "ushort", "htons", "ushort", $iSourcePort) If @error Then $bError = -1 Else $iSourcePort = $aRet[0] EndIf EndIf If (Not $bError) And ($sSourceAddr Or $iSourcePort) Then $tSockAddr = DllStructCreate($tagSockAddr) DllStructSetData($tSockAddr, "sin_family", 2) ;AF_INET If $iSourcePort Then DllStructSetData($tSockAddr, "sin_port", $iSourcePort) Else DllStructSetData($tSockAddr, "sin_port", 0) EndIf If $sSourceAddr Then DllStructSetData($tSockAddr, "S_addr", $sSourceAddr) Else DllStructSetData($tSockAddr, "S_addr", 0x00000000) ;INADDR_ANY EndIf $aRet = DllCall($hWs2, "int", "bind", "uint", $hSock, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf $tSockAddr = 0 EndIf If Not $bError Then $aRet = DllCall($hWs2, "int", "ioctlsocket", "uint", $hSock, "long", 0x8004667e, "ulong*", 1) ;FIONBIO If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf EndIf If Not $bError Then $tSockAddr = DllStructCreate($tagSockAddr) DllStructSetData($tSockAddr, "sin_family", 2) ;AF_INET DllStructSetData($tSockAddr, "sin_port", $iDestPort) DllStructSetData($tSockAddr, "S_addr", $sIPAddr) $aRet = DllCall($hWs2, "int", "connect", "uint", $hSock, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR -> functional with connect() on non-blocking sockets $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $bError = -1 ElseIf ($aRet[0] <> 0) And ($aRet[0] <> 10035) Then ;WSAEWOULDBLOCK $bError = 1 EndIf EndIf $tSockAddr = 0 EndIf If Not $bError Then If $iTimeOut = 0 Then $iTimeOut = Opt("TCPTimeout") If $iTimeOut < 1 Then $iTimeOut = 100 Local $tagFd_set = "uint fd_count; uint fd_array[64]" Local $tFd_set_writefds = DllStructCreate($tagFd_set) DllStructSetData($tFd_set_writefds, "fd_count", 1) DllStructSetData($tFd_set_writefds, "fd_array", $hSock, 1) Local $tFd_set_exceptfds = DllStructCreate($tagFd_set) DllStructSetData($tFd_set_exceptfds, "fd_count", 1) DllStructSetData($tFd_set_exceptfds, "fd_array", $hSock, 1) Local $tTimeval = DllStructCreate("long tv_sec; long tv_usec") DllStructSetData($tTimeval, "tv_sec", Floor($iTimeOut / 1000)) DllStructSetData($tTimeval, "tv_usec", Round(Mod($iTimeOut, 1000) * 1000)) $aRet = DllCall($hWs2, "int", "select", _ "int", $hSock, "ptr", 0, "ptr", DllStructGetPtr($tFd_set_writefds), "ptr", DllStructGetPtr($tFd_set_exceptfds), "ptr", DllStructGetPtr($tTimeval)) If @error Then $bError = -1 ElseIf $aRet[0] = 0 Then ;time expired $bError = 1 $nCode = -6 ;timed out, similar to WSAETIMEDOUT ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Then ;SOCKET_ERROR $bError = 1 Else If Not (DllStructGetData($tFd_set_writefds, "fd_count") = 1) Then $bError = 1 If DllStructGetData($tFd_set_exceptfds, "fd_count") = 1 Then $tBuf = DllStructCreate("int") $aRet = DllCall("Ws2_32.dll", "int", "getsockopt", _ "uint", $hSock, "int", 0xffff, "int", 0x1007, "ptr", DllStructGetPtr($tBuf), "int*", DllStructGetSize($tBuf)) ;SO_ERROR If @error Then $bError = -1 ElseIf $aRet[0] = 0 Then $nCode = DllStructGetData($tBuf, 1) EndIf Else $nCode = -5 ;NOT_CONNECTED EndIf EndIf EndIf EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure If $hSock Then TCPCloseSocket($hSock) ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf $nReturn = -1 If $hSock Then TCPCloseSocket($hSock) Else $nReturn = $hSock EndIf DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_TCPConnect ; #MODIFIED WRAPPER# ============================================================================================================ ; Name...........: _TCPSend ; Description ...: Wrapper of _TCPSend function, see the guide. ; Syntax.........: _TCPSend($iMainsocket, $iData, $iFlag = 0) ; Parameters ....: $iMainsocket - The array as returned by _TCPAccept ; or the connected socket identifier (SocketID) as returned by _TCPConnect. ; $iData - Data sent. ; |Text or binary data ; $iFlag - values can be added together ; |$TCP_DATA_DEFAULT (0) - It doesn't add anything at the end of the string [Default] ; |$TCP_DATA_EOT (2) - It adds an End of Text ASCII character (Chr(3)) at the end of the string ; Return values .: see the guide. ; Author ........: j0kky ; Modified ......: 1.0.0 ; Remarks .......: If Unicode strings need to be transmitted they must be encoded/decoded with StringToBinary()/BinaryToString(). ; $iFlag = $TCP_DATA_EOT must be set in couple with _TCPRecv, so don't use it for external application ; Links .........: send: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740149(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _TCPSend($iMainsocket, $iData, $iFlag = 0) If IsArray($iMainsocket) And (UBound($iMainsocket, 0) = 1) And (UBound($iMainsocket) > 0) Then $iMainsocket = $iMainsocket[0] If BitAND($iFlag, 2) = 2 Then $iData = String($iData) & Chr(3) $iResult = TCPSend($iMainsocket, $iData) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCPSend ; #WRAPPER# ===================================================================================================================== Func _TCPNameToIP($sName) $iResult = TCPNameToIP($sName) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCPNameToIP ; #FUNCTION# ==================================================================================================================== ; Name...........: _GetIps ; Description ...: Get local and public IP address of a network/computer ; Syntax.........: _GetIps($iServerName = "") ; Parameters ....: $iServerName - The server name which can retrieve your public IP ; |For example: "www.something.com/somethingelse" [Default = ""] ; Return values .: On success it returns an array: ; |[0] - Local IP (on LAN) of the adapter used to connect to Internet. ; |[1] - Public IP. ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter (not used) ; |-5 - servers are offline ; |-6 - IP retrieving failed ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Remarks .......: It works with Winsock library, so it must be initialized with _TCPStartup(). ; Local and public IPs are both retrieved through internet. ; Links .........: error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _GetIps($iServerName = "") If $iServerName = Default Then $iServerName = "" $iServerName = String($iServerName) $iServerName = StringRegExpReplace($iServerName, "^http.?://", "") If StringInStr($iServerName, "/") Then If StringRegExp($iServerName, "/(.*)", 1)[0] Then If StringRight($iServerName, 1) = "/" Then $iServerName = StringTrimRight($iServerName, 1) EndIf Else $iServerName &= "/" EndIf If Not StringRegExp($iServerName, ".+\..{2,}") Then $iServerName = "" ; invalid parameter Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0, $sLocalIP = "", $sPublicIP = "" Local $tagSockAddr = "short sin_family; ushort sin_port; " & _ "STRUCT; ulong S_addr; ENDSTRUCT; " & _ ;sin_addr "char sin_zero[8]" Local $hSock = DllCall($hWs2, "uint", "socket", "int", 2, "int", 1, "int", 6); AF_INET, SOCK_STREAM, IPPROTO_TCP If @error Then $bError = -1 ElseIf ($hSock[0] = 4294967295) Or ($hSock[0] = -1) Then ;INVALID_SOCKET $bError = 1 Else $hSock = $hSock[0] EndIf If Not $bError Then If $iServerName Then Local $aGetIPURL[][2] = [["www.myexternalip.com/raw"], ["checkip.dyndns.org/"], ["bot.whatismyipaddress.com/"], [$iServerName]], $nElements = 0 Else Local $aGetIPURL[][2] = [["www.myexternalip.com/raw"], ["checkip.dyndns.org/"], ["bot.whatismyipaddress.com/"]], $nElements = 0 EndIf For $i = 0 To (UBound($aGetIPURL) - 1) $sServerIp = TCPNameToIP(StringRegExp($aGetIPURL[$i][0], "(.*?)/", 1)[0]) If $sServerIp <> "" Then $aGetIPURL[$nElements][0] = $aGetIPURL[$i][0] $aGetIPURL[$nElements][1] = $sServerIp $nElements += 1 EndIf Next If $nElements Then ReDim $aGetIPURL[$nElements][2] Else $bError = 1 $nCode = -5 ;there is no valid server for checking IP EndIf EndIf If Not $bError Then $aRet = DllCall($hWs2, "ushort", "htons", "ushort", 80) If @error Then $bError = -1 Else $iDestPort = $aRet[0] EndIf EndIf If Not $bError Then For $i = 0 To (UBound($aGetIPURL) - 1) $sServerIp = $aGetIPURL[$i][1] If Not $bError Then $aRet = DllCall($hWs2, "int", "ioctlsocket", "uint", $hSock, "long", 0x8004667e, "ulong*", 1) ;FIONBIO If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf EndIf If Not $bError Then $aRet = DllCall($hWs2, "ulong", "inet_addr", "str", $sServerIp) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Or ($aRet[0] = 0) Then ;INADDR_NONE or INADDR_ANY $bError = 1 Else $sServerIp = $aRet[0] EndIf EndIf If Not $bError Then $tSockAddr = DllStructCreate($tagSockAddr) DllStructSetData($tSockAddr, "sin_family", 2) ;AF_INET DllStructSetData($tSockAddr, "sin_port", $iDestPort) DllStructSetData($tSockAddr, "S_addr", $sServerIp) $aRet = DllCall($hWs2, "int", "connect", "uint", $hSock, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR -> functional with connect() on non-blocking sockets $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $bError = -1 ElseIf ($aRet[0] <> 0) And ($aRet[0] <> 10035) Then ;WSAEWOULDBLOCK $bError = 1 EndIf EndIf $tSockAddr = 0 EndIf If Not $bError Then Local $tagFd_set = "uint fd_count; uint fd_array[64]" Local $tFd_set_writefds = DllStructCreate($tagFd_set) DllStructSetData($tFd_set_writefds, "fd_count", 1) DllStructSetData($tFd_set_writefds, "fd_array", $hSock, 1) Local $tFd_set_exceptfds = DllStructCreate($tagFd_set) DllStructSetData($tFd_set_exceptfds, "fd_count", 1) DllStructSetData($tFd_set_exceptfds, "fd_array", $hSock, 1) Local $tTimeval = DllStructCreate("long tv_sec; long tv_usec") DllStructSetData($tTimeval, "tv_sec", Floor(500 / 1000)) DllStructSetData($tTimeval, "tv_usec", Round(Mod(500, 1000) * 1000)) $aRet = DllCall($hWs2, "int", "select", _ "int", $hSock, "ptr", 0, "ptr", DllStructGetPtr($tFd_set_writefds), "ptr", DllStructGetPtr($tFd_set_exceptfds), "ptr", DllStructGetPtr($tTimeval)) If @error Then $bError = -1 ElseIf ($aRet[0] = 0) Or ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Then $bError = 1 Else If Not (DllStructGetData($tFd_set_writefds, "fd_count") = 1) Then $bError = 1 EndIf EndIf If Not $bError And Not $sLocalIP Then $tSockAddr = DllStructCreate($tagSockAddr) $aRet = DllCall($hWs2, "int", "getsockname", "uint", $hSock, "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 Else $aRet = DllCall($hWs2, "ptr", "inet_ntoa", "ulong", DllStructGetData($tSockAddr, "S_addr")) If @error Then $bError = -1 ElseIf $aRet[0] = Null Then $bError = 1 Else $sLocalIP = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) ;IP address EndIf EndIf $tSockAddr = 0 EndIf If Not $bError Then $sRequest = "GET /" & StringRegExp($aGetIPURL[$i][0], "/(.*)", 1)[0] & " HTTP/1.1" & @CRLF & _ "Host: " & StringRegExp($aGetIPURL[$i][0], "(.*?)/", 1)[0] & @CRLF & _ "Connection: close" & @CRLF & @CRLF TCPSend($hSock, $sRequest) Local $sRecv = "", $hTimer = TimerInit() While 1 $sRecv &= _TCPRecv($hSock, 2048) If @error Or @extended Then If @error Then $bError = 1 ExitLoop EndIf If TimerDiff($hTimer) > 2500 Then ExitLoop Sleep(10) WEnd EndIf If Not $bError Then $aPublicIP = StringRegExp($sRecv, "((?:\d{1,3}\.){3}\d{1,3})", 3) ;STR_REGEXPARRAYGLOBALMATCH If Not @error Then $sPublicIP = $aPublicIP[0] ExitLoop Else $bError = 1 EndIf EndIf If $bError And $i = (UBound($aGetIPURL) - 1) Then $nCode = -6 ExitLoop Else $bError = 0 $nCode = 0 TCPCloseSocket($hSock) EndIf Local $hSock = DllCall($hWs2, "uint", "socket", "int", 2, "int", 1, "int", 6); AF_INET, SOCK_STREAM, IPPROTO_TCP If @error Then $bError = -1 ElseIf ($hSock[0] = 4294967295) Or ($hSock[0] = -1) Then ;INVALID_SOCKET $bError = 1 Else $hSock = $hSock[0] EndIf Next EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf $nReturn = -1 Else Local $nReturn[2] = [$sLocalIP, $sPublicIP] EndIf If $hSock Then TCPCloseSocket($hSock) DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_GetIps ; #MODIFIED WRAPPER# ============================================================================================================ ; Name...........: _TCPCloseSocket ; Description ...: Wrapper of TCPCloseSocket function, see the guide. ; Syntax.........: _TCPCloseSocket($iMainsocket) ; Parameters ....: $iMainsocket - The array as returned by _TCPAccept ; or the connected socket identifier (SocketID) as returned by _TCPListen and _TCPConnect. ; Return values .: see the guide. ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: recv: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _TCPCloseSocket($iMainsocket) If IsArray($iMainsocket) And (UBound($iMainsocket, 0) = 1) And (UBound($iMainsocket) > 0) Then $iMainsocket = $iMainsocket[0] $iResult = TCPCloseSocket($iMainsocket) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCPCloseSocket ; #WRAPPER# ===================================================================================================================== Func _TCPShutdown() $iResult = TCPShutdown() Return SetError(@error, 0, $iResult) EndFunc ;==>_TCPShutdown ; #WRAPPER# ===================================================================================================================== Func _UDPStartup() $iResult = UDPStartup() Return SetError(@error, 0, $iResult) EndFunc ;==>_UDPStartup ; #FUNCTION# ==================================================================================================================== ; Name...........: _UDPBind ; Description ...: Creates and bind a socket to a local IP and a local port. ; Syntax.........: _UDPBind($sSourceAddr = "", $iSourcePort = 0) ; Parameters ....: $sSourceAddr - Source IP ; |Internet Protocol dotted address(IpV4) as "192.162.1.1". [Default = ""] ; $iSourcePort - Source port. ; |1 : 65534 - port on which the created socket will be bind (on the local PC). [Default = 0] ; Return values .: On success it returns the main socket identifier. ; |Any value > 0 ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Remarks .......: It could be used before both of _UDPSendTo (client app) and _UDPRecvFrom (server app) functions ; Links .........: bind: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _UDPBind($sSourceAddr = "", $iSourcePort = 0) If $sSourceAddr = Default Then $sSourceAddr = "" If $iSourcePort = Default Then $iSourcePort = 0 $sSourceAddr = String($sSourceAddr) $iSourcePort = Number($iSourcePort) If Not ($iSourcePort >= 0 And $iSourcePort < 65535) Then Return SetError(-4, 0, -1) ; invalid parameter If $sSourceAddr <> "" Then StringRegExp($sSourceAddr, "((?:\d{1,3}\.){3}\d{1,3})", 3) ;$STR_REGEXPARRAYGLOBALMATCH If @error Then Return SetError(-4, 0, -1) EndIf Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0 Local $tagSockAddr = "short sin_family; ushort sin_port; " & _ "STRUCT; ulong S_addr; ENDSTRUCT; " & _ ;sin_addr "char sin_zero[8]" Local $hSock = DllCall($hWs2, "uint", "socket", "int", 2, "int", 2, "int", 17); AF_INET, SOCK_DGRAM, IPPROTO_UDP If @error Then $bError = -1 ElseIf ($hSock[0] = 4294967295) Or ($hSock[0] = -1) Then ;INVALID_SOCKET $bError = 1 Else $hSock = $hSock[0] EndIf If (Not $bError) And ($sSourceAddr <> "") Then $aRet = DllCall($hWs2, "ulong", "inet_addr", "str", $sSourceAddr) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Or ($aRet[0] = 0) Then ;INADDR_NONE or INADDR_ANY $bError = 1 Else $sSourceAddr = $aRet[0] EndIf EndIf If (Not $bError) And $iSourcePort Then $aRet = DllCall($hWs2, "ushort", "htons", "ushort", $iSourcePort) If @error Then $bError = -1 Else $iSourcePort = $aRet[0] EndIf EndIf If Not $bError Then $tSockAddr = DllStructCreate($tagSockAddr) DllStructSetData($tSockAddr, "sin_family", 2) ;AF_INET If $iSourcePort Then DllStructSetData($tSockAddr, "sin_port", $iSourcePort) Else DllStructSetData($tSockAddr, "sin_port", 0) EndIf If $sSourceAddr Then DllStructSetData($tSockAddr, "S_addr", $sSourceAddr) Else DllStructSetData($tSockAddr, "S_addr", 0x00000000) ;INADDR_ANY EndIf $aRet = DllCall($hWs2, "int", "bind", "uint", $hSock, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf $tSockAddr = 0 EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure If $hSock Then UDPCloseSocket($hSock) ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf $nReturn = -1 If $hSock Then UDPCloseSocket($hSock) Else $nReturn = $hSock EndIf DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_UDPBind ; #FUNCTION# ==================================================================================================================== ; Name...........: _UDPSendTo ; Description ...: Sends data to an address/port, it uses a socket created by _UDPBind or it creates a socket itself ; Syntax.........: _UDPSendTo($sIPAddr, $iDestPort, $iData, $iMainsocket = 0) ; Parameters ....: $sIPAddr - Destination IP. ; |Internet Protocol dotted address(IpV4) as "192.162.1.1". ; $iDestPort - Destination port. ; |1 : 65534 - port which the created socket will connect on. ; $iData - Data sent. ; |Text or binary data ; $iMainsocket - Main socket identifier returned by _UDPBind. ; |Any value > 0 [Default = 0] ; Return values .: On success it returns an array: ; |[0] - The number of bytes sent. ; |[1] - The main socket identifier used. ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: sendto: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740148(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _UDPSendTo($sIPAddr, $iDestPort, $iData, $iMainsocket = 0) If $iMainsocket = Default Then $iMainsocket = 0 $iMainsocket = Number($iMainsocket) $sIPAddr = String($sIPAddr) $iDestPort = Number($iDestPort) If Not IsBinary($iData) Then $iData = String($iData) If Not ($iDestPort > 0 And $iDestPort < 65535) Or _ $iMainsocket < 0 Then Return SetError(-4, 0, -1) ; invalid parameter StringRegExp($sIPAddr, "((?:\d{1,3}\.){3}\d{1,3})", 3) ;$STR_REGEXPARRAYGLOBALMATCH If @error Then Return SetError(-4, 0, -1) Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0 Local $tagSockAddr = "short sin_family; ushort sin_port; " & _ "STRUCT; ulong S_addr; ENDSTRUCT; " & _ ;sin_addr "char sin_zero[8]" If Not $iMainsocket Then Local $aRet = DllCall($hWs2, "uint", "socket", "int", 2, "int", 2, "int", 17); AF_INET, SOCK_DGRAM, IPPROTO_UDP If @error Then $bError = -1 ElseIf ($aRet[0] = 4294967295) Or ($aRet[0] = -1) Then ;INVALID_SOCKET $bError = 1 Else $iMainsocket = $aRet[0] EndIf EndIf If Not $bError Then $aRet = DllCall($hWs2, "ulong", "inet_addr", "str", $sIPAddr) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Or ($aRet[0] = 0) Then ;INADDR_NONE or INADDR_ANY $bError = 1 Else $sIPAddr = $aRet[0] EndIf EndIf If Not $bError Then $aRet = DllCall($hWs2, "ushort", "htons", "ushort", $iDestPort) If @error Then $bError = -1 Else $iDestPort = $aRet[0] EndIf EndIf If Not $bError Then $aRet = DllCall($hWs2, "int", "ioctlsocket", "uint", $iMainsocket, "long", 0x8004667e, "ulong*", 1) ;FIONBIO If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf EndIf If Not $bError Then Local $tSockAddr = DllStructCreate($tagSockAddr) DllStructSetData($tSockAddr, "sin_family", 2) ;AF_INET DllStructSetData($tSockAddr, "sin_port", $iDestPort) DllStructSetData($tSockAddr, "S_addr", $sIPAddr) Local $nLenght, $tBuf If IsBinary($iData) Then $nLenght = BinaryLen($iData) $tBuf = DllStructCreate("byte[" & $nLenght & "]") DllStructSetData($tBuf, 1, $iData) Else $nLenght = StringLen($iData) $tBuf = DllStructCreate("char[" & $nLenght & "]") DllStructSetData($tBuf, 1, $iData) EndIf $aRet = DllCall($hWs2, "int", "sendto", _ "uint", $iMainsocket, "ptr", DllStructGetPtr($tBuf), "int", $nLenght, "int", 0, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Then ;SOCKET_ERROR $bError = 1 Else Local $aReturn[2] = [$aRet[0], $iMainsocket] EndIf EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf $nReturn = -1 Else $nReturn = $aReturn EndIf DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_UDPSendTo ; #FUNCTION# ==================================================================================================================== ; Name...........: _UDPRecvFrom ; Description ...: Receives data from a bound socket on the local PC. ; Syntax.........: _UDPRecvFrom($iMainsocket, $iMaxLen, $iFlag = 0) ; Parameters ....: $iMainsocket - Main socket identifier. ; |Any value > 0 ; $iMaxLen - Max # of characters to receive (usually 2048). ; $iFlag ; |0 - Text data. [Default] ; |1 - Binary data. ; Return values .: On success it returns an array: ; |[0] - The data received. ; |[1] - The IP address of the sender. ; |[2] - The port used by the sender for connection. ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: recvfrom: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740120(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _UDPRecvFrom($iMainsocket, $iMaxLen, $iFlag = 0) If $iFlag = Default Then $iFlag = 0 $iMainsocket = Number($iMainsocket) $iMaxLen = Number($iMaxLen) $iFlag = Number($iFlag) If $iMainsocket < 0 Or _ $iMaxLen < 1 Or _ Not ($iFlag = 0 Or $iFlag = 1) Then Return SetError(-4, 0, -1) ; invalid parameter Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0 Local $tagSockAddr = "short sin_family; ushort sin_port; " & _ "STRUCT; ulong S_addr; ENDSTRUCT; " & _ ;sin_addr "char sin_zero[8]" If Not $bError Then $aRet = DllCall($hWs2, "int", "ioctlsocket", "uint", $iMainsocket, "long", 0x8004667e, "ulong*", 1) ;FIONBIO If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf EndIf Local $tSockAddr = DllStructCreate($tagSockAddr) Local $tBuf If $iFlag Then $tBuf = DllStructCreate("byte[" & $iMaxLen & "]") Else $tBuf = DllStructCreate("char[" & $iMaxLen & "]") EndIf $aRet = DllCall($hWs2, "int", "recvfrom", _ "uint", $iMainsocket, "ptr", DllStructGetPtr($tBuf), "int", $iMaxLen, "int", 0, "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Then $bError = -1 ElseIf ($aRet[0] = -1) Or ($aRet[0] = 4294967295) Then ;SOCKET_ERROR $bError = 1 $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $bError = -1 ElseIf $aRet[0] = 0 Or $aRet[0] = 10035 Then ;WSAEWOULDBLOCK $nCode = -10 ;internal function value, it means no error EndIf Else Local $aResult[3] = [DllStructGetData($tBuf, 1)] ;data $aRet = DllCall($hWs2, "ptr", "inet_ntoa", "ulong", DllStructGetData($tSockAddr, "S_addr")) If @error Then $bError = -1 ElseIf $aRet[0] = Null Then $bError = 1 Else $aResult[1] = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) ;IP address $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", DllStructGetData($tSockAddr, "sin_port")) If @error Then $bError = -1 Else $aResult[2] = $aRet[0] ;port EndIf EndIf EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf If $nCode = -10 Then $nCode = 0 $nReturn = -1 Else $nReturn = $aResult EndIf DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_UDPRecvFrom ; #FUNCTION# ==================================================================================================================== ; Name...........: _UDPCloseSocket ; Description ...: Close a UDP socket. ; Syntax.........: _UDPCloseSocket($iMainsocket) ; Parameters ....: $iMainsocket - Main socket identifier returned by _UDPBind or the array returned by _UDPSendTo. ; |Any value > 0 ; Return values .: On success it returns 1. ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - undefined error ; |-4 - invalid parameter ; |Any Windows Socket Error Code retrieved by WSAGetLastError ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: closesocket: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737582(v=vs.85).aspx ; error codes: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ; =============================================================================================================================== Func _UDPCloseSocket($iMainsocket) If IsArray($iMainsocket) Then If Not ((UBound($iMainsocket, 0) = 1) And (UBound($iMainsocket) = 2)) Then Return SetError(-1, 0, -4) $iMainsocket = $iMainsocket[1] Else If $iMainsocket < 1 Then Return SetError(-1, 0, -4) EndIf Local $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, 0, -1) ;missing DLL Local $bError = 0, $nCode = 0 $aRet = DllCall($hWs2, "int", "closesocket", "uint", $iMainsocket) If @error Then $bError = -1 ElseIf $aRet[0] <> 0 Then ;SOCKET_ERROR $bError = 1 EndIf If $bError < 0 Then $nCode = -1 ;internal error $nReturn = -1 ;failure ElseIf $bError > 0 Then If Not $nCode Then $aRet = DllCall($hWs2, "int", "WSAGetLastError") If @error Then $nCode = -1 Else $nCode = $aRet[0] EndIf If $nCode = 0 Then $nCode = -3 ;undefined error EndIf $nReturn = -1 Else $nReturn = 1 EndIf DllClose($hWs2) Return SetError($nCode, 0, $nReturn) EndFunc ;==>_UDPCloseSocket ; #WRAPPER# ===================================================================================================================== Func _UDPShutdown() $iResult = UDPShutdown() Return SetError(@error, 0, $iResult) EndFunc ;==>_UDPShutdown Obviously there can be a lot of errors, so please report here any problem\suggestion! Updated to: 11/01/16 winsock.zip
-
Hi everybody! I wanted to learn winsockets, and for this, I try to reproduce AutoIt's TCP functions. My code is working pretty good! I juste want somebody, an AutoIt dev, to look my code and tell me if I'm doing something wrong, or something need to be done differently. Another problem, is that when I close a socket on one side of a connection, the recv functions in the other side doesn't detect the close action! (like TCPRecv would return an @error) Thanks in advance! (I compile it with GCC 4x) Here is the code #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #define WINVER 0x0501 #define _WIN32_WINNT 0x0501 #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #include <stdio.h> #include <stdlib.h> /* -------------------------------------------------------------------------- */ #define SIMPLE_TCP_BUILD_DLL #include "simpletcp.h" /* -------------------------------------------------------------------------- */ #define CHECK_INIT if (_global_ == NULL) return; #define CHECK_INIT_RET(ret) if (_global_ == NULL) return ret; #define SET_ERR(func) sprintf(_global_->err_func, "%s", func); _global_->err = WSAGetLastError(); #define UNSET_ERR sprintf(_global_->err_func, "%s", ""); _global_->err = 0; /* -------------------------------------------------------------------------- */ typedef struct { WSADATA wsaData; char err_func[20]; int err; } simple_tcp_t; simple_tcp_t* _global_ = NULL; /* -------------------------------------------------------------------------- */ /* Standard functions */ /** \brief * * \return */ int SIMPLE_TCP TCPStartup () { if (_global_ != NULL) { return 1; } _global_ = malloc(sizeof(simple_tcp_t)); if (_global_ == NULL) { return 0; } if (WSAStartup(MAKEWORD(2, 2), &_global_->wsaData) != 0) { free(_global_); _global_ = NULL; return 0; } UNSET_ERR return 1; } /** \brief * * \return */ void SIMPLE_TCP TCPShutdown () { if (_global_ == NULL) { return; } WSACleanup(); free(_global_); _global_ = NULL; } /** \brief * * \param * \param * * \return */ int SIMPLE_TCP TCPGetError (char* err_func, const size_t err_func_len) { CHECK_INIT_RET(0) int err = _global_->err; if (err_func != NULL && err_func_len > 0) { snprintf(err_func, err_func_len, "%s", _global_->err_func); } UNSET_ERR return err; } /** \brief * * \param * \param * * \return */ int SIMPLE_TCP TCPConnect (const char* host, const char* port) { CHECK_INIT_RET(0) UNSET_ERR struct addrinfo hints, *result = NULL; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; // IP v4 hints.ai_socktype = SOCK_STREAM; // Stream socket hints.ai_protocol = IPPROTO_TCP; // TCP if (getaddrinfo(host, port, &hints, &result) != 0) { SET_ERR("getaddrinfo") return 0; } SOCKET ConnectSocket = INVALID_SOCKET; ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { freeaddrinfo(result); SET_ERR("socket") return 0; } if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) != 0) { freeaddrinfo(result); SET_ERR("connect") return 0; } freeaddrinfo(result); unsigned long mode = 1; if (ioctlsocket(ConnectSocket, FIONBIO, &mode) != 0) { SET_ERR("ioctlsocket") return 0; } return ConnectSocket; } /** \brief * * \param * * \return */ int SIMPLE_TCP TCPListen (const char* port) { CHECK_INIT_RET(0) UNSET_ERR struct addrinfo hints, *result = NULL; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; // IP v4 hints.ai_socktype = SOCK_STREAM; // Stream socket hints.ai_protocol = IPPROTO_TCP; // TCP hints.ai_flags = AI_PASSIVE; // this + node = NULL => local host IP if (getaddrinfo(NULL, port, &hints, &result) != 0) { SET_ERR("getaddrinfo") return 0; } SOCKET ListenSocket = INVALID_SOCKET; ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { freeaddrinfo(result); SET_ERR("socket") return 0; } unsigned long mode = 1; if (ioctlsocket(ListenSocket, FIONBIO, &mode) != 0) { freeaddrinfo(result); SET_ERR("ioctlsocket") return 0; } if (bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen) != 0) { freeaddrinfo(result); SET_ERR("bind") return 0; } freeaddrinfo(result); if (listen(ListenSocket, SOMAXCONN) != 0) { SET_ERR("listen") return 0; } return ListenSocket; } /** \brief * * \param * * \return */ int SIMPLE_TCP TCPAccept (int socket) { CHECK_INIT_RET(0) UNSET_ERR int err; SOCKET ClientSocket = INVALID_SOCKET; ClientSocket = accept(socket, NULL, NULL); err = WSAGetLastError(); if (ClientSocket == INVALID_SOCKET && err != WSAEWOULDBLOCK) { SET_ERR("accept") return INVALID_SOCKET; } if (ClientSocket != INVALID_SOCKET) { unsigned long mode = 1; if (ioctlsocket(ClientSocket, FIONBIO, &mode) != 0) { SET_ERR("ioctlsocket") return INVALID_SOCKET; } } return ClientSocket; } /** \brief * * \param * * \return */ int SIMPLE_TCP TCPCloseSocket (int socket) { CHECK_INIT_RET(0) UNSET_ERR if (shutdown(socket, SD_BOTH) != 0) { SET_ERR("shutdown") return 0; } if (closesocket(socket) != 0) { SET_ERR("closesocket") return 0; } return 1; } /** \brief * * \param * \param * \param * * \return */ int SIMPLE_TCP TCPSend (int socket, const char* data, const size_t data_len) { CHECK_INIT_RET(0) UNSET_ERR int ret = send(socket, data, data_len, 0); if ((ret == SOCKET_ERROR || ret == 0) && WSAGetLastError() != WSAEWOULDBLOCK) { SET_ERR("send") return 0; } return ret; } /** \brief * * \param * \param * \param * * \return */ int SIMPLE_TCP TCPRecv (int socket, char* data, const size_t data_len) { CHECK_INIT_RET(0) UNSET_ERR int ret = recv(socket, data, data_len, 0); if ((ret == 0 || ret == SOCKET_ERROR) && WSAGetLastError() != WSAEWOULDBLOCK) { SET_ERR("recv") return 0; } return ret; } /** \brief * * \param * \param * \param * * \return */ int SIMPLE_TCP TCPNameToIP (const char* name, char* ip, const size_t ip_len) { CHECK_INIT_RET(0) UNSET_ERR struct addrinfo hints, *result = NULL; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; // IP v4 hints.ai_socktype = SOCK_STREAM; // Stream socket hints.ai_protocol = IPPROTO_TCP; // TCP if (getaddrinfo(name, NULL, &hints, &result) != 0) { SET_ERR("getaddrinfo") return 0; } if (result->ai_family != AF_INET || result->ai_addrlen != sizeof(struct sockaddr_in)) { SET_ERR("bad address family") freeaddrinfo(result); return 0; } struct sockaddr_in* addr = (struct sockaddr_in*)result->ai_addr; char* ret = inet_ntoa(addr->sin_addr); snprintf(ip, ip_len, "%s", ret); freeaddrinfo(result); return 1; } /** \brief * * \param * \param * \param * * \return */ int SIMPLE_TCP TCPSocketToIP (int socket, char* ip, const size_t ip_len) { CHECK_INIT_RET(0) UNSET_ERR struct sockaddr_in addr_in; int len = sizeof(addr_in); if (getpeername(socket, (struct sockaddr*)&addr_in, &len) != 0) { SET_ERR("getpeername") return 0; } char* ret = inet_ntoa(addr_in.sin_addr); if (ret == NULL) { SET_ERR("inet_ntoa") return 0; } snprintf(ip, ip_len, "%s", ret); return 1; } and the header #ifndef __SIMPLE_TCP_H__ #define __SIMPLE_TCP_H__ #ifdef SIMPLE_TCP_BUILD_DLL #define SIMPLE_TCP __stdcall __declspec(dllexport) #else #define SIMPLE_TCP __stdcall __declspec(dllimport) #endif /* -------------------------------------------------------------------------- */ /* Standard functions */ int SIMPLE_TCP TCPStartup (); void SIMPLE_TCP TCPShutdown (); int SIMPLE_TCP TCPGetError (char* err_func, const size_t err_func_len); int SIMPLE_TCP TCPConnect (const char* ip, const char* port); int SIMPLE_TCP TCPListen (const char* port); int SIMPLE_TCP TCPAccept (int socket); int SIMPLE_TCP TCPCloseSocket (int socket); int SIMPLE_TCP TCPSend (int socket, const char* data, const size_t data_len); int SIMPLE_TCP TCPRecv (int socket, char* data, const size_t data_len); int SIMPLE_TCP TCPNameToIP (const char* name, char* ip, const size_t ip_len); int SIMPLE_TCP TCPSocketToIP (int socket, char* ip, const size_t ip_len); #endif // __SIMPLE_TCP_H__