-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstreamingclient.go
120 lines (98 loc) · 2.53 KB
/
streamingclient.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
package betfair
import (
"crypto/tls"
"encoding/json"
"errors"
"io"
"math/rand/v2"
)
type (
StreamingClientConfig struct {
SegmentationEnabled bool
ConflateMs int
HeartbeatMs int
InitialClk string
Clk string
}
StreamingClient struct {
Connection *tls.Conn
Config *StreamingClientConfig
}
StatusMessage struct {
ID int `json:"id"`
StatusCode string `json:"statusCode"`
ConnectionClosed bool `json:"connectionClosed"`
ErrorCode string `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
ConnectionsAvailable int `json:"connectionsAvailable"`
}
)
type (
ConnectionMessage struct {
Op string `json:"op"`
ConnectionID string `json:"connectionId"`
}
AuthenticationMessage struct {
ID int `json:"id"`
Op string `json:"op"`
AppKey string `json:"appKey"`
Session string `json:"session"`
}
)
func NewStreamingClient(config *StreamingClientConfig) (client *StreamingClient) {
return &StreamingClient{Config: config}
}
func (client *StreamingClient) Authenticate(config *tls.Config, applicationKey, sessionToken string) (err error) {
if client.Connection, err = tls.Dial("tcp", "stream-api.betfair.com:443", config); err != nil {
return err
}
cm := &ConnectionMessage{}
if err = client.Read(cm); err != nil {
client.Connection = nil
return err
}
am := AuthenticationMessage{
ID: int(rand.Uint32()),
Op: "authentication",
AppKey: applicationKey,
Session: sessionToken,
}
if err = client.Write(am, true); err != nil {
client.Connection = nil
}
return err
}
func (client *StreamingClient) Close() error {
if client.Connection != nil {
return client.Connection.Close()
}
return nil
}
func (client *StreamingClient) Read(response any) error {
if client.Connection == nil {
return errors.New("connection not established: please authenticate")
}
if err := json.NewDecoder(client.Connection).Decode(&response); err != nil && err != io.EOF {
return err
}
return nil
}
func (client *StreamingClient) Write(request any, isRequest bool) error {
if client.Connection == nil {
return errors.New("connection not established: please authenticate")
}
if err := json.NewEncoder(client.Connection).Encode(request); err != nil {
return err
}
if !isRequest {
return nil
}
status := &StatusMessage{}
if err := client.Read(status); err != nil {
return err
}
if status.ErrorCode != "" {
return errors.New(status.ErrorCode)
}
return nil
}