--[[
---------------------------------------------------------------------------
Remote Train Control Program for Windows

© Copyright 2019 by Mark DiVecchio

	This file is part of Remote Train Control.

	Remote Train Control is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Remote Train Control is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Remote Train Control.  If not, see <http://www.gnu.org/licenses/>.

 Home Page : http://www.silogic.com/trains/RTC_Running.html
---------------------------------------------------------------------------]]
-- Semicolons are not required in Lua code
-- 
title = "TCP Test"
-- load the socket support and its friends
local socket = require("socket")
print(socket._VERSION)

local TimeoutSeconds = 2;
local DataErrCount = 0;
local TimeoutErrCount = 0;
local ReceivedPacketCount = 0;
local starttime;
local PACKETS = 20000;
local host, port;
local tcp;
local ip;

-- main program
function setup() 
print("TCP Client Test");
print("Run with ESP8266 sketch Tcp.ino");
-- Now send and receive TCP packets to/from the ESP8266
port = 8888;
ip = "192.168.1.110"

--[[
https://web.tecgraf.puc-rio.br/luasocket/old/luasocket-2.0-beta2/introduction.html

https://web.tecgraf.puc-rio.br/luasocket/old/luasocket-2.0-beta2/tcp.html

https://web.tecgraf.puc-rio.br/luasocket/old/luasocket-2.0-beta2/udp.html

TCP (Transfer Control Protocol) is reliable stream protocol. In other words, 
applications communicating through TCP can send and receive data as an error 
stream of bytes. Data is split in one end and reassembled transparently on the 
other end. There are no boundaries in the data transfers. The library allows 
users to read data from the sockets in several different granularities: patterns 
are available for lines, arbitrary sized blocks or "read up to connection 
closed", all with good performance.

The library distinguishes three types of TCP sockets: master, client and server sockets.

Master sockets are newly created TCP sockets returned by the function socket.tcp. 
A master socket is transformed into a server socket after it is associated with a 
local address by a call to the bind method followed by a call to the listen. 
Conversely, a master socket can be changed into a client socket with the method connect, 
which associates it with a remote address.

On server sockets, applications can use the accept method to wait for a client connection. 
Once a connection is established, a client socket object is returned representing this 
connection. The other methods available for server socket objects are getsockname, 
setoption, settimeout, and close.

Client sockets are used to exchange data between two applications over the Internet. 
Applications can call the methods send and receive to send and receive data. The other 
methods available for client socket objects are getsockname, getpeername, setoption, 
settimeout, shutdown, and close.  

]]

tcp = socket.tcp();
tcp:connect(ip, port);

-- make sure we don't block waiting for this client's line
tcp:settimeout(TimeoutSeconds)

starttime = os.time();
for idx = 1,PACKETS do
	-- send a request packet
	tcp:send("req\n")
	--
	-- receive response(data) waiting for timeout seconds
	local data, status, partial = tcp:receive()
	if (status) then print("status " .. status); end;
	if (partial) then print("partial " .. partial) end;
	if status == "closed" then break end
	--
	if (data) then
		ReceivedPacketCount = ReceivedPacketCount + 1;
		if ((idx % 1000) == 0) then
			print(".");
			end;
		if (data ~= "ack") then 
			DataErrCount = DataErrCount + 1;
			print(":" .. ReceivedPacketCount .. ": ", data);
			end;	
		else 
			TimeoutErrCount = TimeoutErrCount + 1;	
			print("--timeout #" .. TimeoutErrCount);
		end;
	--
	Yield();	-- check for [STOP] or function button
	end

print("Elapsed time = " .. os.time() - starttime .. " seconds"); 
print("Done");
return Stop();
end
--[[---------------------------------------------------------------------------------------]]
function cleanup(Engine, TIU)
	-- this function is called once when the user presses the [STOP] button or the Stop() function is called
	print("cleanup() Running");
	tcp:close()
	if (DataErrCount == 0 and TimeoutErrCount == 0) then
		print("No errors in " .. ReceivedPacketCount .. " packets with " .. PACKETS - ReceivedPacketCount .. " packet(s) lost");
		else
		print(TimeoutErrCount .. " timeout error(s) and " .. DataErrCount .. " data error(s)");
		print(ReceivedPacketCount .. " packets with " .. PACKETS - ReceivedPacketCount .. " packet(s) lost");
		end;	
	return true;		-- false=cleanup failed, true=cleanup succeeded
	end
--[[---------------------------------------------------------------------------------------]]
