2020-10-08 10:12:26 +00:00
|
|
|
package connection
|
|
|
|
|
|
|
|
import (
|
2021-01-15 17:25:56 +00:00
|
|
|
"fmt"
|
2020-10-08 10:12:26 +00:00
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
2020-10-23 14:49:24 +00:00
|
|
|
"strings"
|
2020-10-08 10:12:26 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
)
|
|
|
|
|
2020-12-28 18:10:01 +00:00
|
|
|
const LogFieldConnIndex = "connIndex"
|
2020-10-08 10:12:26 +00:00
|
|
|
|
|
|
|
type Config struct {
|
2020-12-09 21:46:53 +00:00
|
|
|
OriginProxy OriginProxy
|
2020-10-08 10:12:26 +00:00
|
|
|
GracePeriod time.Duration
|
|
|
|
ReplaceExisting bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type NamedTunnelConfig struct {
|
2020-11-23 21:36:16 +00:00
|
|
|
Credentials Credentials
|
|
|
|
Client pogs.ClientInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
// Credentials are stored in the credentials file and contain all info needed to run a tunnel.
|
|
|
|
type Credentials struct {
|
|
|
|
AccountTag string
|
|
|
|
TunnelSecret []byte
|
|
|
|
TunnelID uuid.UUID
|
|
|
|
TunnelName string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Credentials) Auth() pogs.TunnelAuth {
|
|
|
|
return pogs.TunnelAuth{
|
|
|
|
AccountTag: c.AccountTag,
|
|
|
|
TunnelSecret: c.TunnelSecret,
|
|
|
|
}
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ClassicTunnelConfig struct {
|
|
|
|
Hostname string
|
|
|
|
OriginCert []byte
|
|
|
|
// feature-flag to use new edge reconnect tokens
|
|
|
|
UseReconnectToken bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ClassicTunnelConfig) IsTrialZone() bool {
|
|
|
|
return c.Hostname == ""
|
|
|
|
}
|
|
|
|
|
2021-01-11 19:59:45 +00:00
|
|
|
// Type indicates the connection type of the connection.
|
|
|
|
type Type int
|
|
|
|
|
|
|
|
const (
|
|
|
|
TypeWebsocket Type = iota
|
|
|
|
TypeTCP
|
2021-01-15 17:25:56 +00:00
|
|
|
TypeControlStream
|
2021-01-11 19:59:45 +00:00
|
|
|
TypeHTTP
|
|
|
|
)
|
|
|
|
|
2021-01-15 17:25:56 +00:00
|
|
|
// ShouldFlush returns whether this kind of connection should actively flush data
|
|
|
|
func (t Type) shouldFlush() bool {
|
|
|
|
switch t {
|
|
|
|
case TypeWebsocket, TypeTCP, TypeControlStream:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t Type) String() string {
|
|
|
|
switch t {
|
|
|
|
case TypeWebsocket:
|
|
|
|
return "websocket"
|
|
|
|
case TypeTCP:
|
|
|
|
return "tcp"
|
|
|
|
case TypeControlStream:
|
|
|
|
return "control stream"
|
|
|
|
case TypeHTTP:
|
|
|
|
return "http"
|
|
|
|
default:
|
|
|
|
return fmt.Sprintf("Unknown Type %d", t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-09 21:46:53 +00:00
|
|
|
type OriginProxy interface {
|
2021-02-05 13:01:53 +00:00
|
|
|
// If Proxy returns an error, the caller is responsible for writing the error status to ResponseWriter
|
2021-01-11 19:59:45 +00:00
|
|
|
Proxy(w ResponseWriter, req *http.Request, sourceConnectionType Type) error
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ResponseWriter interface {
|
2020-12-09 21:46:53 +00:00
|
|
|
WriteRespHeaders(status int, header http.Header) error
|
2020-10-27 22:27:15 +00:00
|
|
|
WriteErrorResponse()
|
2020-10-08 10:12:26 +00:00
|
|
|
io.ReadWriter
|
|
|
|
}
|
|
|
|
|
|
|
|
type ConnectedFuse interface {
|
|
|
|
Connected()
|
|
|
|
IsConnected() bool
|
|
|
|
}
|
|
|
|
|
2020-11-18 11:53:59 +00:00
|
|
|
func IsServerSentEvent(headers http.Header) bool {
|
|
|
|
if contentType := headers.Get("content-type"); contentType != "" {
|
|
|
|
return strings.HasPrefix(strings.ToLower(contentType), "text/event-stream")
|
|
|
|
}
|
|
|
|
return false
|
2020-10-08 10:12:26 +00:00
|
|
|
}
|
2020-10-23 14:49:24 +00:00
|
|
|
|
2020-11-18 11:53:59 +00:00
|
|
|
func uint8ToString(input uint8) string {
|
|
|
|
return strconv.FormatUint(uint64(input), 10)
|
2020-10-23 14:49:24 +00:00
|
|
|
}
|