nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/protocol/rep/rep.go (about)

     1  // Copyright 2019 The Mangos Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use file except in compliance with the License.
     5  // You may obtain a copy of the license at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package rep implements the REP protocol, which is the response side of
    16  // the request/response pattern.  (REQ is the request.)
    17  package rep
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"nanomsg.org/go/mangos/v2/protocol"
    24  )
    25  
    26  // Protocol identity information.
    27  const (
    28  	Self     = protocol.ProtoRep
    29  	Peer     = protocol.ProtoReq
    30  	SelfName = "rep"
    31  	PeerName = "req"
    32  )
    33  
    34  type pipe struct {
    35  	s      *socket
    36  	p      protocol.Pipe
    37  	sendQ  chan *protocol.Message
    38  	closeQ chan struct{}
    39  }
    40  
    41  type recvQEntry struct {
    42  	m *protocol.Message
    43  	p *pipe
    44  }
    45  
    46  type socket struct {
    47  	closed   bool
    48  	ttl      int
    49  	sendQLen int
    50  	recvQ    chan recvQEntry
    51  	contexts map[*context]struct{}
    52  	master   *context
    53  	sync.Mutex
    54  }
    55  
    56  type context struct {
    57  	s          *socket
    58  	closed     bool
    59  	recvWait   bool
    60  	recvExpire time.Duration
    61  	recvPipe   *pipe
    62  	closeQ     chan struct{}
    63  	sendExpire time.Duration
    64  	bestEffort bool
    65  	backtrace  []byte
    66  }
    67  
    68  // closedQ represents a non-blocking time channel.
    69  var closedQ <-chan time.Time
    70  
    71  // nilQ represents a nil time channel (blocks forever)
    72  var nilQ <-chan time.Time
    73  
    74  func init() {
    75  	tq := make(chan time.Time)
    76  	closedQ = tq
    77  	close(tq)
    78  }
    79  
    80  func (c *context) RecvMsg() (*protocol.Message, error) {
    81  	s := c.s
    82  	s.Lock()
    83  
    84  	if c.closed {
    85  		s.Unlock()
    86  		return nil, protocol.ErrClosed
    87  	}
    88  	if c.recvWait {
    89  		s.Unlock()
    90  		return nil, protocol.ErrProtoState
    91  	}
    92  	c.recvWait = true
    93  
    94  	cq := c.closeQ
    95  	wq := nilQ
    96  	expireTime := c.recvExpire
    97  	s.Unlock()
    98  
    99  	if expireTime > 0 {
   100  		wq = time.After(expireTime)
   101  	}
   102  
   103  	var err error
   104  	var m *protocol.Message
   105  	var p *pipe
   106  
   107  	select {
   108  	case entry := <-s.recvQ:
   109  		m, p = entry.m, entry.p
   110  	case <-wq:
   111  		err = protocol.ErrRecvTimeout
   112  	case <-cq:
   113  		err = protocol.ErrClosed
   114  	}
   115  
   116  	s.Lock()
   117  
   118  	if m != nil {
   119  		c.backtrace = append([]byte{}, m.Header...)
   120  		m.Header = nil
   121  		c.recvPipe = p
   122  	}
   123  	c.recvWait = false
   124  	s.Unlock()
   125  	return m, err
   126  }
   127  
   128  func (c *context) SendMsg(m *protocol.Message) error {
   129  	r := c.s
   130  	r.Lock()
   131  
   132  	if r.closed || c.closed {
   133  		r.Unlock()
   134  		return protocol.ErrClosed
   135  	}
   136  	if c.backtrace == nil {
   137  		r.Unlock()
   138  		return protocol.ErrProtoState
   139  	}
   140  	p := c.recvPipe
   141  	c.recvPipe = nil
   142  
   143  	bestEffort := c.bestEffort
   144  	timeQ := nilQ
   145  	if bestEffort {
   146  		timeQ = closedQ
   147  	} else if c.sendExpire > 0 {
   148  		timeQ = time.After(c.sendExpire)
   149  	}
   150  
   151  	m.Header = c.backtrace
   152  	c.backtrace = nil
   153  	cq := c.closeQ
   154  	r.Unlock()
   155  
   156  	select {
   157  	case <-cq:
   158  		m.Header = nil
   159  		return protocol.ErrClosed
   160  	case <-p.closeQ:
   161  		// Pipe closed, so no way to get it to the recipient.
   162  		// Just discard the message.
   163  		m.Free()
   164  		return nil
   165  	case <-timeQ:
   166  		if bestEffort {
   167  			// No way to report to caller, so just discard
   168  			// the message.
   169  			m.Free()
   170  			return nil
   171  		}
   172  		m.Header = nil
   173  		return protocol.ErrSendTimeout
   174  
   175  	case p.sendQ <- m:
   176  		return nil
   177  	}
   178  }
   179  
   180  func (c *context) Close() error {
   181  	s := c.s
   182  	s.Lock()
   183  	if c.closed {
   184  		s.Unlock()
   185  		return protocol.ErrClosed
   186  	}
   187  	delete(s.contexts, c)
   188  	c.closed = true
   189  	close(c.closeQ)
   190  	s.Unlock()
   191  	return nil
   192  }
   193  
   194  func (c *context) GetOption(name string) (interface{}, error) {
   195  	switch name {
   196  	case protocol.OptionBestEffort:
   197  		c.s.Lock()
   198  		v := c.bestEffort
   199  		c.s.Unlock()
   200  		return v, nil
   201  
   202  	case protocol.OptionRecvDeadline:
   203  		c.s.Lock()
   204  		v := c.recvExpire
   205  		c.s.Unlock()
   206  		return v, nil
   207  
   208  	case protocol.OptionSendDeadline:
   209  		c.s.Lock()
   210  		v := c.sendExpire
   211  		c.s.Unlock()
   212  		return v, nil
   213  
   214  	default:
   215  		return nil, protocol.ErrBadOption
   216  	}
   217  }
   218  
   219  func (c *context) SetOption(name string, v interface{}) error {
   220  	switch name {
   221  	case protocol.OptionBestEffort:
   222  		if val, ok := v.(bool); ok {
   223  			c.s.Lock()
   224  			c.bestEffort = val
   225  			c.s.Unlock()
   226  			return nil
   227  		}
   228  		return protocol.ErrBadValue
   229  
   230  	case protocol.OptionSendDeadline:
   231  		if val, ok := v.(time.Duration); ok && val > 0 {
   232  			c.s.Lock()
   233  			c.sendExpire = val
   234  			c.s.Unlock()
   235  			return nil
   236  		}
   237  		return protocol.ErrBadValue
   238  
   239  	case protocol.OptionRecvDeadline:
   240  		if val, ok := v.(time.Duration); ok && val > 0 {
   241  			c.s.Lock()
   242  			c.recvExpire = val
   243  			c.s.Unlock()
   244  			return nil
   245  		}
   246  		return protocol.ErrBadValue
   247  
   248  	default:
   249  		return protocol.ErrBadOption
   250  	}
   251  }
   252  
   253  func (p *pipe) receiver() {
   254  	s := p.s
   255  outer:
   256  	for {
   257  		m := p.p.RecvMsg()
   258  		if m == nil {
   259  			break
   260  		}
   261  
   262  		// Move backtrace from body to header.
   263  		hops := 0
   264  		for {
   265  			if hops >= s.ttl {
   266  				m.Free() // ErrTooManyHops
   267  				continue outer
   268  			}
   269  			hops++
   270  			if len(m.Body) < 4 {
   271  				m.Free() // ErrGarbled
   272  				continue outer
   273  			}
   274  			m.Header = append(m.Header, m.Body[:4]...)
   275  			m.Body = m.Body[4:]
   276  			// Check for high order bit set (0x80000000, big endian)
   277  			if m.Header[len(m.Header)-4]&0x80 != 0 {
   278  				break
   279  			}
   280  		}
   281  
   282  		entry := recvQEntry{m: m, p: p}
   283  		select {
   284  		case s.recvQ <- entry:
   285  		case <-p.closeQ:
   286  			// Either the pipe or the socket has closed (which
   287  			// closes the pipe.)  In either case, we have no
   288  			// way to return a response, so we have to abandon.
   289  			m.Free()
   290  			break outer
   291  		}
   292  	}
   293  	go p.close()
   294  }
   295  
   296  func (p *pipe) sender() {
   297  	for {
   298  		select {
   299  		case m := <-p.sendQ:
   300  			if p.p.SendMsg(m) != nil {
   301  				p.close()
   302  				return
   303  			}
   304  		case <-p.closeQ:
   305  			return
   306  		}
   307  	}
   308  }
   309  
   310  func (p *pipe) close() {
   311  	_ = p.p.Close()
   312  }
   313  
   314  func (s *socket) Close() error {
   315  
   316  	s.Lock()
   317  
   318  	if s.closed {
   319  		s.Unlock()
   320  		return protocol.ErrClosed
   321  	}
   322  	s.closed = true
   323  	var contexts []*context
   324  	for c := range s.contexts {
   325  		contexts = append(contexts, c)
   326  	}
   327  	s.Unlock()
   328  
   329  	for _, c := range contexts {
   330  		_ = c.Close()
   331  	}
   332  	return nil
   333  }
   334  
   335  func (*socket) Info() protocol.Info {
   336  	return protocol.Info{
   337  		Self:     Self,
   338  		Peer:     Peer,
   339  		SelfName: SelfName,
   340  		PeerName: PeerName,
   341  	}
   342  }
   343  
   344  func (s *socket) AddPipe(pp protocol.Pipe) error {
   345  
   346  	p := &pipe{
   347  		p:      pp,
   348  		s:      s,
   349  		sendQ:  make(chan *protocol.Message, s.sendQLen),
   350  		closeQ: make(chan struct{}),
   351  	}
   352  	pp.SetPrivate(p)
   353  	s.Lock()
   354  	if s.closed {
   355  		s.Unlock()
   356  		return protocol.ErrClosed
   357  	}
   358  	go p.sender()
   359  	go p.receiver()
   360  	s.Unlock()
   361  	return nil
   362  }
   363  
   364  func (s *socket) RemovePipe(pp protocol.Pipe) {
   365  
   366  	p := pp.GetPrivate().(*pipe)
   367  	close(p.closeQ)
   368  }
   369  
   370  func (s *socket) SetOption(name string, v interface{}) error {
   371  	switch name {
   372  	case protocol.OptionWriteQLen:
   373  		if qlen, ok := v.(int); ok && qlen >= 0 {
   374  			s.Lock()
   375  			s.sendQLen = qlen
   376  			s.Unlock()
   377  			return nil
   378  		}
   379  		return protocol.ErrBadValue
   380  
   381  	case protocol.OptionTTL:
   382  		if ttl, ok := v.(int); ok && ttl > 0 && ttl < 256 {
   383  			s.Lock()
   384  			s.ttl = ttl
   385  			s.Unlock()
   386  			return nil
   387  		}
   388  		return protocol.ErrBadValue
   389  	}
   390  	return s.master.SetOption(name, v)
   391  }
   392  
   393  func (s *socket) GetOption(name string) (interface{}, error) {
   394  	switch name {
   395  	case protocol.OptionRaw:
   396  		return false, nil
   397  	case protocol.OptionTTL:
   398  		s.Lock()
   399  		v := s.ttl
   400  		s.Unlock()
   401  		return v, nil
   402  	case protocol.OptionWriteQLen:
   403  		s.Lock()
   404  		v := s.sendQLen
   405  		s.Unlock()
   406  		return v, nil
   407  	}
   408  
   409  	return s.master.GetOption(name)
   410  }
   411  
   412  func (s *socket) OpenContext() (protocol.Context, error) {
   413  	s.Lock()
   414  	defer s.Unlock()
   415  	if s.closed {
   416  		return nil, protocol.ErrClosed
   417  	}
   418  	c := &context{
   419  		s:      s,
   420  		closeQ: make(chan struct{}),
   421  	}
   422  	s.contexts[c] = struct{}{}
   423  	return c, nil
   424  }
   425  
   426  func (s *socket) RecvMsg() (*protocol.Message, error) {
   427  	return s.master.RecvMsg()
   428  }
   429  
   430  func (s *socket) SendMsg(m *protocol.Message) error {
   431  	return s.master.SendMsg(m)
   432  }
   433  
   434  // NewProtocol allocates a protocol state for the REP protocol.
   435  func NewProtocol() protocol.Protocol {
   436  	s := &socket{
   437  		ttl:      8,
   438  		contexts: make(map[*context]struct{}),
   439  		recvQ:    make(chan recvQEntry), // unbuffered!
   440  		master: &context{
   441  			closeQ: make(chan struct{}),
   442  		},
   443  	}
   444  	s.master.s = s
   445  	s.contexts[s.master] = struct{}{}
   446  	return s
   447  }
   448  
   449  // NewSocket allocates a new Socket using the REP protocol.
   450  func NewSocket() (protocol.Socket, error) {
   451  	return protocol.MakeSocket(NewProtocol()), nil
   452  }