summaryrefslogtreecommitdiff
path: root/src/nslcd_proto/io.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/nslcd_proto/io.go')
-rw-r--r--src/nslcd_proto/io.go149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/nslcd_proto/io.go b/src/nslcd_proto/io.go
new file mode 100644
index 0000000..0804e98
--- /dev/null
+++ b/src/nslcd_proto/io.go
@@ -0,0 +1,149 @@
+package nslcd_proto
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "net"
+ "reflect"
+)
+
+//#include <sys/socket.h>
+import "C"
+
+type NslcdObject interface {
+ NslcdWrite(fd io.Writer)
+}
+type NslcdObjectPtr interface {
+ NslcdRead(fd io.Reader)
+}
+
+func write(fd io.Writer, data interface{}) {
+ switch data := data.(type) {
+ // basic data types
+ case []byte:
+ _, err := fd.Write(data)
+ if err != nil {
+ panic(err)
+ }
+ case int32:
+ err := binary.Write(fd, binary.BigEndian, data)
+ if err != nil {
+ panic(err)
+ }
+ case NslcdObject:
+ data.NslcdWrite(fd)
+ // composite datatypes
+ case string:
+ write(fd, int32(len(data)))
+ write(fd, []byte(data))
+ case []string:
+ write(fd, int32(len(data)))
+ for _, item := range data {
+ write(fd, item)
+ }
+ case net.IP:
+ var af int32 = -1
+ switch len(data) {
+ case net.IPv4len:
+ af = C.AF_INET
+ case net.IPv6len:
+ af = C.AF_INET6
+ }
+ var bytes []byte
+ if af < 0 {
+ bytes = make([]byte, 0)
+ } else {
+ bytes = data
+ }
+ write(fd, af)
+ write(fd, int32(len(bytes)))
+ write(fd, bytes)
+ case []net.IP:
+ write(fd, int32(len(data)))
+ for _, item := range data {
+ 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())
+ }
+ default:
+ panic("Invalid structure for NSLCD protocol data")
+ }
+ }
+ panic("not reached")
+}
+
+func read(fd io.Reader, data interface{}) {
+ switch data := data.(type) {
+ // basic data types
+ case *[]byte:
+ _, err := fd.Read(*data)
+ if err != nil {
+ panic(err)
+ }
+ case *int32:
+ err := binary.Read(fd, binary.BigEndian, data)
+ if err != nil {
+ panic(err)
+ }
+ case NslcdObjectPtr:
+ data.NslcdRead(fd)
+ // composite datatypes
+ case *string:
+ var len int32
+ read(fd, &len)
+ buf := make([]byte, len)
+ read(fd, &buf)
+ *data = string(buf)
+ case *[]string:
+ var num int32
+ read(fd, &num)
+ *data = make([]string, num)
+ for i := 0; i < int(num); i++ {
+ read(fd, &((*data)[i]))
+ }
+ case *net.IP:
+ var af int32
+ read(fd, &af)
+ var _len int32
+ switch af {
+ case C.AF_INET:
+ _len = net.IPv4len
+ case C.AF_INET6:
+ _len = net.IPv6len
+ default:
+ panic(NslcdError(fmt.Sprintf("incorrect address family specified: %d", af)))
+ }
+ var len int32
+ read(fd, &len)
+ if len != _len {
+ panic(NslcdError(fmt.Sprintf("address length incorrect: %d", len)))
+ }
+ buf := make([]byte, len)
+ read(fd, &buf)
+ *data = buf
+ case *[]net.IP:
+ var num int32
+ read(fd, &num)
+ *data = make([]net.IP, num)
+ for i := 0; i < int(num); i++ {
+ read(fd, &((*data)[i]))
+ }
+ default:
+ v := reflect.ValueOf(data)
+ switch v.Kind() {
+ case reflect.Struct:
+ for i, n := 0, v.NumField(); i < n; i++ {
+ read(fd, v.Field(i).Interface())
+ }
+ default:
+ panic("Invalid structure for NSLCD protocol data")
+ }
+ }
+ panic("not reached")
+}