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

mendersoftware / mender-connect / 780906967

pending completion
780906967

push

gitlab-ci

GitHub
Merge pull request #94 from kjaskiewiczz/test-fix

2440 of 3151 relevant lines covered (77.44%)

13.35 hits per line

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

76.67
/client/dbus/dbus_libgio.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
//go:build !nodbus && cgo
15
// +build !nodbus,cgo
16

17
package dbus
18

19
// #cgo pkg-config: gio-2.0
20
// #include <stdlib.h>
21
// #include <gio/gio.h>
22
// #include "dbus_libgio.go.h"
23
import "C"
24
import (
25
        "runtime"
26
        "time"
27
        "unsafe"
28

29
        "github.com/pkg/errors"
30
)
31

32
type dbusAPILibGio struct {
33
        signals map[string]chan []SignalParams
34
}
35

36
// constants for GDBusProxyFlags
37
const (
38
        GDbusProxyFlagsNone                         = 0
39
        GDbusProxyFlagsDoNotLoadProperties          = (1 << 0)
40
        GDbusProxyFlagsDoNotConnectSignals          = (1 << 1)
41
        GDbusProxyFlagsDoNotAutoStart               = (1 << 2)
42
        GDbusProxyFlagsGetInvalidatedProperties     = (1 << 3)
43
        GDbusProxyFlagsDoNotAutoStartAtConstruction = (1 << 4)
44
)
45

46
// constants for GDBusCallFlags
47
const (
48
        GDBusCallFlagsNone                          = 0
49
        GDBusCallFlagsNoAutoStart                   = (1 << 0)
50
        GDBusCallFlagsAllowInteractiveAuthorization = (1 << 1)
51
)
52

53
const (
54
        GDBusTypeString = "s"
55
)
56

57
// BusGet synchronously connects to the message bus specified by bus_type
58
// https://developer.gnome.org/gio/stable/GDBusConnection.html#g-bus-get-sync
59
func (d *dbusAPILibGio) BusGet(busType uint) (Handle, error) {
6✔
60
        var gerror *C.GError
6✔
61
        conn := C.g_bus_get_sync(C.GBusType(busType), nil, &gerror)
6✔
62
        if Handle(gerror) != nil {
6✔
63
                return Handle(nil), ErrorFromNative(Handle(gerror))
×
64
        }
×
65
        return Handle(conn), nil
6✔
66
}
67

68
// BusProxyNew creates a proxy for accessing an interface over DBus
69
// https://developer.gnome.org/gio/stable/GDBusProxy.html#g-dbus-proxy-new-sync
70
func (d *dbusAPILibGio) BusProxyNew(
71
        conn Handle,
72
        name string,
73
        objectPath string,
74
        interfaceName string,
75
) (Handle, error) {
8✔
76
        var gerror *C.GError
8✔
77
        gconn := C.to_gdbusconnection(unsafe.Pointer(conn))
8✔
78
        flags := C.GDBusProxyFlags(GDbusProxyFlagsDoNotLoadProperties)
8✔
79
        cname := C.CString(name)
8✔
80
        defer C.free(unsafe.Pointer(cname))
8✔
81
        cobjectPath := C.CString(objectPath)
8✔
82
        defer C.free(unsafe.Pointer(cobjectPath))
8✔
83
        cinterfaceName := C.CString(interfaceName)
8✔
84
        defer C.free(unsafe.Pointer(cinterfaceName))
8✔
85
        proxy := C.g_dbus_proxy_new_sync(
8✔
86
                gconn,
8✔
87
                flags,
8✔
88
                nil,
8✔
89
                cname,
8✔
90
                cobjectPath,
8✔
91
                cinterfaceName,
8✔
92
                nil,
8✔
93
                &gerror,
8✔
94
        )
8✔
95
        if Handle(gerror) != nil {
8✔
96
                return Handle(nil), ErrorFromNative(Handle(gerror))
×
97
        } else if proxy == nil {
10✔
98
                return Handle(nil), errors.New("unable to create a new dbus proxy")
2✔
99
        }
2✔
100
        C.g_signal_connect_on_proxy(proxy)
6✔
101
        return Handle(proxy), nil
6✔
102
}
103

104
// BusProxyCall synchronously invokes a method method on a proxy
105
// https://developer.gnome.org/gio/stable/GDBusProxy.html#g-dbus-proxy-call-sync
106
func (d *dbusAPILibGio) BusProxyCall(
107
        proxy Handle,
108
        methodName string,
109
        params interface{},
110
        timeout int,
111
) (DBusCallResponse, error) {
4✔
112
        var gerror *C.GError
4✔
113
        gproxy := C.to_gdbusproxy(unsafe.Pointer(proxy))
4✔
114
        cmethodName := C.CString(methodName)
4✔
115
        defer C.free(unsafe.Pointer(cmethodName))
4✔
116
        flags := C.GDBusCallFlags(GDBusCallFlagsNone)
4✔
117
        result := C.g_dbus_proxy_call_sync(
4✔
118
                gproxy,
4✔
119
                cmethodName,
4✔
120
                nil,
4✔
121
                flags,
4✔
122
                C.gint(timeout),
4✔
123
                nil,
4✔
124
                &gerror,
4✔
125
        )
4✔
126
        if Handle(gerror) != nil {
6✔
127
                return nil, ErrorFromNative(Handle(gerror))
2✔
128
        }
2✔
129
        return NewDBusCallResponse(unsafe.Pointer(result)), nil
2✔
130
}
131

