-
Notifications
You must be signed in to change notification settings - Fork 15
/
status.go
135 lines (111 loc) · 2.92 KB
/
status.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
/* ipp-usb - HTTP reverse proxy, backed by IPP-over-USB connection to device
*
* Copyright (C) 2020 and up by Alexander Pevzner ([email protected])
* See LICENSE for license terms and conditions
*
* ipp-usb status support
*/
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net"
"net/http"
"sort"
"strconv"
"sync"
)
// statusOfDevice represents a status of the particular device
type statusOfDevice struct {
desc UsbDeviceDesc // Device descriptor
init error // Initialization error, nil if none
HTTPPort int // Assigned http port for the device
}
var (
// statusTable maintains a per-device status,
// indexed by the UsbAddr
statusTable = make(map[UsbAddr]*statusOfDevice)
// statusLock protects access to the statusTable
statusLock sync.RWMutex
)
// StatusRetrieve connects to the running ipp-usb daemon, retrieves
// its status and returns retrieved status as a printable text
func StatusRetrieve() ([]byte, error) {
t := &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return CtrlsockDial()
},
}
c := &http.Client{
Transport: t,
}
rsp, err := c.Get("http://localhost/status")
if err != nil {
return nil, err
}
defer rsp.Body.Close()
return ioutil.ReadAll(rsp.Body)
}
// StatusFormat formats ipp-usb status as a text
func StatusFormat() []byte {
buf := &bytes.Buffer{}
// Lock the statusTable
statusLock.RLock()
defer statusLock.RUnlock()
// Dump ipp-usb daemon status. If we are here, we are
// definitely running :-)
buf.WriteString("ipp-usb daemon: running\n")
// Sort devices by address
devs := make([]*statusOfDevice, len(statusTable))
i := 0
for _, status := range statusTable {
devs[i] = status
i++
}
sort.Slice(devs, func(i, j int) bool {
return devs[i].desc.UsbAddr.Less(devs[j].desc.UsbAddr)
})
// Format per-device status
buf.WriteString("ipp-usb devices:")
if len(statusTable) == 0 {
buf.WriteString(" not found\n")
} else {
buf.WriteString("\n")
fmt.Fprintf(buf, " Num Device Vndr:Prod Port Model\n")
for i, status := range devs {
info, _ := status.desc.GetUsbDeviceInfo()
s := "-"
if status.HTTPPort != 0 {
s = strconv.Itoa(status.HTTPPort)
}
fmt.Fprintf(buf, " %3d. %s %4.4x:%.4x %-5s %q\n",
i+1, status.desc.UsbAddr,
info.Vendor, info.Product, s,
info.MfgAndProduct)
s = "OK"
if status.init != nil {
s = devs[i].init.Error()
}
fmt.Fprintf(buf, " status: %s\n", s)
}
}
return buf.Bytes()
}
// StatusSet adds device to the status table or updates status
// of the already known device
func StatusSet(addr UsbAddr, desc UsbDeviceDesc, HTTPPort int, init error) {
statusLock.Lock()
statusTable[addr] = &statusOfDevice{
desc: desc,
init: init,
HTTPPort: HTTPPort,
}
statusLock.Unlock()
}
// StatusDel deletes device from the status table
func StatusDel(addr UsbAddr) {
statusLock.Lock()
delete(statusTable, addr)
statusLock.Unlock()
}