Beispiel #1
0
func NewConn(rwc io.ReadWriteCloser) (*Conn, error) {
	c := &Conn{
		rwc:     rwc,
		tagmap:  make(map[uint16]chan *plan9.Fcall),
		freetag: make(map[uint16]bool),
		freefid: make(map[uint32]bool),
		nexttag: 1,
		nextfid: 1,
		msize:   131072,
		version: "9P2000",
	}

	//	XXX raw messages, not c.rpc
	tx := &plan9.Fcall{Type: plan9.Tversion, Msize: c.msize, Version: c.version}
	rx, err := c.rpc(tx)
	if err != nil {
		return nil, err
	}

	if rx.Msize > c.msize {
		return nil, plan9.ProtocolError(fmt.Sprintf("invalid msize %d in Rversion", rx.Msize))
	}
	c.msize = rx.Msize
	if rx.Version != "9P2000" {
		return nil, plan9.ProtocolError(fmt.Sprintf("invalid version %s in Rversion", rx.Version))
	}
	return c, nil
}
Beispiel #2
0
func (c *Conn) rpc(tx *plan9.Fcall) (rx *plan9.Fcall, err error) {
	ch := make(chan *plan9.Fcall, 1)
	tx.Tag, err = c.newtag(ch)
	if err != nil {
		return nil, err
	}
	c.w.Lock()
	if err := c.write(tx); err != nil {
		c.w.Unlock()
		return nil, err
	}
	c.w.Unlock()

	for rx = range ch {
		if rx != &yourTurn {
			break
		}
		rx, err = c.read()
		if err != nil {
			break
		}
		c.mux(rx)
	}

	if rx == nil {
		return nil, c.getErr()
	}
	if rx.Type == plan9.Rerror {
		return nil, Error(rx.Ename)
	}
	if rx.Type != tx.Type+1 {
		return nil, plan9.ProtocolError("packet type mismatch")
	}
	return rx, nil
}
Beispiel #3
0
func (c *Conn) newfid() (*Fid, error) {
	c.x.Lock()
	defer c.x.Unlock()
	var fidnum uint32
	for fidnum, _ = range c.freefid {
		delete(c.freefid, fidnum)
		goto found
	}
	fidnum = c.nextfid
	if c.nextfid == plan9.NOFID {
		return nil, plan9.ProtocolError("out of fids")
	}
	c.nextfid++
found:
	return &Fid{fid: fidnum, c: c}, nil
}
Beispiel #4
0
func (c *Conn) newtag(ch chan *plan9.Fcall) (uint16, error) {
	c.x.Lock()
	defer c.x.Unlock()
	var tagnum uint16
	for tagnum, _ = range c.freetag {
		delete(c.freetag, tagnum)
		goto found
	}
	tagnum = c.nexttag
	if c.nexttag == plan9.NOTAG {
		return 0, plan9.ProtocolError("out of tags")
	}
	c.nexttag++
found:
	c.tagmap[tagnum] = ch
	if !c.muxer {
		c.muxer = true
		ch <- &yourTurn
	}
	return tagnum, nil
}