132
// MainLoopNew creates a new GMainLoop structure
133
// https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-loop-new
134
func (d *dbusAPILibGio) MainLoopNew() MainLoop {
2✔
135
        loop := MainLoop(C.g_main_loop_new(nil, 0))
2✔
136
        runtime.SetFinalizer(&loop, func(loop *MainLoop) {
2✔
137
                gloop := C.to_gmainloop(unsafe.Pointer(*loop))
×
138
                C.g_main_loop_unref(gloop)
×
139
        })
×
140
        return loop
2✔
141
}
142

143
// MainLoopRun runs a main loop until MainLoopQuit() is called
144
// https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-loop-run
145
func (d *dbusAPILibGio) MainLoopRun(loop MainLoop) {
2✔
146
        gloop := C.to_gmainloop(unsafe.Pointer(loop))
2✔
147
        go C.g_main_loop_run(gloop)
2✔
148
}
2✔
149

150
// MainLoopQuit stops a main loop from running
151
// https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-loop-quit
152
func (d *dbusAPILibGio) MainLoopQuit(loop MainLoop) {
2✔
153
        gloop := C.to_gmainloop(unsafe.Pointer(loop))
2✔
154
        C.g_main_loop_quit(gloop)
2✔
155
}
2✔
156

157
// GetChannelForSignal returns a channel that can be used to wait for signals
158
func (d *dbusAPILibGio) GetChannelForSignal(signalName string) chan []SignalParams {
14✔
159
        channel, ok := d.signals[signalName]
14✔
160
        if !ok {
16✔
161
                channel = make(chan []SignalParams, 1)
2✔
162
                d.signals[signalName] = channel
2✔
163
        }
2✔
164
        return channel
14✔
165
}
166

167
// DrainSignal drains the channel used to wait for signals
168
func (d *dbusAPILibGio) DrainSignal(signalName string) {
8✔
169
        channel := d.GetChannelForSignal(signalName)
8✔
170
        select {
8✔
171
        case <-channel:
×
172
        default:
8✔
173
        }
174
}
175

176
// HandleSignal handles a DBus signal
177
func (d *dbusAPILibGio) HandleSignal(signalName string, params []SignalParams) {
2✔
178
        channel := d.GetChannelForSignal(signalName)
2✔
179
        select {
2✔
180
        case channel <- params:
2✔
181
        default:
×
182
        }
183
}
184

185
// WaitForSignal waits for a DBus signal
186
func (d *dbusAPILibGio) WaitForSignal(
187
        signalName string,
188
        timeout time.Duration,
189
) ([]SignalParams, error) {
4✔
190
        channel := d.GetChannelForSignal(signalName)
4✔
191
        select {
4✔
192
        case p := <-channel:
2✔
193
                return p, nil
2✔
194
        case <-time.After(timeout):
2✔
195
                return []SignalParams{}, errors.New("timeout waiting for signal " + signalName)
2✔
196
        }
197
}
198

199
//export handle_on_signal_callback
200
func handle_on_signal_callback(
201
        proxy *C.GDBusProxy,
202
        senderName *C.gchar,
203
        signalName *C.gchar,
204
        params *C.GVariant,
205
        userData C.gpointer,
206
) {
×
207
        goSignalName := C.GoString(signalName)
×
208
        api, _ := GetDBusAPI()
×
209
        var goParams []SignalParams
×
210
        i := C.g_variant_iter_new(params)
×
211
        defer C.g_variant_iter_free(i)
×
212
        for {
×
213
                p := C.g_variant_iter_next_value(i)
×
214
                if p == nil {
×
215
                        break
×
216
                }
217
                typeString := C.GoString(C.g_variant_get_type_string(p))
×
218
                var goParam SignalParams
×
219
                switch typeString {
×
220
                case GDBusTypeString:
×
221
                        goParam = SignalParams{
×
222
                                ParamType: typeString,
×
223
                                ParamData: C.GoString(C.g_variant_get_string(p, nil)),
×
224
                        }
×
225
                        goParams = append(goParams, goParam)
×
226
                }
227
        }
228
        api.HandleSignal(goSignalName, goParams)
×
229
}
230

231
func newDBusAPILibGio() *dbusAPILibGio {
4✔
232
        return &dbusAPILibGio{
4✔
233
                signals: make(map[string]chan []SignalParams),
4✔
234
        }
4✔
235
}
4✔
236

237
func init() {
2✔
238
        dbusAPI = newDBusAPILibGio()
2✔
239
}
2✔
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