github.com/gdamore/mangos@v1.4.0/pipe.go (about)

     1  // Copyright 2015 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 mangos
    16  
    17  import (
    18  	"math/rand"
    19  	"sync"
    20  	"time"
    21  )
    22  
    23  var pipes struct {
    24  	byid   map[uint32]*pipe
    25  	nextid uint32
    26  	sync.Mutex
    27  }
    28  
    29  // pipe wraps the Pipe data structure with the stuff we need to keep
    30  // for the core.  It implements the Endpoint interface.
    31  type pipe struct {
    32  	pipe   Pipe
    33  	closeq chan struct{} // only closed, never passes data
    34  	id     uint32
    35  	index  int // index in master list of pipes for socket
    36  
    37  	l       *listener
    38  	d       *dialer
    39  	sock    *socket
    40  	closing bool // true if we were closed
    41  
    42  	sync.Mutex
    43  }
    44  
    45  func init() {
    46  	pipes.byid = make(map[uint32]*pipe)
    47  	pipes.nextid = uint32(rand.NewSource(time.Now().UnixNano()).Int63())
    48  }
    49  
    50  func newPipe(tranpipe Pipe) *pipe {
    51  	p := &pipe{pipe: tranpipe, index: -1}
    52  	p.closeq = make(chan struct{})
    53  	for {
    54  		pipes.Lock()
    55  		p.id = pipes.nextid & 0x7fffffff
    56  		pipes.nextid++
    57  		if p.id != 0 && pipes.byid[p.id] == nil {
    58  			pipes.byid[p.id] = p
    59  			pipes.Unlock()
    60  			break
    61  		}
    62  		pipes.Unlock()
    63  	}
    64  	return p
    65  }
    66  
    67  func (p *pipe) GetID() uint32 {
    68  	return p.id
    69  }
    70  
    71  func (p *pipe) Close() error {
    72  	var hook PortHook
    73  	p.Lock()
    74  	sock := p.sock
    75  	if sock != nil {
    76  		hook = sock.porthook
    77  	}
    78  	if p.closing {
    79  		p.Unlock()
    80  		return nil
    81  	}
    82  	p.closing = true
    83  	p.Unlock()
    84  	close(p.closeq)
    85  	if sock != nil {
    86  		sock.remPipe(p)
    87  	}
    88  	p.pipe.Close()
    89  	pipes.Lock()
    90  	delete(pipes.byid, p.id)
    91  	pipes.Unlock()
    92  	if hook != nil {
    93  		hook(PortActionRemove, p)
    94  	}
    95  	return nil
    96  }
    97  
    98  func (p *pipe) SendMsg(msg *Message) error {
    99  
   100  	if err := p.pipe.Send(msg); err != nil {
   101  		p.Close()
   102  		return err
   103  	}
   104  	return nil
   105  }
   106  
   107  func (p *pipe) RecvMsg() *Message {
   108  
   109  	msg, err := p.pipe.Recv()
   110  	if err != nil {
   111  		p.Close()
   112  		return nil
   113  	}
   114  	msg.Port = p
   115  	return msg
   116  }
   117  
   118  func (p *pipe) Address() string {
   119  	switch {
   120  	case p.l != nil:
   121  		return p.l.Address()
   122  	case p.d != nil:
   123  		return p.d.Address()
   124  	}
   125  	return ""
   126  }
   127  
   128  func (p *pipe) GetProp(name string) (interface{}, error) {
   129  	return p.pipe.GetProp(name)
   130  }
   131  
   132  func (p *pipe) IsOpen() bool {
   133  	return p.pipe.IsOpen()
   134  }
   135  
   136  func (p *pipe) IsClient() bool {
   137  	return p.d != nil
   138  }
   139  
   140  func (p *pipe) IsServer() bool {
   141  	return p.l != nil
   142  }
   143  
   144  func (p *pipe) LocalProtocol() uint16 {
   145  	return p.pipe.LocalProtocol()
   146  }
   147  
   148  func (p *pipe) RemoteProtocol() uint16 {
   149  	return p.pipe.RemoteProtocol()
   150  }
   151  
   152  func (p *pipe) Dialer() Dialer {
   153  	return p.d
   154  }
   155  
   156  func (p *pipe) Listener() Listener {
   157  	return p.l
   158  }