Skip to content

Commit

Permalink
Add WiFi close notifications (#799)
Browse files Browse the repository at this point in the history
* Start adding support for WiFi notifications

* Add wifi closed notifications

* Add is_closed to ethernet

* Update gold

* Reflow comment

* Drop tabs
  • Loading branch information
kasperl authored Jun 16, 2022
1 parent f1d7923 commit 743eb58
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 50 deletions.
14 changes: 11 additions & 3 deletions lib/core/events.toit
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ monitor ResourceState_:
group: return group_
resource: return resource_

set_callback callback/Lambda -> none:
callback_ = callback

wait_for_state bits:
return wait_for_state_ bits

wait:
return wait_for_state_ 0xffffff
return wait_for_state_ 0x3fff_ffff

clear:
state_ = 0
Expand All @@ -29,15 +32,19 @@ monitor ResourceState_:
unregister_monitor_notifier_ group_ resource_
resource_ = null
group_ = null
callback_ = null
remove_finalizer this

// Called on timeouts and when the state changes because of the call
// to [register_object_notifier] in the constructor.
notify_:
resource := resource_
if resource:
state := read_state_ group_ resource
state_ |= state
state := state_ | (read_state_ group_ resource)
state_ = state
callback := callback_
if callback:
callback.call state
// Always call the super implementation to avoid getting
// into a situation, where timeouts might be ignored.
super
Expand All @@ -55,6 +62,7 @@ monitor ResourceState_:

group_ := ?
resource_ := ?
callback_/Lambda? := null
state_ := 0

read_state_ module id:
Expand Down
3 changes: 3 additions & 0 deletions lib/net/ethernet.toit
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ class EthernetInterface_ implements net.Interface:
return it.address
unreachable

is_closed -> bool:
return not open_

close -> none:
if not open_: return
open_ = false
Expand Down
15 changes: 9 additions & 6 deletions lib/net/impl.toit
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ open -> net.Interface:
if not service: throw "Network unavailable"
return SystemInterface_ service service.connect

// TODO(kasper): Find a way to listen for network closing.
class SystemInterface_ extends NetworkResource implements net.Interface:
// The proxy mask contains bits for all the operations that must be
// proxied through the service client. The service definition tells the
Expand All @@ -33,7 +32,7 @@ class SystemInterface_ extends NetworkResource implements net.Interface:
super service handle

address -> net.IpAddress:
if not handle_: throw "Network closed"
if is_closed: throw "Network closed"
if (proxy_mask_ & NetworkService.PROXY_ADDRESS) != 0: return super
socket := Socket
try:
Expand All @@ -45,13 +44,17 @@ class SystemInterface_ extends NetworkResource implements net.Interface:
finally:
socket.close

on_notified_ notification/any -> none:
if notification == NetworkService.NOTIFY_CLOSED:
task:: close

resolve host/string -> List:
if not handle_: throw "Network closed"
if is_closed: throw "Network closed"
if (proxy_mask_ & NetworkService.PROXY_RESOLVE) != 0: return super host
return [dns.dns_lookup host]

udp_open --port/int?=null -> udp.Socket:
if not handle_: throw "Network closed"
if is_closed: throw "Network closed"
if (proxy_mask_ & NetworkService.PROXY_UDP) != 0: return super --port=port
return Socket "0.0.0.0" (port ? port : 0)

Expand All @@ -61,14 +64,14 @@ class SystemInterface_ extends NetworkResource implements net.Interface:
net.SocketAddress ips[0] port

tcp_connect address/net.SocketAddress -> tcp.Socket:
if not handle_: throw "Network closed"
if is_closed: throw "Network closed"
if (proxy_mask_ & NetworkService.PROXY_TCP) != 0: return super address
result := TcpSocket
result.connect address.ip.stringify address.port
return result

tcp_listen port/int -> tcp.ServerSocket:
if not handle_: throw "Network closed"
if is_closed: throw "Network closed"
if (proxy_mask_ & NetworkService.PROXY_TCP) != 0: return super port
result := TcpServerSocket
result.listen "0.0.0.0" port
Expand Down
4 changes: 3 additions & 1 deletion lib/net/net.toit
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ open -> Interface:

interface Interface implements udp.Interface tcp.Interface:
address -> IpAddress
is_closed -> bool

resolve host/string -> List

udp_open -> udp.Socket
Expand All @@ -26,4 +28,4 @@ interface Interface implements udp.Interface tcp.Interface:
tcp_connect address/SocketAddress -> tcp.Socket
tcp_listen port/int -> tcp.ServerSocket

close
close -> none
6 changes: 6 additions & 0 deletions lib/system/api/network.toit
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ interface NetworkService:
static SOCKET_OPTION_UDP_BROADCAST /int ::= 0
static SOCKET_OPTION_TCP_NO_DELAY /int ::= 100

/**
The notification constants are used as arguments to $ServiceResource.notify_
and consequently $ServiceResourceProxy.on_notified_.
*/
static NOTIFY_CLOSED /int ::= 200

// The connect call returns a handle to the network resource and
// the proxy mask bits in a list. The proxy mask bits indicate
// which operations the service definition wants the client to
Expand Down
3 changes: 3 additions & 0 deletions lib/system/services.toit
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ abstract class ServiceResourceProxy:
if _handle_ & 1 == 1:
ServiceResourceProxyManager_.instance.register client_.id _handle_ this

is_closed -> bool:
return _handle_ == null

handle_ -> int:
return _handle_

Expand Down
50 changes: 32 additions & 18 deletions src/resources/wifi_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ namespace toit {

enum {
WIFI_CONNECTED = 1 << 0,
WIFI_DHCP_SUCCESS = 1 << 1,
WIFI_DISCONNECTED = 1 << 2,
WIFI_RETRY = 1 << 3,
WIFI_IP_ASSIGNED = 1 << 1,
WIFI_IP_LOST = 1 << 2,
WIFI_DISCONNECTED = 1 << 3,
WIFI_RETRY = 1 << 4,
};

const int kInvalidWifi = -1;
Expand Down Expand Up @@ -117,11 +118,12 @@ class WifiEvents : public SystemResource {
FATAL_IF_NOT_ESP_OK(esp_wifi_stop());
}

uint8_t disconnect_reason() { return _disconnect_reason; }
uint8 disconnect_reason() const { return _disconnect_reason; }
void set_disconnect_reason(uint8 reason) { _disconnect_reason = reason; }

private:
friend class WifiResourceGroup;
uint8_t _disconnect_reason;
uint8 _disconnect_reason;
};

class IPEvents : public SystemResource {
Expand All @@ -135,7 +137,7 @@ class IPEvents : public SystemResource {
free(_ip);
}

const char* ip() {
const char* ip() const {
return _ip;
}

Expand Down Expand Up @@ -164,7 +166,7 @@ uint32_t WifiResourceGroup::on_event(Resource* resource, word data, uint32_t sta
state |= WIFI_DISCONNECTED;
break;
}
static_cast<WifiEvents*>(resource)->_disconnect_reason = reason;
static_cast<WifiEvents*>(resource)->set_disconnect_reason(reason);
break;
}

Expand All @@ -175,34 +177,46 @@ uint32_t WifiResourceGroup::on_event(Resource* resource, word data, uint32_t sta
case WIFI_EVENT_STA_STOP:
break;

case WIFI_EVENT_STA_BEACON_TIMEOUT:
// The beacon timeout mechanism is used by ESP32 station to detect whether the AP
// is alive or not. If the station continuously loses 60 beacons of the connected
// AP, the beacon timeout happens.
//
// After the beacon times out, the station sends 5 probe requests to the AP. If
// still no probe response or beacon is received from AP, the station disconnects
// from the AP and raises the WIFI_EVENT_STA_DISCONNECTED event.
break;

case IP_EVENT_STA_GOT_IP: {
ip_event_got_ip_t* event = reinterpret_cast<ip_event_got_ip_t*>(system_event->event_data);
uint32_t addr = event->ip_info.ip.addr;
sprintf(static_cast<IPEvents*>(resource)->_ip,
sprintf(
static_cast<IPEvents*>(resource)->_ip,
#ifdef CONFIG_IDF_TARGET_ESP32C3
"%lu.%lu.%lu.%lu",
"%lu.%lu.%lu.%lu",
#else
"%d.%d.%d.%d",
"%d.%d.%d.%d",
#endif
(addr >> 0) & 0xff,
(addr >> 8) & 0xff,
(addr >> 16) & 0xff,
(addr >> 24) & 0xff);
state |= WIFI_DHCP_SUCCESS;
(addr >> 0) & 0xff,
(addr >> 8) & 0xff,
(addr >> 16) & 0xff,
(addr >> 24) & 0xff);
state |= WIFI_IP_ASSIGNED;
break;
}

case IP_EVENT_STA_LOST_IP:
state |= WIFI_IP_LOST;
break;

default:
printf(
#ifdef CONFIG_IDF_TARGET_ESP32C3
"unhandled WiFi event: %lu\n",
"unhandled WiFi event: %lu\n",
#else
"unhandled Wifi event: %d\n",
"unhandled WiFi event: %d\n",
#endif
system_event->id
system_event->id
);
}

Expand Down
Loading

0 comments on commit 743eb58

Please sign in to comment.