Skip to content

Commit

Permalink
Add proxy service implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
fancycode committed Aug 13, 2020
1 parent 4446b07 commit b7c258b
Show file tree
Hide file tree
Showing 9 changed files with 1,506 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ bin/
vendor/

*_easyjson.go
*.pem
*.prof
*.socket
*.tar.gz

cover.out
proxy.conf
server.conf
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,14 @@ server: dependencies common
mkdir -p $(BINDIR)
GOPATH=$(GOPATH) $(GO) build $(BUILDARGS) -ldflags '$(INTERNALLDFLAGS)' -o $(BINDIR)/signaling ./src/server/...

proxy: dependencies common
mkdir -p $(BINDIR)
GOPATH=$(GOPATH) $(GO) build $(BUILDARGS) -ldflags '$(INTERNALLDFLAGS)' -o $(BINDIR)/proxy ./src/proxy/...

clean:
rm -f src/signaling/*_easyjson.go

build: server
build: server proxy

tarball:
git archive \
Expand Down
1 change: 1 addition & 0 deletions dependencies.tsv
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
github.com/dlintw/goconf git dcc070983490608a14480e3bf943bad464785df5 2012-02-28T08:26:10Z
github.com/google/uuid git 0e4e31197428a347842d152773b4cace4645ca25 2020-07-02T18:56:42Z
github.com/gorilla/context git 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 2016-08-17T18:46:32Z
github.com/gorilla/mux git ac112f7d75a0714af1bd86ab17749b31f7809640 2017-07-04T07:43:45Z
github.com/gorilla/securecookie git e59506cc896acb7f7bf732d4fdf5e25f7ccd8983 2017-02-24T19:38:04Z
Expand Down
55 changes: 55 additions & 0 deletions proxy.conf.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[http]
# IP and port to listen on for HTTP requests.
# Comment line to disable the listener.
#listen = 127.0.0.1:9090

[app]
# Set to "true" to install pprof debug handlers.
# See "https://golang.org/pkg/net/http/pprof/" for further information.
#debug = false

# ISO 3166 country this proxy is located at. This will be used by the signaling
# servers to determine the closest proxy for publishers.
#country = DE

[sessions]
# Secret value used to generate checksums of sessions. This should be a random
# string of 32 or 64 bytes.
hashkey = secret-for-session-checksums

# Optional key for encrypting data in the sessions. Must be either 16, 24 or
# 32 bytes.
# If no key is specified, data will not be encrypted (not recommended).
blockkey = -encryption-key-

[nats]
# Url of NATS backend to use. This can also be a list of URLs to connect to
# multiple backends. For local development, this can be set to ":loopback:"
# to process NATS messages internally instead of sending them through an
# external NATS backend.
#url = nats://localhost:4222

[tokens]
# Mapping of <tokenid> = <publickey> of signaling servers allowed to connect.
#server1 = pubkey1.pem
#server2 = pubkey2.pem

[mcu]
# The type of the MCU to use. Currently only "janus" is supported.
type = janus

# The URL to the websocket endpoint of the MCU server.
url = ws://localhost:8188/

# The maximum bitrate per publishing stream (in bits per second).
# Defaults to 1 mbit/sec.
#maxstreambitrate = 1048576

# The maximum bitrate per screensharing stream (in bits per second).
# Default is 2 mbit/sec.
#maxscreenbitrate = 2097152

[stats]
# Comma-separated list of IP addresses that are allowed to access the stats
# endpoint. Leave empty (or commented) to only allow access from "127.0.0.1".
#allowed_ips =
153 changes: 153 additions & 0 deletions src/proxy/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2020 struktur AG
*
* @author Joachim Bauch <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main

import (
"flag"
"fmt"
"log"
"net"
"net/http"
"os"
"os/signal"
"runtime"
"strings"
"syscall"
"time"

"github.com/dlintw/goconf"
"github.com/gorilla/mux"
"github.com/nats-io/go-nats"

"signaling"
)

var (
version = "unreleased"

configFlag = flag.String("config", "proxy.conf", "config file to use")

showVersion = flag.Bool("version", false, "show version and quit")
)

const (
defaultReadTimeout = 15
defaultWriteTimeout = 15

proxyDebugMessages = false
)

func main() {
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
flag.Parse()

if *showVersion {
fmt.Printf("nextcloud-spreed-signaling-proxy version %s/%s\n", version, runtime.Version())
os.Exit(0)
}

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
signal.Notify(sigChan, syscall.SIGHUP)

log.Printf("Starting up version %s/%s as pid %d", version, runtime.Version(), os.Getpid())

config, err := goconf.ReadConfigFile(*configFlag)
if err != nil {
log.Fatal("Could not read configuration: ", err)
}

cpus := runtime.NumCPU()
runtime.GOMAXPROCS(cpus)
log.Printf("Using a maximum of %d CPUs\n", cpus)

natsUrl, _ := config.GetString("nats", "url")
if natsUrl == "" {
natsUrl = nats.DefaultURL
}

nats, err := signaling.NewNatsClient(natsUrl)
if err != nil {
log.Fatal("Could not create NATS client: ", err)
}

r := mux.NewRouter()

proxy, err := NewProxyServer(r, version, config, nats)
if err != nil {
log.Fatal(err)
}

if err := proxy.Start(config); err != nil {
log.Fatal(err)
}
defer proxy.Stop()

if addr, _ := config.GetString("http", "listen"); addr != "" {
readTimeout, _ := config.GetInt("http", "readtimeout")
if readTimeout <= 0 {
readTimeout = defaultReadTimeout
}
writeTimeout, _ := config.GetInt("http", "writetimeout")
if writeTimeout <= 0 {
writeTimeout = defaultWriteTimeout
}

for _, address := range strings.Split(addr, " ") {
go func(address string) {
log.Println("Listening on", address)
listener, err := net.Listen("tcp", address)
if err != nil {
log.Fatal("Could not start listening: ", err)
}
srv := &http.Server{
Handler: r,
Addr: addr,

ReadTimeout: time.Duration(readTimeout) * time.Second,
WriteTimeout: time.Duration(writeTimeout) * time.Second,
}
if err := srv.Serve(listener); err != nil {
log.Fatal("Could not start server: ", err)
}
}(address)
}
}

loop:
for {
switch sig := <-sigChan; sig {
case os.Interrupt:
log.Println("Interrupted")
break loop
case syscall.SIGHUP:
log.Printf("Received SIGHUP, reloading %s", *configFlag)
config, err := goconf.ReadConfigFile(*configFlag)
if err != nil {
log.Printf("Could not read configuration from %s: %s", *configFlag, err)
continue
}

proxy.Reload(config)
}
}
}
55 changes: 55 additions & 0 deletions src/proxy/proxy_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2020 struktur AG
*
* @author Joachim Bauch <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main

import (
"sync/atomic"
"unsafe"

"github.com/gorilla/websocket"

"signaling"
)

type ProxyClient struct {
signaling.Client

proxy *ProxyServer

session unsafe.Pointer
}

func NewProxyClient(proxy *ProxyServer, conn *websocket.Conn, addr string) (*ProxyClient, error) {
client := &ProxyClient{
proxy: proxy,
}
client.SetConn(conn, addr)
return client, nil
}

func (c *ProxyClient) GetSession() *ProxySession {
return (*ProxySession)(atomic.LoadPointer(&c.session))
}

func (c *ProxyClient) SetSession(session *ProxySession) {
atomic.StorePointer(&c.session, unsafe.Pointer(session))
}
Loading

0 comments on commit b7c258b

Please sign in to comment.