This change adds two new connection failure events for snowflake
proxies. One fires when the datachannel times out and another fires when
the connection to the proxy goes stale.
The race condition occurs because concurrent goroutines are intermixing
reads and writes of `WebRTCPeer.closed`.
Spotted when integrating Snowflake inside OONI in
https://github.com/ooni/probe-cli/pull/373.
The race condition occurs because concurrent goroutines are
intermixing reads and writes of `WebRTCPeer.lastReceive`.
Spotted when integrating Snowflake inside OONI in
https://github.com/ooni/probe-cli/pull/373.
This update required two main changes to how we use the library. First,
we had to make sure we created the datachannel on the offering peer side
before creating the offer. Second, we had to make sure we wait for the
gathering of all candidates to complete since trickle-ice is enabled by
default. See the release notes for more details:
https://github.com/pion/webrtc/wiki/Release-WebRTC@v3.0.0.
Instead of continuously polling the broker until the client receives a
snowflake, fail back to the Connect() loop and try again to collect more
peers after ReconnectTimeout.
It was sticking out in the context of other log messages.
2020/04/30 22:39:10 WebRTC: DataChannel created.
2020/04/30 22:39:20 establishDataChannel: timeout waiting for DataChannel.OnOpen
2020/04/30 22:39:20 WebRTC: closing PeerConnection
2020/04/30 22:39:20 WebRTC: Closing
2020/04/30 22:39:20 WebRTC: WebRTC: Could not establish DataChannel Retrying in 10s...
Now callers cannot call Write without there being a DataChannel to write
to. This lets us remove the internal buffer and checks for transport ==
nil.
Don't set internal fields like writePipe, transport, and pc to nil when
closing; just close them and let them return errors if further calls are
made on them.
There's now a constant DataChannelTimeout that's separate from
SnowflakeTimeout (the latter is what checkForStaleness uses). Now we can
set DataChannel timeout to a lower value, to quickly dispose of
unconnectable proxies, while still keeping the threshold for detecting
the failure of a once-working proxy at 30 seconds.
https://bugs.torproject.org/33897
Formerly, preparePeerConnection set up a callback that sent into a
channel, and exchangeSDP waited until it could receive from the channel.
We can move the channel entirely into preparePeerConnection (having it
not return until the callback has been called) and that way remove some
shared state.
Do it as a side effect of NewWebRTCPeer.
Remove WebRTCPeer tests as they currently require invasively modifying
internal fields at different stages of construction.
The other interfaces in client/lib/interfaces.go exist for the purpose
of running tests, but not Snowflake. Existing code would not have worked
with other types anyway, because it does unchecked .(*WebRTCPeer)
conversions.
A short write will result in a non-nil error. It's an io.PipeWriter
anyway, which blocks until all the data has been read or the read end is
closed, in which case it returns io.ErrClosedPipe if not some other
error.
- Error strings are no longer capitalized nor end with punctuation
- Alias import
- Remove extraneous initilisation code (No need to provide zero value
for variables, because the compiler does that anyway)
We need to set up the pion/webrtc logger to write output to the
snowflake log, otherwise the warnings we are getting from the pion
library are being lost.
Note: this requires go version 1.13 and later in order to use the
`log.Writer()` function.
Modified the snowflake client to use pion/webrtc as the webrtc library.
This involved a few small changes to match function signatures as well
as several larger ones:
- OnNegotiationNeeded is no longer supported, so CreateOffer and
SetLocalDescription have been moved to a go routine called after the
other peer connection callbacks are set
- We need our own deserialize/serialize functions
- We need to use a SettingEngine in order to access the
OnICEGatheringStateChange callback