github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/syscall/srpc_nacl.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Native Client SRPC message passing. 6 // This code is needed to invoke SecureRandom, the NaCl equivalent of /dev/random. 7 8 package syscall 9 10 import ( 11 "errors" 12 "sync" 13 "unsafe" 14 ) 15 16 // An srpcClient represents the client side of an SRPC connection. 17 type srpcClient struct { 18 fd int // to server 19 r msgReceiver 20 s msgSender 21 service map[string]srpcService // services by name 22 23 outMu sync.Mutex // protects writing to connection 24 25 mu sync.Mutex // protects following fields 26 muxer bool // is someone reading and muxing responses 27 pending map[uint32]*srpc 28 idGen uint32 // generator for request IDs 29 } 30 31 // An srpcService is a single method that the server offers. 32 type srpcService struct { 33 num uint32 // method number 34 fmt string // argument format; see "parsing of RPC messages" below 35 } 36 37 // An srpc represents a single srpc issued by a client. 38 type srpc struct { 39 Ret []interface{} 40 Done chan *srpc 41 Err error 42 c *srpcClient 43 id uint32 44 } 45 46 // newClient allocates a new SRPC client using the file descriptor fd. 47 func newClient(fd int) (*srpcClient, error) { 48 c := new(srpcClient) 49 c.fd = fd 50 c.r.fd = fd 51 c.s.fd = fd 52 c.service = make(map[string]srpcService) 53 c.pending = make(map[uint32]*srpc) 54 55 // service discovery request 56 m := &msg{ 57 isRequest: 1, 58 template: []interface{}{[]byte(nil)}, 59 size: []int{4000}, // max size to accept for returned byte slice 60 } 61 if err := m.pack(); err != nil { 62 return nil, errors.New("Native Client SRPC service_discovery: preparing request: " + err.Error()) 63 } 64 c.s.send(m) 65 m, err := c.r.recv() 66 if err != nil { 67 return nil, err 68 } 69 m.unpack() 70 if m.status != uint32(srpcOK) { 71 return nil, errors.New("Native Client SRPC service_discovery: " + srpcErrno(m.status).Error()) 72 } 73 list := m.value[0].([]byte) 74 var n uint32 75 for len(list) > 0 { 76 var line []byte 77 i := byteIndex(list, '\n') 78 if i < 0 { 79 line, list = list, nil 80 } else { 81 line, list = list[:i], list[i+1:] 82 } 83 i = byteIndex(line, ':') 84 if i >= 0 { 85 c.service[string(line)] = srpcService{n, string(line[i+1:])} 86 } 87 n++ 88 } 89 90 return c, nil 91 } 92 93 func byteIndex(b []byte, c byte) int { 94 for i, bi := range b { 95 if bi == c { 96 return i 97 } 98 } 99 return -1 100 } 101 102 var yourTurn srpc 103 104 func (c *srpcClient) wait(r *srpc) { 105 var rx *srpc 106 for rx = range r.Done { 107 if rx != &yourTurn { 108 break 109 } 110 c.input() 111 } 112 return 113 } 114 115 func (c *srpcClient) input() { 116 // read message 117 m, err := c.r.recv() 118 if err != nil { 119 println("Native Client SRPC receive error:", err.Error()) 120 return 121 } 122 if m.unpack(); m.status != uint32(srpcOK) { 123 println("Native Client SRPC receive error: invalid message: ", srpcErrno(m.status).Error()) 124 return 125 } 126 127 // deliver to intended recipient 128 c.mu.Lock() 129 rpc, ok := c.pending[m.id] 130 if ok { 131 delete(c.pending, m.id) 132 } 133 134 // wake a new muxer if there are more RPCs to read 135 c.muxer = false 136 for _, rpc := range c.pending { 137 c.muxer = true 138 rpc.Done <- &yourTurn 139 break 140 } 141 c.mu.Unlock() 142 if !ok { 143 println("Native Client: unexpected response for ID", m.id) 144 return 145 } 146 rpc.Ret = m.value 147 rpc.Done <- rpc 148 } 149 150 // Wait blocks until the RPC has finished. 151 func (r *srpc) Wait() { 152 r.c.wait(r) 153 } 154 155 // Start issues an RPC request for method name with the given arguments. 156 // The RPC r must not be in use for another pending request. 157 // To wait for the RPC to finish, receive from r.Done and then 158 // inspect r.Ret and r.Errno. 159 func (r *srpc) Start(name string, arg []interface{}) { 160 r.Err = nil 161 r.c.mu.Lock() 162 srv, ok := r.c.service[name] 163 if !ok { 164 r.c.mu.Unlock() 165 r.Err = srpcErrBadRPCNumber 166 r.Done <- r 167 return 168 } 169 r.c.pending[r.id] = r 170 if !r.c.muxer { 171 r.c.muxer = true 172 r.Done <- &yourTurn 173 } 174 r.c.mu.Unlock() 175 176 var m msg 177 m.id = r.id 178 m.isRequest = 1 179 m.rpc = srv.num 180 m.value = arg 181 182 // Fill in the return values and sizes to generate 183 // the right type chars. We'll take most any size. 184 185 // Skip over input arguments. 186 // We could check them against arg, but the server 187 // will do that anyway. 188 i := 0 189 for srv.fmt[i] != ':' { 190 i++ 191 } 192 format := srv.fmt[i+1:] 193 194 // Now the return prototypes. 195 m.template = make([]interface{}, len(format)) 196 m.size = make([]int, len(format)) 197 for i := 0; i < len(format); i++ { 198 switch format[i] { 199 default: 200 println("Native Client SRPC: unexpected service type " + string(format[i])) 201 r.Err = srpcErrBadRPCNumber 202 r.Done <- r 203 return 204 case 'b': 205 m.template[i] = false 206 case 'C': 207 m.template[i] = []byte(nil) 208 m.size[i] = 1 << 30 209 case 'd': 210 m.template[i] = float64(0) 211 case 'D': 212 m.template[i] = []float64(nil) 213 m.size[i] = 1 << 30 214 case 'h': 215 m.template[i] = int(-1) 216 case 'i': 217 m.template[i] = int32(0) 218 case 'I': 219 m.template[i] = []int32(nil) 220 m.size[i] = 1 << 30 221 case 's': 222 m.template[i] = "" 223 m.size[i] = 1 << 30 224 } 225 } 226 227 if err := m.pack(); err != nil { 228 r.Err = errors.New("Native Client RPC Start " + name + ": preparing request: " + err.Error()) 229 r.Done <- r 230 return 231 } 232 233 r.c.outMu.Lock() 234 r.c.s.send(&m) 235 r.c.outMu.Unlock() 236 } 237 238 // Call is a convenience wrapper that starts the RPC request, 239 // waits for it to finish, and then returns the results. 240 // Its implementation is: 241 // 242 // r.Start(name, arg) 243 // r.Wait() 244 // return r.Ret, r.Errno 245 // 246 func (c *srpcClient) Call(name string, arg ...interface{}) (ret []interface{}, err error) { 247 r := c.NewRPC(nil) 248 r.Start(name, arg) 249 r.Wait() 250 return r.Ret, r.Err 251 } 252 253 // NewRPC creates a new RPC on the client connection. 254 func (c *srpcClient) NewRPC(done chan *srpc) *srpc { 255 if done == nil { 256 done = make(chan *srpc, 1) 257 } 258 c.mu.Lock() 259 id := c.idGen 260 c.idGen++ 261 c.mu.Unlock() 262 return &srpc{Done: done, c: c, id: id} 263 } 264 265 // The current protocol number. 266 // Kind of useless, since there have been backwards-incompatible changes 267 // to the wire protocol that did not update the protocol number. 268 // At this point it's really just a sanity check. 269 const protocol = 0xc0da0002 270 271 // An srpcErrno is an SRPC status code. 272 type srpcErrno uint32 273 274 const ( 275 srpcOK srpcErrno = 256 + iota 276 srpcErrBreak 277 srpcErrMessageTruncated 278 srpcErrNoMemory 279 srpcErrProtocolMismatch 280 srpcErrBadRPCNumber 281 srpcErrBadArgType 282 srpcErrTooFewArgs 283 srpcErrTooManyArgs 284 srpcErrInArgTypeMismatch 285 srpcErrOutArgTypeMismatch 286 srpcErrInternalError 287 srpcErrAppError 288 ) 289 290 var srpcErrstr = [...]string{ 291 srpcOK - srpcOK: "ok", 292 srpcErrBreak - srpcOK: "break", 293 srpcErrMessageTruncated - srpcOK: "message truncated", 294 srpcErrNoMemory - srpcOK: "out of memory", 295 srpcErrProtocolMismatch - srpcOK: "protocol mismatch", 296 srpcErrBadRPCNumber - srpcOK: "invalid RPC method number", 297 srpcErrBadArgType - srpcOK: "unexpected argument type", 298 srpcErrTooFewArgs - srpcOK: "too few arguments", 299 srpcErrTooManyArgs - srpcOK: "too many arguments", 300 srpcErrInArgTypeMismatch - srpcOK: "input argument type mismatch", 301 srpcErrOutArgTypeMismatch - srpcOK: "output argument type mismatch", 302 srpcErrInternalError - srpcOK: "internal error", 303 srpcErrAppError - srpcOK: "application error", 304 } 305 306 func (e srpcErrno) Error() string { 307 if e < srpcOK || int(e-srpcOK) >= len(srpcErrstr) { 308 return "srpcErrno(" + itoa(int(e)) + ")" 309 } 310 return srpcErrstr[e-srpcOK] 311 } 312 313 // A msgHdr is the data argument to the imc_recvmsg 314 // and imc_sendmsg system calls. 315 type msgHdr struct { 316 iov *iov 317 niov int32 318 desc *int32 319 ndesc int32 320 flags uint32 321 } 322 323 // A single region for I/O. 324 type iov struct { 325 base *byte 326 len int32 327 } 328 329 const maxMsgSize = 1<<16 - 4*4 330 331 // A msgReceiver receives messages from a file descriptor. 332 type msgReceiver struct { 333 fd int 334 data [maxMsgSize]byte 335 desc [8]int32 336 hdr msgHdr 337 iov iov 338 } 339 340 func (r *msgReceiver) recv() (*msg, error) { 341 // Init pointers to buffers where syscall recvmsg can write. 342 r.iov.base = &r.data[0] 343 r.iov.len = int32(len(r.data)) 344 r.hdr.iov = &r.iov 345 r.hdr.niov = 1 346 r.hdr.desc = &r.desc[0] 347 r.hdr.ndesc = int32(len(r.desc)) 348 n, _, e := Syscall(sys_imc_recvmsg, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0) 349 if e != 0 { 350 println("Native Client imc_recvmsg: ", e.Error()) 351 return nil, e 352 } 353 354 // Make a copy of the data so that the next recvmsg doesn't 355 // smash it. The system call did not update r.iov.len. Instead it 356 // returned the total byte count as n. 357 m := new(msg) 358 m.data = make([]byte, n) 359 copy(m.data, r.data[0:]) 360 361 // Make a copy of the desc too. 362 // The system call *did* update r.hdr.ndesc. 363 if r.hdr.ndesc > 0 { 364 m.desc = make([]int32, r.hdr.ndesc) 365 copy(m.desc, r.desc[:]) 366 } 367 368 return m, nil 369 } 370 371 // A msgSender sends messages on a file descriptor. 372 type msgSender struct { 373 fd int 374 hdr msgHdr 375 iov iov 376 } 377 378 func (s *msgSender) send(m *msg) error { 379 if len(m.data) > 0 { 380 s.iov.base = &m.data[0] 381 } 382 s.iov.len = int32(len(m.data)) 383 s.hdr.iov = &s.iov 384 s.hdr.niov = 1 385 s.hdr.desc = nil 386 s.hdr.ndesc = 0 387 _, _, e := Syscall(sys_imc_sendmsg, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0) 388 if e != 0 { 389 println("Native Client imc_sendmsg: ", e.Error()) 390 return e 391 } 392 return nil 393 } 394 395 // A msg is the Go representation of an SRPC message. 396 type msg struct { 397 data []byte // message data 398 desc []int32 // message file descriptors 399 400 // parsed version of message 401 id uint32 402 isRequest uint32 403 rpc uint32 404 status uint32 405 value []interface{} 406 template []interface{} 407 size []int 408 format string 409 broken bool 410 } 411 412 // reading from a msg 413 414 func (m *msg) uint32() uint32 { 415 if m.broken { 416 return 0 417 } 418 if len(m.data) < 4 { 419 m.broken = true 420 return 0 421 } 422 b := m.data[:4] 423 x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 424 m.data = m.data[4:] 425 return x 426 } 427 428 func (m *msg) uint64() uint64 { 429 x := uint64(m.uint32()) | uint64(m.uint32())<<32 430 if m.broken { 431 return 0 432 } 433 return x 434 } 435 436 func (m *msg) bytes(n int) []byte { 437 if m.broken { 438 return nil 439 } 440 if len(m.data) < n { 441 m.broken = true 442 return nil 443 } 444 x := m.data[0:n] 445 m.data = m.data[n:] 446 return x 447 } 448 449 // writing to a msg 450 451 func (m *msg) wuint32(x uint32) { 452 m.data = append(m.data, byte(x), byte(x>>8), byte(x>>16), byte(x>>24)) 453 } 454 455 func (m *msg) wuint64(x uint64) { 456 lo := uint32(x) 457 hi := uint32(x >> 32) 458 m.data = append(m.data, byte(lo), byte(lo>>8), byte(lo>>16), byte(lo>>24), byte(hi), byte(hi>>8), byte(hi>>16), byte(hi>>24)) 459 } 460 461 func (m *msg) wbytes(p []byte) { 462 m.data = append(m.data, p...) 463 } 464 465 func (m *msg) wstring(s string) { 466 m.data = append(m.data, s...) 467 } 468 469 // Parsing of RPC messages. 470 // 471 // Each message begins with 472 // total_size uint32 473 // total_descs uint32 474 // fragment_size uint32 475 // fragment_descs uint32 476 // 477 // If fragment_size < total_size or fragment_descs < total_descs, the actual 478 // message is broken up in multiple messages; follow-up messages omit 479 // the "total" fields and begin with the "fragment" fields. 480 // We do not support putting fragmented messages back together. 481 // To do this we would need to change the message receiver. 482 // 483 // After that size information, the message header follows: 484 // protocol uint32 485 // requestID uint32 486 // isRequest uint32 487 // rpcNumber uint32 488 // status uint32 489 // numValue uint32 490 // numTemplate uint32 491 // 492 // After the header come numTemplate fixed-size arguments, 493 // numValue fixed-size arguments, and then the variable-sized 494 // part of the values. The templates describe the expected results 495 // and have no associated variable sized data in the request. 496 // 497 // Each fixed-size argument has the form: 498 // tag uint32 // really a char, like 'b' or 'C' 499 // pad uint32 // unused 500 // val1 uint32 501 // val2 uint32 502 // 503 // The tags are: 504 // 'b': bool; val1 == 0 or 1 505 // 'C': []byte; val1 == len, data in variable-sized section 506 // 'd': float64; (val1, val2) is data 507 // 'D': []float64; val1 == len, data in variable-sized section 508 // 'h': int; val1 == file descriptor 509 // 'i': int32; descriptor in next entry in m.desc 510 // 'I': []int; val1 == len, data in variable-sized section 511 // 's': string; val1 == len, data in variable-sized section 512 // 513 514 func (m *msg) pack() error { 515 m.data = m.data[:0] 516 m.desc = m.desc[:0] 517 518 // sizes, to fill in later 519 m.wuint32(0) 520 m.wuint32(0) 521 m.wuint32(0) 522 m.wuint32(0) 523 524 // message header 525 m.wuint32(protocol) 526 m.wuint32(m.id) 527 m.wuint32(m.isRequest) 528 m.wuint32(m.rpc) 529 m.wuint32(m.status) 530 m.wuint32(uint32(len(m.value))) 531 m.wuint32(uint32(len(m.template))) 532 533 // fixed-size templates 534 for i, x := range m.template { 535 var tag, val1, val2 uint32 536 switch x.(type) { 537 default: 538 return errors.New("unexpected template type") 539 case bool: 540 tag = 'b' 541 case []byte: 542 tag = 'C' 543 val1 = uint32(m.size[i]) 544 case float64: 545 tag = 'd' 546 case []float64: 547 tag = 'D' 548 val1 = uint32(m.size[i]) 549 case int: 550 tag = 'h' 551 case int32: 552 tag = 'i' 553 case []int32: 554 tag = 'I' 555 val1 = uint32(m.size[i]) 556 case string: 557 tag = 's' 558 val1 = uint32(m.size[i]) 559 } 560 m.wuint32(tag) 561 m.wuint32(0) 562 m.wuint32(val1) 563 m.wuint32(val2) 564 } 565 566 // fixed-size values 567 for _, x := range m.value { 568 var tag, val1, val2 uint32 569 switch x := x.(type) { 570 default: 571 return errors.New("unexpected value type") 572 case bool: 573 tag = 'b' 574 if x { 575 val1 = 1 576 } 577 case []byte: 578 tag = 'C' 579 val1 = uint32(len(x)) 580 case float64: 581 tag = 'd' 582 v := float64bits(x) 583 val1 = uint32(v) 584 val2 = uint32(v >> 32) 585 case []float64: 586 tag = 'D' 587 val1 = uint32(len(x)) 588 case int32: 589 tag = 'i' 590 m.desc = append(m.desc, x) 591 case []int32: 592 tag = 'I' 593 val1 = uint32(len(x)) 594 case string: 595 tag = 's' 596 val1 = uint32(len(x) + 1) 597 } 598 m.wuint32(tag) 599 m.wuint32(0) 600 m.wuint32(val1) 601 m.wuint32(val2) 602 } 603 604 // variable-length data for values 605 for _, x := range m.value { 606 switch x := x.(type) { 607 case []byte: 608 m.wbytes(x) 609 case []float64: 610 for _, f := range x { 611 m.wuint64(float64bits(f)) 612 } 613 case []int32: 614 for _, j := range x { 615 m.wuint32(uint32(j)) 616 } 617 case string: 618 m.wstring(x) 619 m.wstring("\x00") 620 } 621 } 622 623 // fill in sizes 624 data := m.data 625 m.data = m.data[:0] 626 m.wuint32(uint32(len(data))) 627 m.wuint32(uint32(len(m.desc))) 628 m.wuint32(uint32(len(data))) 629 m.wuint32(uint32(len(m.desc))) 630 m.data = data 631 632 return nil 633 } 634 635 func (m *msg) unpack() error { 636 totalSize := m.uint32() 637 totalDesc := m.uint32() 638 fragSize := m.uint32() 639 fragDesc := m.uint32() 640 if totalSize != fragSize || totalDesc != fragDesc { 641 return errors.New("Native Client: fragmented RPC messages not supported") 642 } 643 if m.uint32() != protocol { 644 return errors.New("Native Client: RPC protocol mismatch") 645 } 646 647 // message header 648 m.id = m.uint32() 649 m.isRequest = m.uint32() 650 m.rpc = m.uint32() 651 m.status = m.uint32() 652 m.value = make([]interface{}, m.uint32()) 653 m.template = make([]interface{}, m.uint32()) 654 m.size = make([]int, len(m.template)) 655 if m.broken { 656 return errors.New("Native Client: malformed message") 657 } 658 659 // fixed-size templates 660 for i := range m.template { 661 tag := m.uint32() 662 m.uint32() // padding 663 val1 := m.uint32() 664 m.uint32() // val2 665 switch tag { 666 default: 667 return errors.New("Native Client: unexpected template type " + string(rune(tag))) 668 case 'b': 669 m.template[i] = false 670 case 'C': 671 m.template[i] = []byte(nil) 672 m.size[i] = int(val1) 673 case 'd': 674 m.template[i] = float64(0) 675 case 'D': 676 m.template[i] = []float64(nil) 677 m.size[i] = int(val1) 678 case 'i': 679 m.template[i] = int32(0) 680 case 'I': 681 m.template[i] = []int32(nil) 682 m.size[i] = int(val1) 683 case 'h': 684 m.template[i] = int(0) 685 case 's': 686 m.template[i] = "" 687 m.size[i] = int(val1) 688 } 689 } 690 691 // fixed-size values 692 var ( 693 strsize []uint32 694 d int 695 ) 696 for i := range m.value { 697 tag := m.uint32() 698 m.uint32() // padding 699 val1 := m.uint32() 700 val2 := m.uint32() 701 switch tag { 702 default: 703 return errors.New("Native Client: unexpected value type " + string(rune(tag))) 704 case 'b': 705 m.value[i] = val1 > 0 706 case 'C': 707 m.value[i] = []byte(nil) 708 strsize = append(strsize, val1) 709 case 'd': 710 m.value[i] = float64frombits(uint64(val1) | uint64(val2)<<32) 711 case 'D': 712 m.value[i] = make([]float64, val1) 713 case 'i': 714 m.value[i] = int32(val1) 715 case 'I': 716 m.value[i] = make([]int32, val1) 717 case 'h': 718 m.value[i] = int(m.desc[d]) 719 d++ 720 case 's': 721 m.value[i] = "" 722 strsize = append(strsize, val1) 723 } 724 } 725 726 // variable-sized parts of values 727 for i, x := range m.value { 728 switch x := x.(type) { 729 case []byte: 730 m.value[i] = m.bytes(int(strsize[0])) 731 strsize = strsize[1:] 732 case []float64: 733 for i := range x { 734 x[i] = float64frombits(m.uint64()) 735 } 736 case []int32: 737 for i := range x { 738 x[i] = int32(m.uint32()) 739 } 740 case string: 741 m.value[i] = string(m.bytes(int(strsize[0]))) 742 strsize = strsize[1:] 743 } 744 } 745 746 if len(m.data) > 0 { 747 return errors.New("Native Client: junk at end of message") 748 } 749 return nil 750 } 751 752 func float64bits(x float64) uint64 { 753 return *(*uint64)(unsafe.Pointer(&x)) 754 } 755 756 func float64frombits(x uint64) float64 { 757 return *(*float64)(unsafe.Pointer(&x)) 758 } 759 760 // At startup, connect to the name service. 761 var nsClient = nsConnect() 762 763 func nsConnect() *srpcClient { 764 var ns int32 = -1 765 _, _, errno := Syscall(sys_nameservice, uintptr(unsafe.Pointer(&ns)), 0, 0) 766 if errno != 0 { 767 println("Native Client nameservice:", errno.Error()) 768 return nil 769 } 770 771 sock, _, errno := Syscall(sys_imc_connect, uintptr(ns), 0, 0) 772 if errno != 0 { 773 println("Native Client nameservice connect:", errno.Error()) 774 return nil 775 } 776 777 c, err := newClient(int(sock)) 778 if err != nil { 779 println("Native Client nameservice init:", err.Error()) 780 return nil 781 } 782 783 return c 784 } 785 786 const ( 787 nsSuccess = 0 788 nsNameNotFound = 1 789 nsDuplicateName = 2 790 nsInsufficientResources = 3 791 nsPermissionDenied = 4 792 nsInvalidArgument = 5 793 ) 794 795 func openNamedService(name string, mode int32) (fd int, err error) { 796 if nsClient == nil { 797 return 0, errors.New("no name service") 798 } 799 ret, err := nsClient.Call("lookup:si:ih", name, int32(mode)) 800 if err != nil { 801 return 0, err 802 } 803 status := ret[0].(int32) 804 fd = ret[1].(int) 805 switch status { 806 case nsSuccess: 807 // ok 808 case nsNameNotFound: 809 return -1, ENOENT 810 case nsDuplicateName: 811 return -1, EEXIST 812 case nsInsufficientResources: 813 return -1, EWOULDBLOCK 814 case nsPermissionDenied: 815 return -1, EPERM 816 case nsInvalidArgument: 817 return -1, EINVAL 818 default: 819 return -1, EINVAL 820 } 821 return fd, nil 822 }