summaryrefslogtreecommitdiff
path: root/src/lib.go
blob: 3733475243faae2254b7bcdf14c1af5698406a04 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package wscat

import (
	"fmt"
	"net"
	"net/http"
	"os"

	g "euandre.org/gobang/src"

	"github.com/gorilla/websocket"
)



type CLIArgs struct {
	FromAddr string
	ToAddr   string
}



const X = 1

var EmitActiveConnection = g.MakeGauge("active-connections")



func ParseArgs(args []string) CLIArgs {
	if len(args) != 3 {
		fmt.Fprintf(
			os.Stderr,
			"Usage: %s FROM.socket TO.socket\n",
			args[0],
		)
		os.Exit(2)
	}
	return CLIArgs {
		FromAddr: args[1],
		ToAddr:   args[2],
	}
}

func Listen(fromAddr string) net.Listener {
	listener, err := net.Listen("unix", fromAddr)
	g.FatalIf(err)
	g.Info("Started listening", "listen-start", "from-address", fromAddr)
	return listener
}

func Start(toAddr string, listener net.Listener) {
	upgrader := websocket.Upgrader {}
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		connFrom, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			g.Warning(
				"Error upgrading connection",
				"upgrade-connection-error",
				"err", err,
			)
			return
		}
		defer connFrom.Close()
		EmitActiveConnection.Inc()

		connTo, err := net.Dial("unix", toAddr)
		if err != nil {
			g.Error(
				"Error dialing connection",
				"dial-connection",
				"err", err,
			)
			os.Exit(1)
		}
		defer connTo.Close()

		messageType, reader, err := connFrom.NextReader()
		if err != nil {
			g.Warning(
				"Failed to get next reader from connection",
				"connection-next-reader-error",
				"err", err,
			)
			return
		}

		writer, err := connFrom.NextWriter(messageType)
		if err != nil {
			g.Warning(
				"Failed to get next reader from connection",
				"connection-next-reader-error",
				"err", err,
			)
			return
		}


		c := make(chan g.CopyResult)
		go g.CopyData(c, "c2s", connTo, writer)
		go g.CopyData(c, "s2c", reader, connTo)
		go func() {
			<- c
			EmitActiveConnection.Dec()
		}()
	});

	server := http.Server{}
	err := server.Serve(listener)
	g.FatalIf(err)
}


func Main() {
	g.Init()
	args := ParseArgs(os.Args)
	listener := Listen(args.FromAddr)
	Start(args.ToAddr, listener)
}