Sending and Receiving Data
A separate set of "TLS" properties and methods have been provided to send and receive encrypted data. Although similar to their unencrypted counterparts used for handing plain data, these properties and methods are not exactly the same. The table below summarizes all the differences:
Plain data |
TLS data |
Comment |
sock.getdata method |
sock.tlsgetdata method |
|
sock.newtxlen R/O property |
--- |
Not implemented for TLS buffers. |
sock.notifysent method |
--- |
For asynchronous sending of data you can still use sock.notifysent and on_sock_data_sent. |
sock.peekdata method |
sock.tlspeekdata method |
|
sock.rxclear method |
--- |
Not implemented for TLS buffers. Do not call on a TLS-enabled socket. |
sock.rxlen R/O property |
sock.tlsrxlen R/O property |
|
sock.setdata method |
sock.tlssetdata method |
Unlike sock.setdata, sock.tlssetdata returns the number of bytes that were actually accepted into the TLS TX buffer. This "excuses" the absense of the "sock.tlstxfree" and "sock.tlstxlen" properties. |
sock.send method |
--- |
You must still use sock.send to send out the data |
sock.txclear method |
Not implemented for TLS buffers. Do not call on a TLS-enabled socket. |
|
sock.txfree R/O property |
--- |
When placing data into the TLS TX buffer, check the number of accepted bytes; it is returned by sock.tlssetdata. |
sock.txlen R/O property |
--- |
When placing data into the TLS TX buffer, check the number of accepted bytes; it is returned by sock.tlssetdata. |
Sending Encrypted Data
To prepare the data for transmission via a TLS socket, call sock.tlssetdata, which takes a string parameter containing the data. The data is placed into the TLS TX buffer. Note that the data has not been sent yet; doing so remains the job of sock.send, which will encrypt the data, place the encrypted data into the TX buffer, and commence the sending process.
'This example code sends an HTTP GET request; note the carriage returns,
'which are used to signal to the server the end of each parameter
sock.tlssetdata("GET / HTTP/1.1\r\nHost:your.example.com\r\n\r\n")
sock.send()
In cases where the data you want to place into the TLS TX buffer exceeds the buffer's free space, sock.tlssetdata will fit as much data as possible into the TLS TX buffer and truncate the rest. As sock.tlssetdata returns the number of bytes it was able to store into the TLS buffer, you can include logic to track the progress of the transmission and sequentially call sock.tlssetdata and sock.send until all data has been sent.
Here is a sample "blocking" code that sends a file over a TLS socket:
romfile.open("test.txt") 'Replace "test.txt" with the file containing your data
dim datasent as dword = 0 'This variable tracks the total amount of data sent
dim sent as dword = 0 'This variable tracks the amount of data successfully
'placed in the TLS buffer
dim s as string = "" 'This variable holds the data being sent
while datasent <> romfile.size 'This loops operations until the entire file is read
if s = "" then 'If s is empty (i.e., at the start of transmission),
s = romfile.getdata(255) 'this reads the next 255 bytes and places them in s
end if
sent = sock.tlssetdata(s) 'The data is placed in the TLS buffer by
'sock.tlssetdata and the return is passed to the sent
'variable to keep track of the transmission's progress
if sent <> 255 then
s = right(s,len(s)-sent) 'This retains the data that did not fit in the TLS buffer
'so it can be added next time around the loop
sock.send()
else
s = "" 'This clears the variable s so more data can be read
end if
datasent = datasent + sent 'This keeps track of how much data has been sent
wend
sock.send() 'This sends anything left in the TLS buffer
The next example shows the "non-blocking," asynchronous way of sending a large block of data — sock.notifysent and on_sock_data_sent are used in the same manner they are used in non-encrypted communications. First, at the start of your main.tbs project file:
dim datasent as dword = 0 'These variables are now global
dim sent as dword = 0
dim s as string = ""
declare sub send_file() 'This declares a function that will contain the
'core code to transmit data, which allows for
'it to be called sequentially as needed
The following section should be placed where you place to start a transmission in your code. For example, this can be inside the on_button_pressed event handler:
sub on_button_pressed()
romfile.open("test.txt") 'Replace "test.txt" with the file containing your data
datasent = 0 'Reset the value of the variables before starting a
sent = 0 'new transmission
s = ""
send_file()
end sub
Here is the code for the send_file procedure declared earlier:
sub send_file()
if datasent <> romfile.size then 'This checks whether the transmission has been completed
if s = "" then
s = romfile.getdata(255)
end if
sent = sock.tlssetdata(s)
if sent <> 255 then
s = right(s,len(s)-sent)
else
s = ""
end if
datasent = datasent + sent
end if
sock.notifysent(0) 'This causes the on_sock_data_sent event to be
'generated, which will be used to continue the
'transmission until the transfer is completed
sock.send() 'This sends anything left in the TLS buffer
end sub
Finally, we use the on_sock_data_sent event handler to call send_file as needed.
sub on_sock_data_sent()
if datasent <> romfile.size then 'This checks whether the transmission has been completed
send_file() 'and calls send_file() if not
else
sys.debugprint("Mission Complete"+"\r\n") 'This announces when the transmission has
'has been completed
end if
end sub
Receiving Encrypted Data
When receiving encrypted data, sock.tlsgetdata retrieves the data from the RX buffer, decrypts it, places the decrypted data into the TLS RX buffer, and then extracts the requested number of bytes (or up to the available number of bytes) from the TLS RX buffer.
The following example illustrates the use of the on_sock_data_arrival event handler to handle encrypted data as it arrives. In the TLS mode, this event is triggered when the TLS RX buffer (and not the RX buffer) has at least one data byte:
sub on_sock_data_arrival()
sys.debugprint(sock.tlsgetdata(255) 'This will print the decrypted data received via TLS
'into the Output panel in TIDE
end sub
The sock.tlspeekdata method can be used to "peek" at the decrypted data in the TLS RX buffer without removing it from the buffer. There is also the sock.tlsrxlen read-only property, which tells you the length of decrypted data available for retrieval.