summaryrefslogtreecommitdiff
path: root/src/nslcd-proto/io.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2015-08-25 14:19:33 -0600
committerLuke Shumaker <lukeshu@sbcglobal.net>2015-08-25 14:19:33 -0600
commit75c89781ab3ed908307920e4acdeb86f275f2faa (patch)
treee9cf634a2d1990949b915bc17e6d48b8c3f4322a /src/nslcd-proto/io.go
initial commit
Diffstat (limited to 'src/nslcd-proto/io.go')
-rw-r--r--src/nslcd-proto/io.go141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/nslcd-proto/io.go b/src/nslcd-proto/io.go
new file mode 100644
index 0000000..9ed6fd5
--- /dev/null
+++ b/src/nslcd-proto/io.go
@@ -0,0 +1,141 @@
+package nslcd_proto
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "net"
+ "reflect"
+)
+
+//#include <sys/socket.h>
+import "C"
+
+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 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]))
+ }
+ // Entities
+ case Netgroup:
+ read(fd, &data.Name)
+ 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 NSLCD protocol data")
+ }
+ }
+ panic("not reached")
+}