Commit Graph

40 Commits

Author SHA1 Message Date
Jamil
4d84e1f12e chore(connlib): Add external ID to FFI, return fd in on_set_interface_config (#1945)
(Supersedes #1944)

* Fixes https://github.com/firezone/product/issues/649
* Passes `dns_fallback_strategy` over FFI (these are hardcoded for now)
* Incorporates @conectado 's #1944 and cleans up a few places `fd` was
still passed

Draft for now until I can test it more tomorrow

---------

Co-authored-by: conectado <gabrielalejandro7@gmail.com>
2023-08-25 15:44:08 -07:00
Jamil
d1de8eac22 feat(connlib): implement name() and mtu() for android (#1943)
Implement `name()` to retrieve the tunnel name via `TUNGETIFF`, then use
that to retrieve the mtu via `SIOCGIFMTU`.

Verified to be working:

```
2023-08-23 20:25:50.211  4830-4928  connlib                 dev.firezone.android                 D  firezone_tunnel::tun: MTU for tun0 is 1280
```

Will update the `log::debug!` calls to tracing in the next PR.
2023-08-25 05:42:08 +00:00
Jamil
3316d9098a fix(android): Fix auth flow and callback thread safety, and pass fd through FFI (#1930)
* Refactor sharedPreferences to only save the AccountId
* Update TeamId -> AccountId to match naming elsewhere
* Update JWT -> Token to avoid confusion; this token is **not** a valid
JWT and should be treated as an opaque token
* Update FFI `connect` to accept an optional file descriptor (int32) as
a first argument. This seemed to be the most straightforward way to pass
it to the tunnel stack. Retrieving it via callback is another option,
but retrieving return vars with the `jni` was more complex. We could
have used a similar approach that we did in the Apple client
(enumerating all fd's in the `new()` function until we found ours) but
this approach is [explicitly
documented/recommended](https://developer.android.com/reference/android/net/VpnService.Builder#establish())
by the Android docs so I figured it's not likely to break.

Additionally, there was a thread safety bug in the recent JNI callback
implementation that consistently crashed the VM with `JNI DETECTED ERROR
IN APPLICATION: use of invalid jobject...`. The fix was to use
`GlobalRef` which has the explicit purpose of outliving the `JNIEnv`
lifetime so that no `static` lifetimes need to be used.

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Pratik Velani <pratikvelani@gmail.com>
Co-authored-by: Gabi <gabrielalejandro7@gmail.com>
2023-08-23 14:13:55 -07:00
Gabi
8621953fe6 connlib: fix how we handle disconnect (#1923)
Basically we were having a panic inside a panic before, when I tried to
drop the runtime in `on_disconnect` since you can't drop a runtime
within a runtime. This PR spawns a new thread that listen for
disconnection and stops the runtime right there.

This also fixes the timer for reconnections.

Note: That I first stop it and the drop it which is redundant but I
rather be safe :)
2023-08-23 00:35:11 +00:00
Jamil
54e1a79a50 fix(ios): portal connectivity and tunnel setup (#1927)
This PR fixes issues with the iOS client connecting to the portal and
setting up the tunnel.

- portal IPv6 unique-local prefix typo
- Use `rustls-webpki-roots` instead of `rustls-native-roots` for tokio
tungstenite since the latter [only supports macOS, Linux, and
Windows](https://github.com/rustls/rustls-native-certs) while the former
seems to work on all platforms(?)
- Remove Multipath TCP entitlement for iOS since it's not relevant for
us.

@conectado After this is merged, we _almost_ have a working tunnel on
iOS. I believe the error we're hitting now is the 4-byte address family
header that we need to add and strip from each packet written to / read
from the tunnel. See below log for sample output when attempting to
connect to the `HTTPbin` resource:

```
dev.firezone.firezone.network-extension	packet-tunnel	debug	16:10:13.401705-0700	FirezoneNetworkExtensioniOS	Adapter state changed to: tunnelReady
dev.firezone.firezone.network-extension	packet-tunnel	debug	16:10:13.401731-0700	FirezoneNetworkExtensioniOS	Beginning path monitoring
com.apple.network	path	default	16:10:13.402211-0700	FirezoneNetworkExtensioniOS	nw_path_evaluator_start [1ACDE975-615B-4557-BF7C-678F3594452E <NULL> generic, multipath service: 1, attribution: developer]
	path: satisfied (Path is satisfied), interface: en0[802.11], scoped, ipv4, ipv6, dns
com.apple.network	path	info	16:10:13.402235-0700	FirezoneNetworkExtensioniOS	nw_path_evaluator_call_update_handler [1ACDE975-615B-4557-BF7C-678F3594452E] scheduling update
com.apple.network	path	info	16:10:13.402261-0700	FirezoneNetworkExtensioniOS	nw_path_evaluator_call_update_handler_block_invoke [1ACDE975-615B-4557-BF7C-678F3594452E] delivering update
com.apple.network		debug	16:10:13.402286-0700	FirezoneNetworkExtensioniOS	nw_path_copy_interface_with_generation Cache miss for interface for index 3 (generation 4574)
com.apple.network		debug	16:10:13.402312-0700	FirezoneNetworkExtensioniOS	nw_path_copy_interface_with_generation Cache miss for interface for index 31 (generation 141)
dev.firezone.firezone.network-extension	packet-tunnel	debug	16:10:13.402363-0700	FirezoneNetworkExtensioniOS	Suppressing calls to disableSomeRoamingForBrokenMobileSemantics() and bumpSockets()
dev.firezone.firezone	connlib	debug	16:10:14.368105-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:15.369018-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:16.095618-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:16.370908-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:17.372035-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:18.373423-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:20.402863-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:24.381581-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:32.374566-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:10:38.137437-0700	FirezoneNetworkExtensioniOS	Text("{\"ref\":null,\"topic\":\"phoenix\",\"event\":\"phx_reply\",\"payload\":{\"status\":\"ok\",\"response\":{}}}")
dev.firezone.firezone	connlib	debug	16:10:38.137757-0700	FirezoneNetworkExtensioniOS	Phoenix status message
dev.firezone.firezone	connlib	debug	16:10:48.376339-0700	FirezoneNetworkExtensioniOS	Reading from iface 76 bytes
dev.firezone.firezone	connlib	debug	16:11:08.148369-0700	FirezoneNetworkExtensioniOS	Text("{\"ref\":null,\"topic\":\"phoenix\",\"event\":\"phx_reply\",\"payload\":{\"status\":\"ok\",\"response\":{}}}")
dev.firezone.firezone	connlib	debug	16:11:08.148654-0700	FirezoneNetworkExtensioniOS	Phoenix status message
```
2023-08-21 20:48:30 -07:00
Gabi
d1537b0839 connlib: different backoff strategy for gateway/client (#1910)
With this PR we will keep retrying reconnection forever for the gateway
after it disconnects.
2023-08-16 22:05:48 +00:00
dependabot[bot]
ae9a619703 build(deps): Bump pnet_packet from 0.33.0 to 0.34.0 in /rust (#1905)
Bumps [pnet_packet](https://github.com/libpnet/libpnet) from 0.33.0 to
0.34.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/libpnet/libpnet/releases">pnet_packet's
releases</a>.</em></p>
<blockquote>
<h2>v0.34.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Add blanket impls of Packet for Box<!-- raw HTML omitted --> and
&amp;T. by <a href="https://github.com/landhb"><code>@​landhb</code></a>
in <a
href="https://redirect.github.com/libpnet/libpnet/pull/606">libpnet/libpnet#606</a></li>
<li>GitHub actions updates by <a
href="https://github.com/mrmonday"><code>@​mrmonday</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/608">libpnet/libpnet#608</a></li>
<li>Fix typos by <a
href="https://github.com/darxriggs"><code>@​darxriggs</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/609">libpnet/libpnet#609</a></li>
<li>Update pnet_macros to use syn v2 by <a
href="https://github.com/james-jra"><code>@​james-jra</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/627">libpnet/libpnet#627</a></li>
<li>Spell check with <code>typos</code>. Add <code>spell-check</code> CI
job by <a href="https://github.com/vvv"><code>@​vvv</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/621">libpnet/libpnet#621</a></li>
<li>Add LINKTYPE_LINUX_SLL2 support and fix link to SLL by <a
href="https://github.com/reticulis"><code>@​reticulis</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/619">libpnet/libpnet#619</a></li>
<li>TCP header remove NS flag by <a
href="https://github.com/rikonaka"><code>@​rikonaka</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/625">libpnet/libpnet#625</a></li>
<li>Assorted cleanup by <a
href="https://github.com/mrmonday"><code>@​mrmonday</code></a> in <a
href="https://redirect.github.com/libpnet/libpnet/pull/630">libpnet/libpnet#630</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/james-jra"><code>@​james-jra</code></a>
made their first contribution in <a
href="https://redirect.github.com/libpnet/libpnet/pull/627">libpnet/libpnet#627</a></li>
<li><a href="https://github.com/vvv"><code>@​vvv</code></a> made their
first contribution in <a
href="https://redirect.github.com/libpnet/libpnet/pull/621">libpnet/libpnet#621</a></li>
<li><a href="https://github.com/reticulis"><code>@​reticulis</code></a>
made their first contribution in <a
href="https://redirect.github.com/libpnet/libpnet/pull/619">libpnet/libpnet#619</a></li>
<li><a href="https://github.com/rikonaka"><code>@​rikonaka</code></a>
made their first contribution in <a
href="https://redirect.github.com/libpnet/libpnet/pull/625">libpnet/libpnet#625</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/libpnet/libpnet/compare/v0.33.0...v0.34.0">https://github.com/libpnet/libpnet/compare/v0.33.0...v0.34.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9bd20d82c0"><code>9bd20d8</code></a>
Release v0.34.0</li>
<li><a
href="b8bd8e031e"><code>b8bd8e0</code></a>
Merge pull request <a
href="https://redirect.github.com/libpnet/libpnet/issues/630">#630</a>
from mrmonday/fix-build-warnings</li>
<li><a
href="47ae47de30"><code>47ae47d</code></a>
Assorted cleanup</li>
<li><a
href="c32d9db6ec"><code>c32d9db</code></a>
Merge pull request <a
href="https://redirect.github.com/libpnet/libpnet/issues/625">#625</a>
from rikonaka/master</li>
<li><a
href="391b133ef7"><code>391b133</code></a>
Merge pull request <a
href="https://redirect.github.com/libpnet/libpnet/issues/619">#619</a>
from reticulis/sll2</li>
<li><a
href="12636deb8a"><code>12636de</code></a>
Merge pull request <a
href="https://redirect.github.com/libpnet/libpnet/issues/621">#621</a>
from vvv/spell-check</li>
<li><a
href="d29848e39b"><code>d29848e</code></a>
Merge pull request <a
href="https://redirect.github.com/libpnet/libpnet/issues/627">#627</a>
from james-jra/syn-2</li>
<li><a
href="08622c53c9"><code>08622c5</code></a>
Fix compile test stderr for correct rustc version</li>
<li><a
href="431ced23f8"><code>431ced2</code></a>
add more compilation error tests for #[construct_with]</li>
<li><a
href="b46f7f36b0"><code>b46f7f3</code></a>
Update compile fail test error messages</li>
<li>Additional commits viewable in <a
href="https://github.com/libpnet/libpnet/compare/v0.33.0...v0.34.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pnet_packet&package-manager=cargo&previous-version=0.33.0&new-version=0.34.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 19:49:25 +00:00
dependabot[bot]
66e78c5e72 build(deps): Bump log from 0.4.19 to 0.4.20 in /rust (#1903)
Bumps [log](https://github.com/rust-lang/log) from 0.4.19 to 0.4.20.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/log/blob/master/CHANGELOG.md">log's
changelog</a>.</em></p>
<blockquote>
<h2>[0.4.20] - 2023-07-11</h2>
<ul>
<li>Remove rustversion dev-dependency by <a
href="https://github.com/Thomasdezeeuw"><code>@​Thomasdezeeuw</code></a>
in <a
href="https://redirect.github.com/rust-lang/log/pull/568">rust-lang/log#568</a></li>
<li>Remove <code>local_inner_macros</code> usage by <a
href="https://github.com/EFanZh"><code>@​EFanZh</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/570">rust-lang/log#570</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4708f1484c"><code>4708f14</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/574">#574</a>
from chrysn-pull-requests/doc-log-to-defmt</li>
<li><a
href="6de3cccc36"><code>6de3ccc</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/571">#571</a>
from rust-lang/cargo/0.4.20</li>
<li><a
href="838920cf18"><code>838920c</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/575">#575</a>
from EFanZh/group-target-module-path-and-file</li>
<li><a
href="3985711f74"><code>3985711</code></a>
Group <code>target</code>, <code>module_path</code> and
<code>file</code> arguments</li>
<li><a
href="3f534d00e4"><code>3f534d0</code></a>
Move private APIs into a single module</li>
<li><a
href="f5ab686e9b"><code>f5ab686</code></a>
doc: Add log-to-defmt to other-facilities section</li>
<li><a
href="6d173bf941"><code>6d173bf</code></a>
prepare for 0.4.20 release</li>
<li><a
href="cab10885de"><code>cab1088</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/570">#570</a>
from EFanZh/remove-local-inner-macros</li>
<li><a
href="9d052b17d3"><code>9d052b1</code></a>
Remove <code>local_inner_macros</code> usage</li>
<li><a
href="e9123d6d9a"><code>e9123d6</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/568">#568</a>
from Thomasdezeeuw/remove-rustversion-dep</li>
<li>Additional commits viewable in <a
href="https://github.com/rust-lang/log/compare/0.4.19...0.4.20">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=log&package-manager=cargo&previous-version=0.4.19&new-version=0.4.20)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 19:48:32 +00:00
Gabi
721d2ffc45 Fix/webrtc failure (#1896) 2023-08-11 17:15:42 -05:00
Jamil
3a79f4c0aa apple: refactor portal_url to be opaque (#1881)
* Remove JWT to be an opaque token and update variable names accordingly
* Use new `actor_name` param from the portal instead of user info from
old JWT
* Log attempted portal URL from connlib
* Remove account slug/id from portal_url before sending to connlib

@roop The token from the portal is a Phoenix.Token, not a valid JWT, so
this was causing a JWTDecodeError. Discussed with @AndrewDryga and
concluded this should be an opaque token. Expiry and other invalid token
scenarios will be bubbled up from connlib via an `onError` callback (or
perhaps a dedicated `onTokenInvalid` callback). For now connlib doesn't
handle this specifically.
2023-08-11 06:17:44 -05:00
Gabi
744b4b12cb connlib: enable TLS support for websocket (#1882) 2023-08-10 23:03:16 +00:00
Gabi
a0a5acd542 connlib: correct checksum for all handled protocols (#1880)
Signed-off-by: conectado <gabrielalejandro7@gmail.com>
2023-08-10 21:58:28 +00:00
Gabi
90289e3a38 connlib: update the url scheme for http/https (#1879)
This just updates the portal's url scheme based on what we discussed
with @jamilbk
2023-08-10 12:41:26 -05:00
Andrew Dryga
3a5877eaa3 Update protocol to reuse gateway connections (#1825)
This is a result of our discussion with @conectado, this PR will add a
new message type which will allow reusing existing connections to the
gateway to access a new resource. We will also change the LB strategy to
be aware of the current device connection so that we will not pick a
different one if we have a connected gateway that can serve a new
resource.

---------

Co-authored-by: conectado <gabrielalejandro7@gmail.com>
2023-08-10 12:41:06 -05:00
Jamil
9b538e92d4 apple: Tunnel stack (#1876)
This PR adds the remaining bits of the Apple tunnel stack for macOS and
iOS devices.

- [x] Find file descriptor corresponding to NE-managed tunnel interface
- [ ] Testing

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: conectado <gabrielalejandro7@gmail.com>
2023-08-10 12:40:46 -05:00
Francesca Lovebloom
bc3a5d9e54 connlib: JNI bridge (#1848)
The biggest internal change is that all the methods on `Callbacks` (on
the Rust side!) return a `Result` now, so errors from the bridge or even
the client callbacks will be handled.

@roop there's nothing for you to review here, but note:

- the `bool` return values you've asked about in the past are gone now
- the route string for `onAddRoute`/`onRemoveRoute` no longer has the
extra quotes (it's no longer JSON)

---------

Signed-off-by: Francesca Lovebloom <franlovebloom@gmail.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2023-08-07 19:03:28 -05:00
Gabi
44e4295a4e connlib: fix DNS PTR record query (#1854)
Some programs(such as `ping`) after resolving the dns name do a reverse
dns lookup using PTR, if this doesn't respond the program hangs making
performance slower.

This PR fixes it by handling PTR queries.

---------

Signed-off-by: Gabi <gabrielalejandro7@gmail.com>
Co-authored-by: Francesca Lovebloom <franlovebloom@gmail.com>
Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
2023-08-04 19:08:34 +00:00
Gabi
b563c7ad5a connlib: fix ipv6 (#1855)
Fixes some of the ipv6 handling.

Making this PR I also realized we need to update checksums on UDP and
TCP too, since we're mangling packets.
2023-08-04 03:17:35 +00:00
Gabi
dcf9e68eb7 connlib: implements reverse-dns lookup that's used for gateways (#1842)
This PR implements the reverse lookup for DNS from the gateway side (the
other part of #1807)

Also, adds a fix in general for Ipv6 DNS packets (nothing to do with
AAAA, only DNS packets using ipv6), and removes resource candidates from
SDP.

Although there are still a few fixes coming related to this PR, if you
do `docker compose exec client ping google.com` it should work now
(given that the seeds include google) as Client -> Gateway -> google.com

---------

Signed-off-by: Gabi <gabrielalejandro7@gmail.com>
Signed-off-by: conectado <gabrielalejandro7@gmail.com>
Co-authored-by: Francesca Lovebloom <franlovebloom@gmail.com>
2023-08-01 22:03:34 +00:00
Francesca Lovebloom
9d4df04501 connlib: Simpler FFI (#1823)
As per discussion from the client sync,
- this removes `TunnelAddresses` in favor of simply passing the IPv4 and
IPv6 addresses as two separate strings.
- this changes `onDisconnect`'s semantics to be called _after_
disconnect instead of before.

Additionally, as per earlier discussion, errors are now passed as
strings. These errors already weren't intended to be actionable on the
client side, so the ability to handle them programmatically is
unnecessary. When internationalization is added down the road, we'll
likely replace these with error codes for looking up localized strings;
until then, this design improves diagnostics and reduces complexity.

Closes #1796
Closes #1822
2023-07-29 23:47:39 +00:00
Francesca Lovebloom
9fb842ed24 connlib: Fix resource list JSON (#1818)
Addresses one of the issues raised in firezone/product#634

Previously, we were joining a `Vec` of serialized JSON objects into a
comma-separated string, which isn't valid JSON. Now the entire thing is
simply serialized, `Vec` and all.

Additionally, I've moved serialization to happen just before the FFI
boundary, which removes some indirection from connlib and will avoid a
deserialization step when writing non-FFI clients.
2023-07-24 23:17:43 +00:00
dependabot[bot]
5b387df2fa build(deps): bump uuid from 1.4.0 to 1.4.1 in /rust (#1816)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.4.0 to 1.4.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/uuid-rs/uuid/releases">uuid's
releases</a>.</em></p>
<blockquote>
<h2>1.4.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix macro hygiene by <a
href="https://github.com/teohhanhui"><code>@​teohhanhui</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/694">uuid-rs/uuid#694</a></li>
<li>Add #[inline] for Uuid::from_bytes[_ref] and Uuid::{as,into}_bytes
by <a
href="https://github.com/jrose-signal"><code>@​jrose-signal</code></a>
in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/693">uuid-rs/uuid#693</a></li>
<li>Print uuids in examples by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/697">uuid-rs/uuid#697</a></li>
<li>Prepare for 1.4.1 release by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/698">uuid-rs/uuid#698</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/teohhanhui"><code>@​teohhanhui</code></a> made
their first contribution in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/694">uuid-rs/uuid#694</a></li>
<li><a
href="https://github.com/jrose-signal"><code>@​jrose-signal</code></a>
made their first contribution in <a
href="https://redirect.github.com/uuid-rs/uuid/pull/693">uuid-rs/uuid#693</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/uuid-rs/uuid/compare/1.4.0...1.4.1">https://github.com/uuid-rs/uuid/compare/1.4.0...1.4.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="97b7f07b3e"><code>97b7f07</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/698">#698</a> from
uuid-rs/cargo/1.4.1</li>
<li><a
href="8e930cf511"><code>8e930cf</code></a>
prepare for 1.4.1 release</li>
<li><a
href="0041b3b0b4"><code>0041b3b</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/697">#697</a> from
uuid-rs/chore/example-printing</li>
<li><a
href="5a1f3f56d3"><code>5a1f3f5</code></a>
use uuid_unstable</li>
<li><a
href="6b0cfb2e28"><code>6b0cfb2</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/693">#693</a> from
jrose-signal/inline-from_bytes</li>
<li><a
href="33f6b3edd9"><code>33f6b3e</code></a>
print uuids in examples</li>
<li><a
href="bd7df72944"><code>bd7df72</code></a>
Merge pull request <a
href="https://redirect.github.com/uuid-rs/uuid/issues/694">#694</a> from
teohhanhui/fix/macro-hygiene</li>
<li><a
href="1d1ae31e6c"><code>1d1ae31</code></a>
Fix macro hygiene</li>
<li><a
href="317d925536"><code>317d925</code></a>
Add #[inline] for Uuid::from_bytes[_ref] and Uuid::{as,into}_bytes</li>
<li>See full diff in <a
href="https://github.com/uuid-rs/uuid/compare/1.4.0...1.4.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=uuid&package-manager=cargo&previous-version=1.4.0&new-version=1.4.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Gabi <gabrielalejandro7@gmail.com>
2023-07-24 22:31:54 +00:00
Gabi
7ad2fb623a connlib: add client dns interception support (#1807) 2023-07-24 21:41:42 +00:00
Francesca Lovebloom
52898a69af connlib: Disconnect on panic (#1815) 2023-07-24 21:18:38 +00:00
dependabot[bot]
f01ffaf17b Bump tokio-tungstenite from 0.18.0 to 0.19.0 in /rust (#1787)
Bumps [tokio-tungstenite](https://github.com/snapview/tokio-tungstenite)
from 0.18.0 to 0.19.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/snapview/tokio-tungstenite/blob/master/CHANGELOG.md">tokio-tungstenite's
changelog</a>.</em></p>
<blockquote>
<h1>0.19.0</h1>
<ul>
<li>Allow users to enable/disable Nagle algorithm when using
<code>connect()</code> helpers.</li>
<li>Improve the behavior of the <code>Sink</code> for the
<code>WebSocketStream</code>, so it does not return an error when it’s
not necessary (when <code>poll_flush()</code> is called on a connection
that has just been closed).</li>
<li>Workaround an issue where <code>rustls</code> TLS backend expected
domain in a certain format and reject IPv6 addresses if they contained
square brackets in them.</li>
<li>Update dependencies and remove unused errors.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d8101030ac"><code>d810103</code></a>
Update changelog and bump version</li>
<li><a
href="cb11969676"><code>cb11969</code></a>
Remove boilerplace in <code>poll_flush()</code></li>
<li><a
href="e5e8421f1b"><code>e5e8421</code></a>
Merge pull request <a
href="https://redirect.github.com/snapview/tokio-tungstenite/issues/280">#280</a>
from mjquigley/support-ipv6</li>
<li><a
href="d6f5d45e64"><code>d6f5d45</code></a>
Merge pull request <a
href="https://redirect.github.com/snapview/tokio-tungstenite/issues/281">#281</a>
from CBenoit/fix-poll-flush</li>
<li><a
href="f31c425e29"><code>f31c425</code></a>
Merge pull request <a
href="https://redirect.github.com/snapview/tokio-tungstenite/issues/279">#279</a>
from mjquigley/patch-2</li>
<li><a
href="e2e8b94e41"><code>e2e8b94</code></a>
Support IPv6 URIs with rustls</li>
<li><a
href="2c3c6419fc"><code>2c3c641</code></a>
Fix poll_flush on closed connection</li>
<li><a
href="862922ffc1"><code>862922f</code></a>
Revert tokio requirement to 1.0.0</li>
<li><a
href="8803232d81"><code>8803232</code></a>
Merge pull request <a
href="https://redirect.github.com/snapview/tokio-tungstenite/issues/277">#277</a>
from nickelc/deps/webpki</li>
<li><a
href="d447d4620f"><code>d447d46</code></a>
Removed unused <code>webpki</code> dependency</li>
<li>Additional commits viewable in <a
href="https://github.com/snapview/tokio-tungstenite/compare/v0.18.0...v0.19.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio-tungstenite&package-manager=cargo&previous-version=0.18.0&new-version=0.19.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Gabi <gabrielalejandro7@gmail.com>
2023-07-24 19:40:12 +00:00
dependabot[bot]
46aa962773 Bump itertools from 0.10.5 to 0.11.0 in /rust (#1786)
Bumps [itertools](https://github.com/rust-itertools/itertools) from
0.10.5 to 0.11.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md">itertools's
changelog</a>.</em></p>
<blockquote>
<h2>0.11.0</h2>
<h3>Breaking</h3>
<ul>
<li>Make <code>Itertools::merge_join_by</code> also accept functions
returning bool (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/704">#704</a>)</li>
<li>Implement <code>PeekingNext</code> transitively over mutable
references (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/643">#643</a>)</li>
<li>Change <code>with_position</code> to yield <code>(Position,
Item)</code> instead of <code>Position&lt;Item&gt;</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/699">#699</a>)</li>
</ul>
<h3>Added</h3>
<ul>
<li>Add <code>Itertools::take_while_inclusive</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/616">#616</a>)</li>
<li>Implement <code>PeekingNext</code> for <code>PeekingTakeWhile</code>
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/644">#644</a>)</li>
<li>Add <code>EitherOrBoth::{just_left, just_right, into_left,
into_right, as_deref, as_deref_mut, left_or_insert, right_or_insert,
left_or_insert_with, right_or_insert_with, insert_left, insert_right,
insert_both}</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/629">#629</a>)</li>
<li>Implement <code>Clone</code> for <code>CircularTupleWindows</code>
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/686">#686</a>)</li>
<li>Implement <code>Clone</code> for <code>Chunks</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/683">#683</a>)</li>
<li>Add <code>Itertools::process_results</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/680">#680</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Use <code>Cell</code> instead of <code>RefCell</code> in
<code>Format</code> and <code>FormatWith</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/608">#608</a>)</li>
<li>CI tweaks (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/674">#674</a>,
<a
href="https://redirect.github.com/rust-itertools/itertools/issues/675">#675</a>)</li>
<li>Document and test the difference between stable and unstable sorts
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/653">#653</a>)</li>
<li>Fix documentation error on <code>Itertools::max_set_by_key</code>
(<a
href="https://redirect.github.com/rust-itertools/itertools/issues/692">#692</a>)</li>
<li>Move MSRV metadata to <code>Cargo.toml</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/672">#672</a>)</li>
<li>Implement <code>equal</code> with <code>Iterator::eq</code> (<a
href="https://redirect.github.com/rust-itertools/itertools/issues/591">#591</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="62a6401afd"><code>62a6401</code></a>
chore: Release itertools version 0.11.0</li>
<li><a
href="8f17227193"><code>8f17227</code></a>
remove <code>no-dev-version</code> Cargo release directive</li>
<li><a
href="bb2fc59edd"><code>bb2fc59</code></a>
Merge <a
href="https://redirect.github.com/rust-itertools/itertools/issues/706">#706</a></li>
<li><a
href="0ef6b7eaad"><code>0ef6b7e</code></a>
prepare v0.11.0 release</li>
<li><a
href="c5b64c9ed7"><code>c5b64c9</code></a>
Merge <a
href="https://redirect.github.com/rust-itertools/itertools/issues/616">#616</a></li>
<li><a
href="eb561e537b"><code>eb561e5</code></a>
Merge <a
href="https://redirect.github.com/rust-itertools/itertools/issues/704">#704</a></li>
<li><a
href="3e92550903"><code>3e92550</code></a>
Merge <a
href="https://redirect.github.com/rust-itertools/itertools/issues/643">#643</a></li>
<li><a
href="8184e4c3f6"><code>8184e4c</code></a>
Merge <a
href="https://redirect.github.com/rust-itertools/itertools/issues/644">#644</a></li>
<li><a
href="ae31559af5"><code>ae31559</code></a>
<code>MergeJoinBy</code> also accept functions returning
<code>bool</code></li>
<li><a
href="8bc377efe4"><code>8bc377e</code></a>
Merge <a
href="https://redirect.github.com/rust-itertools/itertools/issues/629">#629</a></li>
<li>Additional commits viewable in <a
href="https://github.com/rust-itertools/itertools/compare/v0.10.5...v0.11.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=itertools&package-manager=cargo&previous-version=0.10.5&new-version=0.11.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Gabi <gabrielalejandro7@gmail.com>
2023-07-24 18:56:13 +00:00
Francesca Lovebloom
e5e18e78a3 connlib: Disconnect on fatal error (#1801)
Resolves firezone/product#619

This additionally removes `ErrorType`:
- `on_error` is now exclusively used for recoverable errors, and no
longer has an `error_type` parameter.
- `on_disconnect` now has an optional `error` parameter, which specifies
the fatal error that caused the disconnect if relevant.
2023-07-19 22:36:06 +00:00
Francesca Lovebloom
e413e96ccb connlib: Refine callbacks (#1776)
This follows-up on the discussion in #1744 and brings connlib in line
with the callback revisions outlined in firezone/product#586

(It also adds some logging to the Apple bridge that was helpful when
testing this)

---------

Co-authored-by: Roopesh Chander <roop@roopc.net>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2023-07-17 18:26:46 +00:00
Francesca Lovebloom
58c2ce5e80 connlib: Hook up callbacks (#1744)
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2023-07-11 19:40:35 +00:00
Gabi
b70124f090 headless & gateway: impl callbacks (#1757)
After rebasing over this #1744 CI should pass
2023-07-11 18:17:33 +00:00
Gabi
45c921b69e Feat/expire peers (#1739)
This PR takes care of expiring connections with peer from the gateway
side.

---------

Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2023-07-10 22:28:32 +00:00
Gabi
c817473aef Feat/connlib handle error messages (#1735)
With this PR we handle in the client an error message due to
gateway/relay although rate limiting is needed.

Waiting for #1729 to be merged.
2023-07-06 18:47:01 +00:00
Gabi
eb5fc34f35 CI: add a flow that test client to resource ping (#1729)
This PR fixes a bunch of small things to allow a new flow to test
clients pinging a resource within docker compose.

Masquerade/Forwarding is enabled directly in the container for now, this
might change in the future.

Also added a README to be able to run this locally.

---------

Signed-off-by: Gabi <gabrielalejandro7@gmail.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2023-07-05 03:17:26 +00:00
Gabi
8967b53170 Feat/connlib full flow (#1722)
With this PR the full control-plane message flow is working.

Meaning that if you do:

```
docker compose up -d
docker compose exec -it client "ping 172.20.0.2" # will fix this IP later
```

Messages start flowing to gateway. The gateway still not correctly
forwards the messages to the resource since masquerading is still not
working, although I suspect there might be an additional problem. Will
fix this in my next PR along with a README on how to test this whole
flow.

This PR also fixes how we sent the stamp secret to the gateway from the
relay, but I still see some warnings in the webrtc that I'm sure that
are due to a mismatch between how webrtc-rs and the relay handle
messages (The most important being `bind() failed: unexpected response
type`), I will take a look at that and a way to test that the flow works
when:
1. hole-punching is available
2. through relay when it's not
Since the flow right now works without hole-punching or relay since the
gateway is in the same network in the docker compose.
2023-07-03 19:25:37 +00:00
Francesca Lovebloom
d0a8333976 connlib: Connection mock (#1721)
Resolves firezone/product#607

Setting the env var `CONNLIB_MOCK` when building through either
`build-rust.sh` or `gradle` will activate the `mock` feature.
2023-07-03 18:48:55 +00:00
Thomas Eizinger
9deae3653a chore: unify and optimize Rust CI (#1710)
- Instead of having two, very similar jobs, we run our fmt, clippy and
tests steps across all crates and operating systems.
- We remove the dependency of the android and apple builds on the tests
and thus get faster feedback.
- We force clippy to fail on any warning. This one is super important
IMO. Warnings in Rust are very useful and ignoring them can lead to bugs
(think "unused Result" etc).

Resolves #1714.

---------

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Francesca Lovebloom <franlovebloom@gmail.com>
2023-06-29 23:33:02 +00:00
Thomas Eizinger
1882b58bc4 fix(connlib): format with cargo fmt (#1709)
Runs `cargo fmt` on the entire `rust/` directory. This somehow doesn't
seem to be enforced, I think that is because we changed the previous CI
to now only run for the `relay` crate.

I'd like to merge this first to avoid the diff and in a 2nd PR, we can
work on unifying CI again.
2023-06-28 21:33:06 +00:00
Gabi
720b2f8cd9 Fix/docker compose up (#1705)
This PR fixes `docker compose up` but it doesn't have the test client ->
resource flow working but it prevent anything from erroring at startup.

This fixes:
* tokens (use the correct token for the client user agent we are using)
* randomize `name_suffix` at start up for connlib (we will eventually
allow options to set it manually)
* remove port ranges for relay (see firezone/product#613)
2023-06-28 18:48:33 +00:00
Francesca Lovebloom
a4810986c7 connlib: Improve FFI bridges for Apple and Android (#1691)
This makes it possible to build the Apple/Android FFI bridges and
integrate them with their respective client apps.

---------

Signed-off-by: Francesca Lovebloom <franlovebloom@gmail.com>
Co-authored-by: Roopesh Chander <roop@roopc.net>
2023-06-28 11:29:59 -06:00
Gabi
e9be4b9ef5 connlib: moves it to the main firezone library
This brindgs connlib from its own separated repo to firezone's monorepo.
    
 On top of bringing connlib we also add and unify the Dockerfile for all
 rust binaries and add a docker-compose that can run a headless client, a
 relay and a gateway which eventually will test the whole flow between a
 client and a resource. For this to work we also incorporated some elixir
 scripts to generate portal tokens for those components.
2023-06-23 16:39:58 -06:00