github.com/godevsig/adaptiveservice@v0.9.23/chantransport.go (about)

     1  package adaptiveservice
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  	"reflect"
     8  	"unsafe"
     9  
    10  	"github.com/barkimedes/go-deepcopy"
    11  )
    12  
    13  type chanTransportMsg struct {
    14  	srcChan chan interface{}
    15  	msg     interface{}
    16  }
    17  
    18  type handshake struct {
    19  	connClose      chan struct{}
    20  	serverChanInfo chan chan *chanTransportMsg
    21  }
    22  
    23  // server main receive chan transport.
    24  type chanTransport struct {
    25  	svc        *service
    26  	acceptChan chan handshake
    27  	closed     chan struct{}
    28  }
    29  
    30  func (svc *service) newChanTransport() (*chanTransport, error) {
    31  	ct := &chanTransport{
    32  		svc:        svc,
    33  		acceptChan: make(chan handshake),
    34  		closed:     make(chan struct{}),
    35  	}
    36  	go ct.receiver()
    37  	regServiceChan(svc.publisherName, svc.serviceName, ct)
    38  	svc.s.lg.Infof("service %s %s listening on internal channel", svc.publisherName, svc.serviceName)
    39  	return ct, nil
    40  }
    41  
    42  func (ct *chanTransport) close() {
    43  	close(ct.closed)
    44  	delServiceChan(ct.svc.publisherName, ct.svc.serviceName)
    45  }
    46  
    47  type chanServerStream struct {
    48  	Context
    49  	netconn     chanconn
    50  	connClose   *chan struct{}
    51  	srcChan     chan interface{}
    52  	privateChan chan interface{} // dedicated to the client
    53  	timeouter
    54  }
    55  
    56  func (ss *chanServerStream) GetNetconn() Netconn {
    57  	return ss.netconn
    58  }
    59  
    60  func (ss *chanServerStream) Send(msg interface{}) error {
    61  	if *ss.connClose == nil {
    62  		return io.EOF
    63  	}
    64  	ss.srcChan <- msg
    65  	return nil
    66  }
    67  
    68  func (ss *chanServerStream) Recv(msgPtr interface{}) (err error) {
    69  	connClose := *ss.connClose
    70  	if *ss.connClose == nil {
    71  		return io.EOF
    72  	}
    73  	rptr := reflect.ValueOf(msgPtr)
    74  	if msgPtr != nil && (rptr.Kind() != reflect.Ptr || rptr.IsNil()) {
    75  		panic("not a pointer or nil pointer")
    76  	}
    77  
    78  	select {
    79  	case <-connClose:
    80  		return io.EOF
    81  	case <-ss.timeouter.timeoutChan():
    82  		return ErrRecvTimeout
    83  	case msg := <-ss.privateChan:
    84  		if err, ok := msg.(error); ok {
    85  			return err
    86  		}
    87  		if msgPtr == nil { // msgPtr is nil
    88  			return nil // user just looks at error, no error here
    89  		}
    90  
    91  		rv := rptr.Elem()
    92  		defer func() {
    93  			if e := recover(); e != nil {
    94  				err = fmt.Errorf("message type mismatch: %v", e)
    95  			}
    96  		}()
    97  		rv.Set(reflect.ValueOf(msg))
    98  	}
    99  
   100  	return
   101  }
   102  
   103  func (ss *chanServerStream) SendRecv(msgSnd interface{}, msgRcvPtr interface{}) error {
   104  	if err := ss.Send(msgSnd); err != nil {
   105  		return err
   106  	}
   107  	if err := ss.Recv(msgRcvPtr); err != nil {
   108  		return err
   109  	}
   110  	return nil
   111  }
   112  
   113  type chanAddr uint64
   114  
   115  type chanconn struct {
   116  	localAddr  chanAddr
   117  	remoteAddr chanAddr
   118  }
   119  
   120  func (cc chanconn) Close() error {
   121  	return nil
   122  }
   123  
   124  func (cc chanconn) LocalAddr() net.Addr {
   125  	return cc.localAddr
   126  }
   127  
   128  func (cc chanconn) RemoteAddr() net.Addr {
   129  	return cc.remoteAddr
   130  }
   131  
   132  func (ca chanAddr) Network() string {
   133  	return "chan"
   134  }
   135  
   136  func (ca chanAddr) String() string {
   137  	return fmt.Sprintf("0x%x", uint64(ca))
   138  }
   139  
   140  func (ct *chanTransport) receiver() {
   141  	mq := ct.svc.s.mq
   142  	lg := ct.svc.s.lg
   143  
   144  	for {
   145  		select {
   146  		case <-ct.closed:
   147  			return
   148  		case hs := <-ct.acceptChan:
   149  			go func() {
   150  				connClose := hs.connClose
   151  				recvChan := make(chan *chanTransportMsg, ct.svc.s.qsize)
   152  				hs.serverChanInfo <- recvChan
   153  				cc := chanconn{
   154  					localAddr:  chanAddr(uintptr(unsafe.Pointer(&ct.closed))),
   155  					remoteAddr: chanAddr(uintptr(unsafe.Pointer(&connClose))),
   156  				}
   157  				lg.Debugf("%s %s new chan connection from: %s", ct.svc.publisherName, ct.svc.serviceName, cc.RemoteAddr().String())
   158  				if ct.svc.fnOnConnect != nil {
   159  					lg.Debugf("%s %s on connect", ct.svc.publisherName, ct.svc.serviceName)
   160  					if ct.svc.fnOnConnect(cc) {
   161  						return
   162  					}
   163  				}
   164  				defer func() {
   165  					if ct.svc.fnOnDisconnect != nil {
   166  						lg.Debugf("%s %s on disconnect", ct.svc.publisherName, ct.svc.serviceName)
   167  						ct.svc.fnOnDisconnect(cc)
   168  					}
   169  					lg.Debugf("%s %s chan connection disconnected: %s", ct.svc.publisherName, ct.svc.serviceName, cc.RemoteAddr().String())
   170  				}()
   171  				ssMap := make(map[chan interface{}]*chanServerStream)
   172  				for {
   173  					select {
   174  					case <-connClose:
   175  						connClose = nil
   176  						return
   177  					case tm := <-recvChan:
   178  						ss := ssMap[tm.srcChan]
   179  						if ss == nil {
   180  							ss = &chanServerStream{
   181  								netconn:     cc,
   182  								connClose:   &connClose,
   183  								Context:     &contextImpl{},
   184  								srcChan:     tm.srcChan,
   185  								privateChan: make(chan interface{}, cap(tm.srcChan)),
   186  							}
   187  							ssMap[tm.srcChan] = ss
   188  							if ct.svc.fnOnNewStream != nil {
   189  								lg.Debugf("%s %s on new stream", ct.svc.publisherName, ct.svc.serviceName)
   190  								ct.svc.fnOnNewStream(ss)
   191  							}
   192  						}
   193  						if ct.svc.canHandle(tm.msg) {
   194  							mm := &metaKnownMsg{
   195  								stream: ss,
   196  								msg:    tm.msg.(KnownMessage),
   197  							}
   198  							mq.putMetaMsg(mm)
   199  						} else {
   200  							ss.privateChan <- tm.msg
   201  						}
   202  					}
   203  				}
   204  			}()
   205  		}
   206  	}
   207  }
   208  
   209  // below for client side
   210  
   211  type chanClientStream struct {
   212  	conn    *chanConnection
   213  	msgChan chan interface{}
   214  	timeouter
   215  }
   216  
   217  type clientChanTransport struct {
   218  	owner *Client
   219  	ct    *chanTransport
   220  }
   221  
   222  // chan connection for client.
   223  type chanConnection struct {
   224  	Stream
   225  	cct        *clientChanTransport
   226  	connClose  chan struct{}
   227  	serverChan chan *chanTransportMsg // link to server receive chan
   228  }
   229  
   230  // newConnection creates a new connection to the chan transport for client.
   231  func (cct *clientChanTransport) newConnection() *chanConnection {
   232  	connClose := make(chan struct{})
   233  	serverChanInfo := make(chan chan *chanTransportMsg)
   234  
   235  	cct.ct.acceptChan <- handshake{connClose, serverChanInfo}
   236  	conn := &chanConnection{
   237  		cct:        cct,
   238  		connClose:  connClose,
   239  		serverChan: <-serverChanInfo,
   240  	}
   241  	conn.Stream = conn.NewStream()
   242  	return conn
   243  }
   244  
   245  // NewStream creates a new client stream.
   246  func (conn *chanConnection) NewStream() Stream {
   247  	cs := &chanClientStream{
   248  		conn:    conn,
   249  		msgChan: make(chan interface{}, cap(conn.serverChan)),
   250  	}
   251  	return cs
   252  }
   253  
   254  func (conn *chanConnection) Close() {
   255  	close(conn.connClose)
   256  }
   257  
   258  func (cs *chanClientStream) GetNetconn() Netconn {
   259  	cc := chanconn{
   260  		localAddr:  chanAddr(uintptr(unsafe.Pointer(&cs.conn.connClose))),
   261  		remoteAddr: chanAddr(uintptr(unsafe.Pointer(&cs.conn.cct.ct.closed))),
   262  	}
   263  	return cc
   264  }
   265  
   266  func (cs *chanClientStream) Send(msg interface{}) error {
   267  	if cs.msgChan == nil {
   268  		return io.EOF
   269  	}
   270  	if cs.conn.cct.owner.deepCopy {
   271  		msg = deepcopy.MustAnything(msg)
   272  	}
   273  	cs.conn.serverChan <- &chanTransportMsg{srcChan: cs.msgChan, msg: msg}
   274  	return nil
   275  }
   276  
   277  func (cs *chanClientStream) Recv(msgPtr interface{}) (err error) {
   278  	msgChan := cs.msgChan
   279  	if cs.msgChan == nil {
   280  		return io.EOF
   281  	}
   282  	rptr := reflect.ValueOf(msgPtr)
   283  	if msgPtr != nil && (rptr.Kind() != reflect.Ptr || rptr.IsNil()) {
   284  		panic("not a pointer or nil pointer")
   285  	}
   286  
   287  	select {
   288  	case <-cs.timeouter.timeoutChan():
   289  		return ErrRecvTimeout
   290  	case msg := <-msgChan:
   291  		if err, ok := msg.(error); ok { // message handler returned error
   292  			if err == io.EOF {
   293  				cs.msgChan = nil
   294  			}
   295  			return err
   296  		}
   297  		if msgPtr == nil { // msgPtr is nil
   298  			return nil // user just looks at error, no error here
   299  		}
   300  
   301  		rv := rptr.Elem()
   302  		mrv := reflect.ValueOf(msg)
   303  		if rv.Kind() != reflect.Ptr && mrv.Kind() == reflect.Ptr {
   304  			mrv = mrv.Elem()
   305  		}
   306  		defer func() {
   307  			if e := recover(); e != nil {
   308  				err = fmt.Errorf("message type mismatch: %v", e)
   309  			}
   310  		}()
   311  		rv.Set(mrv)
   312  	}
   313  
   314  	return
   315  }
   316  
   317  func (cs *chanClientStream) SendRecv(msgSnd interface{}, msgRcvPtr interface{}) error {
   318  	if err := cs.Send(msgSnd); err != nil {
   319  		return err
   320  	}
   321  	if err := cs.Recv(msgRcvPtr); err != nil {
   322  		return err
   323  	}
   324  	return nil
   325  }