github.com/awesome-flow/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 }