github.com/gdamore/mangos@v1.4.0/transport/ipc/ipc_unix.go (about)

     1  // +build !windows,!nacl,!plan9
     2  
     3  // Copyright 2018 The Mangos Authors
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use file except in compliance with the License.
     7  // You may obtain a copy of the license at
     8  //
     9  //    http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  // Package ipc implements the IPC transport on top of UNIX domain sockets.
    18  package ipc
    19  
    20  import (
    21  	"net"
    22  
    23  	"nanomsg.org/go-mangos"
    24  )
    25  
    26  // options is used for shared GetOption/SetOption logic.
    27  type options map[string]interface{}
    28  
    29  // GetOption retrieves an option value.
    30  func (o options) get(name string) (interface{}, error) {
    31  	if o == nil {
    32  		return nil, mangos.ErrBadOption
    33  	}
    34  	v, ok := o[name]
    35  	if !ok {
    36  		return nil, mangos.ErrBadOption
    37  	}
    38  	return v, nil
    39  }
    40  
    41  // SetOption sets an option.  We have none, so just ErrBadOption.
    42  func (o options) set(string, interface{}) error {
    43  	return mangos.ErrBadOption
    44  }
    45  
    46  type dialer struct {
    47  	addr *net.UnixAddr
    48  	sock mangos.Socket
    49  	opts options
    50  }
    51  
    52  // Dial implements the PipeDialer Dial method
    53  func (d *dialer) Dial() (mangos.Pipe, error) {
    54  
    55  	conn, err := net.DialUnix("unix", nil, d.addr)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	return mangos.NewConnPipeIPC(conn, d.sock)
    60  }
    61  
    62  // SetOption implements a stub PipeDialer SetOption method.
    63  func (d *dialer) SetOption(n string, v interface{}) error {
    64  	return d.opts.set(n, v)
    65  }
    66  
    67  // GetOption implements a stub PipeDialer GetOption method.
    68  func (d *dialer) GetOption(n string) (interface{}, error) {
    69  	return d.opts.get(n)
    70  }
    71  
    72  type listener struct {
    73  	addr     *net.UnixAddr
    74  	sock     mangos.Socket
    75  	listener *net.UnixListener
    76  	opts     options
    77  }
    78  
    79  // Listen implements the PipeListener Listen method.
    80  func (l *listener) Listen() error {
    81  	listener, err := net.ListenUnix("unix", l.addr)
    82  	if err != nil {
    83  		return err
    84  	}
    85  	l.listener = listener
    86  	return nil
    87  }
    88  
    89  func (l *listener) Address() string {
    90  	return "ipc://" + l.addr.String()
    91  }
    92  
    93  // Accept implements the the PipeListener Accept method.
    94  func (l *listener) Accept() (mangos.Pipe, error) {
    95  
    96  	conn, err := l.listener.AcceptUnix()
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	return mangos.NewConnPipeIPC(conn, l.sock)
   101  }
   102  
   103  // Close implements the PipeListener Close method.
   104  func (l *listener) Close() error {
   105  	l.listener.Close()
   106  	return nil
   107  }
   108  
   109  // SetOption implements a stub PipeListener SetOption method.
   110  func (l *listener) SetOption(n string, v interface{}) error {
   111  	return l.opts.set(n, v)
   112  }
   113  
   114  // GetOption implements a stub PipeListener GetOption method.
   115  func (l *listener) GetOption(n string) (interface{}, error) {
   116  	return l.opts.get(n)
   117  }
   118  
   119  type ipcTran struct{}
   120  
   121  // Scheme implements the Transport Scheme method.
   122  func (t *ipcTran) Scheme() string {
   123  	return "ipc"
   124  }
   125  
   126  // NewDialer implements the Transport NewDialer method.
   127  func (t *ipcTran) NewDialer(addr string, sock mangos.Socket) (mangos.PipeDialer, error) {
   128  	var err error
   129  
   130  	if addr, err = mangos.StripScheme(t, addr); err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	d := &dialer{sock: sock, opts: nil}
   135  	if d.addr, err = net.ResolveUnixAddr("unix", addr); err != nil {
   136  		return nil, err
   137  	}
   138  	return d, nil
   139  }
   140  
   141  // NewListener implements the Transport NewListener method.
   142  func (t *ipcTran) NewListener(addr string, sock mangos.Socket) (mangos.PipeListener, error) {
   143  	var err error
   144  	l := &listener{sock: sock}
   145  
   146  	if addr, err = mangos.StripScheme(t, addr); err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	if l.addr, err = net.ResolveUnixAddr("unix", addr); err != nil {
   151  		return nil, err
   152  	}
   153  
   154  	return l, nil
   155  }
   156  
   157  // NewTransport allocates a new IPC transport.
   158  func NewTransport() mangos.Transport {
   159  	return &ipcTran{}
   160  }