Example #1
0
func Open(options ...EndpointOption) (*Endpoint, error) {
	e := &Endpoint{
		TID:       tracer.NewID(),
		modules:   make(map[interface{}]Module),
		tokens:    make(map[cipherset.Token]*Exchange),
		hashnames: make(map[hashname.H]*Exchange),
	}

	e.listenerSet = newListenerSet()
	e.listenerSet.addrFunc = func() net.Addr {
		return e.LocalHashname()
	}
	e.listenerSet.dropChannelFunc = func(c *Channel, reason error) {
		c.Kill()
	}

	e.endpointHooks.endpoint = e
	e.exchangeHooks.endpoint = e
	e.channelHooks.endpoint = e
	e.exchangeHooks.Register(ExchangeHook{OnClosed: e.onExchangeClosed})

	err := e.setOptions(
		RegisterModule(modTransportsKey, &modTransports{e}),
		RegisterModule(modNetwatchKey, &modNetwatch{endpoint: e}))
	if err != nil {
		return nil, e.traceError(err)
	}

	err = e.setOptions(options...)
	if err != nil {
		return nil, e.traceError(err)
	}

	err = e.setOptions(
		defaultRandomKeys,
		defaultTransport)
	if err != nil {
		return nil, e.traceError(err)
	}

	e.traceNew()

	err = e.start()
	if err != nil {
		e.close()
		return nil, e.traceError(err)
	}

	e.traceStarted()
	return e, nil
}
Example #2
0
func newChannel(
	hn hashname.H, typ string,
	reliable bool, serverside bool,
	x exchangeI,
	options ...ChannelOption,
) *Channel {
	c := &Channel{
		TID:          tracer.NewID(),
		x:            x,
		hashname:     hn,
		typ:          typ,
		reliable:     reliable,
		serverside:   serverside,
		readBuffer:   make([]*readBufferEntry, 0, cReadBufferSize),
		writeBuffer:  make(map[uint32]*writeBufferEntry, cWriteBufferSize),
		oSeq:         cBlankSeq,
		iBufferedSeq: cBlankSeq,
		iSeenSeq:     cBlankSeq,
		iSeq:         cBlankSeq,
		oAckedSeq:    cBlankSeq,
		iAckedSeq:    cBlankSeq,
	}

	c.cndRead = sync.NewCond(&c.mtx)
	c.cndWrite = sync.NewCond(&c.mtx)
	c.cndClose = sync.NewCond(&c.mtx)

	c.setOpenDeadline()

	c.tReadDeadline = time.AfterFunc(10*time.Second, c.onReadDeadlineReached)
	c.tWriteDeadline = time.AfterFunc(10*time.Second, c.onWriteDeadlineReached)
	c.tReadDeadline.Stop()
	c.tWriteDeadline.Stop()

	if reliable {
		c.tResend = time.AfterFunc(1*time.Second, c.resendLastPacket)
		c.tAcker = time.AfterFunc(10*time.Second, c.autoDeliverAck)
	}

	c.setOptions(options...)
	c.traceNew()

	return c
}
Example #3
0
func (e *Endpoint) traceDroppedPacket(msg []byte, conn net.Conn, reason string) {
	if tracer.Enabled {
		pkt := tracer.Info{
			"msg": base64.StdEncoding.EncodeToString(msg),
		}

		if conn != nil {
			pkt["src"] = conn.RemoteAddr()
			pkt["dst"] = conn.LocalAddr()
		}

		tracer.Emit("endpoint.drop.packet", tracer.Info{
			"endpoint_id": e.TID,
			"packet_id":   tracer.NewID(),
			"reason":      reason,
			"packet":      pkt,
		})
	}
}
Example #4
0
func (c *Channel) write(pkt *lob.Packet, p *Pipe) error {
	if pkt.TID == 0 {
		pkt.TID = tracer.NewID()
	}

	if c.broken {
		// When a channel is marked as broken the all writes
		// must return a BrokenChannelError.
		return c.traceWriteError(pkt, p,
			&BrokenChannelError{c.hashname, c.typ, c.id})
	}

	if c.writeDeadlineReached {
		// When a channel reached a write deadline then all writes
		// must return a ErrTimeout.
		return c.traceWriteError(pkt, p,
			ErrTimeout)
	}

	if c.deliveredEnd {
		// When a channel sent a packet with the "end" header set
		// then all subsequent writes must return io.EOF
		return c.traceWriteError(pkt, p,
			io.EOF)
	}

	c.oSeq++
	hdr := pkt.Header()
	hdr.C, hdr.HasC = c.id, true
	if c.reliable {
		hdr.Seq, hdr.HasSeq = c.oSeq, true
	}
	if !c.serverside && c.oSeq == cInitialSeq {
		hdr.Type, hdr.HasType = c.typ, true
	}

	end := hdr.HasEnd && hdr.End
	if end {
		c.deliveredEnd = true
		c.setCloseDeadline()
	}

	if c.reliable {
		if c.oSeq%30 == 0 || hdr.End {
			c.applyAckHeaders(pkt)
		}
		c.writeBuffer[c.oSeq] = &writeBufferEntry{pkt, end, time.Time{}, p}
		c.needsResend = false
	}

	err := c.x.deliverPacket(pkt, p)
	if err != nil {
		return c.traceWriteError(pkt, p, err)
	}
	statChannelSndPkt.Add(1)
	if pkt.Header().HasAck {
		statChannelSndAckInline.Add(1)
	}

	if c.oSeq == cInitialSeq && c.serverside {
		c.unsetOpenDeadline()
	}

	c.traceWrite(pkt, p)

	if !c.reliable {
		pkt.Free()
	}

	return nil
}