fcall.go (32530B)
1 package lib9p 2 3 import ( 4 "fmt" 5 ) 6 7 // A MsgType is Message type defined by 9P. 8 type MsgType uint8 9 10 const ( 11 Tversion MsgType = 100 12 Rversion = 101 13 Tauth = 102 14 Rauth = 103 15 Tattach = 104 16 Rattach = 105 17 Terror = 106 /* illegal */ 18 Rerror = 107 19 Tflush = 108 20 Rflush = 109 21 Twalk = 110 22 Rwalk = 111 23 Topen = 112 24 Ropen = 113 25 Tcreate = 114 26 Rcreate = 115 27 Tread = 116 28 Rread = 117 29 Twrite = 118 30 Rwrite = 119 31 Tclunk = 120 32 Rclunk = 121 33 Tremove = 122 34 Rremove = 123 35 Tstat = 124 36 Rstat = 125 37 Twstat = 126 38 Rwstat = 127 39 Tmax = 128 40 ) 41 42 // IOHDRSZ is the ample room for Twrite/Rread header. 43 // - Twrite: size[4] type[1] Tag[2] fid[4] offset[8] count[4] = 23 44 // - Rread: size[4] type[1] Tag[2] count[4] = 11 45 // 46 // In Plan9, this const is 24. 47 const IOHDRSZ = 23 48 49 // The Tag used by version messages. 50 // The client can use it, when establishing a connection, to 51 // override Tag matching in version messages. 52 const NOTAG = ^uint16(0) 53 54 // A Msg represents any kind of message of 9P. 55 // It defines methods for common fields. 56 // For each message type <T>, new<T>([]byte) function parses the byte array 57 // of 9P message into the corresponding message struct. 58 // For detailed information on each message, consult the documentation 59 // of 9P protocol. 60 type Msg interface { 61 // Size returns the size field of message. 62 // Size field holds the size of the message in bytes 63 // including the 4-byte size field itself. 64 Size() uint32 65 // Type returns the type field of message. 66 Type() MsgType 67 // GetTag returns the Tag of message. 68 // Tag is the identifier of each message. 69 // The Get prefix is to avoid name confliction with the each 70 // message's Tag field. 71 GetTag() uint16 72 // SetTag sets the Tag field of the message. 73 SetTag(uint16) 74 // Marshal convert Msg to byte array to be transmitted. 75 marshal() []byte 76 String() string 77 } 78 79 // A bufMsg is Msg with just an array of bytes. 80 // TODO: rename. 81 type bufMsg []byte 82 83 func (msg bufMsg) Size() uint32 { return gbit32(msg[0:4]) } 84 func (msg bufMsg) Type() MsgType { return MsgType(msg[4]) } 85 func (msg bufMsg) GetTag() uint16 { return gbit16(msg[5:7]) } 86 func (msg bufMsg) SetTag(t uint16) { pbit16(msg[5:7], t) } 87 func (msg bufMsg) marshal() []byte { return []byte(msg)[:msg.Size()] } 88 func (msg bufMsg) String() string { 89 switch msg.Type() { 90 case Tversion: 91 return newTVersion(msg).String() 92 case Rversion: 93 return newRVersion(msg).String() 94 case Tauth: 95 return newTAuth(msg).String() 96 case Rauth: 97 return newRAuth(msg).String() 98 case Tattach: 99 return newTAttach(msg).String() 100 case Rattach: 101 return newRAttach(msg).String() 102 case Rerror: 103 return newRError(msg).String() 104 case Tflush: 105 return newTFlush(msg).String() 106 case Rflush: 107 return newRFlush(msg).String() 108 case Twalk: 109 return newTWalk(msg).String() 110 case Rwalk: 111 return newRWalk(msg).String() 112 case Topen: 113 return newTOpen(msg).String() 114 case Ropen: 115 return newROpen(msg).String() 116 case Tcreate: 117 return newTCreate(msg).String() 118 case Rcreate: 119 return newRCreate(msg).String() 120 case Tread: 121 return newTRead(msg).String() 122 case Rread: 123 return newRRead(msg).String() 124 case Twrite: 125 return newTWrite(msg).String() 126 case Rwrite: 127 return newRWrite(msg).String() 128 case Tclunk: 129 return newTClunk(msg).String() 130 case Rclunk: 131 return newRClunk(msg).String() 132 case Tremove: 133 return newTRemove(msg).String() 134 case Rremove: 135 return newRRemove(msg).String() 136 case Tstat: 137 return newTStat(msg).String() 138 case Rstat: 139 return newRStat(msg).String() 140 case Twstat: 141 return newTWstat(msg).String() 142 case Rwstat: 143 return newRWstat(msg).String() 144 default: 145 return fmt.Sprint([]byte(msg[:msg.Size()])) 146 } 147 } 148 149 type TVersion struct { 150 Tag uint16 151 Msize uint32 152 Version string 153 } 154 155 func newTVersion(buf []byte) *TVersion { 156 msg := new(TVersion) 157 msg.Tag = gbit16(buf[5:7]) 158 msg.Msize = gbit32(buf[7:11]) 159 vs := gbit16(buf[11:13]) 160 msg.Version = string(buf[13 : 13+vs]) 161 return msg 162 } 163 func (msg *TVersion) Size() uint32 { return uint32(4 + 1 + 2 + 4 + 2 + len(msg.Version)) } 164 func (msg *TVersion) Type() MsgType { return Tversion } 165 func (msg *TVersion) GetTag() uint16 { return msg.Tag } 166 func (msg *TVersion) SetTag(t uint16) { msg.Tag = t } 167 func (msg *TVersion) marshal() []byte { 168 m := make([]byte, msg.Size()) 169 pbit32(m[0:4], msg.Size()) 170 m[4] = uint8(Tversion) 171 pbit16(m[5:7], msg.Tag) 172 pbit32(m[7:11], msg.Msize) 173 v := msg.Version 174 pbit16(m[11:13], uint16(len(v))) 175 for i := 0; i < len(v); i++ { 176 m[13+i] = v[i] 177 } 178 return m 179 } 180 func (msg *TVersion) String() string { 181 return fmt.Sprintf("Tversion Tag %d msize %d version '%s'", 182 msg.Tag, msg.Msize, msg.Version) 183 } 184 185 type RVersion struct { 186 Tag uint16 187 Msize uint32 188 Version string 189 } 190 191 func newRVersion(buf []byte) *RVersion { 192 msg := new(RVersion) 193 msg.Tag = gbit16(buf[5:7]) 194 msg.Msize = gbit32(buf[7:11]) 195 vs := gbit16(buf[11:13]) 196 msg.Version = string(buf[13 : 13+vs]) 197 return msg 198 } 199 func (msg *RVersion) Size() uint32 { return uint32(4 + 1 + 2 + 4 + 2 + len(msg.Version)) } 200 func (msg *RVersion) Type() MsgType { return Rversion } 201 func (msg *RVersion) GetTag() uint16 { return msg.Tag } 202 func (msg *RVersion) SetTag(t uint16) { msg.Tag = t } 203 func (msg *RVersion) marshal() []byte { 204 cur := 0 205 buf := make([]byte, msg.Size()) 206 pbit32(buf[cur:cur+4], msg.Size()) 207 cur += 4 208 buf[cur] = uint8(Rversion) 209 cur += 1 210 pbit16(buf[cur:cur+2], msg.Tag) 211 cur += 2 212 pbit32(buf[cur:cur+4], msg.Msize) 213 cur += 4 214 pbit16(buf[cur:cur+2], uint16(len(msg.Version))) 215 cur += 2 216 for i, b := range []byte(msg.Version) { 217 buf[cur+i] = b 218 } 219 cur += len(msg.Version) 220 if cur != len(buf) { 221 panic("length of buf and cursor not match") 222 } 223 return buf 224 } 225 func (msg *RVersion) String() string { 226 return fmt.Sprintf("Rversion Tag %d msize %d version '%s'", 227 msg.Tag, msg.Msize, msg.Version) 228 } 229 230 type TAuth struct { 231 Tag uint16 232 Afid uint32 233 Uname string 234 Aname string 235 } 236 237 func newTAuth(buf []byte) *TAuth { 238 cur := 0 239 msg := new(TAuth) 240 cur += 4 241 cur += 1 // message type 242 msg.Tag = gbit16(buf[cur : cur+2]) 243 cur += 2 244 msg.Afid = gbit32(buf[cur : cur+4]) 245 cur += 4 246 l := int(gbit16(buf[cur : cur+2])) 247 cur += 2 248 msg.Uname = string(buf[cur : cur+l]) 249 cur += l 250 l = int(gbit16(buf[cur : cur+2])) 251 cur += 2 252 msg.Aname = string(buf[cur : cur+l]) 253 cur += l 254 if cur != int(gbit32(buf[0:4])) { 255 panic("length of buf and cursor position not match") 256 } 257 return msg 258 } 259 func (msg *TAuth) Size() uint32 { 260 return uint32(4 + 1 + 2 + 4 + 2 + len(msg.Uname) + 2 + len(msg.Aname)) 261 } 262 func (msg *TAuth) Type() MsgType { return Tauth } 263 func (msg *TAuth) GetTag() uint16 { return msg.Tag } 264 func (msg *TAuth) SetTag(t uint16) { msg.Tag = t } 265 func (msg *TAuth) marshal() []byte { 266 cur := 0 267 buf := make([]byte, msg.Size()) 268 pbit32(buf[cur:cur+4], msg.Size()) 269 cur += 4 270 buf[cur] = uint8(Tauth) 271 cur += 1 272 pbit16(buf[cur:cur+2], msg.Tag) 273 cur += 2 274 pbit32(buf[cur:cur+4], msg.Afid) 275 cur += 4 276 pbit16(buf[cur:cur+2], uint16(len(msg.Uname))) 277 cur += 2 278 for i := 0; i < len(msg.Uname); i++ { 279 buf[cur+i] = msg.Uname[i] 280 } 281 cur += len(msg.Uname) 282 pbit16(buf[cur:cur+2], uint16(len(msg.Aname))) 283 cur += 2 284 for i := 0; i < len(msg.Aname); i++ { 285 buf[cur+i] = msg.Aname[i] 286 } 287 cur += len(msg.Aname) 288 if cur != len(buf) { 289 panic("length of buf and cursor position don't match") 290 } 291 return buf 292 } 293 func (msg *TAuth) String() string { 294 afid := int64(msg.Afid) 295 if afid == int64(NOFID) { 296 afid = -1 297 } 298 return fmt.Sprintf("Tauth Tag %d afid %d uname %s aname %s", 299 msg.Tag, afid, msg.Uname, msg.Aname) 300 } 301 302 type RAuth struct { 303 Tag uint16 304 Aqid Qid 305 } 306 307 func newRAuth(buf []byte) *RAuth { 308 msg := new(RAuth) 309 msg.Tag = gbit16(buf[5:7]) 310 msg.Aqid = unmarshalQid(buf[7:]) 311 return msg 312 } 313 func (msg *RAuth) Size() uint32 { return 4 + 1 + 2 + 13 } 314 func (msg *RAuth) Type() MsgType { return Rauth } 315 func (msg *RAuth) GetTag() uint16 { return msg.Tag } 316 func (msg *RAuth) SetTag(t uint16) { msg.Tag = t } 317 func (msg *RAuth) marshal() []byte { 318 cur := 0 319 buf := make([]byte, msg.Size()) 320 pbit32(buf[cur:cur+4], msg.Size()) 321 cur += 4 322 buf[cur] = uint8(Rauth) 323 cur += 1 324 pbit16(buf[cur:cur+2], msg.Tag) 325 cur += 2 326 qid := msg.Aqid.marshal() 327 for i := 0; i < len(qid); i++ { 328 buf[cur+i] = qid[i] 329 } 330 cur += len(qid) 331 if cur != len(buf) { 332 panic("length of buf and cursor position don't match") 333 } 334 return buf 335 } 336 func (msg *RAuth) String() string { 337 return fmt.Sprintf("Tauth Tag %d aqid %v", 338 msg.Tag, msg.Aqid) 339 } 340 341 type TAttach struct { 342 Tag uint16 343 Fid uint32 344 Afid uint32 345 Uname string 346 Aname string 347 } 348 349 func newTAttach(buf []byte) *TAttach { 350 cur := 0 351 msg := new(TAttach) 352 cur += 4 353 cur += 1 // message type 354 msg.Tag = gbit16(buf[cur : cur+2]) 355 cur += 2 356 msg.Fid = gbit32(buf[cur : cur+4]) 357 cur += 4 358 msg.Afid = gbit32(buf[cur : cur+4]) 359 cur += 4 360 l := int(gbit16(buf[cur : cur+2])) 361 cur += 2 362 msg.Uname = string(buf[cur : cur+l]) 363 cur += l 364 l = int(gbit16(buf[cur : cur+2])) 365 cur += 2 366 msg.Aname = string(buf[cur : cur+l]) 367 cur += l 368 if cur != int(gbit32(buf[0:4])) { 369 panic("length of buf and cursor position not match") 370 } 371 return msg 372 } 373 func (msg *TAttach) Size() uint32 { 374 return uint32(4 + 1 + 2 + 4 + 4 + 2 + len(msg.Uname) + 2 + len(msg.Aname)) 375 } 376 func (msg *TAttach) Type() MsgType { return Tattach } 377 func (msg *TAttach) GetTag() uint16 { return msg.Tag } 378 func (msg *TAttach) SetTag(t uint16) { msg.Tag = t } 379 func (msg *TAttach) marshal() []byte { 380 cur := 0 381 buf := make([]byte, msg.Size()) 382 pbit32(buf[cur:cur+4], msg.Size()) 383 cur += 4 384 buf[cur] = uint8(msg.Type()) 385 cur += 1 386 pbit16(buf[cur:cur+2], msg.Tag) 387 cur += 2 388 pbit32(buf[cur:cur+4], msg.Fid) 389 cur += 4 390 pbit32(buf[cur:cur+4], msg.Afid) 391 cur += 4 392 pbit16(buf[cur:cur+2], uint16(len(msg.Uname))) 393 cur += 2 394 for i := 0; i < len(msg.Uname); i++ { 395 buf[cur+i] = msg.Uname[i] 396 } 397 cur += len(msg.Uname) 398 pbit16(buf[cur:cur+2], uint16(len(msg.Aname))) 399 cur += 2 400 for i := 0; i < len(msg.Aname); i++ { 401 buf[cur+i] = msg.Aname[i] 402 } 403 cur += len(msg.Aname) 404 if cur != len(buf) { 405 panic("length of buf and cursor position don't match") 406 } 407 return buf 408 } 409 func (msg *TAttach) String() string { 410 fid := int64(msg.Fid) 411 if fid == int64(NOFID) { 412 fid = -1 413 } 414 afid := int64(msg.Afid) 415 if afid == int64(NOFID) { 416 afid = -1 417 } 418 return fmt.Sprintf("Tattach Tag %d fid %d afid %d uname %s aname %s", 419 msg.Tag, fid, afid, msg.Uname, msg.Aname) 420 } 421 422 type RAttach struct { 423 Tag uint16 424 Qid Qid 425 } 426 427 func newRAttach(buf []byte) *RAttach { 428 msg := new(RAttach) 429 msg.Tag = gbit16(buf[5:7]) 430 msg.Qid = unmarshalQid(buf[7:]) 431 return msg 432 } 433 func (msg *RAttach) Size() uint32 { return 4 + 1 + 2 + 13 } 434 func (msg *RAttach) Type() MsgType { return Rattach } 435 func (msg *RAttach) GetTag() uint16 { return msg.Tag } 436 func (msg *RAttach) SetTag(t uint16) { msg.Tag = t } 437 func (msg *RAttach) marshal() []byte { 438 cur := 0 439 buf := make([]byte, msg.Size()) 440 pbit32(buf[cur:cur+4], msg.Size()) 441 cur += 4 442 buf[cur] = uint8(Rattach) 443 cur += 1 444 pbit16(buf[cur:cur+2], msg.Tag) 445 cur += 2 446 qid := msg.Qid.marshal() 447 for i := 0; i < len(qid); i++ { 448 buf[cur+i] = qid[i] 449 } 450 cur += len(qid) 451 if cur != len(buf) { 452 panic("length of buf and cursor position don't match") 453 } 454 return buf 455 } 456 func (msg *RAttach) String() string { 457 return fmt.Sprintf("Rattach Tag %d qid %v", 458 msg.Tag, msg.Qid) 459 } 460 461 type RError struct { 462 Tag uint16 463 Ename error 464 } 465 466 func newRError(buf []byte) *RError { 467 msg := new(RError) 468 msg.Tag = gbit16(buf[5:7]) 469 es := gbit16(buf[7:9]) 470 msg.Ename = fmt.Errorf("%s", string(buf[9:9+es])) 471 return msg 472 } 473 func (msg *RError) Size() uint32 { return uint32(4 + 1 + 2 + 2 + len(msg.Ename.Error())) } 474 func (msg *RError) Type() MsgType { return Rerror } 475 func (msg *RError) GetTag() uint16 { return msg.Tag } 476 func (msg *RError) SetTag(t uint16) { msg.Tag = t } 477 func (msg *RError) marshal() []byte { 478 cur := 0 479 buf := make([]byte, msg.Size()) 480 pbit32(buf[cur:cur+4], msg.Size()) 481 cur += 4 482 buf[cur] = uint8(Rerror) 483 cur += 1 484 pbit16(buf[cur:cur+2], msg.Tag) 485 cur += 2 486 ename := msg.Ename.Error() 487 pbit16(buf[cur:cur+2], uint16(len(ename))) 488 cur += 2 489 for i := 0; i < len(ename); i++ { 490 buf[cur+i] = ename[i] 491 } 492 cur += len(ename) 493 if cur != len(buf) { 494 panic("length of buf and cursor position don't match") 495 } 496 return buf 497 } 498 499 func (msg *RError) String() string { 500 return fmt.Sprintf("Rerror Tag %d ename %v", msg.Tag, msg.Ename.Error()) 501 } 502 503 type TFlush struct { 504 Tag uint16 505 Oldtag uint16 506 } 507 508 func newTFlush(buf []byte) *TFlush { 509 msg := new(TFlush) 510 msg.Tag = gbit16(buf[5:7]) 511 msg.Oldtag = gbit16(buf[7:9]) 512 return msg 513 } 514 515 func (msg *TFlush) Size() uint32 { return 9 } 516 func (msg *TFlush) Type() MsgType { return Tflush } 517 func (msg *TFlush) GetTag() uint16 { return msg.Tag } 518 func (msg *TFlush) SetTag(t uint16) { msg.Tag = t } 519 func (msg *TFlush) marshal() []byte { 520 buf := make([]byte, msg.Size()) 521 pbit32(buf[0:4], msg.Size()) 522 buf[4] = uint8(msg.Type()) 523 pbit16(buf[5:7], msg.Tag) 524 pbit16(buf[7:9], msg.Oldtag) 525 return buf 526 } 527 func (msg *TFlush) String() string { 528 return fmt.Sprintf("Tflush Tag %d oldTag %d", msg.Tag, msg.Oldtag) 529 } 530 531 type RFlush struct { 532 Tag uint16 533 } 534 535 func newRFlush(buf []byte) *RFlush { 536 msg := new(RFlush) 537 msg.Tag = gbit16(buf[5:7]) 538 return msg 539 } 540 541 func (msg *RFlush) Size() uint32 { return 7 } 542 func (msg *RFlush) Type() MsgType { return Rflush } 543 func (msg *RFlush) GetTag() uint16 { return msg.Tag } 544 func (msg *RFlush) SetTag(t uint16) { msg.Tag = t } 545 func (msg *RFlush) marshal() []byte { 546 buf := make([]byte, msg.Size()) 547 pbit32(buf[0:4], msg.Size()) 548 buf[4] = uint8(msg.Type()) 549 pbit16(buf[5:7], msg.Tag) 550 return buf 551 } 552 func (msg *RFlush) String() string { 553 return fmt.Sprintf("Rflush Tag %d", msg.Tag) 554 } 555 556 type TWalk struct { 557 Tag uint16 558 Fid uint32 559 Newfid uint32 560 Wnames []string 561 } 562 563 func newTWalk(buf []byte) *TWalk { 564 cur := 0 565 msg := new(TWalk) 566 msize := gbit32(buf[cur : cur+4]) 567 cur += 4 568 cur += 1 // msgType 569 msg.Tag = gbit16(buf[cur : cur+2]) 570 cur += 2 571 msg.Fid = gbit32(buf[cur : cur+4]) 572 cur += 4 573 msg.Newfid = gbit32(buf[cur : cur+4]) 574 cur += 4 575 nwname := gbit16(buf[cur : cur+2]) 576 cur += 2 577 msg.Wnames = make([]string, nwname) 578 for i := 0; i < int(nwname); i++ { 579 size := int(gbit16(buf[cur : cur+2])) 580 cur += 2 581 msg.Wnames[i] = string(buf[cur : cur+size]) 582 cur += size 583 } 584 if cur != int(msize) { 585 panic(fmt.Errorf("message size %d != cursor position %d", msize, cur)) 586 } 587 return msg 588 } 589 590 func (msg *TWalk) Size() uint32 { 591 size := uint32(4 + 1 + 2 + 4 + 4 + 2) 592 for _, wn := range msg.Wnames { 593 size += 2 + uint32(len(wn)) 594 } 595 return size 596 } 597 func (msg *TWalk) Type() MsgType { return Twalk } 598 func (msg *TWalk) GetTag() uint16 { return msg.Tag } 599 func (msg *TWalk) SetTag(t uint16) { msg.Tag = t } 600 func (msg *TWalk) marshal() []byte { 601 cur := 0 602 buf := make([]byte, msg.Size()) 603 pbit32(buf[cur:cur+4], msg.Size()) 604 cur += 4 605 buf[cur] = uint8(Twalk) 606 cur += 1 607 pbit16(buf[cur:cur+2], msg.Tag) 608 cur += 2 609 pbit32(buf[cur:cur+4], msg.Fid) 610 cur += 4 611 pbit32(buf[cur:cur+4], msg.Newfid) 612 cur += 4 613 nwname := uint16(len(msg.Wnames)) 614 pbit16(buf[cur:cur+2], nwname) 615 cur += 2 616 for _, wn := range msg.Wnames { 617 pbit16(buf[cur:cur+2], uint16(len(wn))) 618 cur += 2 619 for i := 0; i < len(wn); i++ { 620 buf[cur+i] = wn[i] 621 } 622 cur += len(wn) 623 } 624 return buf 625 } 626 627 func (msg *TWalk) String() string { 628 s := fmt.Sprintf("Twalk Tag %d fid %d newfid %d nwname %d", 629 msg.Tag, msg.Fid, msg.Newfid, len(msg.Wnames)) 630 for i, wn := range msg.Wnames { 631 s += fmt.Sprintf(" %d:%s", i, wn) 632 } 633 return s 634 } 635 636 type RWalk struct { 637 Tag uint16 638 Qids []Qid 639 } 640 641 func newRWalk(buf []byte) *RWalk { 642 msg := new(RWalk) 643 msg.Tag = gbit16(buf[5:7]) 644 nwqid := int(gbit16(buf[7:9])) 645 msg.Qids = make([]Qid, nwqid) 646 cur := 9 647 for i := 0; i < nwqid; i++ { 648 msg.Qids[i] = unmarshalQid(buf[cur : cur+13]) 649 cur += 13 650 } 651 if int(msg.Size()) != cur { 652 panic("length of buf and cursor position don't match") 653 } 654 return msg 655 } 656 func (msg *RWalk) Size() uint32 { 657 return uint32(4 + 1 + 2 + 2 + len(msg.Qids)*13) 658 } 659 func (msg *RWalk) Type() MsgType { return Rwalk } 660 func (msg *RWalk) GetTag() uint16 { return msg.Tag } 661 func (msg *RWalk) SetTag(t uint16) { msg.Tag = t } 662 func (msg *RWalk) marshal() []byte { 663 cur := 0 664 buf := make([]byte, msg.Size()) 665 pbit32(buf[cur:cur+4], msg.Size()) 666 cur += 4 667 buf[cur] = uint8(msg.Type()) 668 cur += 1 669 pbit16(buf[cur:cur+2], msg.Tag) 670 cur += 2 671 pbit16(buf[cur:cur+2], uint16(len(msg.Qids))) 672 cur += 2 673 for _, qid := range msg.Qids { 674 for i, bit := range qid.marshal() { 675 buf[cur+i] = bit 676 } 677 cur += 13 678 } 679 if cur != len(buf) { 680 panic("length of buf and cursor position don't match") 681 } 682 return buf 683 } 684 func (msg *RWalk) String() string { 685 s := fmt.Sprintf("Rwalk Tag %d nwqid %d", msg.Tag, len(msg.Qids)) 686 for i, q := range msg.Qids { 687 s += fmt.Sprintf(" %d:%v", i, q) 688 } 689 return s 690 } 691 692 type TOpen struct { 693 Tag uint16 694 Fid uint32 695 Mode OpenMode 696 } 697 698 func newTOpen(buf []byte) *TOpen { 699 cur := 0 700 msg := new(TOpen) 701 size := gbit32(buf[cur : cur+4]) 702 cur += 4 703 cur += 1 // type 704 msg.Tag = gbit16(buf[cur : cur+2]) 705 cur += 2 706 msg.Fid = gbit32(buf[cur : cur+4]) 707 cur += 4 708 msg.Mode = OpenMode(buf[cur]) 709 cur += 1 710 if cur != int(size) { 711 panic("size and cursor position don't match") 712 } 713 return msg 714 } 715 func (msg *TOpen) Size() uint32 { return 4 + 1 + 2 + 4 + 1 } 716 func (msg *TOpen) Type() MsgType { return Topen } 717 func (msg *TOpen) GetTag() uint16 { return msg.Tag } 718 func (msg *TOpen) SetTag(t uint16) { msg.Tag = t } 719 func (msg *TOpen) marshal() []byte { 720 cur := 0 721 buf := make([]byte, msg.Size()) 722 pbit32(buf[cur:cur+4], msg.Size()) 723 cur += 4 724 buf[cur] = uint8(Topen) 725 cur += 1 726 pbit16(buf[cur:cur+2], msg.Tag) 727 cur += 2 728 pbit32(buf[cur:cur+4], msg.Fid) 729 cur += 4 730 buf[cur] = uint8(msg.Mode) 731 cur += 1 732 if cur != len(buf) { 733 panic("length of buf and cursor position don't match") 734 } 735 return buf 736 } 737 738 func (msg *TOpen) String() string { 739 return fmt.Sprintf("Topen Tag %d fid %d mode 0x%x", 740 msg.Tag, msg.Fid, msg.Mode) 741 } 742 743 type ROpen struct { 744 Tag uint16 745 Qid Qid 746 Iounit uint32 747 } 748 749 func newROpen(buf []byte) *ROpen { 750 msg := new(ROpen) 751 msg.Tag = gbit16(buf[5:7]) 752 msg.Qid = unmarshalQid(buf[7:20]) 753 msg.Iounit = gbit32(buf[20:24]) 754 return msg 755 } 756 func (msg *ROpen) Size() uint32 { 757 return uint32(4 + 1 + 2 + 13 + 4) 758 } 759 func (msg *ROpen) Type() MsgType { return Ropen } 760 func (msg *ROpen) GetTag() uint16 { return msg.Tag } 761 func (msg *ROpen) SetTag(t uint16) { msg.Tag = t } 762 func (msg *ROpen) marshal() []byte { 763 cur := 0 764 buf := make([]byte, msg.Size()) 765 pbit32(buf[cur:cur+4], msg.Size()) 766 cur += 4 767 buf[cur] = uint8(msg.Type()) 768 cur += 1 769 pbit16(buf[cur:cur+2], msg.Tag) 770 cur += 2 771 for i, bit := range msg.Qid.marshal() { 772 buf[cur+i] = bit 773 } 774 cur += 13 775 pbit32(buf[cur:cur+4], msg.Iounit) 776 cur += 4 777 if cur != len(buf) { 778 panic("length of buf and cursor position don't match") 779 } 780 return buf 781 } 782 func (msg *ROpen) String() string { 783 return fmt.Sprintf("Ropen Tag %d qid %v iounit %d", 784 msg.Tag, msg.Qid, msg.Iounit) 785 } 786 787 type TCreate struct { 788 Tag uint16 789 Fid uint32 790 Name string 791 Perm FileMode 792 Mode OpenMode 793 } 794 795 func newTCreate(buf []byte) *TCreate { 796 msg := new(TCreate) 797 cur := 5 798 msg.Tag = gbit16(buf[cur : cur+2]) 799 cur += 2 800 msg.Fid = gbit32(buf[cur : cur+4]) 801 cur += 4 802 nameSize := int(gbit16(buf[cur : cur+2])) 803 cur += 2 804 msg.Name = string(buf[cur : cur+nameSize]) 805 cur += nameSize 806 msg.Perm = FileMode(gbit32(buf[cur : cur+4])) 807 cur += 4 808 msg.Mode = OpenMode(buf[cur]) 809 cur += 1 810 if cur != len(buf) { 811 panic("length and cursor position don't match") 812 } 813 return msg 814 } 815 816 func (msg *TCreate) Size() uint32 { 817 return uint32(4 + 1 + 2 + 4 + 2 + len(msg.Name) + 4 + 1) 818 } 819 func (msg *TCreate) Type() MsgType { return Tcreate } 820 func (msg *TCreate) GetTag() uint16 { return msg.Tag } 821 func (msg *TCreate) SetTag(t uint16) { msg.Tag = t } 822 func (msg *TCreate) marshal() []byte { 823 cur := 0 824 buf := make([]byte, msg.Size()) 825 pbit32(buf[cur:cur+4], msg.Size()) 826 cur += 4 827 buf[cur] = uint8(msg.Type()) 828 cur += 1 829 pbit16(buf[cur:cur+2], msg.Tag) 830 cur += 2 831 pbit32(buf[cur:cur+4], msg.Fid) 832 cur += 4 833 nameSize := len(msg.Name) 834 pbit16(buf[cur:cur+2], uint16(nameSize)) 835 cur += 2 836 for i := 0; i < nameSize; i++ { 837 buf[cur+i] = msg.Name[i] 838 } 839 cur += nameSize 840 pbit32(buf[cur:cur+4], uint32(msg.Perm)) 841 cur += 4 842 buf[cur] = uint8(msg.Mode) 843 cur += 1 844 if cur != len(buf) { 845 panic("length of buf and cursor position don't match") 846 } 847 return buf 848 } 849 850 func (msg *TCreate) String() string { 851 return fmt.Sprintf("Tcreate Tag %d fid %d name %s perm %v mode 0x%x", 852 msg.Tag, msg.Fid, msg.Name, permString(msg.Perm), msg.Mode) 853 } 854 855 type RCreate struct { 856 Tag uint16 857 Qid Qid 858 Iounit uint32 859 } 860 861 func newRCreate(buf []byte) *RCreate { 862 msg := new(RCreate) 863 msg.Tag = gbit16(buf[5:7]) 864 msg.Qid = unmarshalQid(buf[7:20]) 865 msg.Iounit = gbit32(buf[20:24]) 866 return msg 867 } 868 func (msg *RCreate) Size() uint32 { 869 return uint32(4 + 1 + 2 + 13 + 4) 870 } 871 func (msg *RCreate) Type() MsgType { return Rcreate } 872 func (msg *RCreate) GetTag() uint16 { return msg.Tag } 873 func (msg *RCreate) SetTag(t uint16) { msg.Tag = t } 874 func (msg *RCreate) marshal() []byte { 875 cur := 0 876 buf := make([]byte, msg.Size()) 877 pbit32(buf[cur:cur+4], msg.Size()) 878 cur += 4 879 buf[cur] = uint8(msg.Type()) 880 cur += 1 881 pbit16(buf[cur:cur+2], msg.Tag) 882 cur += 2 883 for i, bit := range msg.Qid.marshal() { 884 buf[cur+i] = bit 885 } 886 cur += 13 887 pbit32(buf[cur:cur+4], msg.Iounit) 888 cur += 4 889 if cur != len(buf) { 890 panic("length of buf and cursor position don't match") 891 } 892 return buf 893 } 894 func (msg *RCreate) String() string { 895 return fmt.Sprintf("Rcreate Tag %d qid %v iounit %d", 896 msg.Tag, msg.Qid, msg.Iounit) 897 } 898 899 type TRead struct { 900 Tag uint16 901 Fid uint32 902 Offset uint64 903 Count uint32 904 } 905 906 func newTRead(buf []byte) *TRead { 907 cur := 0 908 msg := new(TRead) 909 size := gbit32(buf[cur : cur+4]) 910 cur += 4 911 cur += 1 // type 912 msg.Tag = gbit16(buf[cur : cur+2]) 913 cur += 2 914 msg.Fid = gbit32(buf[cur : cur+4]) 915 cur += 4 916 msg.Offset = gbit64(buf[cur : cur+8]) 917 cur += 8 918 msg.Count = gbit32(buf[cur : cur+4]) 919 cur += 4 920 if cur != int(size) { 921 panic(fmt.Errorf("size %d != cursor position %d", size, cur)) 922 } 923 return msg 924 } 925 func (msg *TRead) Size() uint32 { return 4 + 1 + 2 + 4 + 8 + 4 } 926 func (msg *TRead) Type() MsgType { return Tread } 927 func (msg *TRead) GetTag() uint16 { return msg.Tag } 928 func (msg *TRead) SetTag(t uint16) { msg.Tag = t } 929 func (msg *TRead) marshal() []byte { 930 cur := 0 931 buf := make([]byte, msg.Size()) 932 pbit32(buf[cur:cur+4], msg.Size()) 933 cur += 4 934 buf[cur] = uint8(msg.Type()) 935 cur += 1 936 pbit16(buf[cur:cur+2], msg.Tag) 937 cur += 2 938 pbit32(buf[cur:cur+4], msg.Fid) 939 cur += 4 940 pbit64(buf[cur:cur+8], msg.Offset) 941 cur += 8 942 pbit32(buf[cur:cur+4], msg.Count) 943 cur += 4 944 if cur != len(buf) { 945 panic("length of buf and cursor position don't match") 946 } 947 return buf 948 } 949 func (msg *TRead) String() string { 950 return fmt.Sprintf("Tread Tag %d fid %d offset %d count %d", 951 msg.Tag, msg.Fid, msg.Offset, msg.Count) 952 } 953 954 type RRead struct { 955 Tag uint16 956 Count uint32 957 Data []byte 958 } 959 960 func newRRead(buf []byte) *RRead { 961 msg := new(RRead) 962 msg.Tag = gbit16(buf[5:7]) 963 msg.Count = gbit32(buf[7:11]) 964 msg.Data = make([]byte, msg.Count) 965 for i := 0; i < int(msg.Count); i++ { 966 msg.Data[i] = buf[11+i] 967 } 968 return msg 969 } 970 func (msg *RRead) Size() uint32 { 971 return uint32(4 + 1 + 2 + 4 + msg.Count) 972 } 973 func (msg *RRead) Type() MsgType { return Rread } 974 func (msg *RRead) GetTag() uint16 { return msg.Tag } 975 func (msg *RRead) SetTag(t uint16) { msg.Tag = t } 976 func (msg *RRead) marshal() []byte { 977 if uint32(len(msg.Data)) != msg.Count { 978 panic(fmt.Errorf("data size %d and count %d don't match", 979 len(msg.Data), msg.Count)) 980 } 981 cur := 0 982 buf := make([]byte, msg.Size()) 983 pbit32(buf[cur:cur+4], msg.Size()) 984 cur += 4 985 buf[cur] = uint8(msg.Type()) 986 cur += 1 987 pbit16(buf[cur:cur+2], msg.Tag) 988 cur += 2 989 pbit32(buf[cur:cur+4], msg.Count) 990 cur += 4 991 for i := 0; i < len(msg.Data); i++ { 992 buf[cur+i] = msg.Data[i] 993 } 994 cur += len(msg.Data) 995 if cur != len(buf) { 996 panic("length of buf and cursor position don't match") 997 } 998 return buf 999 } 1000 func (msg *RRead) String() string { 1001 s := fmt.Sprintf("Rread Tag %d count %d '", 1002 msg.Tag, msg.Count) 1003 i := 0 1004 for ; i+4 < len(msg.Data) && i < 64; i += 4 { 1005 s += fmt.Sprintf(" %02x%02x%02x%02x", 1006 uint8(msg.Data[i]), uint8(msg.Data[i+1]), 1007 uint8(msg.Data[i+2]), uint8(msg.Data[i+3])) 1008 } 1009 if i != len(msg.Data) && i != 64 { 1010 s += " " 1011 } 1012 for ; i < len(msg.Data) && i < 64; i++ { 1013 s += fmt.Sprintf("%02x", uint8(msg.Data[i])) 1014 } 1015 s += "'" 1016 return s 1017 } 1018 1019 type TWrite struct { 1020 Tag uint16 1021 Fid uint32 1022 Offset uint64 1023 Count uint32 1024 Data []byte 1025 } 1026 1027 func newTWrite(buf []byte) *TWrite { 1028 cur := 5 1029 msg := new(TWrite) 1030 msg.Tag = gbit16(buf[cur : cur+2]) 1031 cur += 2 1032 msg.Fid = gbit32(buf[cur : cur+4]) 1033 cur += 4 1034 msg.Offset = gbit64(buf[cur : cur+8]) 1035 cur += 8 1036 msg.Count = gbit32(buf[cur : cur+4]) 1037 cur += 4 1038 msg.Data = make([]byte, msg.Count) 1039 for i := 0; i < int(msg.Count); i++ { 1040 msg.Data[i] = buf[cur+i] 1041 } 1042 cur += int(msg.Count) 1043 if cur != len(buf) { 1044 panic("length of buf and cursor position don't match") 1045 } 1046 return msg 1047 } 1048 func (msg *TWrite) Size() uint32 { 1049 return uint32(4 + 1 + 2 + 4 + 8 + 4 + len(msg.Data)) 1050 } 1051 func (msg *TWrite) Type() MsgType { return Twrite } 1052 func (msg *TWrite) GetTag() uint16 { return msg.Tag } 1053 func (msg *TWrite) SetTag(t uint16) { msg.Tag = t } 1054 func (msg *TWrite) marshal() []byte { 1055 cur := 0 1056 buf := make([]byte, msg.Size()) 1057 pbit32(buf[cur:cur+4], msg.Size()) 1058 cur += 4 1059 buf[cur] = uint8(msg.Type()) 1060 cur += 1 1061 pbit16(buf[cur:cur+2], msg.Tag) 1062 cur += 2 1063 pbit32(buf[cur:cur+4], msg.Fid) 1064 cur += 4 1065 pbit64(buf[cur:cur+8], msg.Offset) 1066 cur += 8 1067 pbit32(buf[cur:cur+4], msg.Count) 1068 cur += 4 1069 for i := 0; i < int(msg.Count); i++ { 1070 buf[cur+i] = msg.Data[i] 1071 } 1072 cur += int(msg.Count) 1073 if cur != len(buf) { 1074 panic("length of buf and cursor position don't match") 1075 } 1076 return buf 1077 } 1078 func (msg *TWrite) String() string { 1079 return fmt.Sprintf("Twrite Tag %d fid %d offset %d count %d '%s'", 1080 msg.Tag, msg.Fid, msg.Offset, msg.Count, msg.Data) 1081 } 1082 1083 type RWrite struct { 1084 Tag uint16 1085 Count uint32 1086 } 1087 1088 func newRWrite(buf []byte) *RWrite { 1089 msg := new(RWrite) 1090 msg.Tag = gbit16(buf[5:7]) 1091 msg.Count = gbit32(buf[7:11]) 1092 return msg 1093 } 1094 func (msg *RWrite) Size() uint32 { 1095 return uint32(4 + 1 + 2 + 4) 1096 } 1097 func (msg *RWrite) Type() MsgType { return Rwrite } 1098 func (msg *RWrite) GetTag() uint16 { return msg.Tag } 1099 func (msg *RWrite) SetTag(t uint16) { msg.Tag = t } 1100 func (msg *RWrite) marshal() []byte { 1101 cur := 0 1102 buf := make([]byte, msg.Size()) 1103 pbit32(buf[cur:cur+4], msg.Size()) 1104 cur += 4 1105 buf[cur] = uint8(msg.Type()) 1106 cur += 1 1107 pbit16(buf[cur:cur+2], msg.Tag) 1108 cur += 2 1109 pbit32(buf[cur:cur+4], msg.Count) 1110 cur += 4 1111 if cur != len(buf) { 1112 panic("length of buf and cursor position don't match") 1113 } 1114 return buf 1115 } 1116 1117 func (msg *RWrite) String() string { 1118 return fmt.Sprintf("Rwrite Tag %d count %d", msg.Tag, msg.Count) 1119 } 1120 1121 type TClunk struct { 1122 Tag uint16 1123 Fid uint32 1124 } 1125 1126 func newTClunk(buf []byte) *TClunk { 1127 msg := new(TClunk) 1128 msg.Tag = gbit16(buf[5:7]) 1129 msg.Fid = gbit32(buf[7:11]) 1130 return msg 1131 } 1132 1133 func (msg *TClunk) Size() uint32 { return 4 + 1 + 2 + 4 } 1134 func (msg *TClunk) Type() MsgType { return Tclunk } 1135 func (msg *TClunk) GetTag() uint16 { return msg.Tag } 1136 func (msg *TClunk) SetTag(t uint16) { msg.Tag = t } 1137 func (msg *TClunk) marshal() []byte { 1138 m := make([]byte, msg.Size()) 1139 pbit32(m[0:4], msg.Size()) 1140 m[4] = uint8(Tclunk) 1141 pbit16(m[5:7], msg.Tag) 1142 pbit32(m[7:11], msg.Fid) 1143 return m 1144 } 1145 func (msg *TClunk) String() string { 1146 return fmt.Sprintf("Tclunk Tag %d fid %d", 1147 msg.Tag, msg.Fid) 1148 } 1149 1150 type RClunk struct { 1151 Tag uint16 1152 } 1153 1154 func newRClunk(buf []byte) *RClunk { 1155 msg := new(RClunk) 1156 msg.Tag = gbit16(buf[5:7]) 1157 return msg 1158 } 1159 func (msg *RClunk) Size() uint32 { return 7 } 1160 func (msg *RClunk) Type() MsgType { return Rclunk } 1161 func (msg *RClunk) GetTag() uint16 { return msg.Tag } 1162 func (msg *RClunk) SetTag(t uint16) { msg.Tag = t } 1163 func (msg *RClunk) marshal() []byte { 1164 m := make([]byte, msg.Size()) 1165 pbit32(m[0:4], msg.Size()) 1166 m[4] = uint8(Rclunk) 1167 pbit16(m[5:7], msg.Tag) 1168 return m 1169 } 1170 func (msg *RClunk) String() string { 1171 return fmt.Sprintf("Rclunk Tag %d", msg.Tag) 1172 } 1173 1174 type TRemove struct { 1175 Tag uint16 1176 Fid uint32 1177 } 1178 1179 func newTRemove(buf []byte) *TRemove { 1180 msg := new(TRemove) 1181 msg.Tag = gbit16(buf[5:7]) 1182 msg.Fid = gbit32(buf[7:11]) 1183 return msg 1184 } 1185 1186 func (msg *TRemove) Size() uint32 { return 4 + 1 + 2 + 4 } 1187 func (msg *TRemove) Type() MsgType { return Tremove } 1188 func (msg *TRemove) GetTag() uint16 { return msg.Tag } 1189 func (msg *TRemove) SetTag(t uint16) { msg.Tag = t } 1190 func (msg *TRemove) marshal() []byte { 1191 m := make([]byte, msg.Size()) 1192 pbit32(m[0:4], msg.Size()) 1193 m[4] = uint8(msg.Type()) 1194 pbit16(m[5:7], msg.Tag) 1195 pbit32(m[7:11], msg.Fid) 1196 return m 1197 } 1198 func (msg *TRemove) String() string { 1199 return fmt.Sprintf("Tremove Tag %d fid %d", msg.Tag, msg.Fid) 1200 } 1201 1202 type RRemove struct { 1203 Tag uint16 1204 } 1205 1206 func newRRemove(buf []byte) *RRemove { 1207 msg := new(RRemove) 1208 msg.Tag = gbit16(buf[5:7]) 1209 return msg 1210 } 1211 func (msg *RRemove) Size() uint32 { return 4 + 1 + 2 } 1212 func (msg *RRemove) Type() MsgType { return Rremove } 1213 func (msg *RRemove) GetTag() uint16 { return msg.Tag } 1214 func (msg *RRemove) SetTag(t uint16) { msg.Tag = t } 1215 func (msg *RRemove) marshal() []byte { 1216 m := make([]byte, msg.Size()) 1217 pbit32(m[0:4], msg.Size()) 1218 m[4] = uint8(msg.Type()) 1219 pbit16(m[5:7], msg.Tag) 1220 return m 1221 } 1222 func (msg *RRemove) String() string { 1223 return fmt.Sprintf("Rremove Tag %d", msg.Tag) 1224 } 1225 1226 type TStat struct { 1227 Tag uint16 1228 Fid uint32 1229 } 1230 1231 func newTStat(buf []byte) *TStat { 1232 msg := new(TStat) 1233 msg.Tag = gbit16(buf[5:7]) 1234 msg.Fid = gbit32(buf[7:11]) 1235 return msg 1236 } 1237 func (msg *TStat) Size() uint32 { return 4 + 1 + 2 + 4 } 1238 func (msg *TStat) Type() MsgType { return Tstat } 1239 func (msg *TStat) GetTag() uint16 { return msg.Tag } 1240 func (msg *TStat) SetTag(t uint16) { msg.Tag = t } 1241 func (msg *TStat) marshal() []byte { 1242 m := make([]byte, msg.Size()) 1243 pbit32(m[0:4], msg.Size()) 1244 m[4] = uint8(Tstat) 1245 pbit16(m[5:7], msg.Tag) 1246 pbit32(m[7:11], msg.Fid) 1247 return m 1248 } 1249 func (msg *TStat) String() string { 1250 return fmt.Sprintf("Tstat Tag %d fid %d", 1251 msg.Tag, msg.Fid) 1252 } 1253 1254 type RStat struct { 1255 Tag uint16 1256 Stat *Stat 1257 } 1258 1259 func newRStat(buf []byte) *RStat { 1260 msg := new(RStat) 1261 size := gbit32(buf[:4]) 1262 msg.Tag = gbit16(buf[5:7]) 1263 msg.Stat = NewStat(buf[9:size]) 1264 return msg 1265 } 1266 func (msg *RStat) Size() uint32 { 1267 return uint32(4 + 1 + 2 + 2 + 2 + msg.Stat.Size()) 1268 } 1269 func (msg *RStat) Type() MsgType { return Rstat } 1270 func (msg *RStat) GetTag() uint16 { return msg.Tag } 1271 func (msg *RStat) SetTag(t uint16) { msg.Tag = t } 1272 func (msg *RStat) marshal() []byte { 1273 buf := make([]byte, msg.Size()) 1274 pbit32(buf[0:4], msg.Size()) 1275 buf[4] = uint8(Rstat) 1276 pbit16(buf[5:7], msg.Tag) 1277 fiBuf := msg.Stat.marshal() 1278 pbit16(buf[7:9], uint16(len(fiBuf))) 1279 for i := 0; i < len(fiBuf); i++ { 1280 buf[9+i] = fiBuf[i] 1281 } 1282 return buf 1283 } 1284 1285 func (msg *RStat) String() string { 1286 return fmt.Sprintf("Rstat Tag %d stat %s", msg.Tag, msg.Stat) 1287 } 1288 1289 type TWstat struct { 1290 Tag uint16 1291 Fid uint32 1292 Stat *Stat 1293 } 1294 1295 func newTWstat(buf []byte) *TWstat { 1296 msg := new(TWstat) 1297 msg.Tag = gbit16(buf[5:7]) 1298 msg.Fid = gbit32(buf[7:11]) 1299 msg.Stat = NewStat(buf[13:]) 1300 return msg 1301 } 1302 func (msg *TWstat) Size() uint32 { 1303 return uint32(4 + 1 + 2 + 4 + 2 + 2 + msg.Stat.Size()) 1304 } 1305 func (msg *TWstat) Type() MsgType { return Twstat } 1306 func (msg *TWstat) GetTag() uint16 { return msg.Tag } 1307 func (msg *TWstat) SetTag(t uint16) { msg.Tag = t } 1308 func (msg *TWstat) marshal() []byte { 1309 buf := make([]byte, msg.Size()) 1310 pbit32(buf[0:4], msg.Size()) 1311 buf[4] = uint8(msg.Type()) 1312 pbit16(buf[5:7], msg.Tag) 1313 pbit32(buf[7:11], msg.Fid) 1314 fiBuf := msg.Stat.marshal() 1315 pbit16(buf[11:13], uint16(len(fiBuf))) 1316 for i := 0; i < len(fiBuf); i++ { 1317 buf[13+i] = fiBuf[i] 1318 } 1319 return buf 1320 } 1321 1322 func (msg *TWstat) String() string { 1323 return fmt.Sprintf("Twstat Tag %d fid %d stat %s", msg.Tag, msg.Fid, msg.Stat) 1324 } 1325 1326 type RWstat struct { 1327 Tag uint16 1328 } 1329 1330 func newRWstat(buf []byte) *RWstat { 1331 msg := new(RWstat) 1332 msg.Tag = gbit16(buf[5:7]) 1333 return msg 1334 } 1335 func (msg *RWstat) Size() uint32 { return 4 + 1 + 2 } 1336 func (msg *RWstat) Type() MsgType { return Rwstat } 1337 func (msg *RWstat) GetTag() uint16 { return msg.Tag } 1338 func (msg *RWstat) SetTag(t uint16) { msg.Tag = t } 1339 func (msg *RWstat) marshal() []byte { 1340 m := make([]byte, msg.Size()) 1341 pbit32(m[0:4], msg.Size()) 1342 m[4] = uint8(msg.Type()) 1343 pbit16(m[5:7], msg.Tag) 1344 return m 1345 } 1346 func (msg *RWstat) String() string { 1347 return fmt.Sprintf("Rwstat Tag %d", msg.Tag) 1348 }