/
obj.go
executable file
·66 lines (61 loc) · 1.34 KB
/
obj.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
/*
Package gopenflow implements common openflow routines.
*/
package gopenflow
import (
"encoding"
"encoding/binary"
"fmt"
"github.com/hkwi/gopenflow/ofp4"
"io"
"syscall"
)
func Parse(data []byte) (encoding.BinaryMarshaler, error) {
switch data[0] {
default:
return nil, &Error{1, 0}
case 4: // Openflow 1.3
length := int(binary.BigEndian.Uint16(data[2:4]))
return ofp4.Header(data[0:length]), nil
}
}
type Error struct {
Type uint16
Code uint16
}
func (obj Error) Error() string {
return fmt.Sprintf("ofp_error type=%d code=%d", obj.Type, obj.Code)
}
func ReadMessage(source io.Reader) ([]byte, error) {
hdr := make([]byte, 8)
if n, err := source.Read(hdr); err != nil {
return nil, err
} else if n != 8 {
return nil, fmt.Errorf("openflow header read error")
}
length := int(binary.BigEndian.Uint16(hdr[2:]))
switch {
case length < 8:
return nil, fmt.Errorf("openflow length error")
case length == 8:
return hdr, nil
default:
buf := make([]byte, length)
copy(buf, hdr)
offset := 8
for offset < length {
if n, err := source.Read(buf[offset:]); err != nil {
if e, ok := err.(syscall.Errno); ok && e.Temporary() {
// retry
} else {
return nil, err
}
} else if n == 0 {
return nil, fmt.Errorf("reached EOF during reading openflow body")
} else {
offset += n
}
}
return buf, nil
}
}