1
1
#include <stdarg.h>
2
2
#include <pico/cyw43_arch.h>
3
3
#include <pico/stdlib.h>
4
+ #include <hardware/watchdog.h>
4
5
5
6
#include <lwip/ip4_addr.h>
6
7
#include <lwip/netif.h>
13
14
#include "dns/dnsserver.h"
14
15
#include "server_settings.h"
15
16
#include "httpserver.h"
16
- #include "tools/SimpleFSBuilder/SimpleFS.h"
17
+ #include "../ tools/SimpleFSBuilder/SimpleFS.h"
17
18
18
19
#define TEST_TASK_PRIORITY (tskIDLE_PRIORITY + 2UL)
19
20
@@ -35,7 +36,7 @@ bool simplefs_init(struct SimpleFSContext *ctx, void *data)
35
36
return true;
36
37
}
37
38
38
- static bool do_retrieve_file (http_connection conn , char * path , void * context )
39
+ static bool do_retrieve_file (http_connection conn , enum http_request_type type , char * path , void * context )
39
40
{
40
41
for (int i = 0 ; i < s_SimpleFS .header -> EntryCount ; i ++ )
41
42
{
@@ -53,7 +54,94 @@ static bool do_retrieve_file(http_connection conn, char *path, void *context)
53
54
return false;
54
55
}
55
56
56
- static bool do_handle_api_call (http_connection conn , char * path , void * context )
57
+ static char * parse_server_settings (http_connection conn , pico_server_settings * settings )
58
+ {
59
+ bool has_password = false, use_domain = false, use_second_ip = false;
60
+ bool bad_password = false, bad_domain = false;
61
+
62
+ for (;;)
63
+ {
64
+ char * line = http_server_read_post_line (conn );
65
+ if (!line )
66
+ break ;
67
+
68
+ char * p = strchr (line , '=' );
69
+ if (!p )
70
+ continue ;
71
+ * p ++ = 0 ;
72
+ if (!strcasecmp (line , "has_password" ))
73
+ has_password = !strcasecmp (p , "true" ) || p [0 ] == '1' ;
74
+ else if (!strcasecmp (line , "use_domain" ))
75
+ use_domain = !strcasecmp (p , "true" ) || p [0 ] == '1' ;
76
+ else if (!strcasecmp (line , "use_second_ip" ))
77
+ use_second_ip = !strcasecmp (p , "true" ) || p [0 ] == '1' ;
78
+ else if (!strcasecmp (line , "ssid" ))
79
+ {
80
+ if (strlen (p ) >= sizeof (settings -> network_name ))
81
+ return "SSID too long" ;
82
+ if (!p [0 ])
83
+ return "missing SSID" ;
84
+ strcpy (settings -> network_name , p );
85
+ }
86
+ else if (!strcasecmp (line , "password" ))
87
+ {
88
+ if (strlen (p ) >= sizeof (settings -> network_password ))
89
+ bad_password = true;
90
+ else
91
+ strcpy (settings -> network_password , p );
92
+ }
93
+ else if (!strcasecmp (line , "hostname" ))
94
+ {
95
+ if (strlen (p ) >= sizeof (settings -> hostname ))
96
+ return "hostname too long" ;
97
+ if (!p [0 ])
98
+ return "missing hostname" ;
99
+ strcpy (settings -> hostname , p );
100
+ }
101
+ else if (!strcasecmp (line , "domain" ))
102
+ {
103
+ if (strlen (p ) >= sizeof (settings -> domain_name ))
104
+ bad_domain = true;
105
+ else
106
+ strcpy (settings -> domain_name , p );
107
+ }
108
+ else if (!strcasecmp (line , "ipaddr" ))
109
+ {
110
+ settings -> ip_address = ipaddr_addr (p );
111
+ if (!settings -> ip_address || settings -> ip_address == -1 )
112
+ return "invalid IP address" ;
113
+ }
114
+ else if (!strcasecmp (line , "netmask" ))
115
+ {
116
+ settings -> network_mask = ipaddr_addr (p );
117
+ if (!settings -> network_mask || settings -> network_mask == -1 )
118
+ return "invalid network mask" ;
119
+ }
120
+ else if (!strcasecmp (line , "ipaddr2" ))
121
+ {
122
+ settings -> secondary_address = ipaddr_addr (p );
123
+ }
124
+ }
125
+
126
+ if (!has_password )
127
+ memset (settings -> network_password , 0 , sizeof (settings -> network_password ));
128
+ else if (bad_password )
129
+ return "password too long" ;
130
+
131
+ if (!use_domain )
132
+ memset (settings -> domain_name , 0 , sizeof (settings -> domain_name ));
133
+ else if (bad_domain )
134
+ return "domain too long" ;
135
+
136
+ if (!use_second_ip )
137
+ settings -> secondary_address = 0 ;
138
+ else if (!settings -> secondary_address || settings -> secondary_address == -1 )
139
+ return "invalid secondary IP address" ;
140
+
141
+ return NULL ;
142
+ }
143
+
144
+ static bool do_handle_api_call (http_connection conn , enum http_request_type type , char * path , void * context )
57
145
{
58
146
static int s_InitializedMask = 0 ;
59
147
@@ -116,13 +204,63 @@ static bool do_handle_api_call(http_connection conn, char *path, void *context)
116
204
return true;
117
205
}
118
206
}
207
+ else if (!strcmp (path , "settings" ))
208
+ {
209
+ if (type == HTTP_POST )
210
+ {
211
+ static pico_server_settings settings ;
212
+ settings = * get_pico_server_settings ();
213
+
214
+ char * err = parse_server_settings (conn , & settings );
215
+ if (err )
216
+ {
217
+ http_server_send_reply (conn , "200 OK" , "text/plain" , err , -1 );
218
+ return true;
219
+ }
220
+
221
+ write_pico_server_settings (& settings );
222
+ http_server_send_reply (conn , "200 OK" , "text/plain" , "OK" , -1 );
223
+ watchdog_reboot (0 , SRAM_END , 500 );
224
+ return true;
225
+ }
226
+ else
227
+ {
228
+ const pico_server_settings * settings = get_pico_server_settings ();
229
+ http_write_handle reply = http_server_begin_write_reply (conn , "200 OK" , "text/json" );
230
+ http_server_write_reply (reply , "{\"ssid\": \"%s\"" , settings -> network_name );
231
+ http_server_write_reply (reply , ",\"has_password\": %d, \"password\" : \"%s\"" , settings -> network_password [0 ] != 0 , settings -> network_password );
232
+ http_server_write_reply (reply , ",\"hostname\" : \"%s\"" , settings -> hostname );
233
+ http_server_write_reply (reply , ",\"use_domain\": %d, \"domain\" : \"%s\"" , settings -> domain_name [0 ] != 0 , settings -> domain_name );
234
+ http_server_write_reply (reply , ",\"ipaddr\" : \"%d.%d.%d.%d\"" , (settings -> ip_address >> 0 ) & 0xFF , (settings -> ip_address >> 8 ) & 0xFF , (settings -> ip_address >> 16 ) & 0xFF , (settings -> ip_address >> 24 ) & 0xFF );
235
+ http_server_write_reply (reply , ",\"netmask\" : \"%d.%d.%d.%d\"" , (settings -> network_mask >> 0 ) & 0xFF , (settings -> network_mask >> 8 ) & 0xFF , (settings -> network_mask >> 16 ) & 0xFF , (settings -> network_mask >> 24 ) & 0xFF );
236
+ http_server_write_reply (reply , ",\"use_second_ip\": %d" , settings -> secondary_address != 0 );
237
+ http_server_write_reply (reply , ",\"ipaddr2\" : \"%d.%d.%d.%d\"" , (settings -> secondary_address >> 0 ) & 0xFF , (settings -> secondary_address >> 8 ) & 0xFF , (settings -> secondary_address >> 16 ) & 0xFF , (settings -> secondary_address >> 24 ) & 0xFF );
238
+
239
+ http_server_end_write_reply (reply , "}" );
240
+ return true;
241
+ }
242
+ }
119
243
120
244
return false;
121
245
}
122
246
123
247
248
+ static void set_secondary_ip_address (int address )
249
+ {
250
+ /************************************ !!! WARNING !!! ************************************
251
+ * If you get an 'undefined reference to ip4_secondary_ip_address' error here, *
252
+ * you need to patch your lwIP using the lwip_patch/lwip.patch file from this repository.*
253
+ * This ensures that this device can pretend to be a router redirecting requests to *
254
+ * external IPs to its login page, so the OS can automatically navigate there. *
255
+ *****************************************************************************************/
256
+
257
+ extern int ip4_secondary_ip_address ;
258
+ ip4_secondary_ip_address = address ;
259
+ }
260
+
124
261
static void main_task (__unused void * params )
125
262
{
263
+
126
264
if (cyw43_arch_init ())
127
265
{
128
266
printf ("failed to initialise\n" );
@@ -149,6 +287,7 @@ static void main_task(__unused void *params)
149
287
static dhcp_server_t dhcp_server ;
150
288
dhcp_server_init (& dhcp_server , & netif -> ip_addr , & netif -> netmask , settings -> domain_name );
151
289
dns_server_init (netif -> ip_addr .addr , settings -> secondary_address , settings -> hostname , settings -> domain_name );
290
+ set_secondary_ip_address (settings -> secondary_address );
152
291
http_server_instance server = http_server_create (settings -> hostname , settings -> domain_name , 4 , 4096 );
153
292
static http_zone zone1 , zone2 ;
154
293
http_server_add_zone (server , & zone1 , "" , do_retrieve_file , NULL );
0 commit comments