AutoHotkey Community

It is currently May 27th, 2012, 12:16 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 26 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: July 31st, 2009, 10:57 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7503
Location: Australia
Currently WinSock2.ahk can't be used to send binary data. Ideally WS2_SendData would accept a pointer and data length, but since changing it now would cause compatibility issues, I suggest the following changes/additions:
Code:
WS2_SendData(WS2_Socket, StringToSend) {
    Global __WSA_ErrMsg
    If (__WSA_send(WS2_Socket, &StringToSend, StrLen(StringToSend))=-1) {
        MsgBox, 16, %A_ScriptName%: Send-Error, % __WSA_ErrMsg
    }
}

WS2_SendDataEx(WS2_Socket, DataToSend, DataLength) {
    Global __WSA_ErrMsg
    If (__WSA_send(WS2_Socket, DataToSend, DataLength)=-1) {
        MsgBox, 16, %A_ScriptName%: Send-Error, % __WSA_ErrMsg
    }
}

WS2_SendNumber(WS2_Socket, Num, Type="UInt") {
    Global __WSA_ErrMsg
    VarSetCapacity(DataToSend, 8)
    DataLength := NumPut(Num, DataToSend, 0, Type) - &DataToSend
    If (__WSA_send(WS2_Socket, &DataToSend, DataLength)=-1) {
        MsgBox, 16, %A_ScriptName%: Send-Error, % __WSA_ErrMsg
    }
}

; WSA Send - for internal use only
; Users are encouraged to use the WS2_SendData() Function
__WSA_send(__WSA_Socket, __WSA_Data, __WSA_DataLen)
{
    Global __WSA_ErrMsg

    Result := DllCall("Ws2_32\send"
                       , "UInt", __WSA_Socket
                       , "UInt",  __WSA_Data
                       , "Int", __WSA_DataLen
                       , "Int", 0)
   If (Result = -1)
      __WSA_ErrMsg .=  "Ws2_32\send " __WSA_GetLastError()
   Return Result
}
I also recommend a few changes to __WSA_recv:
Code:
__WSA_recv(wParam, lParam)
{
    Global __WSA_UDF, __WSA_ErrMsg
    ; __WSA_UDF containes the name of the UserDefinedFunction to call when the event
    ; has been triggered and text may be processed (allthough the reveived text might
    ; be inclomplete, especially when receiving large chunks of data, like in eMail-
    ; attachments or sometimes in IRC). The UDF needs to accept two parameter: socket
    ; and the received buffer
   
    __WSA_Socket := wParam
    __WSA_BufferSize = 4096
    Loop
    {
        VarSetCapacity(__WSA_Buffer, __WSA_BufferSize, 0)
        __WSA_BufferLength := DllCall("Ws2_32\recv"
                                        , "UInt", __WSA_Socket
                                        , "Str",  __WSA_Buffer
                                        , "Int",  __WSA_BufferSize
                                        , "Int",  0 )
        if (__WSA_BufferLength <= 0) ; 0 or -1 (probably never < -1)
        {
            __WSA_Err := __WSA_GetLastError(0)
           
            ; __WSA_WOULDBLOCK (from http://www.sockets.com/)
            ; The socket is marked as non-blocking (non-blocking operation mode), and
            ; the requested operation is not complete at this time. The operation is
            ; underway, but as yet incomplete.
            if (__WSA_Err = __WSA_WOULDBLOCK )
                return 1
           
            ; __WSA_CONNRESET: (from http://www.sockets.com/)
            ; A connection was forcibly closed by a peer. This normally results from
            ; a loss of the connection on the remote socket due to a timeout or a reboot.
            if (__WSA_UDF != "" && (__WSA_BufferLength = 0 || __WSA_Err = __WSA_CONNRESET))
                return 1, %__WSA_UDF%(__WSA_Socket, __WSA_Buffer:="", 0)

           
            __WSA_ErrMsg .= "Ws2_32\recv indicated Winsock error " __WSA_Err "`n"
            break
        }

        if __WSA_UDF != ; If set, call UserDefinedFunction and pass Buffer to it
            %__WSA_UDF%(__WSA_Socket, __WSA_Buffer, __WSA_BufferLength)
    }
    return 1
}
I've added an optional third parameter for the user-defined callback function (__WSA_UDF), containing the length of the data received. This allows it to handle binary data, as long as it declares the second parameter ByRef. Additionally, the callback will be called with data:="" and length:=0 when the socket disconnects.

Finally, I suggest __WSA_ErrLookUp be replaced with the Win32 function FormatMessage:
Code:
__WSA_GetLastError(txt=1)
{
    err := DllCall("Ws2_32\WSAGetLastError")
    if txt {
        VarSetCapacity(txt, 1024) ; "Limit" to 1024 chars.
        if DllCall("FormatMessage", uint, 0x1200, uint, 0, int, err
                                , uint, 1024, str, txt, uint, 1024, uint, 0)
            return "indicated Winsock error " . err . ":`n" . txt
    }
    return err
}
__WSA_ErrLookUp can then be deleted.
jdpmd wrote:
Instead of coding a pathway, you can put WinSock.ahk in LIB
I suggest simply naming the file "WS2.ahk" and using the WS2_*() functions as appropriate.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 3rd, 2009, 9:48 pm 
Lexikos, this looks brilliant. I am new to AHK & winsock functions. May I ask to see a runtime demonstration, so to connect this up to send binary data efficiently somewhere? :D that would be so great!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 5th, 2009, 6:39 am 
Lexikos wrote:
Currently WinSock2.ahk can't be used to send binary data. Ideally WS2_SendData would accept a pointer and data length, but since changing it now would cause compatibility issues, I suggest the following changes/additions:



Hi Lexikos, I am attempting to test-work with some of your functions on my Windows Vista machine to connect-loop back on IP-V6.

Below, I implement the following function successfully to establish a waiting socket accepting connections for IP-V4 clients.

Code:

Network_Address=191.1.1.125
Network_Port=1000

socket := CONNECT(Network_Address, Network_Port)



However below is a properly formatted IPV6 IP address. Can you pls suggest how I may establish a similar accepting socket for V6 based clients? WSAConnectByName is robust for just a waiting socket.


Network_Address=fa84::48e7:d4af:16ce:1354%11

socket := WSAConnectByName()





Code:

; ---- IPV4 PLUG

CONNECT(IPAddress, Port)
{
    VarSetCapacity(wsaData, 32)

    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002)

    AF_INET = 2
    SOCK_STREAM = 1
    IPPROTO_TCP = 6
    socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
 
    SizeOfSocketAddress = 16

    VarSetCapacity(SocketAddress, SizeOfSocketAddress)
    InsertInteger(2, SocketAddress, 0, AF_INET)   ; sin_family
    InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)   ; sin_port
    InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)   ; sin_addr.s_addr

    DllCall("Ws2_32\bind", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
    DllCall("Ws2_32\listen", "UInt", socket, "UInt", "SOMAXCONN")

    return socket
}

; ---- IPV4 PLUG


; ---- IPV6 PLUG?



WSAConnectByName(s, nodename, servicename, LocalAddressLength, ByRef LocalAddress
                    , RemoteAddressLength, ByRef RemoteAddress, timeout)
{
    return DllCall("Ws2_32\WSAConnectByNameA", "int", s, "str", nodename
        , "str", servicename, "uint*", LocalAddressLength, "uint", &LocalAddress
        , "uint*", RemoteAddressLength, "uint", &RemoteAddress
        , "int64*", timeout, "uint", 0)
}



; ---- IPV6 PLUG?




Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 5th, 2009, 8:57 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7503
Location: Australia
YellowHen and Trial80,
Please note that this winsock library was written by DerRaphael. My contribution is limited to those few functions in my previous post. Although I'm sure I can help you, it may be a long while before I get enough free time to do so.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 5th, 2009, 8:51 pm 
Lexikos wrote:
YellowHen and Trial80,
Please note that this winsock library was written by DerRaphael. My contribution is limited to those few functions in my previous post. Although I'm sure I can help you, it may be a long while before I get enough free time to do so.


:( - just kidding, and do understand.

Thank you, and respectfully I wait for some ideas when you have a chance. :arrow: Thank you in advance for when a chance is possible for ideas.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 10th, 2009, 8:25 pm 
Offline

Joined: August 8th, 2009, 6:28 am
Posts: 8
Location: Melbourne, AU
Lexikos wrote:
YellowHen and Trial80,
Please note that this winsock library was written by DerRaphael. My contribution is limited to those few functions in my previous post. Although I'm sure I can help you, it may be a long while before I get enough free time to do so.


Lexikos, I am interested too in learning about IPV6 socket connections. This looks very interesting...

Signed, SB
Just my Opinion / AHK Guru


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 10th, 2009, 10:10 pm 
Offline

Joined: November 1st, 2007, 10:03 pm
Posts: 885
Nice script DerRaphael, this makes it easy to make such things like a chat program


Report this post
Top
 Profile  
Reply with quote  
PostPosted: September 7th, 2009, 10:02 pm 
When I use WinSock2.ahk I'm getting a load of errors:
Ws2_32\gethostbyname failed
Ws2_32\connect indicated Winsock error 10038
10038 means Socket operation on non-socket
Ws2_32\WSAAsyncSelect() indicated Winsock error 10038
10038 means Socket operation on non-socket
Ws2_32\send indicated Winsock error 10038
10038 means Socket operation on non-socket
Ws2_32\send indicated Winsock error 10038
10038 means Socket operation on non-socket
Ws2_32\send indicated Winsock error 10038
10038 means Socket operation on non-socket
Ws2_32\send indicated Winsock error 10038
10038 means Socket operation on non-socket

I've checked my script a bunch of times. What's wrong?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: September 7th, 2009, 10:28 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7503
Location: Australia
Clearly you are passing an invalid socket handle to each of those functions (except gethostbyname). WS2_Connect/socket is probably failing.
Quote:
What's wrong?
You didn't post your script. :roll:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 11th, 2009, 6:54 pm 
How to connect to .... jabber.org 5222 ?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 20th, 2009, 10:50 am 
Hi
I'm using this with in a script I have and it works well. :)

Within the same script I would like to be able to capture the first line of a telnet session to a var.

Basically the bit of text that the server outputs as soon as you telnet it, prior to logging in.

Is there anyway to do that using this script ? It seems to make sense to use this as it's already included.

Thanks :)


Report this post
Top
  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page Previous  1, 2

All times are UTC [ DST ]


Who is online

Users browsing this forum: Google [Bot] and 6 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group