/
socket.go
106 lines (87 loc) · 2.66 KB
/
socket.go
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
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package libkb
import (
"fmt"
"net"
"github.com/keybase/client/go/logger"
"github.com/keybase/go-framed-msgpack-rpc/rpc"
)
// NewSocket() (Socket, err) is defined in the various platform-specific socket_*.go files.
type Socket interface {
BindToSocket() (net.Listener, error)
DialSocket() (net.Conn, error)
}
type SocketInfo struct {
log logger.Logger
bindFile string
dialFiles []string
testOwner bool
}
func (s SocketInfo) GetBindFile() string {
return s.bindFile
}
func (s SocketInfo) GetDialFiles() []string {
return s.dialFiles
}
type SocketWrapper struct {
Conn net.Conn
Transporter rpc.Transporter
Err error
}
func (g *GlobalContext) MakeLoopbackServer() (l net.Listener, err error) {
g.socketWrapperMu.Lock()
g.LoopbackListener = NewLoopbackListener(g)
l = g.LoopbackListener
g.socketWrapperMu.Unlock()
return
}
func (g *GlobalContext) BindToSocket() (net.Listener, error) {
return g.SocketInfo.BindToSocket()
}
func NewTransportFromSocket(g *GlobalContext, s net.Conn) rpc.Transporter {
return rpc.NewTransport(s, NewRPCLogFactory(g), MakeWrapError(g), rpc.DefaultMaxFrameLength)
}
// ResetSocket clears and returns a new socket
func (g *GlobalContext) ResetSocket(clearError bool) (net.Conn, rpc.Transporter, bool, error) {
g.SocketWrapper = nil
return g.GetSocket(clearError)
}
func (g *GlobalContext) GetSocket(clearError bool) (conn net.Conn, xp rpc.Transporter, isNew bool, err error) {
g.Trace("GetSocket", func() error { return err })()
// Protect all global socket wrapper manipulation with a
// lock to prevent race conditions.
g.socketWrapperMu.Lock()
defer g.socketWrapperMu.Unlock()
needWrapper := false
if g.SocketWrapper == nil {
needWrapper = true
g.Log.Debug("| empty socket wrapper; need a new one")
} else if g.SocketWrapper.Transporter != nil && !g.SocketWrapper.Transporter.IsConnected() {
// need reconnect
g.Log.Debug("| rpc transport isn't connected, reconnecting...")
needWrapper = true
}
if needWrapper {
sw := SocketWrapper{}
if g.LoopbackListener != nil {
sw.Conn, sw.Err = g.LoopbackListener.Dial()
} else if g.SocketInfo == nil {
sw.Err = fmt.Errorf("Cannot get socket in standalone mode")
} else {
sw.Conn, sw.Err = g.SocketInfo.DialSocket()
g.Log.Debug("| DialSocket -> %s", ErrToOk(sw.Err))
isNew = true
}
if sw.Err == nil {
sw.Transporter = NewTransportFromSocket(g, sw.Conn)
}
g.SocketWrapper = &sw
}
sw := g.SocketWrapper
if sw.Err != nil && clearError {
g.SocketWrapper = nil
}
err = sw.Err
return sw.Conn, sw.Transporter, isNew, err
}