summaryrefslogtreecommitdiff
path: root/nslcd_proto/io.go
diff options
context:
space:
mode:
Diffstat (limited to 'nslcd_proto/io.go')
-rw-r--r--nslcd_proto/io.go100
1 files changed, 70 insertions, 30 deletions
diff --git a/nslcd_proto/io.go b/nslcd_proto/io.go
index a2adade..daced37 100644
--- a/nslcd_proto/io.go
+++ b/nslcd_proto/io.go
@@ -37,6 +37,10 @@ func (o NslcdError) Error() string {
return string(o)
}
+func npanic(err NslcdError) {
+ panic(err)
+}
+
// An nslcdObject is an object with a different network representation
// than a naive structure.
type nslcdObject interface {
@@ -53,9 +57,45 @@ type nslcdObjectPtr interface {
nslcdRead(fd io.Reader)
}
+// Write an object to a stream. Any errors returned are of type
+// NslcdError.
+func Write(fd io.Writer, data interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch r := r.(type) {
+ case NslcdError:
+ err = r
+ default:
+ panic(r)
+ }
+ }
+ }()
+ write(fd, data)
+
+ return err
+}
+
+// Read an object from a stream. Any errors returned are of type
+// NslcdError.
+func Read(fd io.Reader, data interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch r := r.(type) {
+ case NslcdError:
+ err = r
+ default:
+ panic(r)
+ }
+ }
+ }()
+ read(fd, data)
+
+ return err
+}
+
// Write an object to a stream. In the event of an error, this
-// function may panic! Handle it!
-func Write(fd io.Writer, data interface{}) {
+// function may panic(NslcdError)! Handle it!
+func write(fd io.Writer, data interface{}) {
switch data := data.(type) {
// basic data types
case nslcdObject:
@@ -64,22 +104,22 @@ func Write(fd io.Writer, data interface{}) {
if len(data) > 0 {
_, err := fd.Write(data)
if err != nil {
- panic(err)
+ npanic(NslcdError(err.Error()))
}
}
case int32:
err := binary.Write(fd, binary.BigEndian, data)
if err != nil {
- panic(err)
+ npanic(NslcdError(err.Error()))
}
// composite datatypes
case string:
- Write(fd, int32(len(data)))
- Write(fd, []byte(data))
+ write(fd, int32(len(data)))
+ write(fd, []byte(data))
case []string:
- Write(fd, int32(len(data)))
+ write(fd, int32(len(data)))
for _, item := range data {
- Write(fd, item)
+ write(fd, item)
}
case net.IP:
var af int32 = -1
@@ -95,20 +135,20 @@ func Write(fd io.Writer, data interface{}) {
} else {
bytes = data
}
- Write(fd, af)
- Write(fd, int32(len(bytes)))
- Write(fd, bytes)
+ write(fd, af)
+ write(fd, int32(len(bytes)))
+ write(fd, bytes)
case []net.IP:
- Write(fd, int32(len(data)))
+ write(fd, int32(len(data)))
for _, item := range data {
- Write(fd, item)
+ write(fd, item)
}
default:
v := reflect.ValueOf(data)
switch v.Kind() {
case reflect.Struct:
for i, n := 0, v.NumField(); i < n; i++ {
- Write(fd, v.Field(i).Interface())
+ write(fd, v.Field(i).Interface())
}
default:
panic(fmt.Sprintf("Invalid structure to write NSLCD protocol data from: %T ( %#v )", data, data))
@@ -117,8 +157,8 @@ func Write(fd io.Writer, data interface{}) {
}
// Read an object from a stream. In the event of an error, this
-// function may panic! Handle it!
-func Read(fd io.Reader, data interface{}) {
+// function may panic(NslcdError)! Handle it!
+func read(fd io.Reader, data interface{}) {
switch data := data.(type) {
// basic data types
case nslcdObjectPtr:
@@ -127,31 +167,31 @@ func Read(fd io.Reader, data interface{}) {
if len(*data) > 0 {
_, err := io.ReadFull(fd, *data)
if err != nil {
- panic(err)
+ npanic(NslcdError(err.Error()))
}
}
case *int32:
err := binary.Read(fd, binary.BigEndian, data)
if err != nil {
- panic(err)
+ npanic(NslcdError(err.Error()))
}
// composite datatypes
case *string:
var len int32
- Read(fd, &len)
+ read(fd, &len)
buf := make([]byte, len) // BUG(lukeshu): Read: `string` length needs sanity checked
- Read(fd, &buf)
+ read(fd, &buf)
*data = string(buf)
case *[]string:
var num int32
- Read(fd, &num)
+ read(fd, &num)
*data = make([]string, num) // BUG(lukeshu): Read: `[]string` length needs sanity checked
for i := 0; i < int(num); i++ {
- Read(fd, &((*data)[i]))
+ read(fd, &((*data)[i]))
}
case *net.IP:
var af int32
- Read(fd, &af)
+ read(fd, &af)
var _len int32
switch af {
case unix.AF_INET:
@@ -159,22 +199,22 @@ func Read(fd io.Reader, data interface{}) {
case unix.AF_INET6:
_len = net.IPv6len
default:
- panic(NslcdError(fmt.Sprintf("incorrect address family specified: %d", af)))
+ npanic(NslcdError(fmt.Sprintf("incorrect address family specified: %d", af)))
}
var len int32
- Read(fd, &len)
+ read(fd, &len)
if len != _len {
- panic(NslcdError(fmt.Sprintf("address length incorrect: %d", len)))
+ npanic(NslcdError(fmt.Sprintf("address length incorrect: %d", len)))
}
buf := make([]byte, len)
- Read(fd, &buf)
+ read(fd, &buf)
*data = buf
case *[]net.IP:
var num int32
- Read(fd, &num)
+ read(fd, &num)
*data = make([]net.IP, num) // BUG(lukeshu): Read: `[]net.IP` length needs sanity checked
for i := 0; i < int(num); i++ {
- Read(fd, &((*data)[i]))
+ read(fd, &((*data)[i]))
}
default:
p := reflect.ValueOf(data)
@@ -183,7 +223,7 @@ func Read(fd io.Reader, data interface{}) {
panic(fmt.Sprintf("The argument to nslcd_proto.Read() must be a pointer: %T ( %#v )", data, data))
}
for i, n := 0, v.NumField(); i < n; i++ {
- Read(fd, v.Field(i).Addr().Interface())
+ read(fd, v.Field(i).Addr().Interface())
}
}
}