Skip to content

Commit

Permalink
2019-10-30 Add esp32-idf 3.1 dns server return html
Browse files Browse the repository at this point in the history
2019-10-30  Add esp32-idf 3.1 dns server return html
  • Loading branch information
xuhongv committed Oct 30, 2019
1 parent 646d0fe commit 280fa26
Show file tree
Hide file tree
Showing 13 changed files with 1,768 additions and 0 deletions.
1 change: 1 addition & 0 deletions 12_dns_server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
10 changes: 10 additions & 0 deletions 12_dns_server/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := dns_server

COMPONENT_ADD_INCLUDEDIRS := components/include

include $(IDF_PATH)/make/project.mk
26 changes: 26 additions & 0 deletions 12_dns_server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ESP32 dns_server

说明:将 ESP32 当做一个 dns_server and web_server,通過在客戶端登陸網頁域名:www.espressif.com 登陸網頁,獲得特定返回。
## Quick start

### 必須

- 你已经安装好 ESP-IDF 和工具链。
- 你已经有一个手機或者電腦客戶端。
- 將 ESP32 設置為 softAP 模式。

### 步骤

- 使用数据线将开发板连接到你的系统中,让系统能够识别到你的板子(Windows 是`COM\*`, Linux 是`/dev/ttyUSB\*`)。
- 进入`sta`所在目录。
- 执行命名`make menuconfig`进行配置。
- 对热点的 SSID 和密码进行配置。依次进入配置选项`Demo Configuration --->`,然后在`WiFi SSID``WiFi Password`中填写你的 SSID 和密码。然后退出配置菜单,保存配置。
- 对串口进行配置。
- 执行命令`make`进行编译
- 执行命令`make flash monitor`将编译生成的镜像烧写到 ESP32 开发板上面,并查看串口输出。
- 在客戶端打開瀏覽器,輸入 www.espressif.com ,獲得網頁返回。

### 现象

