Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
🏗️ Architecture
# 🏗️ Architecture

This document provides a high-level overview of the components that make up Dino and how they interact to provide dynamic routing and tunneling.

📐 System Diagram
# 📐 System Diagram

![Diagram](assets/architecture.png)

⌨️ CLI (Command Line Interface)
# ⌨️ CLI (Command Line Interface)

The Dino CLI is a statically linked Go binary that acts as the primary administrative tool. It communicates with the Server via gRPC to:

Provision and de-provision tunnels.\
Configure hostname-to-service routing rules.\
Monitor real-time tunnel health and throughput metrics.

🔌 API (Server)
# 🔌 API (Server)

The core of Dino is a high-performance H2C (HTTP/2 Cleartext) server. It serves as the single point of truth for the system state.

Dependency Injection: Built using uber-go/fx for a modular, testable lifecycle.\
Persistence: Manages the state of routes and tunnels (via the Service layer you saw in the code).\
Protocols: Uses gRPC for type-safe, low-latency communication between the CLI and the backend.

󰔚 Tunnel Management
# 󰔚 Tunnel Management

Tunnel Management handles the "Physical" layer of the connection. It abstracts the complexity of different network interfaces into a unified logical tunnel_id.

Isolation: Ensures that traffic arriving on one tunnel cannot "hop" to another unless explicitly routed.\
Lifecycle: Manages the handshake, keep-alives, and clean teardown of network pipes.\
Abstraction: Provides a common interface for Dino to interact with local TUN/TAP devices or remote overlay peers.

󰄱 Proxy (Data Plane)
# 󰄱 Proxy (Data Plane)

The Proxy is the engine that moves bits. It is responsible for the actual "forwarding" decision based on the configuration received from the API.

Expand Down
13 changes: 12 additions & 1 deletion docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@ servers and tunnels can be configured using environment variables. this page wil

`TUNNEL_ID` tunnel id\
`TUNNEL_TOKEN` tunnel token\
`TUNNEL_ENDPOINT` `tunnel.dino.local:4222` tunnel endpoint
`TUNNEL_ENDPOINT` `tunnel.dino.local:4222` tunnel endpoint

## Proxy

`http` proxy configuration

`PROXY_HOST` `127.0.0.1` http server host\
`PROXY_PORT` `8080` http server port\
`PROXY_TIMEOUT` `15` max duration to read entire request (seconds)\
`PROXY_READ_HEADER_TIMEOUT` `15` duration to read request headers (seconds)\
`PROXY_WRITE_TIMEOUT` `15` max duration to write response\
`PROXY_IDLE_TIMEOUT` `30` duration to wait for next request when keepalive is enabled
40 changes: 26 additions & 14 deletions gateway/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"net"
"net/http"
"strings"
"time"

"go.uber.org/fx"
Expand Down Expand Up @@ -61,7 +60,8 @@ type Params struct {

Logger *zap.Logger

Cfg *setup.Server
ServerConfig *setup.Server
ProxyConfig *setup.Proxy

Proxy http.Handler

Expand All @@ -76,7 +76,7 @@ var Module = fx.Module("gateway", fx.Invoke(invokeModule))

func invokeModule(p Params) error {

hostAndPort := net.JoinHostPort(p.Cfg.Host, p.Cfg.Port)
hostAndPort := net.JoinHostPort(p.ServerConfig.Host, p.ServerConfig.Port)

p.Logger.Info("num transports", zap.Int("len", len(p.Transports)))

Expand All @@ -94,17 +94,17 @@ func invokeModule(p Params) error {
mux := http.NewServeMux()
mux.HandleFunc("/", p.Proxy.ServeHTTP)

combinedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("received request")
if r.ProtoMajor == 2 && strings.HasPrefix(r.Header.Get("content-type"), "application/grpc") {
gs.ServeHTTP(w, r)
return
}

mux.ServeHTTP(w, r)
})
proxyAddr := net.JoinHostPort(p.ProxyConfig.Host, p.ProxyConfig.Port)
h1 := &http.Server{
Addr: proxyAddr,
Handler: p.Proxy,
ReadTimeout: time.Second * p.ProxyConfig.ReadTimeout,
ReadHeaderTimeout: time.Second * p.ProxyConfig.ReadHeaderTimeout,
WriteTimeout: time.Second * p.ProxyConfig.WriteTimeout,
IdleTimeout: time.Second * p.ProxyConfig.IdleTimeout,
}

h2h := h2c.NewHandler(combinedHandler, &http2.Server{})
h2h := h2c.NewHandler(gs, &http2.Server{})

pr := new(http.Protocols)
pr.SetHTTP1(true)
Expand All @@ -118,6 +118,13 @@ func invokeModule(p Params) error {

p.Lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
p.Logger.Info("start http/1 proxy server", zap.String("server_addr", h1.Addr))
go func() {
if err := h1.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
p.Logger.Fatal("start http/1 proxy server", zap.Error(err))
}
}()

p.Logger.Info("start hls server", zap.String("server_addr", hls.Addr))
go func() {
if err := hls.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
Expand Down Expand Up @@ -145,9 +152,14 @@ func invokeModule(p Params) error {
OnStop: func(ctx context.Context) error {
var multiErr error

p.Logger.Info("shutdown http/1 proxy server")
if err := h1.Shutdown(ctx); err != nil {
multiErr = multierr.Append(multiErr, fmt.Errorf("h1.Shutdown: %w", err))
}

p.Logger.Info("shutdown hls server")
if err := hls.Shutdown(ctx); err != nil {
multiErr = multierr.Append(err, fmt.Errorf("hls.Shutdown: %w", err))
multiErr = multierr.Append(multiErr, fmt.Errorf("hls.Shutdown: %w", err))
}

p.Logger.Info("shutdown gRPC-QUIC server")
Expand Down
6 changes: 6 additions & 0 deletions setup/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package setup
import (
"context"
"strings"
"time"

"github.com/sethvargo/go-envconfig"
"go.uber.org/fx"
Expand Down Expand Up @@ -45,6 +46,11 @@ type Logger struct {
type Proxy struct {
Host string `env:"HOST, default=127.0.0.1"`
Port string `env:"PORT, default=8080"`

ReadTimeout time.Duration `env:"READ_TIMEOUT, default=15"`
ReadHeaderTimeout time.Duration `env:"READ_HEADER_TIMEOUT, default=15"`
WriteTimeout time.Duration `env:"WRITE_TIMEOUT, default=15"`
IdleTimeout time.Duration `env:"IDLE_TIMEOUT, default=30"`
}

// Server
Expand Down