How to telnet an address? - lua

I'm trying to understand the socket class and i'm using the following example to implement a server sample
local server = assert(socket.bind("*", 0))
-- find out which port the OS chose for us
local ip, port = server:getsockname()
-- print a message informing what's up
print("Please telnet to localhost on IP [" ..ip.. "] and port [" .. port .. "]")
print("After connecting, you have 10s to enter a line to be echoed")
-- loop forever waiting for clients
while true do
-- wait for a connection from any client
local client = server:accept()
-- make sure we don't block waiting for this client's line
client:settimeout(10)
-- receive the line
local line, err = client:receive()
-- if there was no error, send it back to the client
if not err then
client:send(line .. "\n")
end
-- done with client, close the object
client:close()
end
But now the question is, how can I telnet for example the address localhost:8080 via lua?
EDIT:
I forgot to tell something, I donĀ“t even can telnet on cmd. When I type the command:
telnet ip port
it always says "connection lost" after I send a message. What am I doing wrong?

First, follow the instructions from here to enable telnet in Windows 7:
Go to Control Panel
Find Turn Windows features on or off under Programs (depending on layout)
Find Telnet client and enable it.
Once you've done that, it should work as expected.

Done!
local socket = require("socket")
local server = socket.connect(ip, port)
local ok, err = server:send("RETURN\n")
if (err ~= nil) then
print (err)
else
while true do
s, status, partial = server:receive(1024)
print(s or partial)
if (status == "closed") then
break
end
end
end
server:close()

Related

Cannot connect client to Broker

I'm coding on lua for the first time and have created a mqtt client instance for a IO Link Sensor to publish data on a MQTT topic. However, I can't figure out how to connect to my local mosquitto broker, since "the connection is refused" but the broker is online and working.
The setup to my mqtt client looks like this:
local client = MQTTClient.create()
local BROKER_IP = '127.0.0.1'
local USE_TLS = false
client:setIPAddress(BROKER_IP)
if (USE_TLS) then
client:setPort(1883)
client:setTLSEnabled(true)
client:setTLSVersion('TLS_V12')
client:setCABundle('resources/mosquitto/mybroker-cert.pem')
client:setClientCertificate(
'resources/mosquitto/mqtt-client-cert-2.pem',
'resources/mosquitto/mqtt-client-key-2.pem',
'changemeclient'
)
end
Now the error is marked on following client:publish line.
Remark: Here the data to be published is a distance and thus converted to string.
if dataValid == 'PI_STATUS_VALID' then
local sDistance = string.format('%d', distance)
client:publish('/topic/test', sDistance, "QOS0", "NO_RETAIN")
end
Does anyone see were the problem could be?

Send data from ESP32 to a server via WiFi

