2020-10-08 10:12:26 +00:00
|
|
|
package connection
|
|
|
|
|
|
|
|
import (
|
2021-07-28 09:02:55 +00:00
|
|
|
"strings"
|
|
|
|
|
2020-11-25 06:55:13 +00:00
|
|
|
"github.com/rs/zerolog"
|
2020-10-08 10:12:26 +00:00
|
|
|
)
|
|
|
|
|
2021-01-14 22:33:36 +00:00
|
|
|
const (
|
|
|
|
LogFieldLocation = "location"
|
|
|
|
observerChannelBufferSize = 16
|
|
|
|
)
|
2020-12-28 18:10:01 +00:00
|
|
|
|
2020-10-08 10:12:26 +00:00
|
|
|
type Observer struct {
|
2021-01-14 22:33:36 +00:00
|
|
|
log *zerolog.Logger
|
2021-02-03 18:32:54 +00:00
|
|
|
logTransport *zerolog.Logger
|
2021-01-14 22:33:36 +00:00
|
|
|
metrics *tunnelMetrics
|
|
|
|
tunnelEventChan chan Event
|
|
|
|
uiEnabled bool
|
|
|
|
addSinkChan chan EventSink
|
|
|
|
}
|
|
|
|
|
|
|
|
type EventSink interface {
|
|
|
|
OnTunnelEvent(event Event)
|
|
|
|
}
|
|
|
|
|
2021-02-03 18:32:54 +00:00
|
|
|
func NewObserver(log, logTransport *zerolog.Logger, uiEnabled bool) *Observer {
|
2021-01-14 22:33:36 +00:00
|
|
|
o := &Observer{
|
|
|
|
log: log,
|
2021-02-03 18:32:54 +00:00
|
|
|
logTransport: logTransport,
|
2021-01-14 22:33:36 +00:00
|
|
|
metrics: newTunnelMetrics(),
|
|
|
|
uiEnabled: uiEnabled,
|
|
|
|
tunnelEventChan: make(chan Event, observerChannelBufferSize),
|
|
|
|
addSinkChan: make(chan EventSink, observerChannelBufferSize),
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
2021-01-14 22:33:36 +00:00
|
|
|
go o.dispatchEvents()
|
|
|
|
return o
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *Observer) RegisterSink(sink EventSink) {
|
|
|
|
o.addSinkChan <- sink
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
|
2020-11-09 11:40:48 +00:00
|
|
|
func (o *Observer) logServerInfo(connIndex uint8, location, msg string) {
|
2020-11-30 20:05:37 +00:00
|
|
|
o.sendEvent(Event{Index: connIndex, EventType: Connected, Location: location})
|
2020-12-28 18:10:01 +00:00
|
|
|
o.log.Info().
|
|
|
|
Uint8(LogFieldConnIndex, connIndex).
|
|
|
|
Str(LogFieldLocation, location).
|
|
|
|
Msg(msg)
|
2020-11-09 11:40:48 +00:00
|
|
|
o.metrics.registerServerLocation(uint8ToString(connIndex), location)
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
|
2021-01-19 12:20:11 +00:00
|
|
|
func (o *Observer) sendRegisteringEvent(connIndex uint8) {
|
|
|
|
o.sendEvent(Event{Index: connIndex, EventType: RegisteringTunnel})
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (o *Observer) sendConnectedEvent(connIndex uint8, location string) {
|
2020-11-30 20:05:37 +00:00
|
|
|
o.sendEvent(Event{Index: connIndex, EventType: Connected, Location: location})
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
|
2021-07-09 17:52:41 +00:00
|
|
|
func (o *Observer) SendURL(url string) {
|
2020-11-30 20:05:37 +00:00
|
|
|
o.sendEvent(Event{EventType: SetURL, URL: url})
|
2021-07-28 08:27:05 +00:00
|
|
|
|
|
|
|
if !strings.HasPrefix(url, "https://") {
|
|
|
|
// We add https:// in the prefix for backwards compatibility as we used to do that with the old free tunnels
|
|
|
|
// and some tools (like `wrangler tail`) are regexp-ing for that specifically.
|
|
|
|
url = "https://" + url
|
|
|
|
}
|
|
|
|
o.metrics.userHostnamesCounts.WithLabelValues(url).Inc()
|
2020-11-30 20:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (o *Observer) SendReconnect(connIndex uint8) {
|
|
|
|
o.sendEvent(Event{Index: connIndex, EventType: Reconnecting})
|
|
|
|
}
|
|
|
|
|
2021-02-04 21:09:17 +00:00
|
|
|
func (o *Observer) sendUnregisteringEvent(connIndex uint8) {
|
|
|
|
o.sendEvent(Event{Index: connIndex, EventType: Unregistering})
|
|
|
|
}
|
|
|
|
|
2020-11-30 20:05:37 +00:00
|
|
|
func (o *Observer) SendDisconnect(connIndex uint8) {
|
|
|
|
o.sendEvent(Event{Index: connIndex, EventType: Disconnected})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *Observer) sendEvent(e Event) {
|
2021-01-14 22:33:36 +00:00
|
|
|
select {
|
|
|
|
case o.tunnelEventChan <- e:
|
|
|
|
break
|
|
|
|
default:
|
|
|
|
o.log.Warn().Msg("observer channel buffer is full")
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-14 22:33:36 +00:00
|
|
|
|
|
|
|
func (o *Observer) dispatchEvents() {
|
|
|
|
var sinks []EventSink
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case sink := <-o.addSinkChan:
|
|
|
|
sinks = append(sinks, sink)
|
|
|
|
case evt := <-o.tunnelEventChan:
|
|
|
|
for _, sink := range sinks {
|
|
|
|
sink.OnTunnelEvent(evt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type EventSinkFunc func(event Event)
|
|
|
|
|
|
|
|
func (f EventSinkFunc) OnTunnelEvent(event Event) {
|
|
|
|
f(event)
|
|
|
|
}
|