![](http://i.imgur.com/ED5kuKJ.jpg)

7 changes: 7 additions & 0 deletions 12_dns_server/components/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Component Makefile
#

COMPONENT_ADD_INCLUDEDIRS := include

COMPONENT_SRCDIRS := src
26 changes: 26 additions & 0 deletions 12_dns_server/components/include/dns_server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef __DNA_SERVER_H__
#define __DNA_SERVER_H__

#define SIZEOF_DNSANS_HDR 12
#define SIZEOF_DNSANS_HDRQUE 20

#define DNS_SERVER_ID 0x0000
#define DNS_SERVER_FLAGS 0x8180
#define DNS_SERVER_NUMQUE 0x0001
#define DNS_SERVER_ANSRRS 0x0001
#define DNS_SERVER_AUTRRS 0x0000
#define DNS_SERVER_ADDRRS 0x0000
#define TABLENAME "www.xuhong.com"
#define DNS_SERVER_TYPE 0x0001
#define DNS_SERVER_CLASS 0x0001
#define DNS_POINAME 0xC00C
#define DNS_SERVER_ANSTYPE 0x0001
#define DNS_SERVER_ANSTYPEE 0x0001
#define DNS_SERVER_DATALEN 0x0000
#define DNS_SERVER_ANSTIME 0x003c0004
#define DNS_SERVER_ADRESS 0xc0a80401
void dns_server_send(void);
void get_dns_request(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
void my_udp_init(void);

#endif
7 changes: 7 additions & 0 deletions 12_dns_server/components/include/web_server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef __WEB_SERVER_H__
#define __WEB_SERVER_H__


void web_server2(void *pvParameters);

#endif
194 changes: 194 additions & 0 deletions 12_dns_server/components/src/dns_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* @Author: your name
* @Date: 2019-10-30 10:22:47
* @LastEditTime: 2019-10-30 10:56:13
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \esp-idf\mine\ESP32_DNS_Server\components\src\dns_server.c
*/
#include <string.h>
#include <sys/socket.h>
#include "esp_system.h"
#include "esp_log.h"
#include "tcpip_adapter.h"
#include "lwip/opt.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/ip4_addr.h"
#include "lwip/ip6_addr.h"
#include "lwip/api.h"
#include "dns_server.h"

#define TAG "lwip_udp"

uint16_t txid = 0;
uint16_t nquestions = 0;
uint16_t nanswers = 0;
struct udp_pcb *upcb1;
const ip_addr_t *addr1;
u16_t port1;

struct dns_ans_hdr
{
PACK_STRUCT_FIELD(uint16_t id);
PACK_STRUCT_FIELD(uint16_t flag);
PACK_STRUCT_FIELD(uint16_t numquestions);
PACK_STRUCT_FIELD(uint16_t numanswers);
PACK_STRUCT_FIELD(uint16_t numauthrr);
PACK_STRUCT_FIELD(uint16_t numextrarr);
} PACK_STRUCT_STRUCT;

struct dns_ans_ans
{
uint16_t typ;
uint16_t cls;
uint16_t point;
uint16_t antyp;
uint16_t antypp;
uint16_t len;
uint32_t time;
uint32_t addr;
};

struct dns_table_entry
{
uint16_t txid;
uint16_t flags;
uint16_t numque;
uint16_t ansrrs;
uint16_t autrrs;
uint16_t addrrs;
char name[256];
uint16_t type;
uint16_t class;
uint16_t poiname;
uint16_t anstype;
uint16_t anstypee;
uint16_t datalen;
uint32_t anstime;
uint32_t adress;
};

void dns_server_send(void)
{
struct pbuf *rp = NULL;
struct dns_ans_hdr hdr;
struct dns_ans_ans qry;
uint8_t n;
uint16_t query_idx, copy_len;
const char *hostname, *hostname_part;
struct dns_table_entry dns_server_table = {
.txid = DNS_SERVER_ID,
.flags = DNS_SERVER_FLAGS,
.numque = DNS_SERVER_NUMQUE,
.ansrrs = DNS_SERVER_ANSRRS,
.autrrs = DNS_SERVER_AUTRRS,
.addrrs = DNS_SERVER_ADDRRS,
.name = {0},
.type = DNS_SERVER_TYPE,
.class = DNS_SERVER_CLASS,
.poiname = DNS_POINAME,
.anstype = DNS_SERVER_ANSTYPE,
.anstypee = DNS_SERVER_ANSTYPEE,
.datalen = DNS_SERVER_DATALEN,
.anstime = DNS_SERVER_ANSTIME,
.adress = DNS_SERVER_ADRESS};
strcpy(dns_server_table.name, TABLENAME);
struct dns_table_entry *entry = &dns_server_table;

rp = pbuf_alloc(PBUF_TRANSPORT, 51, PBUF_RAM);
if (rp != NULL)
{
memset(&hdr, 0, SIZEOF_DNSANS_HDR);
/* fill dns_ans header */
hdr.id = htons(txid);
hdr.flag = htons(entry->flags);
hdr.numquestions = htons(entry->numque);
hdr.numanswers = htons(entry->ansrrs);
hdr.numauthrr = htons(entry->autrrs);
hdr.numextrarr = htons(entry->addrrs);
pbuf_take(rp, &hdr, SIZEOF_DNSANS_HDR);
/* convert hostname into suitable query format. */
hostname = entry->name;
--hostname;
query_idx = SIZEOF_DNSANS_HDR;
do
{
++hostname;
hostname_part = hostname;
for (n = 0; *hostname != '.' && *hostname != 0; ++hostname)
{
++n;
}
copy_len = (u16_t)(hostname - hostname_part);
pbuf_put_at(rp, query_idx, n);
pbuf_take_at(rp, hostname_part, copy_len, query_idx + 1);
query_idx += n + 1;
} while (*hostname != 0);
pbuf_put_at(rp, query_idx, 0);
query_idx++;
/* fill dns ans */
qry.typ = htons(entry->type);
qry.cls = htons(entry->class);
qry.point = htons(entry->poiname);
qry.antyp = htons(entry->anstype);
qry.antypp = htons(entry->anstypee);
qry.len = htons(entry->datalen);
qry.time = htonl(entry->anstime);
qry.addr = htonl(entry->adress);
printf("the query_idx is %d\n", query_idx);
printf("the qry.addr is %02X\n", qry.addr);
pbuf_take_at(rp, &qry, SIZEOF_DNSANS_HDRQUE, query_idx);

udp_sendto(upcb1, rp, addr1, port1);
// pbuf_free(rp);
}
}

void get_dns_request(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
printf("get the massage from sat\n");
struct dns_ans_hdr hdr;
upcb1 = upcb;
addr1 = addr;
port1 = port;
if (p->tot_len < (SIZEOF_DNSANS_HDR + SIZEOF_DNSANS_HDRQUE))
{
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
printf("dns_recv: pbuf too small\n");
/* free pbuf and return */
}
else
{
pbuf_copy_partial(p, &hdr, SIZEOF_DNSANS_HDR, 0);
txid = ntohs(hdr.id);
nquestions = ntohs(hdr.numquestions);
}
printf("the length of q: %d\n", p->tot_len);
printf("the txid is: %02X and the questions number is %02X\n", txid, nquestions);
pbuf_free(p); //check this
dns_server_send();
}

void my_udp_init(void)
{
struct udp_pcb *upcb;
err_t err;

upcb = udp_new();
err = udp_bind(upcb, IP_ADDR_ANY, 53);
if (err == ERR_OK)
{
udp_recv(upcb, get_dns_request, NULL);
}
else
{
udp_remove(upcb);
}
}
99 changes: 99 additions & 0 deletions 12_dns_server/components/src/web_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

/* Brief: This demo shows how to use esp32 as a webserver
*
* - use a sta connect to this ap
* - open the browser and input the ip_address of this esp32(the default ip_adress is: 192.168.4.1 )
* - and you can see "hello,this is esp32" on this web page
*
*/
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "freertos/portmacro.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "tcpip_adapter.h"
#include "lwip/err.h"
#include "string.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/api.h"
#include "web_server.h"

#define TAG "lwip_udp"

const static char http_html_hdr[] =
"HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
const static char http_index_hml[] = "<!DOCTYPE html>"
"<html>\n"
"<head>\n"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
" <style type=\"text/css\">\n"
" html, body, iframe { margin: 0; padding: 0; height: 100%; }\n"
" iframe { display: block; width: 100%; border: none; }\n"
" </style>\n"
"<title>HELLO ESP32</title>\n"
"</head>\n"
"<body>\n"
"<h1>Hello World, from ESP32!</h1>\n"
"</body>\n"
"</html>\n";

static void web_http_server(struct netconn *conn)
{
struct netbuf *inputbuf;
char *buf;
u16_t buflen;
err_t err;

err = netconn_recv(conn, &inputbuf);
if (err == ERR_OK) {
netbuf_data(inputbuf, (void**)&buf, &buflen);
printf("the received data:\n%s\n",buf);
/* Judge if this is an HTTP GET command */
if (buflen >= 5 && buf[0] == 'G' && buf[1] == 'E' && buf[2] == 'T' && buf[3] == ' ' && buf[4] == '/' ) {
netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);

if(buf[5]=='h') {
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
else if(buf[5]=='l') {
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
// else if(buf[5]=='j') {
// netconn_write(conn, json_unformatted, strlen(json_unformatted), NETCONN_NOCOPY);
// }
else {
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
}
}
netconn_close(conn);
netbuf_delete(inputbuf);
}


void web_server2(void *pvParameters)
{
struct netconn *conn, *newconn;
err_t err;
conn = netconn_new(NETCONN_TCP);
netconn_bind(conn, NULL, 80);
netconn_listen(conn);
while (1) {
err = netconn_accept(conn, &newconn);
if (err == ERR_OK) {
web_http_server(newconn);
netconn_delete(newconn);
}
else {
netconn_close(conn);
netconn_delete(conn);
break;
}
}
}
17 changes: 17 additions & 0 deletions 12_dns_server/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
menu "Demo Configuration"

config WIFI_SSID
string "WiFi SSID"
default "tidyjiang-ssid"
help
SSID (network name) to connect to.

config WIFI_PASSWORD
string "WiFi Password"
default "tidyjiang-passwd"
help
WiFi password (WPA or WPA2) to use.

Can be left blank if the network has no security set.

endmenu
Loading

0 comments on commit 280fa26

Please sign in to comment.