forked from fiorix/go-diameter
/
client.go
172 lines (150 loc) · 4.99 KB
/
client.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Copyright 2013-2015 go-diameter authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Diameter client.
package diam
import (
"crypto/tls"
"net"
"time"
"github.com/fiorix/go-diameter/v4/diam/dict"
)
// DialNetwork connects to the peer pointed to by network & addr and returns the Conn that
// can be used to send diameter messages. Incoming messages are handled
// by the handler, which is typically nil and DefaultServeMux is used.
// If dict is nil, dict.Default is used.
func DialNetwork(network, addr string, handler Handler, dp *dict.Parser) (Conn, error) {
return DialExt(network, addr, handler, dp, 0, nil)
}
func DialNetworkBind(network, laddr, raddr string, handler Handler, dp *dict.Parser) (Conn, error) {
var (
err error
netAddr net.Addr
)
if laddr != "" {
netAddr, err = resolveAddress(network, laddr)
if err != nil {
return nil, err
}
}
return DialExt(network, raddr, handler, dp, 0, netAddr)
}
func DialNetworkTimeout(network, addr string, handler Handler, dp *dict.Parser, timeout time.Duration) (Conn, error) {
return DialExt(network, addr, handler, dp, timeout, nil)
}
// Dial connects to the peer pointed to by addr and returns the Conn that
// can be used to send diameter messages. Incoming messages are handled
// by the handler, which is typically nil and DefaultServeMux is used.
// If dict is nil, dict.Default is used.
func Dial(addr string, handler Handler, dp *dict.Parser) (Conn, error) {
return DialNetwork("tcp", addr, handler, dp)
}
func DialTimeout(addr string, handler Handler, dp *dict.Parser, timeout time.Duration) (Conn, error) {
return DialNetworkTimeout("tcp", addr, handler, dp, timeout)
}
// DialExt - extended dial API connects to the peer pointed to by network &
// addr and returns the Conn that can be used to send diameter messages.
// Incoming messages are handled by the handler, which is typically nil and
// DefaultServeMux is used. Allows binding dailer socket to given laddr.
// If dict is nil, dict.Default is used.
func DialExt(
network, addr string, handler Handler, dp *dict.Parser, timeout time.Duration, laddr net.Addr) (Conn, error) {
srv := &Server{Network: network, Addr: addr, Handler: handler, Dict: dp, LocalAddr: laddr}
return dial(srv, timeout)
}
// dial network wrapper
func dial(srv *Server, timeout time.Duration) (Conn, error) {
network := srv.Network
if len(network) == 0 {
network = "tcp"
}
addr := srv.Addr
if len(addr) == 0 {
addr = ":3868"
}
var rw net.Conn
var err error
dialer := getMultistreamDialer(network, timeout, srv.LocalAddr)
rw, err = dialer.Dial(network, addr)
if err != nil {
return nil, err
}
c, err := srv.newConn(rw)
if err != nil {
return nil, err
}
go c.serve()
return c.writer, nil
}
// DialTLS is the same as Dial, but for TLS.
func DialTLS(addr, certFile, keyFile string, handler Handler, dp *dict.Parser) (Conn, error) {
return DialTLSExt("tcp", addr, certFile, keyFile, handler, dp, 0, nil)
}
// DialTLSTimeout is the same as DialTimeout, but for TLS.
func DialTLSTimeout(addr, certFile, keyFile string, handler Handler, dp *dict.Parser, timeout time.Duration) (Conn, error) {
return DialTLSExt("tcp", addr, certFile, keyFile, handler, dp, timeout, nil)
}
// DialNetworkTLS is the same as DialNetwork, but for TLS.
func DialNetworkTLS(network, addr, certFile, keyFile string, handler Handler, dp *dict.Parser) (Conn, error) {
return DialTLSExt(network, addr, certFile, keyFile, handler, dp, 0, nil)
}
// DialTLSExt is the same as DialExt, but for TLS.
func DialTLSExt(
network,
addr,
certFile,
keyFile string,
handler Handler,
dp *dict.Parser,
timeout time.Duration,
laddr net.Addr) (Conn, error) {
srv := &Server{Network: network, Addr: addr, Handler: handler, Dict: dp, LocalAddr: laddr}
return dialTLS(srv, certFile, keyFile, timeout)
}
// dialTLS net TCP wrapper
func dialTLS(srv *Server, certFile, keyFile string, timeout time.Duration) (Conn, error) {
var err error
network := srv.Network
if len(network) == 0 {
network = "tcp"
}
addr := srv.Addr
if len(addr) == 0 {
addr = ":3868"
}
var config *tls.Config
if srv.TLSConfig == nil {
config = &tls.Config{InsecureSkipVerify: true}
} else {
config = TLSConfigClone(srv.TLSConfig)
}
if len(certFile) != 0 {
config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
}
var rw net.Conn
dialer := getDialer(network, timeout, srv.LocalAddr)
rw, err = dialer.Dial(network, addr)
if err != nil {
return nil, err
}
c, err := srv.newConn(tls.Client(rw, config))
if err != nil {
return nil, err
}
go c.serve()
return c.writer, nil
}
// NewConn is the same as Dial, but using an already open net.Conn.
func NewConn(rw net.Conn, addr string, handler Handler, dp *dict.Parser) (Conn, error) {
srv := &Server{Addr: addr, Handler: handler, Dict: dp}
c, err := srv.newConn(rw)
if err != nil {
return nil, err
}
go c.serve()
return c.writer, nil
}