This repository has been archived by the owner on Nov 27, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathqueryrecord.go
160 lines (143 loc) · 4 KB
/
queryrecord.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package dnssd
import "unsafe"
// QueryCallbackFunc is called when an error occurs or a record is added or removed.
// Results may be cached for ttl seconds. After ttl seconds the result should be discarded.
// Alternatively the operation may be left running in which case the result can be considered valid
// until a callback indicates otherwise.
type QueryCallbackFunc func(op *QueryOp, err error, add bool, interfaceIndex int, fullname string, rrtype, rrclass uint16, rdata []byte, ttl uint32)
// QueryOp represents a query for a specific name, class and type.
type QueryOp struct {
baseOp
name string
rrtype, rrclass uint16
callback QueryCallbackFunc
}
// NewQueryOp creates a new QueryOp with the associated parameters set.
func NewQueryOp(interfaceIndex int, name string, rrtype, rrclass uint16, f QueryCallbackFunc) *QueryOp {
op := &QueryOp{}
op.SetInterfaceIndex(interfaceIndex)
op.SetName(name)
op.SetType(rrtype)
op.SetClass(rrclass)
op.SetCallback(f)
return op
}
// StartQueryOp returns the equivalent of calling NewQueryOp and Start.
func StartQueryOp(interfaceIndex int, name string, rrtype, rrclass uint16, f QueryCallbackFunc) (*QueryOp, error) {
op := NewQueryOp(interfaceIndex, name, rrtype, rrclass, f)
return op, op.Start()
}
// Name returns the domain name for the operation.
func (o *QueryOp) Name() string {
o.m.Lock()
defer o.m.Unlock()
return o.name
}
// SetName sets the domain name for the operation.
func (o *QueryOp) SetName(n string) error {
o.m.Lock()
defer o.m.Unlock()
if o.started {
return ErrStarted
}
o.name = n
return nil
}
// Type returns the DNS Resource Record Type for the operation.
func (o *QueryOp) Type() uint16 {
o.m.Lock()
defer o.m.Unlock()
return o.rrtype
}
// SetType sets the DNS Resource Record Type for the operation.
func (o *QueryOp) SetType(t uint16) error {
o.m.Lock()
defer o.m.Unlock()
if o.started {
return ErrStarted
}
o.rrtype = t
return nil
}
// Class returns the DNS Resource Record Class for the operation.
func (o *QueryOp) Class() uint16 {
o.m.Lock()
defer o.m.Unlock()
return o.rrclass
}
// SetClass sets the DNS Resource Record Class for the operation.
func (o *QueryOp) SetClass(c uint16) error {
o.m.Lock()
defer o.m.Unlock()
if o.started {
return ErrStarted
}
o.rrclass = c
return nil
}
// SetCallback sets the function to call when an error occurs or a record is added or removed.
func (o *QueryOp) SetCallback(f QueryCallbackFunc) error {
o.m.Lock()
defer o.m.Unlock()
if o.started {
return ErrStarted
}
o.callback = f
return nil
}
// Start begins the query operation.
func (o *QueryOp) Start() error {
o.m.Lock()
defer o.m.Unlock()
if o.started {
return ErrStarted
}
if o.callback == nil {
return ErrMissingCallback
}
err := pollServer.startOp(o)
o.started = err == nil || err == ErrStarted
return err
}
func (o *QueryOp) init(sharedref uintptr) (ref uintptr, err error) {
ref = sharedref
o.setFlag(_FlagsShareConnection, ref != 0)
if err = queryStart(&ref, o.flags, o.interfaceIndexC(), o.name, o.rrtype, o.rrclass, unsafe.Pointer(o)); err != nil {
ref = 0
}
return
}
// Stop stops the operation.
func (o *QueryOp) Stop() {
o.m.Lock()
defer o.m.Unlock()
if !o.started {
return
}
o.started = false
}
func (o *QueryOp) handleError(e error) {
if !o.started {
return
}
o.started = false
pollServer.removePollOp(o)
queueCallback(func() { o.callback(o, e, false, 0, "", 0, 0, nil, 0) })
}
func dnssdQueryCallback(sdRef unsafe.Pointer, flags, interfaceIndex uint32, err int32, fullname unsafe.Pointer, rrtype, rrclass, rdlen uint16, rdataptr unsafe.Pointer, ttl uint32, ctx unsafe.Pointer) {
o := (*QueryOp)(ctx)
if e := getError(err); e != nil {
o.handleError(e)
} else {
a := flags&_FlagsAdd != 0
i := int(interfaceIndex)
f := cStringToString(fullname)
var rdata []byte
if rdlen > 0 && rdataptr != nil {
s := (*[65535]byte)(rdataptr)[:rdlen]
rdata = make([]byte, rdlen)
copy(rdata, s)
}
queueCallback(func() { o.callback(o, e, a, i, f, rrtype, rrclass, rdata, ttl) })
}
}