github.com/whiteboxio/flow@v0.0.3-0.20190918184116-508d75d68a2c/pkg/corev1alpha1/actor/receiver_unix.go (about)

     1  package actor
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  
     9  	core "github.com/awesome-flow/flow/pkg/corev1alpha1"
    10  )
    11  
    12  const (
    13  	FlowUnixSock = "/tmp/flow.sock"
    14  )
    15  
    16  type ReceiverUnix struct {
    17  	name     string
    18  	ctx      *core.Context
    19  	queue    chan *core.Message
    20  	addr     *net.UnixAddr
    21  	listener *net.UnixListener
    22  	done     chan struct{}
    23  }
    24  
    25  var _ core.Actor = (*ReceiverUnix)(nil)
    26  
    27  func NewReceiverUnix(name string, ctx *core.Context, params core.Params) (core.Actor, error) {
    28  	bind, ok := params["bind"]
    29  	if !ok {
    30  		bind = FlowUnixSock
    31  	}
    32  	addr, err := net.ResolveUnixAddr("unix", bind.(string))
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	return &ReceiverUnix{
    38  		name:  name,
    39  		ctx:   ctx,
    40  		queue: make(chan *core.Message),
    41  		addr:  addr,
    42  		done:  make(chan struct{}),
    43  	}, nil
    44  }
    45  
    46  func (u *ReceiverUnix) Name() string {
    47  	return u.name
    48  }
    49  
    50  func (u *ReceiverUnix) Start() error {
    51  	stat, err := os.Stat(u.addr.String())
    52  	if err == nil {
    53  		if stat.Mode()&os.ModeSocket == 0 {
    54  			return fmt.Errorf("file %s already exists and it's not a unix socket: can not rebind", u.addr)
    55  		}
    56  		u.ctx.Logger().Warn("file %s already exists, rebinding", u.addr)
    57  		if err := os.Remove(u.addr.String()); err != nil {
    58  			return err
    59  		}
    60  	} else if !os.IsNotExist(err) {
    61  		return err
    62  	}
    63  	l, err := net.ListenUnix("unix", u.addr)
    64  	if err != nil {
    65  		return err
    66  	}
    67  	u.listener = l
    68  
    69  	isdone := false
    70  	go func() {
    71  		<-u.done
    72  		isdone = true
    73  	}()
    74  
    75  	go func() {
    76  		u.ctx.Logger().Info("starting unix listener at %s", u.addr)
    77  		for !isdone {
    78  			c, err := u.listener.AcceptUnix()
    79  			if err != nil {
    80  				u.ctx.Logger().Error(err.Error())
    81  				continue
    82  			}
    83  			go u.handleConn(c)
    84  		}
    85  
    86  		u.listener.Close()
    87  	}()
    88  
    89  	return nil
    90  }
    91  
    92  func (u *ReceiverUnix) Stop() error {
    93  	close(u.done)
    94  	close(u.queue)
    95  
    96  	return os.Remove(u.addr.String())
    97  }
    98  
    99  func (u *ReceiverUnix) Connect(nthreads int, peer core.Receiver) error {
   100  	for i := 0; i < nthreads; i++ {
   101  		go func() {
   102  			for msg := range u.queue {
   103  				if err := peer.Receive(msg); err != nil {
   104  					u.ctx.Logger().Error(err.Error())
   105  				}
   106  			}
   107  		}()
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  func (u *ReceiverUnix) Receive(msg *core.Message) error {
   114  	return fmt.Errorf("unix receiver %q can not receive internal messages", u.name)
   115  }
   116  
   117  func (u *ReceiverUnix) handleConn(conn net.Conn) {
   118  	defer conn.Close()
   119  	reader := bufio.NewReader(conn)
   120  	scanner := bufio.NewScanner(reader)
   121  
   122  	for scanner.Scan() {
   123  		msg := core.NewMessage(scanner.Bytes())
   124  		u.queue <- msg
   125  	}
   126  
   127  	if err := scanner.Err(); err != nil {
   128  		u.ctx.Logger().Error(err.Error())
   129  	}
   130  }