package main import ( "bytes" "fmt" "log" "net" "os" "strings" "time" ) var p4info = []byte{157, 157, 0, 0, 0, 99, 109, 112, 102, 105, 108, 101, 0, 0, 0, 0, 0, 0, 99, 108, 105, 101, 110, 116, 0, 2, 0, 0, 0, 55, 54, 0, 97, 112, 105, 0, 5, 0, 0, 0, 57, 57, 57, 57, 57, 0, 101, 110, 97, 98, 108, 101, 83, 116, 114, 101, 97, 109, 115, 0, 0, 0, 0, 0, 0, 104, 111, 115, 116, 0, 10, 0, 0, 0, 98, 114, 101, 116, 116, 45, 109, 105, 110, 116, 0, 112, 111, 114, 116, 0, 14, 0, 0, 0, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 56, 49, 57, 50, 0, 115, 110, 100, 98, 117, 102, 0, 5, 0, 0, 0, 57, 56, 51, 48, 51, 0, 114, 99, 118, 98, 117, 102, 0, 6, 0, 0, 0, 55, 57, 54, 51, 53, 54, 0, 102, 117, 110, 99, 0, 8, 0, 0, 0, 112, 114, 111, 116, 111, 99, 111, 108, 0, 184, 184, 0, 0, 0, 112, 114, 111, 103, 0, 2, 0, 0, 0, 112, 52, 0, 118, 101, 114, 115, 105, 111, 110, 0, 27, 0, 0, 0, 50, 48, 49, 52, 46, 49, 47, 76, 73, 78, 85, 88, 50, 54, 88, 56, 54, 95, 54, 52, 47, 56, 50, 49, 57, 57, 48, 0, 99, 108, 105, 101, 110, 116, 0, 10, 0, 0, 0, 98, 114, 101, 116, 116, 45, 109, 105, 110, 116, 0, 99, 119, 100, 0, 21, 0, 0, 0, 47, 104, 111, 109, 101, 47, 98, 114, 101, 116, 116, 47, 103, 111, 47, 115, 114, 99, 47, 112, 52, 0, 104, 111, 115, 116, 0, 10, 0, 0, 0, 98, 114, 101, 116, 116, 45, 109, 105, 110, 116, 0, 111, 115, 0, 4, 0, 0, 0, 85, 78, 73, 88, 0, 117, 115, 101, 114, 0, 5, 0, 0, 0, 98, 114, 101, 116, 116, 0, 99, 104, 97, 114, 115, 101, 116, 0, 1, 0, 0, 0, 49, 0, 102, 117, 110, 99, 0, 9, 0, 0, 0, 117, 115, 101, 114, 45, 105, 110, 102, 111, 0} func main() { port := "8192" ips, err := net.LookupIP("localhost") checkError(err) for _, ip := range ips { fmt.Println("Resolved addr ", ip) } addr := strings.Join([]string{ips[0].String(), port}, ":") fmt.Println("Joined addr string ", addr) tcpAddr, err := net.ResolveTCPAddr("tcp", addr) checkError(err) fmt.Println("TCPAddr ", tcpAddr.String()) conn, err := net.DialTCP("tcp", nil, tcpAddr) checkError(err) handleConn(conn) } type message struct { size int data *[]byte } type data struct { header [5]byte value string } func handleConn(c net.Conn) { _, err := c.Write(p4info) checkError(err) msgc := make(chan message) resp := make(chan map[string]data) go translate(msgc, resp) for { c.SetReadDeadline(time.Now().Add(time.Second)) size := getHeader(c) buf := make([]byte, size) n, err := c.Read(buf) checkError(err) if err != nil || n == 0 { c.Close() break } /*Perhaps pointless using channels/goroutine, since we are blocking for the response anyway*/ msgc <- message{size, &buf} kv := <-resp log.Printf("%+v\n\n", kv) // If we get func = release we have finished reading f, ok := kv["func"] if ok && f.value == "release" { log.Println("Finished reading") break } } } func getHeader(c net.Conn) int { header := make([]byte, 5) n, err := c.Read(header) if readError(err, n, 5) { log.Printf("Stopped getting messages\n") c.Close() os.Exit(1) } return int(header[1]) } func translate(m <-chan message, resp chan<- map[string]data) { for msg := range m { buf := bytes.NewBuffer(*msg.data) kv := make(map[string]data) l := buf.Len() i := 0 //Read in the buffer for { if i == l { // We've reached the end break } var key bytes.Buffer for { n := buf.Next(1) if n[0] != 0 { key.Write(n) } else { buf.UnreadByte() break } i++ } var header [5]byte copy(header[:], buf.Next(5)) i += 5 value := buf.Next(int(header[1])) kv[key.String()] = data{header, string(value)} i += int(header[1]) end := buf.Next(1) if int(end[0]) != 0 { log.Panicf("Expected null got %+v", end) } i++ } resp <- kv } } func readError(err error, size int, s_err int) bool { if err != nil || size != s_err { return true } return false } func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } }