Beispiel #1
0
func (pr *consulPipeRouter) handlePipeUpdate(key string, cp consulPipe) {
	// 1. If this pipe is closed, or we're not one of the ends, we
	//    should ensure our local pipe (and bridge) is closed.
	if !cp.DeletedAt.IsZero() || !cp.eitherEndFor(pr.advertise) {
		pipe, ok := pr.activePipes[key]
		delete(pr.activePipes, key)
		if ok {
			log.Infof("Deleting pipe %s", key)
			pipe.Close()
		}

		bridge, ok := pr.bridges[key]
		delete(pr.bridges, key)
		if ok {
			bridge.stop()
		}
		return
	}

	if !cp.eitherEndFor(pr.advertise) {
		return
	}

	// 2. If this pipe if for us, we should have a pipe for it.
	pipe, ok := pr.activePipes[key]
	if !ok {
		log.Infof("Creating pipe %s", key)
		pipe = xfer.NewPipe()
		pr.activePipes[key] = pipe
		for _, pw := range pr.pipeWaiters[key] {
			pw <- pipe
		}
		delete(pr.pipeWaiters, key)
	}

	// 3. Ensure there is a bridging connection for this pipe.
	//    Semantics are the owner of the UIEnd connects to the owner of the ProbeEnd
	shouldBridge := cp.DeletedAt.IsZero() &&
		cp.addrFor(app.UIEnd) != cp.addrFor(app.ProbeEnd) &&
		cp.addrFor(app.UIEnd) == pr.advertise &&
		cp.addrFor(app.ProbeEnd) != ""
	bridge, ok := pr.bridges[key]

	// If we shouldn't be bridging but are, or we should be bridging but are pointing
	// at the wrong place, stop the current bridge.
	if (!shouldBridge && ok) || (shouldBridge && ok && bridge.addr != cp.addrFor(app.ProbeEnd)) {
		delete(pr.bridges, key)
		bridge.stop()
		ok = false
	}

	// If we should be bridging and are not, start a new bridge
	if shouldBridge && !ok {
		bridge = newBridgeConnection(key, cp.addrFor(app.ProbeEnd), pipe)
		pr.bridges[key] = bridge
	}
}
Beispiel #2
0
func (pr *localPipeRouter) Get(_ context.Context, id string, e End) (xfer.Pipe, io.ReadWriter, error) {
	pr.Lock()
	defer pr.Unlock()
	p, ok := pr.pipes[id]
	if !ok {
		log.Infof("Creating pipe id %s", id)
		p = &pipe{
			ui:    end{lastUsedTime: mtime.Now()},
			probe: end{lastUsedTime: mtime.Now()},
			Pipe:  xfer.NewPipe(),
		}
		pr.pipes[id] = p
	}
	if p.Closed() {
		return nil, nil, fmt.Errorf("Pipe %s closed", id)
	}
	end, endIO := p.end(e)
	end.refCount++
	return p, endIO, nil
}
Beispiel #3
0
	pipeID := fmt.Sprintf("pipe-%d", rand.Int63())
	pipe := &pipe{
		Pipe:   p,
		appID:  appID,
		id:     pipeID,
		client: c,
	}
	if err := c.PipeConnection(appID, pipeID, pipe.Pipe); err != nil {
		return "", nil, err
	}
	return pipeID, pipe, nil
}

// NewPipe creates a new pipe and connects it to the app.
var NewPipe = func(c PipeClient, appID string) (string, xfer.Pipe, error) {
	return newPipe(xfer.NewPipe(), c, appID)
}

// NewPipeFromEnds creates a new pipe from its ends and connects it to the app.
func NewPipeFromEnds(local, remote io.ReadWriter, c PipeClient, appID string) (string, xfer.Pipe, error) {
	return newPipe(xfer.NewPipeFromEnds(local, remote), c, appID)
}

func (p *pipe) Close() error {
	err1 := p.Pipe.Close()
	err2 := p.client.PipeClose(p.appID, p.id)
	if err1 != nil {
		return err1
	}
	return err2
}