I am not new here but this is my first question.
I have searched a lot and quite frankly can't understand how this is supposed to work.
I get data periodically (temperature) to my ESP32 and while having it set as a WiFi client, connect to my router and somehow store this data on my Laptop(or somewhere else, like a local/web site, don't know if that's possible/better).
How is the connection supposed to work? I have installed XAMPP and run the Apache and MySQL servers and I tried to connect to my Laptop with some sketches from Arduino using the ESP32 libraries
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
const char* host = "192.168.1.109"; //The local IP of my Laptop
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
but it doesn't connect.
Can someone please explain to me how this connection is supposed to take form or is this question too vague? I really just wanna know the "how-things-should-work-together" in this situation.
Thank you in advance.
OK, so after a lot of research and trying, I managed to work it out. I can now send an HTTP request (like GET or POST) from my ESP32 to a local server that is running on my laptop using XAMP and get a response. I can also connect to my local IP from my mobile phone (which is also in the same WiFi network).
Just for anyone else who wants to connect to a location in a server hosted on a PC in a local network, the steps are:
Create a local server on your PC, laptop whatever using an application like XAMPP (I have Windows 10 so WAMP would also work), download, install, open and start Apache.
Make sure that the Firewall lets your requests pass through (for me it was open by default, but I had seen elsewhere Firewall being an issue)
Go to your network settings, select the network that your devices(ESP32, phone, etc.)are connected and change its profile to Private, meaning that you trust this network, making your PC discoverable and able to accept requests. (That is really simple but took me hours to find)
Now, in order to connect from your phone to your PC, open a browser and enter the local IP (that is the IP that is given to your PC from the router as a local network name) of your PC to a browser and that's it, you are connected.
If you installed and ran XAMP, when connecting to your local IP(from same PC or other local device), it will forward you to 192.168.x.x/dashboard. If you want to create new workspaces and files, browse the XAMP folder in the installed location and inside the '/htdocs' subfolder do your testing.
For the ESP32 communication in Arduino(basic steps, not full code):
#include <WiFi.h>
#include <HTTPClient.h>
String host = "http://192.168.x.x/testfolder/";
String file_to_access = "test_post.php";
String URL = host + file_to_access;
void setup(){
WiFi.begin(ssid, password); //Connect to WiFi
HTTPClient http;
bool http_begin = http.begin(URL);
String message_name = "message_sent";
String message_value = "This is the value of a message sent by the ESP32 to local server
via HTTP POST request";
String payload_request = message_name + "=" + message_value; //Combine the name and value
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpResponseCode = http.sendRequest("POST", payload_request);
String payload_response = http.getString();
}
In the test_post.php (located in "C:\xampp\htdocs\testfolder\") file I used a simple script to echo a message received using a POST request, so it's only 'readable' from POST requests. Connecting to it from your browser will give you the "Sorry, accepting..." message.
<?php
$message_received = "";
if ($_SERVER["REQUEST_METHOD"] == "POST"){
$message_received = $_POST["message_sent"];
echo "Welcome ESP32, the message you sent me is: " . $message_received;
}
else {
echo "Sorry, accepting only POST requests...";
}
?>
Finally, using Serial prints, the output is:
Response Code: 200
Payload: Welcome ESP32, the message you sent me is: This is the value of a message sent by the ESP32 to local server via HTTP POST request
There it is, hope that this helps someone.

ESP8266, NodeMCU, soft AP - UDP server-like soft AP, independent access point

I am using NodeMCU (with ESP8266-E) with an upgraded firmware. All basic commands work perfectly but there is one problem.
I wanted to create an independent access point, which could have a behaviour like a UDP server. That means without direct connection to any other access points. A simple UDP server like soft AP.
I followed these steps:
I have uploaded a new firmware to NodeMCU.
I have downloaded ESPlorer for better work with NodeMCU.
I have uploaded the source code below.
I have connected to the NodeMCU access point on my desktop.
I have sent some strings to the NodeMCU using a Java UDP client program.
I have looked at the messages on ESPlorer.
NodeMCU has not received any such strings.
--
print("ESP8266 Server")
wifi.setmode(wifi.STATIONAP);
wifi.ap.config({ssid="test",pwd="12345678"});
print("Server IP Address:",wifi.ap.getip())
-- 30s timeout for an inactive client
srv = net.createServer(net.UDP, 30)
-- server listens on 5000, if data received, print data to console
srv:listen(5000, function(sk)
sk:on("receive", function(sck, data)
print("received: " .. data)
end)
sk:on("connection", function(s)
print("connection established")
end)
end)
When I tried to send a message using a Java application, there was no change in ESPlorer. Not even when I tried to send a message using the Hercules program (great program for TCP, UDP communication).
I guess that maybe it will be the wrong IP address. I am using the IP address of the AP and not the IP address of the station.
In other words I am using this address: wifi.ap.getip() and not this address wifi.sta.getip() for connections to the UDP server. But sta.getip() returns a nil object. Really I don't know.
I will be glad for any advice.
Thank you very much.
Ok, let's restart this since you updated the question. I should have switched on my brain before I gave you the first hints, sorry about this.
UDP is connectionless and, therefore, there's of course no s:on("connection"). As a consequence you can't register your callbacks on a socket but on the server itself. It is in the documentation but it's easy to miss.
This should get you going:
wifi.setmode(wifi.STATIONAP)
wifi.ap.config({ ssid = "test", pwd = "12345678" })
print("Server IP Address:", wifi.ap.getip())
srv = net.createServer(net.UDP)
srv:listen(5000)
srv:on("receive", function(s, data)
print("received: " .. data)
s:send("echo: " .. data)
end)
I ran this against a firmware from the dev branch and tested from the command line like so
$ echo "foo" | nc -w1 -u 192.168.4.1 5000
echo: foo
ESPlorer then also correctly printed "received: foo".
This line is invalid Lua code. connected is in the wrong place here. you can't just put a single word after a function call.
print(wifi.ap.getip()) connected
I guess you intended to do something like
print(wifi.ap.getip() .. " connected")
Although I think you should add som error handling here in case wifi.ap.getip() does not return an IP.
Here you do not finish the function definition. Neither did you complete the srv:on call
srv:on("receive", function(srv, pl)
print("Strings received")
srv:listen(port)
I assume you just did not copy/paste the complete code.

Lua websockets for heka

I am using lua-websockets https://github.com/lipp/lua-websockets to try and get a web socket server running.
Using the copas example they provided:
local copas = require'copas'
local server = require'websocket'.server.copas.listen
{
port = 8080,
protocols = {
echo = function(ws)
while true do
local message = ws:receive()
if message then
ws:send(message)
else
ws:close()
return
end
end
end
}
}
copas.loop()
This works and starts listening on port 8080 and I am able to connect and get a echo response back.
The problem is when I try and integrate it with heka. I start heka and it starts the websocket server but hangs at Loading plugin. When it tries to "load" a plugin, it executes the lua script.
Now my question is, how do I run the websocket server and send a "success" to heka to let it continue start up. Simply this would be: if the websocket is listening on 8080 return to heka and say the lua script has been executed successfully.
Thanks in advance!
Don't call copas.loop() as it enters an indefinite loop that handles all copas socket interactions. You need to use copas.step() instead (see controlling copas section) and call it at the appropriate time from your heka code (this call will return false on timeout and true when it handles something). In a GUI application it may be called from an IDLE handler.

Writing a wireshark dissector in lua and setting it on a dynamic port

I have a client server protocol that works the following way.
Client sends udp broadcast with servers id (to a fixed port).
Server receives the datagram and if its matches his id he sends the client the port that he is listening to.
Then the client opens a tcp connection to that port.
I'm writing a Wireshark dissector in Lua for this thing and I need to setup the port for the tcp connection dynamically (I don't know in advance on witch port the servers listens).
I tried something like that:
-- declare our protocol
myproto_udp_proto = Proto("myproto_UDP","myproto UDP Protocol")
myproto_tcp_proto = Proto("myproto_TCP","myproto TCP Protocol")
-- create a function to dissect it
function myproto_tcp_proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "myproto TCP"
local subtree = tree:add(myproto_tcp_proto,buffer(),"myproto TCP Protocol Data")
if buffer(0,2):uint() == 0xF00D then
subtree:add(buffer(0,2),"Magic(F00D)")
else
subtree:add(buffer(0,2),"Bad Magic")
end
end
function myproto_udp_proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "myproto UDP"
local subtree = tree:add(myproto_udp_proto,buffer(),"myproto UDP Protocol Data")
if buffer(0,2):uint() == 0xF00D then
subtree:add(buffer(0,2),"Magic(F00D)")
local command;
local port = -1;
if buffer(2,1):uint() == 01 then
command = "Searching for server"
elseif buffer(2,1):uint() == 02 then
command = "I'm server"
port = buffer(7,2):uint()
else
command = "unknown";
end
subtree:add(buffer(2,1),command)
subtree:add(buffer(3,4),"Server id: " .. buffer(3,4):uint())
if port ~= -1 then
subtree:add(buffer(7,2),"Server listening port: " .. buffer(7,2):uint())
subtree:add(buffer(9,4),"check bytes")
myproto_tcp_init(port)
end
else
subtree:add(buffer(0,2),"Bad Magic")
end
end
-- load the udp.port table
udp_table = DissectorTable.get("udp.port")
-- register our protocol to handle udp port 1338
udp_table:add(1338,myproto_udp_proto)
function myproto_tcp_init(port)
-- load the tcp.port table
tcp_table = DissectorTable.get("tcp.port")
-- register our protocol to handle tcp port !DYNAMIC!
tcp_table:add(port,myproto_tcp_proto)
end
What I'm missing?
Thanks in advance
The mechanism presented here works. The problem was that the port number was taken from the wrong bytes (from buffer(4,2) instead of buffer(7,2)).

Resources