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