forked from fiorix/go-diameter
/
client.go
135 lines (119 loc) · 3.9 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
// 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/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) {
srv := &Server{Network: network, Addr: addr, Handler: handler, Dict: dp}
return dial(srv, 0)
}
func DialNetworkTimeout(network, addr string, handler Handler, dp *dict.Parser, timeout time.Duration) (Conn, error) {
srv := &Server{Network: network, Addr: addr, Handler: handler, Dict: dp}
return dial(srv, timeout)
}
// 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)
}
// 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 := getDialer(network, timeout)
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) {
srv := &Server{Addr: addr, Handler: handler, Dict: dp}
return dialTLS(srv, certFile, keyFile, 0)
}
// 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) {
srv := &Server{Addr: addr, Handler: handler, Dict: dp}
return dialTLS(srv, certFile, keyFile, timeout)
}
// DialNetworkTLS is the same as DialNetwork, but for TLS.
func DialNetworkTLS(network, addr, certFile, keyFile string, handler Handler, dp *dict.Parser) (Conn, error) {
srv := &Server{Network: network, Addr: addr, Handler: handler, Dict: dp}
return dialTLS(srv, certFile, keyFile, 0)
}
// 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)
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
}