-
Notifications
You must be signed in to change notification settings - Fork 406
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add AsyncUDP and simple NetBIOS name lookup server (#2234)
Thanks to @me-no-dev's code. Lets Windows look up the PicoW by name using NBNS and needs much less memory and code than mDNS. AsyncUDP ported from the old ESP8266 version, only minimal changes. Will probably only be valid in IPv4 environments and may not match current ESP32 AsyncUDP interfaces.
- Loading branch information
1 parent
352d363
commit c99614c
Showing
9 changed files
with
239 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
libraries/NetBIOS/examples/PicoW_NetBIOS/PicoW_NetBIOS.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Modified from the ESP32-NetBIOS example | ||
|
||
#include <WiFi.h> | ||
#include <NetBIOS.h> | ||
|
||
#ifndef STASSID | ||
#define STASSID "your-ssid" | ||
#define STAPSK "your-password" | ||
#endif | ||
|
||
const char* ssid = STASSID; | ||
const char* password = STAPSK; | ||
|
||
void setup() { | ||
Serial.begin(115200); | ||
|
||
// Connect to WiFi network | ||
WiFi.mode(WIFI_STA); | ||
WiFi.begin(ssid, password); | ||
Serial.println(""); | ||
|
||
// Wait for connection | ||
while (WiFi.status() != WL_CONNECTED) { | ||
delay(500); | ||
Serial.print("."); | ||
} | ||
Serial.println(""); | ||
Serial.print("Connected to "); | ||
Serial.println(ssid); | ||
Serial.print("IP address: "); | ||
Serial.println(WiFi.localIP()); | ||
|
||
// Windows (and other OSes using WINS/NetBIOS resolution should now be able to find the device by name) | ||
NBNS.begin("PicoW"); | ||
} | ||
|
||
void loop() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
####################################### | ||
# Syntax Coloring Map For ESPNBNS | ||
####################################### | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
|
||
NetBIOS KEYWORD1 | ||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
|
||
begin KEYWORD2 | ||
|
||
####################################### | ||
# Instances (KEYWORD2) | ||
####################################### | ||
|
||
NBNS KEYWORD2 | ||
|
||
####################################### | ||
# Constants (LITERAL1) | ||
####################################### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name=NetBIOS | ||
version=2.0.0 | ||
author=Pablo@xpablo.cz | ||
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com> | ||
sentence=Enables NBNS (NetBIOS) name resolution. | ||
paragraph=With this library you can connect to your ESP from Windows using a short name | ||
category=Communication | ||
url=http://www.xpablo.cz/?p=751#more-751 | ||
architectures=rp2040 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#include "NetBIOS.h" | ||
#include <functional> | ||
#include <lwip/netif.h> | ||
|
||
#define NBNS_PORT 137 | ||
#define NBNS_MAX_HOSTNAME_LEN 32 | ||
|
||
typedef struct { | ||
uint16_t id; | ||
uint8_t flags1; | ||
uint8_t flags2; | ||
uint16_t qcount; | ||
uint16_t acount; | ||
uint16_t nscount; | ||
uint16_t adcount; | ||
uint8_t name_len; | ||
char name[NBNS_MAX_HOSTNAME_LEN + 1]; | ||
uint16_t type; | ||
uint16_t clas; | ||
} __attribute__((packed)) nbns_question_t; | ||
|
||
typedef struct { | ||
uint16_t id; | ||
uint8_t flags1; | ||
uint8_t flags2; | ||
uint16_t qcount; | ||
uint16_t acount; | ||
uint16_t nscount; | ||
uint16_t adcount; | ||
uint8_t name_len; | ||
char name[NBNS_MAX_HOSTNAME_LEN + 1]; | ||
uint16_t type; | ||
uint16_t clas; | ||
uint32_t ttl; | ||
uint16_t data_len; | ||
uint16_t flags; | ||
uint32_t addr; | ||
} __attribute__((packed)) nbns_answer_t; | ||
|
||
static void _getnbname(const char *nbname, char *name, uint8_t maxlen) { | ||
uint8_t b; | ||
uint8_t c = 0; | ||
|
||
while ((*nbname) && (c < maxlen)) { | ||
b = (*nbname++ - 'A') << 4; | ||
c++; | ||
if (*nbname) { | ||
b |= *nbname++ - 'A'; | ||
c++; | ||
} | ||
if (!b || b == ' ') { | ||
break; | ||
} | ||
*name++ = b; | ||
} | ||
*name = 0; | ||
} | ||
|
||
static void append_16(void *dst, uint16_t value) { | ||
uint8_t *d = (uint8_t *)dst; | ||
*d++ = (value >> 8) & 0xFF; | ||
*d++ = value & 0xFF; | ||
} | ||
|
||
static void append_32(void *dst, uint32_t value) { | ||
uint8_t *d = (uint8_t *)dst; | ||
*d++ = (value >> 24) & 0xFF; | ||
*d++ = (value >> 16) & 0xFF; | ||
*d++ = (value >> 8) & 0xFF; | ||
*d++ = value & 0xFF; | ||
} | ||
|
||
void NetBIOS::_onPacket(AsyncUDPPacket &packet) { | ||
if (packet.length() >= sizeof(nbns_question_t)) { | ||
nbns_question_t *question = (nbns_question_t *)packet.data(); | ||
if (0 == (question->flags1 & 0x80)) { | ||
char name[NBNS_MAX_HOSTNAME_LEN + 1]; | ||
_getnbname(&question->name[0], (char *)&name, question->name_len); | ||
if (_name.equals(name)) { | ||
nbns_answer_t nbnsa; | ||
nbnsa.id = question->id; | ||
nbnsa.flags1 = 0x85; | ||
nbnsa.flags2 = 0; | ||
append_16((void *)&nbnsa.qcount, 0); | ||
append_16((void *)&nbnsa.acount, 1); | ||
append_16((void *)&nbnsa.nscount, 0); | ||
append_16((void *)&nbnsa.adcount, 0); | ||
nbnsa.name_len = question->name_len; | ||
memcpy(&nbnsa.name[0], &question->name[0], question->name_len + 1); | ||
append_16((void *)&nbnsa.type, 0x20); | ||
append_16((void *)&nbnsa.clas, 1); | ||
append_32((void *)&nbnsa.ttl, 300000); | ||
append_16((void *)&nbnsa.data_len, 6); | ||
append_16((void *)&nbnsa.flags, 0); | ||
nbnsa.addr = packet.localIP(); // Wrong, but better than nothing | ||
// Iterate over all netifs, see if the incoming address matches one of the netmaskes networks | ||
// TODO - is there an easier way of seeing whicn netif produced a packet? | ||
for (auto netif = netif_list; netif; netif = netif->next) { | ||
auto maskedip = ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)); | ||
auto maskedin = ((uint32_t)packet.localIP()) & ip4_addr_get_u32(netif_ip4_netmask(netif)); | ||
if (maskedip == maskedin) { | ||
nbnsa.addr = ip4_addr_get_u32(netif_ip4_addr(netif)); | ||
break; | ||
} | ||
} | ||
_udp.writeTo((uint8_t *)&nbnsa, sizeof(nbnsa), packet.remoteIP(), NBNS_PORT); | ||
} | ||
} | ||
} | ||
} | ||
|
||
NetBIOS::NetBIOS() {} | ||
|
||
NetBIOS::~NetBIOS() { | ||
end(); | ||
} | ||
|
||
bool NetBIOS::begin(const char *name) { | ||
_name = name; | ||
_name.toUpperCase(); | ||
|
||
if (_udp.connected()) { | ||
return true; | ||
} | ||
|
||
_udp.onPacket( | ||
[](void *arg, AsyncUDPPacket & packet) { | ||
((NetBIOS *)(arg))->_onPacket(packet); | ||
}, | ||
this | ||
); | ||
return _udp.listen(NBNS_PORT); | ||
} | ||
|
||
void NetBIOS::end() { | ||
if (_udp.connected()) { | ||
_udp.close(); | ||
} | ||
} | ||
|
||
NetBIOS NBNS; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
|
||
#pragma once | ||
|
||
#include <Arduino.h> | ||
#include <AsyncUDP.h> | ||
|
||
class NetBIOS { | ||
protected: | ||
AsyncUDP _udp; | ||
String _name; | ||
void _onPacket(AsyncUDPPacket &packet); | ||
|
||
public: | ||
NetBIOS(); | ||
~NetBIOS(); | ||
bool begin(const char *name); | ||
void end(); | ||
}; | ||
|
||
extern NetBIOS NBNS; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters