cesanta / mongoose-os

Mongoose OS - an IoT Firmware Development Framework. Supported microcontrollers: ESP32, ESP8266, CC3220, CC3200, STM32F4, STM32L4, STM32F7. Amazon AWS IoT, Microsoft Azure, Google IoT Core integrated. Code in C or JavaScript.
https://mongoose-os.com
Other
2.51k stars 429 forks source link

FR: features for captive portal #335

Open kzyapkov opened 7 years ago

kzyapkov commented 7 years ago

To be able to cause a notification to pop when associating to a device in AP mode with "captive portal"

GET /hotspot-detect.html HTTP/1.0
Host: captive.apple.com
Connection: close
User-Agent: CaptiveNetworkSupport-346.50.1 wispr

GET /hotspot-detect.html HTTP/1.1
Host: captive.apple.com
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Connection: keep-alive
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89

GET /generate_204 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
Host: connectivitycheck.gstatic.com
Connection: Keep-Alive
Accept-Encoding: gzip
gitcodr commented 7 years ago

Here's a guide: https://serverfault.com/questions/679393/captive-portal-popups-the-definitive-guide

Also, note that for iOS, device needs to have a domain for the WiFi network as it assumes a domainless network without access is a home network and just marks it as No Internet Connection instead of Captive Portal.

cpq commented 7 years ago

Just to clarify, is that for making mOS to trigger a login page?

kzyapkov commented 7 years ago

This is correct. The default http handler can be useful in other scenarios as well.

ztittle commented 6 years ago

Good find! This is now working for me on iOS devices. I had to include the following header:

extern "C" {
#include "user_interface.h"
}

Without calling wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &on), iOS immediately determines there is no internet access. Thus, any dns never occur and the AP http server had to be accessed by its IP address. This is not desirable when implementing the web based configuration of the esp8266.

I see that Captive Portals for device onboarding is on the development roadmap, so I sure hope this is addressed.

tripflex commented 6 years ago

I've built out a captive portal wifi setup that i'll work on porting over to a lib when i have a minute, but most of this was easily handled with a 302 redirect:

  mgos_register_http_endpoint("/generate_204", cap_port_redirect_ev_handler, NULL); // Android
  mgos_register_http_endpoint("/ncsi.txt", cap_port_redirect_ev_handler, NULL); // Windows
  mgos_register_http_endpoint("/hotspot-detect.html", cap_port_redirect_ev_handler, NULL); // iOS 8/9
  mgos_register_http_endpoint("/library/test/success.html", cap_port_redirect_ev_handler, NULL); // iOS 8/9
// Captive Portal 302 Redirect Handler
static void cap_port_redirect_ev_handler(struct mg_connection *nc, int ev, void *ev_data, void *user_data) {
  struct http_message *hm = (struct http_message *) ev_data;

  if (ev != MG_EV_HTTP_REQUEST) return;

  printf("Portal Redirect Event: %d, uri: %s\n", ev, hm->uri.p);

  struct mg_str *hdr = mg_get_http_header(hm, "User-Agent");

  printf("Portal Redirect Event USER AGENT: %s \n", hdr->p);

  // User-Agent: CaptiveNetworkSupport-355.50.1 wispr

  LOG(LL_INFO, ("Redirecting for Captive Portal"));
  mg_http_send_redirect(nc, 302, mg_mk_str(s_portal_redirect_url), mg_mk_str(NULL));
  (void) user_data;
}

You will notice I started adding support for handling it based on user agent as well (just never got around to finishing it, since with my esp32 it works perfect on all devices i've tested so far .. android/windows/iphone/osx) .. would just need to string match CaptiveNetworkSupport and send 302 redirect as well (if using user agent)

cpq commented 6 years ago

Does it make sense to wrap it into a library ?

kzyapkov commented 6 years ago

Yep, that'd be nice

tripflex commented 6 years ago

@cpq yes it should be IMO instead of an example app ... i've already got pretty much all of the code working, and even incorporated a completely vanilla js index page that calls RPC to get list of wifi networks, shows a dropdown, and allows selecting and setting the pw ... I just need to find time to finish moving all my code over to a lib, but don't have any problem providing what i've already done if you guys want

tripflex commented 6 years ago

@kzyapkov @cpq I created a captive portal lib for wifi setup you can find here: https://github.com/tripflex/wifi-captive-portal

I'm going to separate this into multiple libs soon, one for specifically captive portal, one for wifi setup UI, and one for the RPC endpoints, but for now it works without issues for me on esp32 (working on fixing esp8266 integration)