• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-connect / 1528711701

04 Nov 2024 08:35AM UTC coverage: 77.427%. Remained the same
1528711701

push

gitlab-ci

web-flow
Merge pull request #142 from mendersoftware/dependabot/go_modules/github.com/creack/pty-1.1.24

chore: bump github.com/creack/pty from 1.1.23 to 1.1.24

2480 of 3203 relevant lines covered (77.43%)

6.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.0
/connection/connection.go
1
// Copyright 2022 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
package connection
16

17
import (
18
        "net/http"
19
        "net/url"
20
        "strconv"
21
        "sync"
22
        "time"
23

24
        "github.com/gorilla/websocket"
25
        log "github.com/sirupsen/logrus"
26
        "github.com/vmihailenco/msgpack/v5"
27

28
        "github.com/mendersoftware/go-lib-micro/ws"
29
)
30

31
type Connection struct {
32
        writeMutex sync.Mutex
33
        // the connection handler
34
        connection *websocket.Conn
35
        // Time allowed to write a message to the peer.
36
        writeWait time.Duration
37
        // Maximum message size allowed from peer.
38
        maxMessageSize int64
39
        // Time allowed to read the next pong message from the peer.
40
        defaultPingWait time.Duration
41
        // Channel to stop the go routines
42
        done chan bool
43
}
44

45
// Websocket connection routine. setup the ping-pong and connection settings
46
func NewConnection(u url.URL,
47
        token string,
48
        writeWait time.Duration,
49
        maxMessageSize int64,
50
        defaultPingWait time.Duration) (*Connection, error) {
4✔
51

4✔
52
        var ws *websocket.Conn
4✔
53
        dialer := *websocket.DefaultDialer
4✔
54

4✔
55
        headers := http.Header{}
4✔
56
        headers.Set("Authorization", "Bearer "+token)
4✔
57
        ws, rsp, err := dialer.Dial(u.String(), headers)
4✔
58
        if err != nil {
4✔
59
                return nil, err
×
60
        }
×
61
        defer rsp.Body.Close()
4✔
62

4✔
63
        c := &Connection{
4✔
64
                connection:      ws,
4✔
65
                writeWait:       writeWait,
4✔
66
                maxMessageSize:  maxMessageSize,
4✔
67
                defaultPingWait: defaultPingWait,
4✔
68
                done:            make(chan bool),
4✔
69
        }
4✔
70
        ws.SetReadLimit(maxMessageSize)
4✔
71

4✔
72
        go c.pingPongHandler()
4✔
73

4✔
74
        return c, nil
4✔
75
}
76

77
func (c *Connection) pingPongHandler() {
4✔
78
        // handle the ping-pong connection health check
4✔
79
        err := c.connection.SetReadDeadline(time.Now().Add(c.defaultPingWait))
4✔
80
        if err != nil {
4✔
81
                return
×
82
        }
×
83

84
        pingPeriod := (c.defaultPingWait * 9) / 10
4✔
85
        ticker := time.NewTicker(pingPeriod)
4✔
86
        defer ticker.Stop()
4✔
87

4✔
88
        c.connection.SetPongHandler(func(string) error {
4✔
89
                log.Debug("PongHandler called")
×
90
                // requires go >= 1.15
×
91
                // ticker.Reset(pingPeriod)
×
92
                return c.connection.SetReadDeadline(time.Now().Add(c.defaultPingWait))
×
93
        })
×
94

95
        c.connection.SetPingHandler(func(msg string) error {
4✔
96
                log.Debug("PingHandler called")
×
97
                // requires go >= 1.15
×
98
                // ticker.Reset(pingPeriod)
×
99
                err := c.connection.SetReadDeadline(time.Now().Add(c.defaultPingWait))
×
100
                if err != nil {
×
101
                        return err
×
102
                }
×
103
                c.writeMutex.Lock()
×
104
                defer c.writeMutex.Unlock()
×
105
                return c.connection.WriteControl(
×
106
                        websocket.PongMessage,
×
107
                        []byte(msg),
×
108
                        time.Now().Add(c.writeWait),
×
109
                )
×
110
        })
111

112
        running := true
4✔
113
        for running {
8✔
114
                select {
4✔
115
                case <-c.done:
×
116
                        running = false
×
117
                        break
×
118
                case <-ticker.C:
×
119
                        log.Debug("ping message")
×
120
                        pongWaitString := strconv.Itoa(int(c.defaultPingWait.Seconds()))
×
121
                        c.writeMutex.Lock()
×
122
                        _ = c.connection.WriteControl(
×
123
                                websocket.PingMessage,
×
124
                                []byte(pongWaitString),
×
125
                                time.Now().Add(c.defaultPingWait),
×
126
                        )
×
127
                        c.writeMutex.Unlock()
×
128
                }
129
        }
130
}
131

132
func (c *Connection) GetWriteTimeout() time.Duration {
1✔
133
        return c.writeWait
1✔
134
}
1✔
135

136
func (c *Connection) WriteMessage(m *ws.ProtoMsg) (err error) {
8✔
137
        data, err := msgpack.Marshal(m)
8✔
138
        if err != nil {
8✔
139
                return err
×
140
        }
×
141
        c.writeMutex.Lock()
8✔
142
        defer c.writeMutex.Unlock()
8✔
143
        _ = c.connection.SetWriteDeadline(time.Now().Add(c.writeWait))
8✔
144
        return c.connection.WriteMessage(websocket.BinaryMessage, data)
8✔
145
}
146

147
func (c *Connection) ReadMessage() (*ws.ProtoMsg, error) {
2✔
148
        _, data, err := c.connection.ReadMessage()
2✔
149
        if err != nil {
2✔
150
                return nil, err
×
151
        }
×
152

153
        m := &ws.ProtoMsg{}
2✔
154
        err = msgpack.Unmarshal(data, m)
2✔
155
        if err != nil {
2✔
156
                return nil, err
×
157
        }
×
158
        return m, nil
2✔
159
}
160

161
func (c *Connection) Close() error {
1✔
162
        select {
1✔
163
        case c.done <- true:
1✔
164
        default:
×
165
        }
166
        return c.connection.Close()
1✔
167
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc