How to send udp packages using nodejs? - javascript

Well, I have a small route that should send an UDP package and print a confirmation. According to the documentation on the node, the following should work fine:
const dgram = require('dgram');
export async function sendUDP(sess, parameters: {}, res) {
const client = dgram.createSocket('udp4');
client.send('Hello World!',0, 12, 12000, '127.0.0.1', function(err, bytes) {
client.close();
});
//res is the response object from express
return res.send("Send udp packet");
}
It should send an UDP request to port 12000 on the callback IP (local machine). And also send a reply that the UDP packet has been sent.
I notice the reply Send udp packet received at postman when I post to the correct URL. So that is working.
However, the UDP packages seem to be lost, using tcpdump on my local ubuntu results in nothingness:
sudo tcpdump -n udp port 12000
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlp5s0, link-type EN10MB (Ethernet), capture size 262144 bytes
0 packets captured
0 packets received by filter
0 packets dropped by kernel
(While tcpdump has been kept running during the test of the functions of course). Where do the UDP requests go? What happened?
I wish to have a life logger so that I can test nodejs applications using udp easily.

You need to tell tcpdump the interface it needs to listen.
tcpdump -i lo udp port 12000
lo is the interface for localhost.
More information in this link
You can use wireshark if you want to save the traffic log.
I use '!(udp.port == 53 || tcp.port == 53) && udp' as a filter to look only to udp packet.
I add this code to my server and send the udp packet there to print the content
const dgram = require('dgram');
const serverUDP = dgram.createSocket('udp4');
serverUDP.on('error', (err) => {
console.log(`serverUDP error:\n${err.stack}`);
serverUDP.close();
});
serverUDP.on('message', (msg, rinfo) => {
console.log(`serverUDP got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});
serverUDP.on('listening', () => {
const address = serverUDP.address();
console.log(`serverUDP listening ${address.address}:${address.port}`);
});
serverUDP.bind(3001);
It is the code sample from the node documentation

Related

Can't decode handshake request from client

I'm trying to connect a python3 socket with a JavaScript WebSocket. I'm testing the server code on localhost:8080, and connecting with Chrome(94.0).
The WebSocket client and the socket server do establish a connection. However, the connection would be shut down if the server did not follow the protocol and respond to the handshake. According to the protocol, the client WebSocket sends a utf-8 encoded GET request to the socket server, and the server must parse that request in order to complete the handshake.
What I get from the client is this:
\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03\x97t\xb1\xf7\xac\x99\x91\xd4\xf5\n\xdf\xc3X\x8af<\xbe\x99(0\x88\x9a!\xc6\xc9\x17]\xfe\xd9sP\xcc \xa8\xcf\x90{\x8a\xfcm\xbcj-5\xdf\xf90\x81\xc8Y\xc1\x85q"\xfe!C\xbb\t\xbd}\xe0\x8d\xf1\xe5\x00 \x1a\x1a\x13\x01\x13\x02\x13\x03\xc0+\xc0/\xc0,\xc00\xcc\xa9\xcc\xa8\xc0\x13\xc0\x14\x00\x9c\x00\x9d\x00/\x005\x01\x00\x01\x93\x1a\x1a\x00\x00\x00\x17\x00\x00\xff\x01\x00\x01\x00\x00\n\x00\n\x00\x08\xfa\xfa\x00\x1d\x00\x17\x00\x18\x00\x0b\x00\x02\x01\x00\x00#\x00\x00\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\r\x00\x12\x00\x10\x04\x03\x08\x04\x04\x01\x05\x03\x08\x05\x05\x01\x08\x06\x06\x01\x00\x12\x00\x00\x003\x00+\x00)\xfa\xfa\x00\x01\x00\x00\x1d\x00 \xfa)\xd5\x85<\x81.\x7f\xc0\x87wA!\xf1\xc9\xf80\xeb\x01\xdc\xed3m\xd1\x98\xd6\xd8\xd7\x7f#\rM\x00-\x00\x02\x01\x01\x00+\x00\x0b\n\x8a\x8a\x03\x04\x03\x03\x03\x02\x03\x01\x00\x1b\x00\x03\x02\x00\x02JJ\x00\x01\x00\x00\x15\x00\xf7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
The client consistently sends these bytes, although it this does not look like a legitimate GET request. This can't be decoded by utf-8 or by other encodings including utf-16-le, utf-16-be, unicode-escape, etc.
client source:
var client = new WebSocket('wss://127.0.0.1:8080')
client.onopen = function(e) {
console.log("open");
}
client.onmessage = function(e) {
console.log(e.data)
}
server handshake handler:
def handshake(client, address):
req = client.recv(1024).decode('utf-8')
key = (re.search('Sec-WebSocket-Key:\s+(.*?)[\n\r]+', req).groups()[0].strip())
response_key = b64encode(sha1(key + sockey).digest())
response = '\r\n'.join(websock_ans).format(key=response_key)
client.send(response.encode('utf-8'))
As the client request isn't utf-8 bytes, this gives a decoding error in line 2.
following the websocket protocol (https://datatracker.ietf.org/doc/html/rfc6455), sockey and websock_ans are defined as follows:
sockey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
websock_ans = {
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: {key}\r\n\r\n',
}
Does WebSocket compress/encrypt its GET requests? As far as I checked, the documents do not state any compression/encryption algorithms.
Thanks in advance.
Use gzip to convert the bytes into objects.

Connection to socket gets error "WebSocket opening handshake timed out" using Javascript and C#

About 4 hours of research...here we go.
I have a C# program that sends and listens for anything coming in a specific Socket. Using the sockets, C# can send stuff to it and can receive from it just fine. Now, going to my JavaScript file, I'm using the WebSocket interface to communicate with C#, but doesn't work (usually times out after a couple of minutes). When the Socket is online, the JavaScript code will take up to about 4 minutes then throw an error saying "WebSocket opening handshake timed out". The thing is I know that it can find because, when the port of the ip doesn't exist the JavaScript file throws an error in the next couple seconds.
Things I've done:
Turn off all firewalls, use both ws and wss at the beginning of the ip and port (ex: wss://xxx.xxx.x.xx:11111), change the port, change the ip to a valid ip still reachable, research for 4 hours.
C#:
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = IPAddress.Parse("ip");
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);
Socket listener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
Console.WriteLine("Waiting connection...");
Socket clientSocket = listener.Accept();
byte[] bytes = new Byte[1024];
string data = null;
while (true)
{
int numByte = clientSocket.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, numByte);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
Console.WriteLine("Text received -> {0} ", data);
byte[] message = Encoding.ASCII.GetBytes("Test Server");
clientSocket.Send(message);
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
JavaScript:
socket = new WebSocket("wss://ip:11111");
socket.onopen = function()
{
alert("Connected!");
}
socket.onerror = function()
{
alert("Connection Failed");
}
The ip is local
Long story short, C# can communicate with itself and JavaScript can find it but can't communicate with it.
Properly complete a handshake. (Or use a library / connection type that does.)
The WebSocket protocol (as original defined in RFC6455 - The WebSocket Protocol) does not open a plain unrestricted socket, in part for security reasons.
Since the handshake is not complete, the client WS request will timeout as the HTTP “Upgrade” response is never received. Until the handshake is complete, the WS will not be active over the underlying TCP connection.
Initiating a WebSocket connection (“the handshake”) is defined in section 4 of the RFC. It is also discussed in How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path.
The client establishes a WebSocket connection through a process known as the WebSocket handshake. This process starts with the client sending a regular HTTP request to the server. An Upgrade header is included in this request which informs the server that the client wishes to establish a WebSocket connection.
..
Now that [after] the handshake is complete the initial HTTP connection is replaced by a WebSocket connection that uses the same underlying TCP/IP connection. At this point, either party can start sending data.

Reading Serial Data Sent From Microbit in Windows

I am trying to send data from my microbit to my windows PC over serial communication. I followed the example here from the microbit website but can't seem to get my Tera Term window to display anything.
The microbit is plugged into one of the USB ports on the front of my PC and has the following code on it:
basic.forever(function () {
serial.writeLine("test")
})
When I add a new connection to Tera Term I select COM1 (this is the only option I have)
I then go into Setup > Serial Port and save the following settings
Unfortunately, this doesn't display any data, I have tried different USB ports and cables to no avail.
The following python 3 code scans through the serial ports until it locates the one connected to your microbit, using the microbit's VID and PID. The script will then display port information. After this, the script displays anything sent through the serial port from the microbit.
You can use the port name to set up Tera Term, or let the script continue to display the data coming through the serial port. The default baud rate for the microbit is 115200. In the example output below, the port name is COM5. Each time you unplug and replug the microbit, the port name can change.
example output:
starting
looking for microbit
scanning ports
port: COM5 - mbed Serial Port (COM5)
pid: 516 vid: 3368
found target device pid: 516 vid: 3368 port: COM5
opening and monitoring microbit port
code:
import serial
import serial.tools.list_ports as list_ports
PID_MICROBIT = 516
VID_MICROBIT = 3368
TIMEOUT = 0.1
def find_comport(pid, vid, baud):
''' return a serial port '''
ser_port = serial.Serial(timeout=TIMEOUT)
ser_port.baudrate = baud
ports = list(list_ports.comports())
print('scanning ports')
for p in ports:
print('port: {}'.format(p))
try:
print('pid: {} vid: {}'.format(p.pid, p.vid))
except AttributeError:
continue
if (p.pid == pid) and (p.vid == vid):
print('found target device pid: {} vid: {} port: {}'.format(
p.pid, p.vid, p.device))
ser_port.port = str(p.device)
return ser_port
return None
def main():
print('looking for microbit')
ser_micro = find_comport(PID_MICROBIT, VID_MICROBIT, 115200)
if not ser_micro:
print('microbit not found')
return
print('opening and monitoring microbit port')
ser_micro.open()
while True:
line = ser_micro.readline().decode('utf-8')
if line: # If it isn't a blank line
print(line)
ser_micro.close()
if __name__ == '__main__':
print('starting')
main()
print('exiting')

NodeJs Server flooded with UDP Broadcasts, doesn't send response

I am building a system using an ESP8266/NodeMcu module (similar to an Arduino, just with networking capabilities) and a NodeJs server running on the local network.
To discover the IP address of the server, I'm trying to use UDP broadcasting on the NodeMcu module. The idea is to send out a message on the local broadcasting IP (e.g. 192.168.1.255). The server then receives the message and sends a response, confirming that it is the server. This way, the NodeMcu knows the direct address of the server for further communication.
The problem is, that the server is completely flooding itself with the same message whenever it receives the first message from the NodeMcu, while the NodeMcu actually sends out a message only once a second.
It looks like this on the NodeMcu side:
[UDP] Sending UDP Broadcast on IP: 192.168.43.255, Port: 8080, Message: ESP8266 UDP Server Discovery Broadcast
The server outputs something like this, many times a second:
[10:33:07] 127.0.0.1:8080 # service discovery : ESP8266 UDP Server Discovery Broadcast
[10:33:07] 127.0.0.1:8080 # service discovery : ESP8266 UDP Server Discovery Broadcast
[10:33:07] 127.0.0.1:8080 # service discovery : ESP8266 UDP Server Discovery Broadcast
It doesn't make sense that it's receiving that many messages, especially because it's apparently coming from 127.0.0.1 and not the IP of the NodeMcu. It also doesn't send out any response.
I tried to receive the broadcast on my phone with a UDP Monitor app, an application called Packet Sender and the Linux Terminal. It all worked fine, and sending a manual response triggered the acknowledgement on the NodeMcu.
So I'm thinking there has to be some kind of error with the server, or with the network I'm using. The server is running on Linux on my computer, while I'm hosting the network via a hotspot on my phone (my real WiFi network blocked UDP broadcasting). The Linux firewall is turned off.
I'm no expert in JavaScript or NodeJs by any means and the server was written by someone I'm working with, but he has no clue either. Anyway, this is the important part on the server:
client.on('listening', function () {
var address = client.address();
debugMessage(
format('Service discovery running on port %s', config.port)
);
client.setBroadcast(true);
});
client.on('message', function (message, rinfo) {
debugMessage(
format('%s:%s # service discovery : %s', rinfo.address, rinfo.port, message)
);
client.send(message, 0, message.length, rinfo.port, rinfo.ip);
});
client.bind(config.port);
The code on the NodeMcu looks like this:
#include <ESP8266WiFi.h> // WiFi library
#include <WiFiUdp.h> // UPD functionality
// UDP variables
WiFiUDP udp;
unsigned int localUdpPort = 8080;
char incomingPacket[255];
const char broadcastMessage[] = "ESP8266 UDP Server Discovery Broadcast";
// Server details - written to when the server is found
IPAddress serverIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); // Use Broadcast Address as default in case the UDP service discovery isn't working as intended
unsigned int serverPort = localUdpPort; // Use local port as default in case the UDP service discovery ins't working as intended
void setupWiFi()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
#if LOGGING
Serial.println("Connecting to network: " + (String) WIFI_SSID);
#endif
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
}
#if LOGGING
Serial.print("Connected to network, Local IP Address: ");
Serial.println(WiFi.localIP());
#endif
udp.begin(localUdpPort); // begin listening on UDP port
#if LOGGING
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
#endif LOGGING
}
// Discover the server via a UDP broadcast, and store it's IP and Port in the local network in field variables for later use
// IMPORTANT - For the server to work, the Linux Firewall has to be disabled!!!
void discoverServer()
{
changeColor(PURPLE, false); // change the color of the RGB status LED to signal that the program is searching for the server
bool serverFound = false; // stop when the server is found
IPAddress broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); // Get the Broadcast IP of the local network (e.g. 192.168.0.255)
while (!serverFound)
{
// Send UDP Broadcast
udp.beginPacket(broadcastIp, localUdpPort);
udp.write(broadcastMessage);
udp.endPacket();
#if LOGGING
Serial.printf("[UDP] Sending UDP Broadcast on IP: %s, Port: %d, Message: %s\n", broadcastIp.toString().c_str(), localUdpPort, broadcastMessage);
#endif
delay(1000); // Pause a few milliseconds to avoid flooding the network
// Receive UDP packets
int packetSize = udp.parsePacket();
if (packetSize > 0)
{
// Read incoming UDP Packet
int len = udp.read(incomingPacket, 255);
if (len > 0)
{
incomingPacket[len] = 0;
}
#if LOGGING
Serial.printf("[UDP] Received %d bytes from %s, port %d\n", packetSize, udp.remoteIP().toString().c_str(), udp.remotePort());
Serial.printf("[UDP] Packet contents: %s\n", incomingPacket);
#endif
// Check if the received message is from the server we are searching for
if (strcmp(incomingPacket, broadcastMessage) == 0)
{
serverIp = udp.remoteIP();
serverPort = udp.remotePort();
#if LOGGING
Serial.printf("[UDP] Found Server on IP: %s, Port: %d\n", serverIp.toString().c_str(), serverPort);
#endif
serverFound = true;
changeColor(YELLOW, false); // Change status color of RGB LED back to yellow
}
}
}
}
I'm really wondering if there is something wrong with the server, the network or the NodeMcu. Especially because every other method I tried worked perfectly, just not when I'm sending it from the NodeMcu. Any help is very much appreciated!
It turned out that there was an error in the server code.
Instead of
client.send(message, 0, message.length, rinfo.port, rinfo.ip);
it should have been
client.send(message, 0, message.length, rinfo.port, rinfo.address);
The server didn't know rinfo.ip, so it spammed itself with the same message over and over again.

Unable to connect to Mosquitto over Websocket

I am unable to connect to my local Mosquitto 1.4.10 broker from a JavaScript client over a Websocket.
The same JavaScript client is successfully connecting to the public broker at test.mosquitto.org on port 8080 over a Websocket.
The MQTT protocol connection on port 1883 is working fine, which I tested using mosquitto_pub and mosquitto_sub.
My broker is set up within a VirtualBox running Ubuntu 14.04.
I have libwebsockets installed on the same virtual machine.
My local broker was compiled with WITH_WEBSOCKETS:=yes in the config.mk file
I am loading the JavaScript client web page from the same virtual machine from a Firefox browser and seeing the following error message in the browser console:
Firefox can't establish a connection to the server at
ws://localhost:8080/mqtt
Your suggestions on fixing this will be greatly appreciated.
Thanks.
Here is my Mosquitto .conf file:
port 1883
listener 8080
protocol websockets
log_type all
websockets_log_level 1023
connection_messages true
Here is the Mosquitto server's log (with websockets logging level set to 1023, and verbose logging turned on - no messages appear when I load the JavaScript web page):
1481381105: mosquitto version 1.4.10 (build date 2016-12-10
18:47:37+0530) starting
1481381105: Config loaded from /etc/mosquitto/mosquitto.conf.
1481381105: Opening websockets listen socket on port 8080.
1481381105: Initial logging level 1023
1481381105: Libwebsockets version: 2.1.0 manavkumarm#manav-alljoyn
1481381105: IPV6 not compiled in
1481381105: libev support not compiled in
1481381105: libuv support not compiled in
1481381105: Threads: 1 each 1024 fds
1481381105: mem: platform fd map: 4096 bytes
1481381105: Compiled with OpenSSL support
1481381105: Creating Vhost 'default' port 8080, 3 protocols, IPv6 off
1481381105: Using non-SSL mode
1481381105: Listening on port 8080
1481381105: mem: per-conn: 376 bytes + protocol rx buf
1481381105: canonical_hostname = mqtt
1481381105: Opening ipv4 listen socket on port 1883.
1481381105: Opening ipv6 listen socket on port 1883.
Here is the JavaScript source code:
<html>
<body>
<script src="mqttws31.js"></script>
<script>
try
{
// Create a client instance
console.log("Creating client object...");
client = new Paho.MQTT.Client("localhost", Number(8080), "manav");
//client = new Paho.MQTT.Client("test.mosquitto.org", Number(8080), "manav");
// set callback handlers
console.log("Setting handlers...");
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
console.log("Connecting...");
client.connect( {
onSuccess: onConnect,
mqttVersion: 4
});
}
catch (e)
{
console.log("Error: " + e.description);
}
// called when the client connects
function onConnect()
{
// Once a connection has been made, make a subscription and send a message.
console.log("Connected");
setTimeout( function() {
client.subscribe("world");
message = new Paho.MQTT.Message("Hello");
message.destinationName = "world";
client.send(message);
//client.disconnect();
}, 5000);
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("Connection lost: " + responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log("Received Message: " + message.payloadString);
client.disconnect();
}
</script>
<h1>My MQTT Websockets Example</h1>
</body>
</html>
I see I am little bit late on answer.
MQTT's port for websocket is 1884 or something else, you have 8080. Maybe thats the problem.
Isnt 8080 a reserved TCP port?
Also, I know you have javascript code, but its paho. I was able to make publisher(it uses same class like subscriber so it must be on subscriber side too - this is just assumption though) work on websockets with paho python client which must be initialized with defining transport parameter. -> communicating with browser(see below for javascript)
mqtt.Client(transport='websockets')
Leaving that parameter MQTT assumes using TCP
mqtt.Client()
Also:
Config on my broker:
# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
include_dir /etc/mosquitto/conf.d
listener 1883
listener 1884
protocol websockets
I found my very old Javascript with paho-mqtt. It was working, so I just put it here.
Its subscriber and publisher at the same time. Together with the config, It was working like charm.
class sub{
constructor(hostname,port,clientid,topic){
this.buffer = []
this.hostname=hostname;
this.port=port;
this.clientid = clientid;
this.topic = topic;
this.client = new Paho.MQTT.Client(hostname,port, clientid);
// set callback handlers
this.client.onConnectionLost = this.onConnectionLost;
this.client.onMessageArrived = this.onMessageArrived.bind(this);
// connect the client
this.client.connect({onSuccess:this.onConnect});
}
onConnect(){
console.log('OnConnect');
}
onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString);
this.buffer.push(JSON.parse(message.payloadString));
}
subsribe(){
this.client.subscribe(this.topic)
}
publish(message){
console.log(message)
var mg = new Paho.MQTT.Message(JSON.stringify(message));
mg.destinationName = this.topic;
this.client.send(mg);
}
}
var x
x = new sub('xx.xx.xx.xx',1884,'clientID','LED');
function on(){
x.publish({'LED':'ON'});
}
function off(){
x.publish({'LED':'OFF'});
}

Categories

Resources