2017-02-25 05:56:40 +00:00
|
|
|
package genericlistener
|
|
|
|
|
|
|
|
import (
|
2017-02-26 05:17:39 +00:00
|
|
|
"bytes"
|
|
|
|
"context"
|
2017-02-25 05:56:40 +00:00
|
|
|
"crypto/tls"
|
2017-02-26 05:17:39 +00:00
|
|
|
"encoding/hex"
|
2017-02-26 23:27:38 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2017-02-26 05:17:39 +00:00
|
|
|
"log"
|
|
|
|
"net"
|
2017-02-26 23:27:38 +00:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2017-02-26 05:17:39 +00:00
|
|
|
"time"
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
jwt "github.com/dgrijalva/jwt-go"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"github.com/gorilla/websocket"
|
|
|
|
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"bufio"
|
|
|
|
|
2017-02-26 23:27:38 +00:00
|
|
|
"git.daplie.com/Daplie/go-rvpn-server/rvpn/packer"
|
2017-02-25 05:56:40 +00:00
|
|
|
)
|
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
type contextKey string
|
|
|
|
|
2017-03-03 00:47:59 +00:00
|
|
|
//CtxConnectionTrack
|
2017-02-26 18:35:06 +00:00
|
|
|
const (
|
2017-02-26 23:27:38 +00:00
|
|
|
ctxSecretKey contextKey = "secretKey"
|
|
|
|
ctxConnectionTable contextKey = "connectionTable"
|
|
|
|
ctxConfig contextKey = "config"
|
|
|
|
ctxDeadTime contextKey = "deadtime"
|
|
|
|
ctxListenerRegistration contextKey = "listenerRegistration"
|
2017-03-03 00:47:59 +00:00
|
|
|
ctxConnectionTrack contextKey = "connectionTrack"
|
2017-03-11 05:36:42 +00:00
|
|
|
ctxWssHostName contextKey = "wsshostname"
|
2017-02-26 18:35:06 +00:00
|
|
|
)
|
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
const (
|
|
|
|
encryptNone int = iota
|
|
|
|
encryptSSLV2
|
|
|
|
encryptSSLV3
|
|
|
|
encryptTLS10
|
|
|
|
encryptTLS11
|
|
|
|
encryptTLS12
|
|
|
|
)
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
//GenericListenAndServe -- used to lisen for any https traffic on 443 (8443)
|
|
|
|
// - setup generic TCP listener, unencrypted TCP, with a Deadtime out
|
|
|
|
// - leaverage the wedgeConn to peek into the buffer.
|
|
|
|
// - if TLS, consume connection with TLS certbundle, pass to request identifier
|
|
|
|
// - else, just pass to the request identififer
|
2017-02-26 23:27:38 +00:00
|
|
|
func GenericListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) {
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 23:27:38 +00:00
|
|
|
loginfo.Println(":" + string(listenerRegistration.port))
|
|
|
|
|
|
|
|
listenAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(listenerRegistration.port))
|
|
|
|
deadTime := ctx.Value(ctxDeadTime).(int)
|
2017-02-26 18:35:06 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
if nil != err {
|
|
|
|
loginfo.Println(err)
|
2017-02-25 05:56:40 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
ln, err := net.ListenTCP("tcp", listenAddr)
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("unable to bind", err)
|
2017-02-26 23:27:38 +00:00
|
|
|
listenerRegistration.status = listenerFault
|
|
|
|
listenerRegistration.err = err
|
|
|
|
listenerRegistration.commCh <- listenerRegistration
|
2017-02-26 05:17:39 +00:00
|
|
|
return
|
|
|
|
}
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 23:27:38 +00:00
|
|
|
listenerRegistration.status = listenerAdded
|
|
|
|
listenerRegistration.commCh <- listenerRegistration
|
|
|
|
|
2017-02-25 05:56:40 +00:00
|
|
|
for {
|
2017-02-26 05:17:39 +00:00
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
loginfo.Println("Cancel signal hit")
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
ln.SetDeadline(time.Now().Add(time.Duration(deadTime) * time.Second))
|
|
|
|
|
|
|
|
conn, err := ln.Accept()
|
|
|
|
|
|
|
|
loginfo.Println("Deadtime reached")
|
|
|
|
|
|
|
|
if nil != err {
|
|
|
|
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
wedgeConn := NewWedgeConn(conn)
|
2017-02-26 18:35:06 +00:00
|
|
|
go handleConnection(ctx, wedgeConn)
|
2017-02-25 05:56:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
//handleConnection -
|
|
|
|
// - accept a wedgeConnection along with all the other required attritvues
|
|
|
|
// - peek into the buffer, determine TLS or unencrypted
|
2017-02-26 18:35:06 +00:00
|
|
|
// - if TSL, then terminate with a TLS endpoint, pass to handleStream
|
|
|
|
// - if clearText, pass to handleStream
|
|
|
|
func handleConnection(ctx context.Context, wConn *WedgeConn) {
|
2017-02-26 05:17:39 +00:00
|
|
|
defer wConn.Close()
|
|
|
|
peekCnt := 10
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
encryptMode := encryptNone
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
loginfo.Println("conn", wConn, wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
|
|
|
peek, err := wConn.Peek(peekCnt)
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("error while peeking")
|
|
|
|
return
|
|
|
|
}
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
//take a look for a TLS header.
|
|
|
|
if bytes.Contains(peek[0:0], []byte{0x80}) && bytes.Contains(peek[2:4], []byte{0x01, 0x03}) {
|
|
|
|
encryptMode = encryptSSLV2
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x00}) {
|
|
|
|
encryptMode = encryptSSLV3
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x01}) {
|
|
|
|
encryptMode = encryptTLS10
|
|
|
|
loginfo.Println("TLS10")
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x02}) {
|
|
|
|
encryptMode = encryptTLS11
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
} else if bytes.Contains(peek[0:3], []byte{0x16, 0x03, 0x03}) {
|
|
|
|
encryptMode = encryptTLS12
|
|
|
|
}
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
oneConn := &oneConnListener{wConn}
|
2017-02-26 18:35:06 +00:00
|
|
|
config := ctx.Value(ctxConfig).(*tls.Config)
|
2017-02-25 05:56:40 +00:00
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
if encryptMode == encryptSSLV2 {
|
|
|
|
loginfo.Println("SSLv2 is not accepted")
|
|
|
|
return
|
|
|
|
|
|
|
|
} else if encryptMode != encryptNone {
|
|
|
|
loginfo.Println("Handle Encryption")
|
2017-03-11 05:36:42 +00:00
|
|
|
|
|
|
|
// check SNI heading
|
|
|
|
// if matched, then looks like a WSS connection
|
|
|
|
// else external don't pull off TLS.
|
|
|
|
|
|
|
|
peek, err := wConn.PeekAll()
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("error while peeking")
|
|
|
|
loginfo.Println(hex.Dump(peek[0:]))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
wssHostName := ctx.Value(ctxWssHostName).(string)
|
|
|
|
sniHostName, err := getHello(peek)
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
loginfo.Println("sni:", sniHostName)
|
|
|
|
|
|
|
|
if wssHostName != sniHostName {
|
|
|
|
//traffic not terminating on the rvpn do not decrypt
|
|
|
|
loginfo.Println("processing non terminating traffic")
|
|
|
|
handleExternalHTTPRequest(ctx, wConn, sniHostName)
|
|
|
|
}
|
|
|
|
|
|
|
|
loginfo.Println("processing traffic terminating on RVPN")
|
|
|
|
|
2017-02-26 05:17:39 +00:00
|
|
|
tlsListener := tls.NewListener(oneConn, config)
|
|
|
|
|
|
|
|
conn, err := tlsListener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println(err)
|
|
|
|
return
|
|
|
|
}
|
2017-02-26 18:35:06 +00:00
|
|
|
|
|
|
|
tlsWedgeConn := NewWedgeConn(conn)
|
|
|
|
handleStream(ctx, tlsWedgeConn)
|
2017-02-26 05:17:39 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
loginfo.Println("Handle Unencrypted")
|
2017-02-26 18:35:06 +00:00
|
|
|
handleStream(ctx, wConn)
|
2017-02-25 05:56:40 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2017-02-26 05:17:39 +00:00
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
//handleStream --
|
|
|
|
// - we have an unencrypted stream connection with the ability to peek
|
|
|
|
// - attempt to identify HTTP
|
|
|
|
// - handle http
|
|
|
|
// - attempt to identify as WSS session
|
|
|
|
// - attempt to identify as ADMIN/API session
|
2017-03-02 03:02:20 +00:00
|
|
|
// - else handle as raw http
|
2017-02-26 18:35:06 +00:00
|
|
|
// - handle other?
|
|
|
|
func handleStream(ctx context.Context, wConn *WedgeConn) {
|
|
|
|
loginfo.Println("handle Stream")
|
2017-03-11 05:36:42 +00:00
|
|
|
loginfo.Println("conn", wConn.LocalAddr().String(), wConn.RemoteAddr().String())
|
2017-02-26 18:35:06 +00:00
|
|
|
|
2017-02-26 18:40:10 +00:00
|
|
|
peek, err := wConn.PeekAll()
|
2017-02-26 05:17:39 +00:00
|
|
|
if err != nil {
|
2017-03-11 05:36:42 +00:00
|
|
|
loginfo.Println("error while peeking", err)
|
2017-02-26 18:35:06 +00:00
|
|
|
loginfo.Println(hex.Dump(peek[0:]))
|
2017-02-26 05:17:39 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
// HTTP Identifcation
|
|
|
|
if bytes.Contains(peek[:], []byte{0x0d, 0x0a}) {
|
|
|
|
//string protocol
|
|
|
|
if bytes.ContainsAny(peek[:], "HTTP/") {
|
|
|
|
loginfo.Println("identifed HTTP")
|
|
|
|
|
|
|
|
r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(peek)))
|
|
|
|
if err != nil {
|
2017-03-02 03:02:20 +00:00
|
|
|
loginfo.Println("identifed as HTTP, failed request parsing", err)
|
2017-02-26 18:35:06 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-26 23:27:38 +00:00
|
|
|
// do we have a valid wss_client?
|
2017-02-26 18:35:06 +00:00
|
|
|
secretKey := ctx.Value(ctxSecretKey).(string)
|
|
|
|
tokenString := r.URL.Query().Get("access_token")
|
|
|
|
result, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
|
|
|
return []byte(secretKey), nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err == nil && result.Valid {
|
|
|
|
loginfo.Println("Valid WSS dected...sending to handler")
|
|
|
|
oneConn := &oneConnListener{wConn}
|
|
|
|
handleWssClient(ctx, oneConn)
|
2017-02-26 23:27:38 +00:00
|
|
|
|
|
|
|
//do we have a invalid domain indicating Admin?
|
|
|
|
//if yes, prep the oneConn and send it to the handler
|
|
|
|
} else if strings.Contains(r.Host, "rvpn.daplie.invalid") {
|
|
|
|
loginfo.Println("admin")
|
|
|
|
oneConn := &oneConnListener{wConn}
|
|
|
|
handleAdminClient(ctx, oneConn)
|
|
|
|
return
|
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
} else {
|
2017-03-11 05:36:42 +00:00
|
|
|
loginfo.Println("unsupported")
|
|
|
|
loginfo.Println(hex.Dump(peek))
|
2017-02-26 23:27:38 +00:00
|
|
|
return
|
2017-02-26 18:35:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-02-26 05:17:39 +00:00
|
|
|
}
|
|
|
|
|
2017-02-26 23:27:38 +00:00
|
|
|
//handleExternalHTTPRequest -
|
|
|
|
// - get a wConn and start processing requests
|
2017-03-11 05:36:42 +00:00
|
|
|
func handleExternalHTTPRequest(ctx context.Context, extConn net.Conn, hostname string) {
|
2017-03-03 00:47:59 +00:00
|
|
|
connectionTracking := ctx.Value(ctxConnectionTrack).(*Tracking)
|
2017-02-26 23:27:38 +00:00
|
|
|
|
2017-03-03 00:47:59 +00:00
|
|
|
defer func() {
|
2017-03-04 18:18:08 +00:00
|
|
|
connectionTracking.unregister <- extConn
|
|
|
|
extConn.Close()
|
2017-03-03 00:47:59 +00:00
|
|
|
}()
|
2017-02-26 23:27:38 +00:00
|
|
|
|
2017-03-03 00:47:59 +00:00
|
|
|
connectionTable := ctx.Value(ctxConnectionTable).(*Table)
|
2017-03-11 05:36:42 +00:00
|
|
|
//find the connection by domain name
|
|
|
|
conn, ok := connectionTable.ConnByDomain(hostname)
|
|
|
|
if !ok {
|
|
|
|
//matching connection can not be found based on ConnByDomain
|
|
|
|
loginfo.Println("unable to match ", hostname, " to an existing connection")
|
|
|
|
//http.Error(, "Domain not supported", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
track := NewTrack(extConn, hostname)
|
|
|
|
connectionTracking.register <- track
|
|
|
|
|
|
|
|
loginfo.Println("Domain Accepted", hostname, extConn.RemoteAddr().String())
|
|
|
|
|
|
|
|
rAddr, rPort, err := net.SplitHostPort(extConn.RemoteAddr().String())
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("unable to decode hostport", extConn.RemoteAddr().String())
|
|
|
|
return
|
|
|
|
}
|
2017-02-26 23:27:38 +00:00
|
|
|
|
2017-03-03 00:47:59 +00:00
|
|
|
var buffer [512]byte
|
2017-02-26 23:27:38 +00:00
|
|
|
for {
|
2017-03-04 18:18:08 +00:00
|
|
|
cnt, err := extConn.Read(buffer[0:])
|
2017-02-26 23:27:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-03-02 03:02:20 +00:00
|
|
|
p := packer.NewPacker()
|
|
|
|
p.Header.SetAddress(rAddr)
|
|
|
|
p.Header.Port, err = strconv.Atoi(rPort)
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("Unable to set Remote port", err)
|
|
|
|
return
|
|
|
|
}
|
2017-02-26 23:27:38 +00:00
|
|
|
|
2017-03-02 03:02:20 +00:00
|
|
|
p.Header.Service = "http"
|
|
|
|
p.Data.AppendBytes(buffer[0:cnt])
|
|
|
|
buf := p.PackV1()
|
2017-02-26 23:27:38 +00:00
|
|
|
|
2017-03-11 05:36:42 +00:00
|
|
|
loginfo.Println(hex.Dump(buf.Bytes()))
|
|
|
|
|
2017-03-03 00:47:59 +00:00
|
|
|
sendTrack := NewSendTrack(buf.Bytes(), hostname)
|
2017-03-02 03:02:20 +00:00
|
|
|
conn.SendCh() <- sendTrack
|
2017-02-26 23:27:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//handleAdminClient -
|
|
|
|
// - expecting an existing oneConnListener with a qualified wss client connected.
|
|
|
|
// - auth will happen again since we were just peeking at the token.
|
|
|
|
func handleAdminClient(ctx context.Context, oneConn *oneConnListener) {
|
2017-03-03 00:47:59 +00:00
|
|
|
connectionTable := ctx.Value(ctxConnectionTable).(*Table)
|
2017-02-26 23:27:38 +00:00
|
|
|
|
|
|
|
router := mux.NewRouter().StrictSlash(true)
|
|
|
|
|
|
|
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
loginfo.Println("HandleFunc /")
|
|
|
|
switch url := r.URL.Path; url {
|
|
|
|
case "/":
|
|
|
|
// check to see if we are using the administrative Host
|
|
|
|
if strings.Contains(r.Host, "rvpn.daplie.invalid") {
|
|
|
|
http.Redirect(w, r, "/admin", 301)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
http.Error(w, "Not Found", 404)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
router.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
|
|
fmt.Fprintln(w, "<html>Welcome..press <a href=/api/servers>Servers</a> to access stats</html>")
|
|
|
|
})
|
|
|
|
|
|
|
|
router.HandleFunc("/api/servers", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Println("here")
|
2017-03-03 00:47:59 +00:00
|
|
|
serverContainer := NewServerAPIContainer()
|
2017-02-26 23:27:38 +00:00
|
|
|
|
|
|
|
for c := range connectionTable.Connections() {
|
2017-03-03 00:47:59 +00:00
|
|
|
serverAPI := NewServerAPI(c)
|
2017-02-26 23:27:38 +00:00
|
|
|
serverContainer.Servers = append(serverContainer.Servers, serverAPI)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
|
|
json.NewEncoder(w).Encode(serverContainer)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
s := &http.Server{
|
|
|
|
Addr: ":80",
|
|
|
|
Handler: router,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := s.Serve(oneConn)
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("Serve error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
loginfo.Println("Cancel signal hit")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
//handleWssClient -
|
|
|
|
// - expecting an existing oneConnListener with a qualified wss client connected.
|
|
|
|
// - auth will happen again since we were just peeking at the token.
|
|
|
|
func handleWssClient(ctx context.Context, oneConn *oneConnListener) {
|
|
|
|
secretKey := ctx.Value(ctxSecretKey).(string)
|
2017-03-03 00:47:59 +00:00
|
|
|
connectionTable := ctx.Value(ctxConnectionTable).(*Table)
|
2017-02-26 18:35:06 +00:00
|
|
|
|
|
|
|
router := mux.NewRouter().StrictSlash(true)
|
|
|
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
loginfo.Println("HandleFunc /")
|
|
|
|
switch url := r.URL.Path; url {
|
|
|
|
case "/":
|
|
|
|
loginfo.Println("websocket opening ", r.RemoteAddr, " ", r.Host)
|
|
|
|
|
|
|
|
tokenString := r.URL.Query().Get("access_token")
|
|
|
|
result, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
|
|
|
return []byte(secretKey), nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil || !result.Valid {
|
|
|
|
w.WriteHeader(http.StatusForbidden)
|
|
|
|
w.Write([]byte("Not Authorized"))
|
|
|
|
loginfo.Println("access_token invalid...closing connection")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
claims := result.Claims.(jwt.MapClaims)
|
|
|
|
domains, ok := claims["domains"].([]interface{})
|
2017-02-26 05:17:39 +00:00
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
var upgrader = websocket.Upgrader{
|
|
|
|
ReadBufferSize: 1024,
|
|
|
|
WriteBufferSize: 1024,
|
|
|
|
}
|
2017-02-26 05:17:39 +00:00
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
conn, err := upgrader.Upgrade(w, r, nil)
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("WebSocket upgrade failed", err)
|
|
|
|
return
|
|
|
|
}
|
2017-02-26 05:17:39 +00:00
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
loginfo.Println("before connection table")
|
2017-02-26 05:17:39 +00:00
|
|
|
|
2017-02-26 18:35:06 +00:00
|
|
|
//newConnection := connection.NewConnection(connectionTable, conn, r.RemoteAddr, domains)
|
|
|
|
|
2017-03-03 00:47:59 +00:00
|
|
|
connectionTrack := ctx.Value(ctxConnectionTrack).(*Tracking)
|
|
|
|
newRegistration := NewRegistration(conn, r.RemoteAddr, domains, connectionTrack)
|
2017-02-26 18:35:06 +00:00
|
|
|
connectionTable.Register() <- newRegistration
|
|
|
|
ok = <-newRegistration.CommCh()
|
|
|
|
if !ok {
|
|
|
|
loginfo.Println("connection registration failed ", newRegistration)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
loginfo.Println("connection registration accepted ", newRegistration)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
s := &http.Server{
|
|
|
|
Addr: ":80",
|
|
|
|
Handler: router,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := s.Serve(oneConn)
|
|
|
|
if err != nil {
|
|
|
|
loginfo.Println("Serve error: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
loginfo.Println("Cancel signal hit")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|