Beispiel #1
0
// Recv receives a message.  For AF_SP_RAW messages the header data will
// be included at he start of the returned byte slice (otherwise it will
// be stripped).  At this time no flags are supported.
func (s *Socket) Recv(flags int) ([]byte, error) {
	var b []byte
	var m *mangos.Message
	var err error

	if flags != 0 {
		return nil, errNoFlag
	}

	// Legacy nanomsg uses the opposite semantic for negative and
	// zero values than mangos.  A bit unfortunate.
	switch {
	case s.rto > 0:
		s.sock.SetOption(mangos.OptionRecvDeadline, s.rto)
	case s.rto == 0:
		s.sock.SetOption(mangos.OptionRecvDeadline, -1)
	case s.rto < 0:
		s.sock.SetOption(mangos.OptionRecvDeadline, 0)
	}

	if m, err = s.sock.RecvMsg(); err != nil {
		return nil, err
	}

	if s.dom == AF_SP_RAW {
		b = make([]byte, 0, len(m.Body)+len(m.Header))
		b = append(b, m.Header...)
		b = append(b, m.Body...)
	} else {
		b = make([]byte, 0, len(m.Body))
		b = append(b, m.Body...)
	}
	m.Free()
	return b, nil
}
Beispiel #2
0
func (x *bus) broadcast(m *mangos.Message, sender uint32) {

	x.Lock()
	for id, pe := range x.eps {
		if m != nil {
			if sender == id {
				continue
			}
			m = m.Dup()
		}
		select {
		case pe.q <- m:
		default:
			// No room on outbound queue, drop it.
			// Note that if we are passing on a linger/shutdown
			// notification and we can't deliver due to queue
			// full, it means we will wind up waiting the full
			// linger time in the lower sender.  Its correct, if
			// suboptimal, behavior.
			if m != nil {
				m.Free()
			}
		}
	}
	x.Unlock()
}
Beispiel #3
0
func (w *wsPipe) Send(m *mangos.Message) error {

	var buf []byte

	if len(m.Header) > 0 {
		buf = make([]byte, 0, len(m.Header)+len(m.Body))
		buf = append(buf, m.Header...)
		buf = append(buf, m.Body...)
	} else {
		buf = m.Body
	}
	if err := websocket.Message.Send(w.ws, buf); err != nil {
		return err
	}
	m.Free()
	return nil
}
Beispiel #4
0
func (x *surveyor) sender() {
	defer x.w.Done()
	sq := x.sock.SendChannel()
	cq := x.sock.CloseChannel()
	for {
		var m *mangos.Message
		select {
		case m = <-sq:
		case <-cq:
			return
		}

		x.Lock()
		for _, pe := range x.peers {
			m := m.Dup()
			select {
			case pe.q <- m:
			default:
				m.Free()
			}
		}
		x.Unlock()
	}
}
Beispiel #5
0
func (x *star) broadcast(m *mangos.Message, sender *starEp) {

	x.Lock()
	for _, pe := range x.eps {
		if sender == pe {
			continue
		}
		if m != nil {
			m = m.Dup()
		}
		select {
		case pe.q <- m:
		default:
			// No room on outbound queue, drop it.
			if m != nil {
				m.Free()
			}
		}
	}
	x.Unlock()

	// Grab a local copy and send it up if we aren't originator
	if m != nil {
		if sender != nil {
			select {
			case x.sock.RecvChannel() <- m:
			case <-x.sock.CloseChannel():
				m.Free()
				return
			default:
				// No room, so we just drop it.
				m.Free()
			}
		} else {
			// Not sending it up, so we need to release it.
			m.Free()
		}
	}
}
Beispiel #6
0
func (r *rep) sender() {
	defer r.w.Done()
	sq := r.sock.SendChannel()
	cq := r.sock.CloseChannel()

	for {
		var m *mangos.Message

		select {
		case m = <-sq:
		case <-cq:
			return
		}

		// Lop off the 32-bit peer/pipe ID.  If absent, drop.
		if len(m.Header) < 4 {
			m.Free()
			continue
		}
		id := binary.BigEndian.Uint32(m.Header)
		m.Header = m.Header[4:]
		r.Lock()
		pe := r.eps[id]
		r.Unlock()
		if pe == nil {
			m.Free()
			continue
		}

		select {
		case pe.q <- m:
		default:
			// If our queue is full, we have no choice but to
			// throw it on the floor.  This shoudn't happen,
			// since each partner should be running synchronously.
			// Devices are a different situation, and this could
			// lead to lossy behavior there.  Initiators will
			// resend if this happens.  Devices need to have deep
			// enough queues and be fast enough to avoid this.
			m.Free()
		}
	}
}
Beispiel #7
0
func (x *resp) sender() {
	// This is pretty easy because we have only one peer at a time.
	// If the peer goes away, we'll just drop the message on the floor.

	defer x.w.Done()
	cq := x.sock.CloseChannel()
	sq := x.sock.SendChannel()
	for {
		var m *mangos.Message
		select {
		case m = <-sq:
		case <-cq:
			return
		}

		// Lop off the 32-bit peer/pipe ID.  If absent, drop.
		if len(m.Header) < 4 {
			m.Free()
			continue
		}

		id := binary.BigEndian.Uint32(m.Header)
		m.Header = m.Header[4:]

		x.Lock()
		peer := x.peers[id]
		x.Unlock()

		if peer == nil {
			m.Free()
			continue
		}

		// Put it on the outbound queue
		select {
		case peer.q <- m:
		default:
			// Backpressure, drop it.
			m.Free()
		}
	}
}
Beispiel #8
0
func benchmarkPair(t *testing.B, url string, size int) {

	if strings.HasPrefix(url, "ipc://") && runtime.GOOS == "windows" {
		t.Skip("IPC not supported on Windows")
		return
	}

	srvopts := make(map[string]interface{})
	cliopts := make(map[string]interface{})

	if strings.HasPrefix(url, "wss://") || strings.HasPrefix(url, "tls+tcp://") {
		srvopts[mangos.OptionTLSConfig] = srvCfg
		cliopts[mangos.OptionTLSConfig] = cliCfg
	}

	finish := make(chan struct{})
	ready := make(chan struct{})
	srvsock, err := pair.NewSocket()
	if err != nil || srvsock == nil {
		t.Errorf("Failed creating server socket: %v", err)
		return
	}
	all.AddTransports(srvsock)
	defer srvsock.Close()

	clisock, err := pair.NewSocket()
	if err != nil || clisock == nil {
		t.Errorf("Failed creating client socket: %v", err)
		return
	}
	all.AddTransports(clisock)
	defer clisock.Close()

	go func() {
		var err error
		var m *mangos.Message

		if err = srvsock.ListenOptions(url, srvopts); err != nil {
			t.Errorf("Server listen failed: %v", err)
			return
		}
		close(ready)
		for i := 0; i < t.N; i++ {
			if m, err = srvsock.RecvMsg(); err != nil {
				t.Errorf("Error receiving %d: %v", i, err)
				return
			}
			m.Free()
		}
		close(finish)

	}()
	<-ready

	if err = clisock.DialOptions(url, cliopts); err != nil {
		t.Errorf("Client dial failed: %v", err)
		return
	}

	time.Sleep(700 * time.Millisecond)
	t.ResetTimer()

	for i := 0; i < t.N; i++ {
		msg := mangos.NewMessage(size)
		if err = clisock.SendMsg(msg); err != nil {
			t.Errorf("Client send failed: %v", err)
			return
		}
	}
	<-finish
	t.StopTimer()
	if size > 128 {
		t.SetBytes(int64(size))
	}
}