コード例 #1
0
ファイル: conn.go プロジェクト: fedgrant/tonika
func (y *Conn) Greet() (string, string, os.Error) {
	y.lk.Lock()
	if y.err != nil {
		y.lk.Unlock()
		return "", "", os.ErrorString("d,conn: closed meantime")
	}
	if y.regime != regimeUnAuth || y.tube == nil {
		panic("d,conn: regime logic")
	}
	y.regime = regimeAuth
	tube := y.tube
	y.lk.Unlock()

	g := &U_Greet{sys.Build, Version}
	err := tube.Encode(g)
	if err == nil {
		err = tube.Decode(g)
	}

	y.lk.Lock()
	if y.err != nil {
		y.lk.Unlock()
		return "", "", os.ErrorString("d,conn: closed meantime")
	}
	if err != nil {
		y.lk.Unlock()
		return "", "", y.kill(os.ErrorString("d,conn: greet failed"))
	}
	y.regime = regimeUnAuth
	y.lk.Unlock()
	return g.Build, g.Version, nil
}
コード例 #2
0
ファイル: handoff.go プロジェクト: fedgrant/tonika
func (h *handoff) Read(p []byte) (n int, err os.Error) {
	tube, err := h.checkForKill()
	if err != nil {
		return 0, err
	}
	h.lk.Lock()
	if h.rclosed {
		h.lk.Unlock()
		return 0, os.EOF
	}
	h.lk.Unlock()

	// No need to lock on h.buf, since it's only used here, and
	// concurrent read calls are not allowed.
	if h.buf.Len() == 0 {
		msg := &U_Cargo{}
		if err = tube.Decode(msg); err != nil {
			return 0, h.kill(err)
		}
		// A 0-length cargo is an indication of session EOF
		if msg.Cargo == nil || len(msg.Cargo) == 0 {
			h.lk.Lock()
			defer h.lk.Unlock()
			if h.y == nil {
				return 0, os.EBADF
			}
			h.rclosed = true
			return 0, os.EOF
		}
		n, _ = h.buf.Write(msg.Cargo)
		if n != len(msg.Cargo) {
			panic("d,conn,h: buf write")
		}
		h.lk.Lock()
		h.rn += int64(n)
		h.rk++
		h.lk.Unlock()
	}

	if h.buf.Len() == 0 {
		panic("handoff logic")
	}
	n, err = h.buf.Read(p)
	if err != nil {
		panic("d,conn,h: buf")
	}

	h.lk.Lock()
	defer h.lk.Unlock()
	if h.y == nil {
		return 0, os.EBADF
	}
	return n, nil
}
コード例 #3
0
ファイル: handoff.go プロジェクト: fedgrant/tonika
// Close terminates this handoff and returns control to the underlying Conn.
func (h *handoff) Close() (err os.Error) {
	h.lk.Lock()
	y := h.y
	h.y = nil
	if y == nil {
		h.lk.Unlock()
		return os.EBADF
	}
	rclosed := h.rclosed
	h.lk.Unlock()

	//fmt.Printf(term.FgCyan+"d·conn[%#p]·h[%#p]:%x —— close\n"+term.Reset, y,h,h.session)

	tube, err := y.getTube()
	if err != nil {
		return os.EIO
	}

	msg := &U_Cargo{}
	if err = tube.Encode(msg); err != nil {
		return h.kill(err)
	}

	if !rclosed {
		msg := &U_Cargo{}
		if err = tube.Decode(msg); err != nil {
			goto __End
		}
		if msg.Cargo == nil || len(msg.Cargo) == 0 {
			goto __End
		}
	}
__End:
	h.lk.Lock()
	ff := h.finfun
	h.finfun = nil
	h.lk.Unlock()
	if ff != nil {
		ff()
	}
	if err != nil {
		err = y.kill(err)
	}
	return err
}
コード例 #4
0
ファイル: conn.go プロジェクト: fedgrant/tonika
func (y *Conn) Poll() (subject string, rwc io.ReadWriteCloser, err os.Error) {
	for {
		y.hlk.Lock()
		y.hlk.Unlock()
		//fmt.Printf(term.FgBlack + "d·conn[%#p] —— loop\n" + term.Reset, y)

		y.lk.Lock()
		if y.err != nil || y.tube == nil {
			y.lk.Unlock()
			return "", nil, os.EBADF
		}
		tube := y.tube
		y.lk.Unlock()

		tch := waitForRead(tube.ExposeBufioReader())
		select {
		case m := <-y.dialch: // dial & kill requests come here
			if m == nil {
				//fmt.Printf(term.FgRed + "d·conn[%#p] —— closing accept loop\n"+ term.Reset, y)
				err = os.EBADF
				return "", nil, err
			}

			//fmt.Printf(term.FgYellow + "d·conn[%#p] —— dialing, subject=%s\n" + term.Reset, y, m.Subject)

			order := y.getRandOrient()
			session := y.getRandSession()
			orient := &U_Orient{order, session}
			if err = tube.Encode(orient); err != nil {
				err = y.kill(err)
				m.Notify <- nil
				return "", nil, err
			}
			err = <-tch // Hack. Reuse wait until data from remote
			if err != nil {
				//fmt.Printf(term.FgRed+"d·conn[%#p] —— dial/orient err: %s\n"+ term.Reset, y, err)
				err = y.kill(err)
				m.Notify <- nil
				return "", nil, err
			}
			err = tube.Decode(orient)
			if err != nil {
				//fmt.Printf(term.FgCyan+"d·conn[%#p] —— orient,dec: %s\n"+ term.Reset, y, err)
				err = y.kill(err)
				m.Notify <- nil
				return "", nil, err
			}
			if orient.Order >= order { // our dial prevails
				y.sendCall(session, m, tube)
			} else { // remote dial prevails
				m.Notify <- nil
				return y.receiveCall(orient.Session, tube)
			}

		case err = <-tch: // read is available on the connection
			if err != nil {
				//fmt.Printf(term.FgRed+"d·conn[%#p] —— ring/orient err: %s\n"+ term.Reset, y, err)
				err = y.kill(err)
				return "", nil, err
			}
			orient := &U_Orient{}
			if err = tube.Decode(orient); err != nil {
				//fmt.Printf(term.FgRed+"d·conn[%#p] —— ori,dec,err: %s\n"+ term.Reset, y, err)
				err = y.kill(err)
				return "", nil, err
			}
			orient.Order++
			session := orient.Session
			if err = tube.Encode(orient); err != nil {
				//fmt.Printf(term.FgRed+"d·conn[%#p] —— ori,enc,err: %s\n"+ term.Reset, y, err)
				err = y.kill(err)
				return "", nil, err
			}
			return y.receiveCall(session, tube)
		} // select
	} // for
	panic("unreach")
}