parse.go (3584B)
1 package lib9p 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 ) 8 9 // Read9PMsg reads a 9P message from r and saves it in a byte slice. 10 // It returns the byte slice read and error if any. 11 func readMsg(r io.Reader) ([]byte, error) { 12 buf := make([]byte, 4) 13 read, err := r.Read(buf) 14 if err != nil { 15 if err == io.EOF { 16 return nil, err 17 } 18 return nil, fmt.Errorf("read size: %v", err) 19 } 20 if read != len(buf) { 21 return buf, fmt.Errorf("read size: invalid message.") 22 } 23 size := bufMsg(buf).Size() 24 mbuf := make([]byte, size-4) 25 for read = 0; read < int(size)-4; { 26 n, err := r.Read(mbuf[read:]) 27 if err != nil { 28 return buf, fmt.Errorf("read body: %v", err) 29 } 30 read += n 31 } 32 buf = append(buf, mbuf...) 33 if uint32(read+4) != size { 34 return buf, fmt.Errorf("read body: size mismatch: %d != %d", read+4, size) 35 } 36 return buf, nil 37 } 38 39 // unmarshal converts a byte array of 9P message into the corresponding 40 // Msg struct. 41 func unmarshal(buf []byte) (Msg, error) { 42 switch t := bufMsg(buf).Type(); t { 43 case Tversion: 44 return newTVersion(buf), nil 45 case Rversion: 46 return newRVersion(buf), nil 47 case Tauth: 48 return newTAuth(buf), nil 49 case Rauth: 50 return newRAuth(buf), nil 51 case Tattach: 52 return newTAttach(buf), nil 53 case Rattach: 54 return newRAttach(buf), nil 55 case Rerror: 56 return newRError(buf), nil 57 case Tflush: 58 return newTFlush(buf), nil 59 case Rflush: 60 return newRFlush(buf), nil 61 case Twalk: 62 return newTWalk(buf), nil 63 case Rwalk: 64 return newRWalk(buf), nil 65 case Topen: 66 return newTOpen(buf), nil 67 case Ropen: 68 return newROpen(buf), nil 69 case Tcreate: 70 return newTCreate(buf), nil 71 case Rcreate: 72 return newRCreate(buf), nil 73 case Tread: 74 return newTRead(buf), nil 75 case Rread: 76 return newRRead(buf), nil 77 case Twrite: 78 return newTWrite(buf), nil 79 case Rwrite: 80 return newRWrite(buf), nil 81 case Tclunk: 82 return newTClunk(buf), nil 83 case Rclunk: 84 return newRClunk(buf), nil 85 case Tremove: 86 return newTRemove(buf), nil 87 case Rremove: 88 return newRRemove(buf), nil 89 case Tstat: 90 return newTStat(buf), nil 91 case Rstat: 92 return newRStat(buf), nil 93 case Twstat: 94 return newTWstat(buf), nil 95 case Rwstat: 96 return newRWstat(buf), nil 97 default: 98 return nil, fmt.Errorf("unknown message type %v", t) 99 } 100 } 101 102 // SendMsg send a 9P message to w 103 func SendMsg(msg Msg, w io.Writer) error { 104 if _, err := w.Write(msg.marshal()); err != nil { 105 return fmt.Errorf("write: %v", err) 106 } 107 return nil 108 } 109 110 // RecvMsg recievs a 9P message from r. 111 func RecvMsg(r io.Reader) (Msg, error) { 112 b, err := readMsg(r) 113 if err == io.EOF { 114 return nil, err 115 } else if err != nil { 116 return nil, fmt.Errorf("readMsg: %v", err) 117 } 118 return unmarshal(b) 119 } 120 121 // Gbit16 reads b as 2-byte long little endian unsigned integer and 122 // returns the result 123 func gbit16(b []byte) uint16 { return binary.LittleEndian.Uint16(b[0:2]) } 124 125 // Gbit32 reads b as 4-byte long little endian unsigned integer and 126 // returns the result 127 func gbit32(b []byte) uint32 { return binary.LittleEndian.Uint32(b[0:4]) } 128 129 // Gbit64 reads b as 8-byte long little endian unsigned integer and 130 // returns the result 131 func gbit64(b []byte) uint64 { return binary.LittleEndian.Uint64(b[0:8]) } 132 133 // Pbit16 puts into b an 2-byte long little endian unsigned integer n. 134 func pbit16(b []byte, n uint16) { binary.LittleEndian.PutUint16(b, n) } 135 136 // Pbit32 puts into b an 4-byte long little endian unsigned integer n. 137 func pbit32(b []byte, n uint32) { binary.LittleEndian.PutUint32(b, n) } 138 139 // Pbit64 puts into b an 8-byte long little endian unsigned integer n. 140 func pbit64(b []byte, n uint64) { binary.LittleEndian.PutUint64(b, n) }