Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 15, 2020 4:14:30 GMT -5
This is the full snippet on the tx side, it's not organised or optimised yet. HEXIN$ is being populated by a receive routine earlier. This "050100D8C1" is effectively a handshake from the external panel, once received I send back the 'ACK' "50 01 00 6d ff" So I'm converting several times to eventually send it as CHR$ [SEND_DATA_OUT]
'ACK command 50 01 00 6d ff IF HEXIN$ = "050100D8C1" THEN TXDATA$ = "50 01 00 6d ff" IF TXDATA$ <> "" THEN
'Convert TXDATA to ASCII text
DATACONVERT$ = TXDATA$ token$ = "?" while token$ <> "" index = index + 1 token$ = word$(DATACONVERT$, index) op = HEXDEC(token$) print "CHR$:"; CHR$(op) OUTPUT$ = OUTPUT$ + CHR$(op) wend
'Replace the converted HEX to CHR$ variables and check the length
TXDATA$ = OUTPUT$ num = LEN(TXDATA$)
'Then send the converted TXDATA$ to the UDP DLL
sendNum = UDPSendTo(hSock, TXDATA$, num, recvFrom$) if sendNum = -1 then theError = GetError() print "UDPSendTo() failed. - ";dechex$(theError) goto [doClose] ELSE print "TXDATA$:"; TXDATA$ end if END IF
'Clear vars TXDATA$ = "" DATACONVERT$ = ""
This is the first capture, IP 0.37 is the PC, 0.174 in the external equipment. This is the return from the external equipment
Yes, Rod you are correct, but byte manipulation is beyond me right now. What's odd is, if I send the 'ACK' command as a "6" to the external equipment, it indeed receives that and stops sending the handshake, however it doesn't send the next messages after the handshake.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 15, 2020 4:26:05 GMT -5
Sorry for the double post. This is the full code.
In the future the idea would be to put the TX side into its own function and pass that info that needs to be sent out.
'WARNING - IF LBNET.DLL GETS UPDATED THIS COULD CAUSE IP TO/FROM STOP WORKING. IN THIS ROUTINE [Collect_IP_Info_from_RX_Data]
'050100D8C1 - Appears to be handshake
GLOBAL port$
'Open a window to allow user to CLOSE the DLL etc whle the rest of the program is listening for traffic UpperLeftX = 32 : UpperLeftY = 52 : WindowWidth = 100 : WindowHeight = 100 BUTTON #main.but1, "CLOSE", [doClose], UL, 10, 10 OPEN "Window" for window AS #main #main, "trapclose [doClose]"
'Setup port port$ = "10002" 'Setup buffer size bufLen = 512
'open DLL file CALL OpenLBNetDLL
'Create socket hSock = UDPCreateListenSocket(port$) if IsSocketInvalid(hSock) then print "UDPCreateListenSocket() failed. - ";GetError() goto [doEnd] end if
print "UDPCreateListenSocket(): ";hSock
[recvLoop] timer 0 'print "Waiting for data..." ret = UDPIsReadAvailable(hSock, 0)
if ret = 0 then 'print "nothing heard..."
timer 1000, [recvLoop] wait end if
[doReceive]
buf$ = space$(bufLen)
'Clear Vars used within this routine. recvFrom$ = "" RXIPv4$ = ""
num = UDPReceiveFrom(hSock, buf$, bufLen, recvFrom$)
theError = GetError()
if num = -1 then
if theError = 10101 then print "Connection closed by server." else print "Socket error occurred. - ";dechex$(theError) end if goto [doClose] end if
'With UDP, if a datagram comes in that is too large for the network stack 'or the specified buffer to handle, the data will be truncated, and the extra data 'is lost. It will still return as many bytes as it can, but it will generate 'the error code WSAEMSGSIZE(10040) while doing so. ' 'While the lost data is unrecoverable, this will at least let the application know 'something was lost. if theError = 10040 then NOTICE "Received message too large for buffer or other network limit. Datagram truncated, extra data lost. Increase buffer size!" end if
print "Data: ";left$(buf$, num) print "Total Char RX: ";num
'Collect the data from buffer and turn it into HEX, clear HEXIN$ first then send HEX to somewhere for parsing further HEXIN$ = "" for n = 1 to num 'print right$("00" + dechex$(asc(mid$(buf$, n, 1))), 2) HEXIN$ = HEXIN$ + right$("00" + dechex$(asc(mid$(buf$, n, 1))), 2) next PRINT "HEXIN$:"; HEXIN$
[Collect_IP_Info_from_RX_Data] 'WARNING - IF LBNET.DLL GET UPDATED THIS COULD CAUSE THIS IS STOP WORKING. 'First two bytes are a ushort indicating address type 'These bytes are ordered in local device order, on Windows, this is little-endian addrFamily = asc(mid$(recvFrom$, 2, 1)) * 256 + asc(mid$(recvFrom$, 1, 1)) if addrFamily = 23 then 'AF_INET6 = 23, means this is an IPv6 address print "RXIPv6 address ---" end if
if addrFamily = 2 then 'AF_INET = 2, means this is an IPv4 address
'Bytes 5-8 are the octets of the IPv4 address, in order for x = 5 to 8 Octet$ = asc(mid$(recvFrom$, x, 1));"." RXIPv4$ = RXIPv4$ + Octet$
next x end if print "RXIPv4 address: "; RXIPv4$ 'print " - Port: ";
'Bytes 3-4 are a ushort containing the remote endpoint's port 'bytes are ordered in network order(big-endian) RXport = asc(mid$(recvFrom$, 3, 1)) * 256 + asc(mid$(recvFrom$, 4, 1)) print "RXport - Recieved data port: ";RXport
[SEND_DATA_OUT]
'ACK command 50 01 00 6d ff
IF HEXIN$ = "050100D8C1" THEN TXDATA$ = "50 01 00 6d ff"
IF TXDATA$ <> "" THEN
'Convert TXDATA to ASCII text DATACONVERT$ = TXDATA$
token$ = "?" while token$ <> "" index = index + 1 token$ = word$(DATACONVERT$, index) op = HEXDEC(token$) print "CHR$:"; CHR$(op) OUTPUT$ = OUTPUT$ + CHR$(op) wend
'Replace the converted HEX to CHR$ variables and check the length 'PRINT "OUTPUT$:"; OUTPUT$ TXDATA$ = OUTPUT$ 'print "TXDATA$:"; TXDATA$ num = LEN(TXDATA$)
'Then send the converted TXDATA$ to the UDP DLL sendNum = UDPSendTo(hSock, TXDATA$, num, recvFrom$) if sendNum = -1 then theError = GetError() print "UDPSendTo() failed. - ";dechex$(theError) goto [doClose] ELSE print "TXDATA$:"; TXDATA$ end if
END IF
'Clear vars TXDATA$ = "" DATACONVERT$ = ""
timer 1000, [recvLoop] wait
[doClose] a = UDPClose(hSock)
[doEnd] call CloseLBNetDLL
[doCloseWindow] CLOSE #main
[UDP_FUNCTIONS] '======================== '==UDP Helper Functions== '======================== Sub OpenLBNetDLL open "LBNet.dll" for DLL as #LBNet a = InitLBNet() End Sub
Sub CloseLBNetDLL a = EndLBNet() close #LBNet End Sub
Function InitLBNet() CallDLL #LBNet, "InitLBNet",_ InitLBNet as long End Function
Function EndLBNet() CallDLL #LBNet, "EndLBNet",_ EndLBNet as long End Function
Function IsSocketInvalid(sock) CallDLL #LBNet, "IsSocketInvalid",_ sock as ulong,_ IsSocketInvalid as long End Function
Function GetError() CallDLL #LBNet, "GetError",_ GetError as long
if GetError < 0 then GetError = (abs(GetError) XOR hexdec("FFFFFFFF")) + 1 end if End Function
Function UDPConnect(host$, srv$, msTimeout) CallDLL #LBNet, "UDPConnect",_ host$ as ptr,_ srv$ as ptr,_ msTimeout as long,_ UDPConnect as long End Function
Function UDPSend(udpSock, buf$, bufLen) CallDLL #LBNet, "UDPSend",_ udpSock as long,_ buf$ as ptr,_ bufLen as long,_ 0 as long,_ UDPSend as long End Function
Function UDPSendTo(udpSock, buf$, bufLen, udpInfo$) CallDLL #LBNet, "UDPSend",_ udpSock as long,_ buf$ as ptr,_ bufLen as long,_ udpInfo$ as ptr,_ UDPSendTo as long End Function
Function UDPClose(udpSock) CallDLL #LBNet, "UDPClose",_ udpSock as long,_ UDPClose as long End Function
Function UDPGetInfoSize() CallDLL #LBNet, "UDPGetInfoSize",_ UDPGetInfoSize as long End Function
Function UDPReceive(udpSock, byref buf$, bufLen) CallDLL #LBNet, "UDPReceive",_ udpSock as long,_ buf$ as ptr,_ bufLen as long,_ 0 as long,_ UDPReceive as long End Function
Function UDPReceiveFrom(udpSock, byref buf$, bufLen, byref udpFrom$) udpFrom$ = space$(UDPGetInfoSize())
CallDLL #LBNet, "UDPReceive",_ udpSock as long,_ buf$ as ptr,_ bufLen as long,_ udpFrom$ as ptr,_ UDPReceiveFrom as long
print "udpFrom$: ";udpFrom$ print "UDPReceiveFrom: ";UDPReceiveFrom
End Function
Function UDPIsReadAvailable(udpSock, msTimeout) CallDLL #LBNet, "UDPIsReadAvailable",_ udpSock as long,_ msTimeout as long,_ UDPIsReadAvailable as long End Function
Function UDPCreateListenSocket(pService$) CallDLL #LBNet, "UDPCreateListenSocket",_ pService$ as ptr,_ UDPCreateListenSocket as long End Function
Yes I know its a mess!
|
|
|
Post by Rod on Feb 15, 2020 7:32:58 GMT -5
The code is not a mess and it wouldn't matter if it was. The point is it works does it not? the device received a message and did something albeit not what you expected.
I think it is less about UDP and more about understanding just exactly what message the remote device wants and how it wants to be connected.
UDP code is working, its getting messages but the device is still not doing what its told? Is that where we are?
How should it be connected? I have read that UDP is usually implemented on a connectionless basis. IE the message is thrown onto the network in the hope it will be received. You give the message a destination IP and port address. Is the response meant to come back over the same port? Should there be two ports in operation? Chris is more sure about this than I.
Secondly what format of message is the device expecting? We use phrases like ACK and HC1 to describe single bytes. But maybe your device is expecting plain English and not encoded bytes. What happens if you send the character string "5001006dff" just as it is. That might be the format the device is expecting. However given it responds with encoded bytes perhaps not.
Are there other messages you could try?
If this is a commercial device I would be really surprised if it did not have a checksum/checkdigit appended to the message. Any mention of that?
Is there a manual or online resource we can browse?
|
|
|
Post by Rod on Feb 15, 2020 8:56:38 GMT -5
Also I need to stop talking about ACK and confusing you. ACK is a control character, decimal value 6. You are using ACK to refer to a hex phrase "50 01 00 6d ff".
What should the device do after it gets this hex phrase (or 5 byte values).
Also given you have sent and received messages via the IPs and port we should discount that as part of the problem as well. So it is the message content we need to focus on.
|
|
|
Post by Chris Iverson on Feb 15, 2020 18:47:20 GMT -5
Do you have the IP addresses backwards in your post, Tasp? You say that .37 is the PC, and .174 is the device, but all the communication code would indicate the opposite.
With the example code you have so far, is the device doing what you want it to do after that? Or is something still not working right?
And like Rod said, is this device something that was commercially available? Something we could look up a manual for?
Also, have a new version for you. ZIP only, as there's new wrapper code, too, since I've added new functions.
UDPGetRemoteIP() and UDPGetRemotePort(). Should be self-explanatory.
Function UDPGetRemoteIP$(udpInfo$) UDPGetRemoteIP$ = ""
CallDLL #LBNet, "UDPGetRemoteIP",_ udpInfo$ as ptr,_ ret as ulong
If ret <> 0 then UDPGetRemoteIP$ = winstring(ret) End Function
Function UDPGetRemotePort(udpInfo$) CallDLL #LBNet, "UDPGetRemotePort",_ udpInfo$ as ptr,_ UDPGetRemotePort as long End Function
Pass in a recvFrom$ blob you get from Receive(), and it'll give you back either the IP address in a string, or the port as a number, depending on which one you call.
Since these are functions of the DLL, they would be kept compatible if I ever changed anything in the recvFrom blob.
Here's the modified part of the example code that uses it:
print "From IP: ";UDPGetRemoteIP$(recvFrom$);" - Port: ";UDPGetRemotePort(recvFrom$) print "Data - ";left$(buf$, num)
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 16, 2020 12:28:50 GMT -5
Thanks for the responses. No the screen shots are round the correct way as the initial handshake is done from the external equipment (0.174), then the PC responds (0.37). The last code I posted is actually working. It is actually wanting an ACK command but in it's own format. Although it is a commercial product the manufacturers don't provide any info at all. The rest of the comms after this initial handshake and ACK is based upon S.I.A Protocol Thanks for the update to LBNet Chris, however I think your comment about it being self explanatory is not taking into account me! But I shall hurry away and try this! Chris I don't see a new ZIP on the git?
|
|
|
Post by Rod on Feb 16, 2020 14:10:38 GMT -5
We need to try and be as clear as possible. What does the above mean? You sent a message and it was received? you sent a message and it was received but not understood?
You say ACK command, you mean an "ACK" message that contains several bytes of info?
The protocol document is not helpful since nowhere does it detail the messages you are trying to use. Where did you get the details of these messages?
According to the standard there is a lot of encryption and data verification that we have so far not addressed. I hate guessing, we can be of little help guessing. While Chris can improve the UDP code I am less sure that will give you a working solution.
|
|
|
Post by Chris Iverson on Feb 16, 2020 14:39:28 GMT -5
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 16, 2020 16:07:08 GMT -5
We need to try and be as clear as possible. What does the above mean? You sent a message and it was received? you sent a message and it was received but not understood? You say ACK command, you mean an "ACK" message that contains several bytes of info? The protocol document is not helpful since nowhere does it detail the messages you are trying to use. Where did you get the details of these messages? According to the standard there is a lot of encryption and data verification that we have so far not addressed. I hate guessing, we can be of little help guessing. While Chris can improve the UDP code I am less sure that will give you a working solution Sorry, the code above is working, from the point that it is receiving and transmitting datasets correctly I received data from the external device, I was able to identify the data it sent was a handshake of sorts, I am able to reply to that with an acknowledge dataset, which is received ok by the equipment. Once it receives that and completes the handshake it sends further data ok. At this time, although I receive further data from the device, which is pretty much all standard human readable ASCII, I'm unable to find out what I need to reply back with, as at the moment it continues to repeat the message. It will do this a certain number of times before giving up. As Rod suggested, I also will make the assumption there will be a checksum sent back to confirm it's been received correctly. I'm only partial way through the protocol document so have only tried basic responses back. Although that document talks initially regarding encryption, it's toggle-able and therefore will remain disabled as it's to complex to implement for me. Maybe at a later stage I may try this, but at first I'm just looking to successfully communicate which it is. It's now mainly study the protocol and see if what I read and what I recieve is the same. Just as an idea this is what I receive once the handshake is complete. Unfortunately it won't copy and paste from the mainwin, I'm assuming there is some character in there that it doesn't like. Thanks Chris for continuing to dev the DLL, it's becoming quite the powerful package and both Rod and Chris for the help so far. Even the seemingly daftest and basic point you make trips things in mind to make it work.
|
|
|
Post by Chris Iverson on Feb 16, 2020 16:41:36 GMT -5
Hmm, perhaps it's being mangled by printing it out, but what's there doesn't seem to match with the message format specified in that doc you linked to earlier. I would actually expect most of that to be human-readable.
Well, hopefully you get it figured out!
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 19, 2020 13:32:17 GMT -5
Actually Chris, you're spot on there, I was so involved with receiving data, I hadn't actually noticed that the data coming out doesn't actually match whats expected as per the document. I'm unsure what the issue is there, I wonder if the external equipment is not sending (which is unlikey) or whether the buffer is missing the first part of the data???
|
|
|
Post by Chris Iverson on Feb 19, 2020 15:57:46 GMT -5
I suppose it's possible, but my UDP code is basically just a direct wrapper around the winsock sockets API calls. I don't touch the buffers at all, I just use what's given and received from the app and the API.
I'd expect data to be missing from the end, not the beginning.
I'd check the communication in wireshark, to see if the payload you're seeing in wireshark matches what LB is receiving.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Feb 21, 2020 10:10:20 GMT -5
It does match exactly, wireshark and the buffer. The issue is not the LBNet.DLL
|
|
|
Post by pandawdy on Mar 12, 2020 12:28:05 GMT -5
Sorry I haven't been reading this whole thread.. does LBnet.dll allow sending and receiving UDP?
|
|
|
Post by Chris Iverson on Mar 12, 2020 12:56:12 GMT -5
|
|