func TestSocketEvent(t *testing.T) { var rep *zmq.Socket defer func() { if rep != nil { rep.SetLinger(0) rep.Close() } }() // REP socket rep, err := zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } // REP socket monitor, all events err = rep.Monitor("inproc://monitor.rep", zmq.EVENT_ALL) if err != nil { t.Fatal("rep.Monitor:", err) } chMsg := make(chan string, 10) go rep_socket_monitor("inproc://monitor.rep", chMsg) time.Sleep(time.Second) // Generate an event err = rep.Bind("tcp://*:9689") if err != nil { t.Fatal("rep.Bind:", err) } rep.Close() rep = nil expect := []string{ "EVENT_LISTENING tcp://0.0.0.0:9689", "EVENT_CLOSED tcp://0.0.0.0:9689", "Done", } i := 0 for msg := range chMsg { if i < len(expect) { if msg != expect[i] { t.Errorf("Expected message %q, got %q", expect[i], msg) } i++ } else { t.Error("Unexpected message: %q", msg) } } for ; i < len(expect); i++ { t.Errorf("Expected message %q, got nothing", expect[i]) } }
func (c *WorkerConnection) run(socket *zmq.Socket) { defer socket.Close() socket.SetRcvtimeo(c.activeTimeout) for { select { case <-c.quit: close(c.wait) return case request := <-c.requestChannel: if _, err := socket.SendMessage(request); err != nil { log.Println("Failed to send request:", err) } case request := <-c.connectionChan: go c.handleConnectionRequest(socket, request) default: message, err := socket.RecvMessageBytes(0) if err != nil { // Needed to yield to goroutines when GOMAXPROCS is 1. // Note: The 1.3 preemptive scheduler doesn't seem to work here, // so this is still required. runtime.Gosched() break } socket.SetRcvtimeo(c.activeTimeout) go c.handleResponse(message) } } }
func StartZeromqProtobufTest(address string, clients int, requestsPerClient int, messageSize int, timer metrics.Timer, requestSize *int) func(wg *sync.WaitGroup) { return func(wg *sync.WaitGroup) { var socket *zmq.Socket var err error var request []byte if socket, err = zmq.NewSocket(zmq.REQ); err != nil { log.Fatal(err) } defer socket.Close() defer wg.Done() if err = socket.Connect("tcp://" + address); err != nil { log.Fatal(err) } if request, err = proto.Marshal(&pb.Request{ Method: "TEST", Payload: strings.Repeat("a", messageSize), }); err != nil { log.Fatal(err) } *requestSize = len(request) for i := 0; i < requestsPerClient; i++ { timer.Time(func() { socket.SendBytes(request, 0) socket.Recv(0) }) } } }
// serveZMQ func serveZMQ(zmqPort int, channelStr chan string, metrics metricContainer) { var zmqListener *zmq.Socket if channelStr == nil { listenerURL := "*:" + strconv.Itoa(zmqPort) fmt.Println("ZeroMQ listening on port: " + listenerURL) zmqListener, _ = zmq.NewSocket(zmq.PULL) defer zmqListener.Close() zmqListener.Bind("tcp://" + listenerURL) } for { var msg string if channelStr == nil { // Wait for next request from client var err error msg, err = zmqListener.Recv(0) if err != nil { fmt.Printf("Error in receive: %v", err) break } } else { msg = <-channelStr } // unmarshall bulked data var bulk []string err := json.Unmarshal([]byte(msg), &bulk) if err != nil { fmt.Println("json unmarshall error:", err) } // extra data for _, data := range bulk { dtime, _ := utils.ParseDate4(data[:19]) //dtime, err := time.Parse(dtFormat, data[:19]) // date time if err != nil { fmt.Println("time.Parse error:", err) } value := data[20:] intval, _ := strconv.Atoi(value) m := metric{dtime, intval} metrics.AddMetric(&m) //fmt.Println("At ", dtime, " value=", value) } } }
// main entry point for data writer func main() { var err error var writerSocket *zmq4.Socket var eventSubSocket *zmq4.Socket fog.Info("program starts") if writerSocket, err = createWriterSocket(); err != nil { fog.Critical("createWriterSocket %s", err) } defer writerSocket.Close() fog.Info("binding writer socket to %s", dataWriterAddress) if err = writerSocket.Bind(dataWriterAddress); err != nil { fog.Critical("Bind(%s) %s", dataWriterAddress, err) } if eventSubSocket, err = createEventSubSocket(); err != nil { fog.Critical("createEventSubSocket %s", err) } defer eventSubSocket.Close() fog.Info("connecting event sub socket to %s", eventAggregatorPubAddress) if err = eventSubSocket.Connect(eventAggregatorPubAddress); err != nil { fog.Critical("Connect(%s) %s", eventAggregatorPubAddress, err) } messageChan := NewMessageHandler() reactor := zmq4.NewReactor() reactor.AddChannel(tools.NewSignalWatcher(), 1, tools.SigtermHandler) reactor.AddSocket(writerSocket, zmq4.POLLIN, NewWriterSocketHandler(writerSocket, messageChan)) reactor.AddSocket(eventSubSocket, zmq4.POLLIN, NewEventSubSocketHandler(eventSubSocket)) fog.Debug("starting reactor.Run") reactor.SetVerbose(true) err = reactor.Run(reactorPollingInterval) if err == tools.SigtermError { fog.Info("program terminates normally due to SIGTERM") } else if errno, ok := err.(syscall.Errno); ok { // we can get 'interrupted system call' if we get SIGTERM while // a socket is waiting on a read. That's not too bad. if errno == syscall.EINTR { fog.Warn("reactor.Run returns '%s' assuming SIGTERM", errno) } else { fog.Error("reactor.Run returns %T '%s'", errno, errno) } } else { fog.Error("reactor.Run returns %T %s", err, err) } }
func TestPairTcp(t *testing.T) { var sb, sc *zmq.Socket defer func() { for _, s := range []*zmq.Socket{sb, sc} { if s != nil { s.SetLinger(0) s.Close() } } }() sb, err := zmq.NewSocket(zmq.PAIR) if err != nil { t.Fatal("NewSocket:", err) } err = sb.Bind("tcp://127.0.0.1:9736") if err != nil { t.Fatal("sb.Bind:", err) } sc, err = zmq.NewSocket(zmq.PAIR) if err != nil { t.Fatal("NewSocket:", err) } err = sc.Connect("tcp://127.0.0.1:9736") if err != nil { t.Fatal("sc.Connect:", err) } msg, err := bounce(sb, sc) if err != nil { t.Error(msg, err) } err = sc.Close() sc = nil if err != nil { t.Error("sc.Close:", err) } err = sb.Close() sb = nil if err != nil { t.Error("sb.Close:", err) } }
func NewReplyHandler() chan<- *ReplyMessage { replyChan := make(chan *ReplyMessage, replyChanCapacity) pushSockets := make(map[string]*zmq4.Socket) go func() { for replyMessage := range replyChan { marshalledReply, err := json.Marshal(replyMessage.Content) if err != nil { fog.Error("unable to marshall reply %s %s", replyMessage, err) continue } var pushSocket *zmq4.Socket var ok bool pushSocket, ok = pushSockets[replyMessage.ClientAddress] if !ok { fog.Info("creating PUSH socket to %s", replyMessage.ClientAddress) if pushSocket, err = createPushSocket(); err != nil { fog.Error("Unable to create PUSH socket for %s %s", replyMessage.ClientAddress, err) continue } if err = pushSocket.Connect(replyMessage.ClientAddress); err != nil { fog.Error("Unable to Connect PUSH socket to %s %s", replyMessage.ClientAddress, err) pushSocket.Close() continue } pushSockets[replyMessage.ClientAddress] = pushSocket } if _, err = pushSocket.SendMessage(marshalledReply); err != nil { fog.Error("pushSocket SendMessage to %s failed %s", replyMessage.ClientAddress, err) pushSocket.Close() delete(pushSockets, replyMessage.ClientAddress) continue } } }() return replyChan }
// Add registers a socket for sending and/or receiving. The caller can't // access the socket directly after this. The send channel (if any) should be // closed by the caller. func (io *IO) Add(s *zmq.Socket, send <-chan Data, recv chan<- Data) (err error) { fd, err := s.GetFd() if err != nil { return } w := newWorker() io.lock.Lock() io.workers[int32(fd)] = w io.lock.Unlock() defer func() { if err != nil { io.lock.Lock() delete(io.workers, int32(fd)) io.lock.Unlock() } }() e := &syscall.EpollEvent{ Events: syscall.EPOLLIN | syscall.EPOLLET&0xffffffff, Fd: int32(fd), } if err = syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_ADD, fd, e); err != nil { return } state, err := s.GetEvents() if err != nil { syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_DEL, fd, nil) return } go func() { defer s.Close() defer syscall.EpollCtl(io.epollFd, syscall.EPOLL_CTL_DEL, fd, nil) w.socketLoop(s, send, recv, state) }() return }
// Remove closes a socket. If it has been registered, it will be removed. The // recv channel (if any) will be closed. func (io *IO) Remove(s *zmq.Socket) (err error) { fd, err := s.GetFd() if err != nil { return } io.lock.Lock() w := io.workers[int32(fd)] if w != nil { delete(io.workers, int32(fd)) } io.lock.Unlock() if w != nil { w.close() } else { err = s.Close() } return }
func TestMultipleContexts(t *testing.T) { chQuit := make(chan interface{}) chErr := make(chan error, 2) needQuit := false var sock1, sock2, serv1, serv2 *zmq.Socket var serv_ctx1, serv_ctx2, ctx1, ctx2 *zmq.Context var err error defer func() { if needQuit { chQuit <- true chQuit <- true <-chErr <-chErr } for _, s := range []*zmq.Socket{sock1, sock2, serv1, serv2} { if s != nil { s.SetLinger(0) s.Close() } } for _, c := range []*zmq.Context{serv_ctx1, serv_ctx2, ctx1, ctx2} { if c != nil { c.Term() } } }() addr1 := "tcp://127.0.0.1:9997" addr2 := "tcp://127.0.0.1:9998" serv_ctx1, err = zmq.NewContext() if err != nil { t.Fatal("NewContext:", err) } serv1, err = serv_ctx1.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } err = serv1.Bind(addr1) if err != nil { t.Fatal("Bind:", err) } serv_ctx2, err = zmq.NewContext() if err != nil { t.Fatal("NewContext:", err) } serv2, err = serv_ctx2.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } err = serv2.Bind(addr2) if err != nil { t.Fatal("Bind:", err) } new_service := func(sock *zmq.Socket, addr string) { socket_handler := func(state zmq.State) error { msg, err := sock.RecvMessage(0) if err != nil { return err } _, err = sock.SendMessage(addr, msg) return err } quit_handler := func(interface{}) error { return errors.New("quit") } reactor := zmq.NewReactor() reactor.AddSocket(sock, zmq.POLLIN, socket_handler) reactor.AddChannel(chQuit, 1, quit_handler) err = reactor.Run(100 * time.Millisecond) chErr <- err } go new_service(serv1, addr1) go new_service(serv2, addr2) needQuit = true time.Sleep(time.Second) // default context sock1, err = zmq.NewSocket(zmq.REQ) if err != nil { t.Fatal("NewSocket:", err) } sock2, err = zmq.NewSocket(zmq.REQ) if err != nil { t.Fatal("NewSocket:", err) } err = sock1.Connect(addr1) if err != nil { t.Fatal("sock1.Connect:", err) } err = sock2.Connect(addr2) if err != nil { t.Fatal("sock2.Connect:", err) } _, err = sock1.SendMessage(addr1) if err != nil { t.Fatal("sock1.SendMessage:", err) } _, err = sock2.SendMessage(addr2) if err != nil { t.Fatal("sock2.SendMessage:", err) } msg, err := sock1.RecvMessage(0) expected := []string{addr1, addr1} if err != nil || !arrayEqual(msg, expected) { t.Errorf("sock1.RecvMessage: expected %v %v, got %v %v", nil, expected, err, msg) } msg, err = sock2.RecvMessage(0) expected = []string{addr2, addr2} if err != nil || !arrayEqual(msg, expected) { t.Errorf("sock2.RecvMessage: expected %v %v, got %v %v", nil, expected, err, msg) } err = sock1.Close() sock1 = nil if err != nil { t.Fatal("sock1.Close:", err) } err = sock2.Close() sock2 = nil if err != nil { t.Fatal("sock2.Close:", err) } // non-default contexts ctx1, err = zmq.NewContext() if err != nil { t.Fatal("NewContext:", err) } ctx2, err = zmq.NewContext() if err != nil { t.Fatal("NewContext:", err) } sock1, err = ctx1.NewSocket(zmq.REQ) if err != nil { t.Fatal("ctx1.NewSocket:", err) } sock2, err = ctx2.NewSocket(zmq.REQ) if err != nil { t.Fatal("ctx2.NewSocket:", err) } err = sock1.Connect(addr1) if err != nil { t.Fatal("sock1.Connect:", err) } err = sock2.Connect(addr2) if err != nil { t.Fatal("sock2.Connect:", err) } _, err = sock1.SendMessage(addr1) if err != nil { t.Fatal("sock1.SendMessage:", err) } _, err = sock2.SendMessage(addr2) if err != nil { t.Fatal("sock2.SendMessage:", err) } msg, err = sock1.RecvMessage(0) expected = []string{addr1, addr1} if err != nil || !arrayEqual(msg, expected) { t.Errorf("sock1.RecvMessage: expected %v %v, got %v %v", nil, expected, err, msg) } msg, err = sock2.RecvMessage(0) expected = []string{addr2, addr2} if err != nil || !arrayEqual(msg, expected) { t.Errorf("sock2.RecvMessage: expected %v %v, got %v %v", nil, expected, err, msg) } err = sock1.Close() sock1 = nil if err != nil { t.Fatal("sock1.Close:", err) } err = sock2.Close() sock2 = nil if err != nil { t.Fatal("sock2.Close:", err) } err = ctx1.Term() ctx1 = nil if err != nil { t.Fatal("ctx1.Term", nil) } err = ctx2.Term() ctx1 = nil if err != nil { t.Fatal("ctx2.Term", nil) } needQuit = false for i := 0; i < 2; i++ { // close(chQuit) doesn't work because the reactor removes closed channels, instead of acting on them chQuit <- true err = <-chErr if err.Error() != "quit" { t.Errorf("Expected error value quit, got %v", err) } } }
func TestSecurityPlain(t *testing.T) { time.Sleep(100 * time.Millisecond) var handler, server, client *zmq.Socket defer func() { for _, s := range []*zmq.Socket{handler} { if s != nil { s.SetLinger(0) s.Close() } } }() handler, err := zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } err = handler.Bind("inproc://zeromq.zap.01") if err != nil { t.Fatal("handler.Bind:", err) } doHandler := func(state zmq.State) error { msg, err := handler.RecvMessage(0) if err != nil { return err // Terminating } version := msg[0] sequence := msg[1] // domain := msg[2] // address := msg[3] identity := msg[4] mechanism := msg[5] username := msg[6] password := msg[7] if version != "1.0" { return errors.New("version != 1.0") } if mechanism != "PLAIN" { return errors.New("mechanism != PLAIN") } if identity != "IDENT" { return errors.New("identity != IDENT") } if username == "admin" && password == "password" { handler.SendMessage(version, sequence, "200", "OK", "anonymous", "") } else { handler.SendMessage(version, sequence, "400", "Invalid username or password", "", "") } return nil } doQuit := func(i interface{}) error { err := handler.Close() if err != nil { t.Error("handler.Close:", err) } return errors.New("Quit") } quit := make(chan interface{}) reactor := zmq.NewReactor() reactor.AddSocket(handler, zmq.POLLIN, doHandler) reactor.AddChannel(quit, 0, doQuit) go func() { reactor.Run(100 * time.Millisecond) quit <- true }() defer func() { quit <- true <-quit close(quit) }() // Server socket will accept connections server, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket", err) } err = server.SetIdentity("IDENT") if err != nil { t.Fatal("server.SetIdentity:", err) } err = server.SetPlainServer(1) if err != nil { t.Fatal("server.SetPlainServer(1):", err) } err = server.Bind("tcp://127.0.0.1:9998") if err != nil { t.Fatal("server.Bind") } // Check PLAIN security with correct username/password client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetPlainUsername("admin") if err != nil { t.Fatal("client.SetPlainUsername:"******"password") if err != nil { t.Fatal("client.SetPlainPassword:"******"tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } msg, err := bounce(server, client) if err != nil { t.Error(msg, err) } err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } // Check PLAIN security with badly configured client (as_server) // This will be caught by the plain_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } client.SetPlainServer(1) if err != nil { t.Fatal("client.SetPlainServer(1):", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } err = server.SetRcvtimeo(time.Second) if err != nil { t.Fatal("server.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } err = server.Close() server = nil if err != nil { t.Fatal("server.Close:", err) } }
func TestAbstractIpc(t *testing.T) { var sb, sc *zmq.Socket defer func() { for _, s := range []*zmq.Socket{sb, sc} { if s != nil { s.SetLinger(0) s.Close() } } }() addr := "ipc://@/tmp/tester" // This is Linux only if runtime.GOOS != "linux" { t.Skip("Only on Linux") } sb, err := zmq.NewSocket(zmq.PAIR) if err != nil { t.Fatal("NewSocket:", err) } err = sb.Bind(addr) if err != nil { t.Fatal("sb.Bind:", err) } endpoint, err := sb.GetLastEndpoint() expected := "ipc://@/tmp/tester" if endpoint != expected || err != nil { t.Fatalf("sb.GetLastEndpoint: expected 'nil' %q, got '%v' %q", expected, err, endpoint) return } sc, err = zmq.NewSocket(zmq.PAIR) if err != nil { t.Fatal("NewSocket:", err) } err = sc.Connect(addr) if err != nil { t.Fatal("sc.Bind:", err) } resp, err := bounce(sb, sc) if err != nil { t.Error(resp, err) } err = sc.Close() sc = nil if err != nil { t.Fatal("sc.Close:", err) } err = sb.Close() sb = nil if err != nil { t.Fatal("sb.Close:", err) } }
func TestSecurityCurve(t *testing.T) { time.Sleep(100 * time.Millisecond) var handler, server, client *zmq.Socket defer func() { for _, s := range []*zmq.Socket{handler} { if s != nil { s.SetLinger(0) s.Close() } } }() if _, minor, _ := zmq.Version(); minor >= 1 && !zmq.HasCurve() { t.Skip("Curve not available") } // Generate new keypairs for this test client_public, client_secret, err := zmq.NewCurveKeypair() if err != nil { t.Fatal("NewCurveKeypair:", err) } server_public, server_secret, err := zmq.NewCurveKeypair() if err != nil { t.Fatal("NewCurveKeypair:", err) } handler, err = zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } err = handler.Bind("inproc://zeromq.zap.01") if err != nil { t.Fatal("handler.Bind:", err) } doHandler := func(state zmq.State) error { msg, err := handler.RecvMessage(0) if err != nil { return err // Terminating } version := msg[0] sequence := msg[1] // domain := msg[2] // address := msg[3] identity := msg[4] mechanism := msg[5] client_key := msg[6] client_key_text := zmq.Z85encode(client_key) if version != "1.0" { return errors.New("version != 1.0") } if mechanism != "CURVE" { return errors.New("mechanism != CURVE") } if identity != "IDENT" { return errors.New("identity != IDENT") } if client_key_text == client_public { handler.SendMessage(version, sequence, "200", "OK", "anonymous", "") } else { handler.SendMessage(version, sequence, "400", "Invalid client public key", "", "") } return nil } doQuit := func(i interface{}) error { err := handler.Close() handler = nil if err != nil { t.Error("handler.Close:", err) } return errors.New("Quit") } quit := make(chan interface{}) reactor := zmq.NewReactor() reactor.AddSocket(handler, zmq.POLLIN, doHandler) reactor.AddChannel(quit, 0, doQuit) go func() { reactor.Run(100 * time.Millisecond) quit <- true }() defer func() { quit <- true <-quit close(quit) }() // Server socket will accept connections server, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = server.SetCurveServer(1) if err != nil { t.Fatal("server.SetCurveServer(1):", err) } err = server.SetCurveSecretkey(server_secret) if err != nil { t.Fatal("server.SetCurveSecretkey:", err) } err = server.SetIdentity("IDENT") if err != nil { t.Fatal("server.SetIdentity:", err) } server.Bind("tcp://127.0.0.1:9998") if err != nil { t.Fatal("server.Bind:", err) } err = server.SetRcvtimeo(time.Second) if err != nil { t.Fatal("server.SetRcvtimeo:", err) } // Check CURVE security with valid credentials client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(client_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(client_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } msg, err := bounce(server, client) if err != nil { t.Error(msg, err) } err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage server key // This will be caught by the curve_server class, not passed to ZAP garbage_key := "0000111122223333444455556666777788889999" client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(garbage_key) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(client_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(client_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage client secret key // This will be caught by the curve_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(garbage_key) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(client_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage client secret key // This will be caught by the curve_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(client_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(garbage_key) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with bogus client credentials // This must be caught by the ZAP handler bogus_public, bogus_secret, _ := zmq.NewCurveKeypair() client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(bogus_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(bogus_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } // Shutdown err = server.Close() server = nil if err != nil { t.Error("server.Close:", err) } }
func TestSecurityNull(t *testing.T) { time.Sleep(100 * time.Millisecond) var handler, server, client *zmq.Socket defer func() { for _, s := range []*zmq.Socket{handler} { if s != nil { s.SetLinger(0) s.Close() } } }() handler, err := zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } err = handler.Bind("inproc://zeromq.zap.01") if err != nil { t.Fatal("handler.Bind:", err) } doHandler := func(state zmq.State) error { msg, err := handler.RecvMessage(0) if err != nil { return err // Terminating } version := msg[0] sequence := msg[1] domain := msg[2] // address := msg[3] // identity := msg[4] mechanism := msg[5] if version != "1.0" { return errors.New("version != 1.0") } if mechanism != "NULL" { return errors.New("mechanism != NULL") } if domain == "TEST" { handler.SendMessage(version, sequence, "200", "OK", "anonymous", "") } else { handler.SendMessage(version, sequence, "400", "BAD DOMAIN", "", "") } return nil } doQuit := func(i interface{}) error { err := handler.Close() handler = nil if err != nil { t.Error("handler.Close:", err) } return errors.New("Quit") } quit := make(chan interface{}) reactor := zmq.NewReactor() reactor.AddSocket(handler, zmq.POLLIN, doHandler) reactor.AddChannel(quit, 0, doQuit) go func() { reactor.Run(100 * time.Millisecond) quit <- true }() defer func() { quit <- true <-quit close(quit) }() // We bounce between a binding server and a connecting client server, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } // We first test client/server with no ZAP domain // Libzmq does not call our ZAP handler, the connect must succeed err = server.Bind("tcp://127.0.0.1:9683") if err != nil { t.Fatal("server.Bind:", err) } err = client.Connect("tcp://127.0.0.1:9683") if err != nil { t.Fatal("client.Connect:", err) } msg, err := bounce(server, client) if err != nil { t.Error(msg, err) } server.Unbind("tcp://127.0.0.1:9683") client.Disconnect("tcp://127.0.0.1:9683") // Now define a ZAP domain for the server; this enables // authentication. We're using the wrong domain so this test // must fail. err = server.SetZapDomain("WRONG") if err != nil { t.Fatal("server.SetZapDomain:", err) } err = server.Bind("tcp://127.0.0.1:9687") if err != nil { t.Fatal("server.Bind:", err) } err = client.Connect("tcp://127.0.0.1:9687") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } err = server.SetRcvtimeo(time.Second) if err != nil { t.Fatal("server.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } server.Unbind("tcp://127.0.0.1:9687") client.Disconnect("tcp://127.0.0.1:9687") // Now use the right domain, the test must pass err = server.SetZapDomain("TEST") if err != nil { t.Fatal("server.SetZapDomain:", err) } err = server.Bind("tcp://127.0.0.1:9688") if err != nil { t.Fatal("server.Bind:", err) } err = client.Connect("tcp://127.0.0.1:9688") if err != nil { t.Fatal("client.Connect:", err) } msg, err = bounce(server, client) if err != nil { t.Error(msg, err) } server.Unbind("tcp://127.0.0.1:9688") client.Disconnect("tcp://127.0.0.1:9688") err = client.Close() client = nil if err != nil { t.Error("client.Close:", err) } err = server.Close() server = nil if err != nil { t.Error("server.Close:", err) } }
func TestHwm(t *testing.T) { MAX_SENDS := 10000 BIND_FIRST := 1 CONNECT_FIRST := 2 test_defaults := func() (result int) { result = -1 // Set up bind socket bind_socket, err := zmq.NewSocket(zmq.PULL) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := bind_socket.Close() if err != nil { t.Error("bind_socket.Close:", err) } }() err = bind_socket.Bind("inproc://a") if err != nil { t.Error("bind_socket.Bind:", err) return } // Set up connect socket connect_socket, err := zmq.NewSocket(zmq.PUSH) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := connect_socket.Close() if err != nil { t.Error("connect_socket.Close:", err) } }() err = connect_socket.Connect("inproc://a") if err != nil { t.Error("connect_socket.Connect:", err) return } // Send until we block send_count := 0 for send_count < MAX_SENDS { _, err := connect_socket.Send("", zmq.DONTWAIT) if err != nil { break } send_count++ } // Now receive all sent messages recv_count := 0 for { _, err := bind_socket.Recv(zmq.DONTWAIT) if err != nil { break } recv_count++ } if send_count != recv_count { t.Error("test_defaults: send_count == recv_count") } return send_count } count_msg := func(send_hwm, recv_hwm, testType int) (result int) { result = -1 var bind_socket, connect_socket *zmq.Socket var err error if testType == BIND_FIRST { // Set up bind socket bind_socket, err = zmq.NewSocket(zmq.PULL) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := bind_socket.Close() if err != nil { t.Error("bind_socket.Close:", err) } }() err = bind_socket.SetRcvhwm(recv_hwm) if err != nil { t.Error("bind_socket.SetRcvhwm:", err) return } err = bind_socket.Bind("inproc://a") if err != nil { t.Error("bind_socket.Bind:", err) return } // Set up connect socket connect_socket, err = zmq.NewSocket(zmq.PUSH) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := connect_socket.Close() if err != nil { t.Error(err) } }() err = connect_socket.SetSndhwm(send_hwm) if err != nil { t.Error("connect_socket.SetSndhwm:", err) return } err = connect_socket.Connect("inproc://a") if err != nil { t.Error("connect_socket.Connect:", err) return } } else { // Set up connect socket connect_socket, err = zmq.NewSocket(zmq.PUSH) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := connect_socket.Close() if err != nil { t.Error("connect_socket.Close:", err) } }() err = connect_socket.SetSndhwm(send_hwm) if err != nil { t.Error("connect_socket.SetSndhwm:", err) return } err = connect_socket.Connect("inproc://a") if err != nil { t.Error("connect_socket.Connect:", err) return } // Set up bind socket bind_socket, err = zmq.NewSocket(zmq.PULL) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := bind_socket.Close() if err != nil { t.Error("bind_socket.Close:", err) } }() err = bind_socket.SetRcvhwm(recv_hwm) if err != nil { t.Error("bind_socket.SetRcvhwm:", err) return } err = bind_socket.Bind("inproc://a") if err != nil { t.Error("bind_socket.Bind:", err) return } } // Send until we block send_count := 0 for send_count < MAX_SENDS { _, err := connect_socket.Send("", zmq.DONTWAIT) if err != nil { break } send_count++ } // Now receive all sent messages recv_count := 0 for { _, err := bind_socket.Recv(zmq.DONTWAIT) if err != nil { break } recv_count++ } if send_count != recv_count { t.Error("count_msg: send_count != recv_count") } // Now it should be possible to send one more. _, err = connect_socket.Send("", 0) if err != nil { t.Error("connect_socket.Send:", err) return } // Consume the remaining message. _, err = bind_socket.Recv(0) if err != nil { t.Error("bind_socket.Recv:", err) } return send_count } test_inproc_bind_first := func(send_hwm, recv_hwm int) int { return count_msg(send_hwm, recv_hwm, BIND_FIRST) } test_inproc_connect_first := func(send_hwm, recv_hwm int) int { return count_msg(send_hwm, recv_hwm, CONNECT_FIRST) } test_inproc_connect_and_close_first := func(send_hwm, recv_hwm int) (result int) { result = -1 // Set up connect socket connect_socket, err := zmq.NewSocket(zmq.PUSH) if err != nil { t.Error("NewSocket:", err) return } defer func() { if connect_socket != nil { connect_socket.Close() } }() err = connect_socket.SetSndhwm(send_hwm) if err != nil { t.Error("connect_socket.SetSndhwm:", err) return } err = connect_socket.Connect("inproc://a") if err != nil { t.Error("connect_socket.Connect:", err) return } // Send until we block send_count := 0 for send_count < MAX_SENDS { _, err := connect_socket.Send("", zmq.DONTWAIT) if err != nil { break } send_count++ } // Close connect err = connect_socket.Close() connect_socket = nil if err != nil { t.Error("connect_socket.Close:", err) return } // Set up bind socket bind_socket, err := zmq.NewSocket(zmq.PULL) if err != nil { t.Error("NewSocket:", err) return } defer func() { err := bind_socket.Close() if err != nil { t.Error("bind_socket.Close:", err) } }() err = bind_socket.SetRcvhwm(recv_hwm) if err != nil { t.Error("bind_socket.SetRcvhwm:", err) return } err = bind_socket.Bind("inproc://a") if err != nil { t.Error("bind_socket.Bind:", err) return } // Now receive all sent messages recv_count := 0 for { _, err := bind_socket.Recv(zmq.DONTWAIT) if err != nil { break } recv_count++ } if send_count != recv_count { t.Error("test_inproc_connect_and_close_first: send_count != recv_count") } return send_count } // Default values are 1000 on send and 1000 one receive, so 2000 total if count := test_defaults(); count != 2000 { t.Errorf("test_defaults: expected 2000, got %d", count) } time.Sleep(100 * time.Millisecond) // Infinite send and receive buffer if count := test_inproc_bind_first(0, 0); count != MAX_SENDS { t.Errorf("test_inproc_bind_first(0, 0): expected %d, got %d", MAX_SENDS, count) } time.Sleep(100 * time.Millisecond) if count := test_inproc_connect_first(0, 0); count != MAX_SENDS { t.Errorf("test_inproc_connect_first(0, 0): expected %d, got %d", MAX_SENDS, count) } time.Sleep(100 * time.Millisecond) // Infinite send buffer if count := test_inproc_bind_first(1, 0); count != MAX_SENDS { t.Errorf("test_inproc_bind_first(1, 0): expected %d, got %d", MAX_SENDS, count) } time.Sleep(100 * time.Millisecond) if count := test_inproc_connect_first(1, 0); count != MAX_SENDS { t.Errorf("test_inproc_connect_first(1, 0): expected %d, got %d", MAX_SENDS, count) } time.Sleep(100 * time.Millisecond) // Infinite receive buffer if count := test_inproc_bind_first(0, 1); count != MAX_SENDS { t.Errorf("test_inproc_bind_first(0, 1): expected %d, got %d", MAX_SENDS, count) } time.Sleep(100 * time.Millisecond) if count := test_inproc_connect_first(0, 1); count != MAX_SENDS { t.Errorf("test_inproc_connect_first(0, 1): expected %d, got %d", MAX_SENDS, count) } time.Sleep(100 * time.Millisecond) // Send and recv buffers hwm 1, so total that can be queued is 2 if count := test_inproc_bind_first(1, 1); count != 2 { t.Errorf("test_inproc_bind_first(1, 1): expected 2, got %d", count) } time.Sleep(100 * time.Millisecond) if count := test_inproc_connect_first(1, 1); count != 2 { t.Errorf("test_inproc_connect_first(1, 1): expected 2, got %d", count) } time.Sleep(100 * time.Millisecond) // Send hwm of 1, send before bind so total that can be queued is 1 if count := test_inproc_connect_and_close_first(1, 0); count != 1 { t.Errorf("test_inproc_connect_and_close_first(1, 0): expected 1, got %d", count) } time.Sleep(100 * time.Millisecond) }
func main() { info := "greenline: notoriously unreliable\n" + "https://github.com/formwork-io/greenline\n" + "This is free software with ABSOLUTELY NO WARRANTY." fmt.Printf("%s\n--\n", info) var rails []Rail if len(os.Args) == 2 { var err error rails, err = ReadConfigFile(os.Args[1]) if err != nil { die(err.Error()) } } else { var err error rails, err = ReadEnvironment() if err != nil { die(err.Error()) } } pprint("configuring %d rails", len(rails)) socketPairs := make(map[*zmq.Socket]*zmq.Socket) socketNames := make(map[*zmq.Socket]string) poller := zmq.NewPoller() railmsg := "%s protocol %s, %d -> %d" for _, rail := range rails { var ingress *zmq.Socket var egress *zmq.Socket switch rail.Protocol { case "broadcast": ingress, egress = railToPubSub(&rail, poller) case "request": ingress, egress = railToRouterDealer(&rail, poller) default: die("The protocol %s is not valid.", rail.Protocol) } titledProtocol := strings.Title(rail.Protocol) pprint(railmsg, titledProtocol, rail.Name, rail.Ingress, rail.Egress) socketPairs[ingress] = egress socketNames[ingress] = fmt.Sprintf("%s (ingress)", rail.Name) socketPairs[egress] = ingress socketNames[egress] = fmt.Sprintf("%s (egress)", rail.Name) defer ingress.Close() defer egress.Close() } pprint("greenline alive") exitchan := make(chan os.Signal, 0) signal.Notify(exitchan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) go func() { sig := <-exitchan out("received %s signal, exiting.\n", sig.String()) os.Exit(0) }() reloadchan := make(chan int) go reloader(reloadchan) readychan := make(chan bool) pollchan := make(chan bool) go func() { for { sockets, err := poller.Poll(-1) if err != nil { // get EINTR while polling? if IsEINTR(err) { // Continue polling; EINTR is normal for us... continue // ... with our use of signals. } // otherwise shutdown readychan <- false break } if len(sockets) != 0 { readychan <- true } // wait to poll once msgs processed <-pollchan } }() pprint("greenline ready") for { select { case reloadOp := <-reloadchan: if reloadOp&BinReload == BinReload { pprint("new binary available, restarting greenline") for key, value := range socketPairs { key.Close() value.Close() } zmq.Term() // exec or die restart() } else if reloadOp&ConfigReload == ConfigReload { pprint("new configuration available, restarting greenline") for key, value := range socketPairs { key.Close() value.Close() } zmq.Term() // exec or die restart() } case ready := <-readychan: if !ready { die("ready set fail") } // ready set go sockets, err := poller.Poll(-1) if err != nil { die("poll returned err: %s", err.Error()) } for _, polled := range sockets { socket := polled.Socket pairedSocket := socketPairs[socket] name := socketNames[socket] pprint("processing message for %s", name) for { msg, err := socket.Recv(0) if err != nil { die("failed on receive: %s", err.Error()) } more, err := socket.GetRcvmore() if err != nil { die("failed on receive more: %s", err.Error()) } if more { pairedSocket.Send(msg, zmq.SNDMORE) } else { pairedSocket.Send(msg, 0) break } } } pollchan <- true } } }
func TestZmqChanSocket(t *testing.T) { var sb, sc *zmq.Socket var cb, cc zmqchan.ChanSocket var err error num := 10 defer func() { if sb != nil { sb.SetLinger(0) sb.Close() } if sc != nil { sc.SetLinger(0) sc.Close() } if cb != nil { log.Println("MAIN: Close") cb.Close() } if cc != nil { log.Println("ECHO: Close") cc.Close() } log.Println("BOTH: Exit") }() if sb, err = zmq.NewSocket(zmq.PAIR); err != nil { t.Fatal("NewSocket:", err) } if sc, err = zmq.NewSocket(zmq.PAIR); err != nil { t.Fatal("NewSocket:", err) } if err = sb.Bind("tcp://127.0.0.1:9737"); err != nil { t.Fatal("sb.Bind:", err) } if err = sc.Connect("tcp://127.0.0.1:9737"); err != nil { t.Fatal("sc.Connect:", err) } if cb, err = zmqchan.NewZmqChanSocket(sb, 0, 0); err != nil { t.Fatal("sb.NewZmqChanSocket:", err) } sb = nil // don't access this or close it on defer if cc, err = zmqchan.NewZmqChanSocket(sc, 0, 0); err != nil { t.Fatal("sb.NewZmqChanSocket:", err) } sc = nil // don't access this or close it on defer var wg sync.WaitGroup wg.Add(1) go func() { runEcho(t, num, cc) wg.Done() }() wg.Add(1) go func() { runWrite(t, num, cb) wg.Done() }() wg.Wait() log.Println("BOTH: done") }
// Send a request to a service func SendRequest(service Service, request, message string) (reply []string, err error) { // Bind to service if not already done var requester *zmq.Socket fmt.Println("Connecting to '", service.Name, "'' at '", service.Address, "'...") requester, err = zmq.NewSocket(zmq.REQ) if err != nil { log.Println(err) return } requester.Connect(service.Address) poller := zmq.NewPoller() poller.Add(requester, zmq.POLLIN) retries_left := REQUEST_RETRIES request_timeout := REQUEST_TIMEOUT if request == PPP_HEARTBEAT { retries_left = 1 request_timeout = 1500 * time.Millisecond } for retries_left > 0 { // Send message // The service required in first packet of envelope // The message for given service in second packet of envelope // Heartbeat messages only contain one message in envelope if request == PPP_HEARTBEAT { _, err = requester.Send(PPP_HEARTBEAT, 0) } else { _, err = requester.Send(request, zmq.SNDMORE) _, err = requester.Send(message, 0) } for expect_reply := true; expect_reply; { // Poll socket for a reply, with timeout var sockets []zmq.Polled sockets, err = poller.Poll(request_timeout) if err != nil { break // Interrupted } // Wait to receive reply if there are no more messages to send if len(sockets) > 0 { // Receive all replies in the envelope before processing var more bool for count := 0; ; count++ { var rep string rep, err = requester.Recv(0) if err != nil { retries_left-- break } reply = append(reply, rep) // Unpacking three parts from the message envelope // The first part: the expected service reply signature // The second part is either: // a. error state (empty if no error) OR // b. the heartbeat reply of the server // The third part: the actual message if count == 0 && rep != service.Reply { err = errors.New("ServiceListOutdated:Bound to wrong service") retries_left = 0 break } if count == 1 && rep != "" && rep != PPP_READY { err = errors.New(rep) retries_left = 0 break } // Break from loop if there are no more messages or // an error condition occurs more, err = requester.GetRcvmore() if !more || err != nil { retries_left-- break } } // If there was an error retrieving the message, then we // should still expect replies if err != nil { break } // All messages retrieved from packet successfully // Leave the retrieve/retry loops retries_left = 0 expect_reply = false } else { retries_left-- if retries_left == 0 { if err == nil { err = errors.New("Error:TimeOut") } requester.Close() return } else { err = nil reply = nil fmt.Println("No response from server, retrying...") // Old socket is confused; close it and open a new one requester.Close() requester, _ = zmq.NewSocket(zmq.REQ) requester.Connect(service.Address) // Recreate poller for new client poller = zmq.NewPoller() poller.Add(requester, zmq.POLLIN) // Send request again, on the new socket if request == PPP_HEARTBEAT { _, err = requester.Send(PPP_HEARTBEAT, 0) } else { _, err = requester.Send(request, zmq.SNDMORE) _, err = requester.Send(message, 0) } } } } } fmt.Println("\tReceived: ", reply) // Deall with invalid/distorted replies first // Followed by heartbeat replies // Then package reply for return to the function caller if len(reply) < 2 { err = errors.New(fmt.Sprintf("Error:UnexpectedReply:%s", err)) requester.Close() return } if reply[1] == PPP_READY { reply = append(reply, reply[1]) } reply = reply[2:] requester.Close() return }
func main() { var rails []rail if len(os.Args) == 2 { var err error rails, err = ReadConfigFile(os.Args[1]) if err != nil { die(err.Error()) } } else { var err error rails, err = ReadEnvironment() if err != nil { die(err.Error()) } } socket_pairs := make(map[*zmq.Socket]*zmq.Socket) socket_names := make(map[*zmq.Socket]string) poller := zmq.NewPoller() for _, rail := range rails { pprint("starting rail %s as %s", rail.Name, rail.Pattern) var ingress *zmq.Socket var egress *zmq.Socket switch rail.Pattern { case "pubsub": ingress, egress = railToPubSub(&rail, poller) case "reqrep": ingress, egress = railToRouterDealer(&rail, poller) default: die("The pattern %s is not valid.", rail.Pattern) } socket_pairs[ingress] = egress socket_names[ingress] = fmt.Sprintf("%s (ingress)", rail.Name) socket_pairs[egress] = ingress socket_names[egress] = fmt.Sprintf("%s (egress)", rail.Name) defer ingress.Close() defer egress.Close() } pprint("greenline alive") exitchan := make(chan os.Signal, 0) signal.Notify(exitchan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) go func() { sig := <-exitchan out("received %s signal, exiting.\n", sig.String()) os.Exit(0) }() pprint("greenline ready") for { sockets, _ := poller.Poll(-1) for _, polled := range sockets { socket := polled.Socket paired_socket := socket_pairs[socket] name := socket_names[socket] pprint("processing message for %s", name) for { msg, err := socket.Recv(0) if err != nil { die("failed on receive: %s", err.Error()) } more, err := socket.GetRcvmore() if err != nil { die("failed on receive more: %s", err.Error()) } if more { paired_socket.Send(msg, zmq.SNDMORE) } else { paired_socket.Send(msg, 0) break } } } } }
func main() { flag.Parse(nil) address_list := flag.Args if len(address_list) == 0 { fmt.Println("No Addresses submitted") fmt.Println(flag.Help()) return } var send, recv bool skip := false var socket *zmq.Socket switch *socket_type { case "PUSH": socket, _ = zmq.NewSocket(zmq.PUSH) send = true case "PULL": socket, _ = zmq.NewSocket(zmq.PULL) recv = true case "PUB": socket, _ = zmq.NewSocket(zmq.PUB) send = true case "SUB": socket, _ = zmq.NewSocket(zmq.SUB) recv = true if len(*subscriptions) == 0 { socket.SetSubscribe("") } for _, subscription := range *subscriptions { socket.SetSubscribe(subscription) } case "REQ": socket, _ = zmq.NewSocket(zmq.REQ) send = true recv = true case "REP": socket, _ = zmq.NewSocket(zmq.REP) send = true recv = true skip = true } defer socket.Close() // connect or bind if *mode { for _, address := range address_list { socket.Connect(address) } } else { for _, address := range address_list { socket.Bind(address) } } delim := byte('\n') if *null { fmt.Println("Setting delim to null") delim = byte(0x00) } reader := bufio.NewReader(os.Stdin) writer := bufio.NewWriter(os.Stdout) for i := 0; i < *number || *number == -1; i++ { if send && !skip { line, _ := reader.ReadBytes(delim) socket.SendBytes([]byte(line), 0) } if recv { data, _ := socket.RecvBytes(0) writer.Write(data) writer.Flush() } if skip { skip = false } } fmt.Println("finished", *number) }
// handleOutPort handles messages sent from this server func (s *serverImpl) handleOutPort() { // fmt.Println("handleOutPort: Waiting for message on outbox") // initial cache refresh s.setAddressOf(make(map[int]string)) s.refreshPeerCache(BROADCAST) peerSocketCache := make(map[int]*zmq.Socket) for { msg := <-s.outbox receivers := list.New() // BROADCAST packet or packet for new server if _, ok := s.address(msg.Pid); !ok { s.refreshPeerCache(msg.Pid) // packet is dropped silently if _, ok := s.address(msg.Pid); !ok && msg.Pid != BROADCAST { fmt.Println("Address of ", msg.Pid, " could not be found") continue } } if msg.Pid != BROADCAST { receivers.PushBack(msg.Pid) } else { s.RLock() for key, _ := range s.addressOf { if key != s.pid { receivers.PushBack(key) } } s.RUnlock() } // change msg.Pid to match this server // receiving server will then find correct Pid msg.Pid = s.Pid() // send message to receivers gobbedMessage := EnvelopeToBytes(msg) for pid := receivers.Front(); pid != nil; pid = pid.Next() { // cache connections to peers var requester *zmq.Socket var ok bool var err error pidInt := 0 if pidInt, ok = pid.Value.(int); ok { } if requester, ok = peerSocketCache[pidInt]; !ok { requester, err = zmq.NewSocket(zmq.PUSH) if err != nil { fmt.Println("Error in creating request socket. ", err.Error()) return } peerSocketCache[pidInt] = requester socketStr, _ := s.address(pidInt) requester.Connect("tcp://" + socketStr) defer requester.Close() } requester.SendBytes(gobbedMessage, 0) } } }
func Example_test_hwm() { MAX_SENDS := 10000 BIND_FIRST := 1 CONNECT_FIRST := 2 test_defaults := func() int { // Set up bind socket bind_socket, err := zmq.NewSocket(zmq.PULL) if checkErr(err) { return 0 } defer func() { err := bind_socket.Close() checkErr(err) }() err = bind_socket.Bind("inproc://a") if checkErr(err) { return 0 } // Set up connect socket connect_socket, err := zmq.NewSocket(zmq.PUSH) if checkErr(err) { return 0 } defer func() { err := connect_socket.Close() checkErr(err) }() err = connect_socket.Connect("inproc://a") if checkErr(err) { return 0 } // Send until we block send_count := 0 for send_count < MAX_SENDS { _, err := connect_socket.Send("", zmq.DONTWAIT) if err != nil { break } send_count++ } // Now receive all sent messages recv_count := 0 for { _, err := bind_socket.Recv(zmq.DONTWAIT) if err != nil { break } recv_count++ } fmt.Println("send_count == recv_count:", send_count == recv_count) return send_count } count_msg := func(send_hwm, recv_hwm, testType int) int { var bind_socket, connect_socket *zmq.Socket var err error if testType == BIND_FIRST { // Set up bind socket bind_socket, err = zmq.NewSocket(zmq.PULL) if checkErr(err) { return 0 } defer func() { err := bind_socket.Close() checkErr(err) }() err = bind_socket.SetRcvhwm(recv_hwm) if checkErr(err) { return 0 } err = bind_socket.Bind("inproc://a") if checkErr(err) { return 0 } // Set up connect socket connect_socket, err = zmq.NewSocket(zmq.PUSH) if checkErr(err) { return 0 } defer func() { err := connect_socket.Close() checkErr(err) }() err = connect_socket.SetSndhwm(send_hwm) if checkErr(err) { return 0 } err = connect_socket.Connect("inproc://a") if checkErr(err) { return 0 } } else { // Set up connect socket connect_socket, err = zmq.NewSocket(zmq.PUSH) if checkErr(err) { return 0 } defer func() { err := connect_socket.Close() checkErr(err) }() err = connect_socket.SetSndhwm(send_hwm) if checkErr(err) { return 0 } err = connect_socket.Connect("inproc://a") if checkErr(err) { return 0 } // Set up bind socket bind_socket, err = zmq.NewSocket(zmq.PULL) if checkErr(err) { return 0 } defer func() { err := bind_socket.Close() checkErr(err) }() err = bind_socket.SetRcvhwm(recv_hwm) if checkErr(err) { return 0 } err = bind_socket.Bind("inproc://a") if checkErr(err) { return 0 } } // Send until we block send_count := 0 for send_count < MAX_SENDS { _, err := connect_socket.Send("", zmq.DONTWAIT) if err != nil { break } send_count++ } // Now receive all sent messages recv_count := 0 for { _, err := bind_socket.Recv(zmq.DONTWAIT) if err != nil { break } recv_count++ } fmt.Println("send_count == recv_count:", send_count == recv_count) // Now it should be possible to send one more. _, err = connect_socket.Send("", 0) if checkErr(err) { return 0 } // Consume the remaining message. _, err = bind_socket.Recv(0) checkErr(err) return send_count } test_inproc_bind_first := func(send_hwm, recv_hwm int) int { return count_msg(send_hwm, recv_hwm, BIND_FIRST) } test_inproc_connect_first := func(send_hwm, recv_hwm int) int { return count_msg(send_hwm, recv_hwm, CONNECT_FIRST) } test_inproc_connect_and_close_first := func(send_hwm, recv_hwm int) int { // Set up connect socket connect_socket, err := zmq.NewSocket(zmq.PUSH) if checkErr(err) { return 0 } err = connect_socket.SetSndhwm(send_hwm) if checkErr(err) { connect_socket.Close() return 0 } err = connect_socket.Connect("inproc://a") if checkErr(err) { connect_socket.Close() return 0 } // Send until we block send_count := 0 for send_count < MAX_SENDS { _, err := connect_socket.Send("", zmq.DONTWAIT) if err != nil { break } send_count++ } // Close connect err = connect_socket.Close() if checkErr(err) { return 0 } // Set up bind socket bind_socket, err := zmq.NewSocket(zmq.PULL) if checkErr(err) { return 0 } defer func() { err := bind_socket.Close() checkErr(err) }() err = bind_socket.SetRcvhwm(recv_hwm) if checkErr(err) { return 0 } err = bind_socket.Bind("inproc://a") if checkErr(err) { return 0 } // Now receive all sent messages recv_count := 0 for { _, err := bind_socket.Recv(zmq.DONTWAIT) if err != nil { break } recv_count++ } fmt.Println("send_count == recv_count:", send_count == recv_count) return send_count } // Default values are 1000 on send and 1000 one receive, so 2000 total fmt.Println("Default values") count := test_defaults() fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) // Infinite send and receive buffer fmt.Println("\nInfinite send and receive") count = test_inproc_bind_first(0, 0) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) count = test_inproc_connect_first(0, 0) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) // Infinite send buffer fmt.Println("\nInfinite send buffer") count = test_inproc_bind_first(1, 0) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) count = test_inproc_connect_first(1, 0) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) // Infinite receive buffer fmt.Println("\nInfinite receive buffer") count = test_inproc_bind_first(0, 1) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) count = test_inproc_connect_first(0, 1) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) // Send and recv buffers hwm 1, so total that can be queued is 2 fmt.Println("\nSend and recv buffers hwm 1") count = test_inproc_bind_first(1, 1) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) count = test_inproc_connect_first(1, 1) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) // Send hwm of 1, send before bind so total that can be queued is 1 fmt.Println("\nSend hwm of 1, send before bind") count = test_inproc_connect_and_close_first(1, 0) fmt.Println("count:", count) time.Sleep(100 * time.Millisecond) fmt.Println("\nDone") // Output: // Default values // send_count == recv_count: true // count: 2000 // // Infinite send and receive // send_count == recv_count: true // count: 10000 // send_count == recv_count: true // count: 10000 // // Infinite send buffer // send_count == recv_count: true // count: 10000 // send_count == recv_count: true // count: 10000 // // Infinite receive buffer // send_count == recv_count: true // count: 10000 // send_count == recv_count: true // count: 10000 // // Send and recv buffers hwm 1 // send_count == recv_count: true // count: 2 // send_count == recv_count: true // count: 2 // // Send hwm of 1, send before bind // send_count == recv_count: true // count: 1 // // Done }
func (w *Worker) run(socket *zmq.Socket) { defer close(w.wait) defer socket.Close() socket.SetRcvtimeo(w.passiveTimeout) socket.Bind(w.address) atomic.StoreInt32(&w.runningWorkers, 0) responseChannel := make(chan *messageContext) sendResponse := func(response [][]byte) { atomic.AddInt32(&w.runningWorkers, -1) if _, err := socket.SendMessage(response); err != nil { log.Println("Failed to send response:", err) } if atomic.LoadInt32(&w.runningWorkers) == 0 { socket.SetRcvtimeo(w.passiveTimeout) } } for { if atomic.LoadInt32(&w.runningWorkers) == w.maxWorkers { // We're already running maxWorkers so block until a response is ready select { case response := <-responseChannel: w.logFinish(response) sendResponse(response.data) case <-w.quit: return } } select { case <-w.quit: return case response := <-responseChannel: w.logFinish(response) sendResponse(response.data) break default: message, err := socket.RecvMessageBytes(0) if err != nil { // Needed to yield to goroutines when GOMAXPROCS is 1. // Note: The 1.3 preemptive scheduler doesn't seem to work here, // so this is still required. runtime.Gosched() break } request, err := w.unmarshal(message[len(message)-1]) if err != nil { log.Println("Received invalid message", err) break } workerFunction := w.registeredWorkerFunctions[request.Method] if workerFunction == nil { log.Println("Unregistered worker function:", request.Method) break } context := messageContext{data: message, startTime: time.Now(), method: request.Method} if atomic.LoadInt32(&w.runningWorkers) == 0 { socket.SetRcvtimeo(w.activeTimeout) } atomic.AddInt32(&w.runningWorkers, 1) go w.runFunction(responseChannel, &context, request.Parameters, workerFunction) } } }
func TestConflate(t *testing.T) { var s_in, s_out *zmq.Socket defer func() { for _, s := range []*zmq.Socket{s_in, s_out} { if s != nil { s.SetLinger(0) s.Close() } } }() bind_to := "tcp://127.0.0.1:5555" err := zmq.SetIoThreads(1) if err != nil { t.Fatal("SetIoThreads(1):", err) } s_in, err = zmq.NewSocket(zmq.PULL) if err != nil { t.Fatal("NewSocket 1:", err) } err = s_in.SetConflate(true) if err != nil { t.Fatal("SetConflate(true):", err) } err = s_in.Bind(bind_to) if err != nil { t.Fatal("s_in.Bind:", err) } s_out, err = zmq.NewSocket(zmq.PUSH) if err != nil { t.Fatal("NewSocket 2:", err) } err = s_out.Connect(bind_to) if err != nil { t.Fatal("s_out.Connect:", err) } message_count := 20 for j := 0; j < message_count; j++ { _, err = s_out.Send(fmt.Sprint(j), 0) if err != nil { t.Fatalf("s_out.Send %d: %v", j, err) } } time.Sleep(time.Second) payload_recved, err := s_in.Recv(0) if err != nil { t.Error("s_in.Recv:", err) } else { i, err := strconv.Atoi(payload_recved) if err != nil { t.Error("strconv.Atoi:", err) } if i != message_count-1 { t.Error("payload_recved != message_count - 1") } } err = s_in.Close() s_in = nil if err != nil { t.Error("s_in.Close:", err) } err = s_out.Close() s_out = nil if err != nil { t.Error("s_out.Close:", err) } }
func TestRouterElement(t *testing.T) { var c *zmq.Context var m *Mirror var sa, sb *zmq.Socket var err error var addra string var addrb string defer func() { if sa != nil { sa.Close() } if sb != nil { sb.Close() } if m != nil { m.Close() } if c != nil { c.Term() } }() if c, err = zmq.NewContext(); err != nil { t.Fatalf("Failed to create ZMQ context: %v", err) } if m, err = NewMirror(t, c, 1); err != nil { t.Fatalf("Failed to create a new mirror: %v", err) } if sa, addra, err = svcrouter.NewHalfPair(c, true); err != nil { t.Fatalf("Failed to create half pair A: %v", err) } if sb, addrb, err = svcrouter.NewHalfPair(c, true); err != nil { t.Fatalf("Failed to create half pair B: %v", err) } if err = m.AddPeer(svcrouter.PeerDefinition{ Name: "ab", ZmqType: zmq.PAIR, Address: addra, Bind: false, PeerImpl: &MirrorPeerImpl{}, }); err != nil { t.Fatalf("Could not add peer A: %v", err) } if err = m.AddPeer(svcrouter.PeerDefinition{ Name: "ba", ZmqType: zmq.PAIR, Address: addrb, Bind: false, PeerImpl: &MirrorPeerImpl{}, }); err != nil { t.Fatalf("Could not add peer B: %v", err) } svcrouter.Barrier() num := 100 var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() for i := 0; i < num; i++ { if _, err := sb.RecvMessage(0); err != nil { t.Fatalf("sb receive error: %v", err) } } }() msg := [][]byte{[]byte("Hello"), []byte("World")} for i := 0; i < num; i++ { if _, err := sa.SendMessage(msg); err != nil { t.Fatalf("sa send error: %v", err) } } wg.Wait() }
func TestDisconnectInproc(t *testing.T) { var pubSocket, subSocket *zmq.Socket defer func() { for _, s := range []*zmq.Socket{pubSocket, subSocket} { if s != nil { s.SetLinger(0) s.Close() } } }() publicationsReceived := 0 isSubscribed := false pubSocket, err := zmq.NewSocket(zmq.XPUB) if err != nil { t.Fatal("NewSocket XPUB:", err) } subSocket, err = zmq.NewSocket(zmq.SUB) if err != nil { t.Fatal("NewSocket SUB:", err) } err = subSocket.SetSubscribe("foo") if err != nil { t.Fatal("subSocket.SetSubscribe:", err) } err = pubSocket.Bind("inproc://someInProcDescriptor") if err != nil { t.Fatal("pubSocket.Bind:", err) } iteration := 0 poller := zmq.NewPoller() poller.Add(subSocket, zmq.POLLIN) // read publications poller.Add(pubSocket, zmq.POLLIN) // read subscriptions for { sockets, err := poller.Poll(100 * time.Millisecond) if err != nil { t.Error("Poll:", err) break // Interrupted } for _, socket := range sockets { if socket.Socket == pubSocket { for { buffer, err := pubSocket.Recv(0) if err != nil { t.Fatal("pubSocket.Recv", err) } exp := "\x01foo" if isSubscribed { exp = "\x00foo" } if buffer != exp { t.Errorf("pubSocket.Recv: expected %q, got %q", exp, buffer) } if buffer[0] == 0 { if isSubscribed != true { t.Errorf("Poller: expected subscribed") } isSubscribed = false } else { if isSubscribed != false { t.Errorf("Poller: expected not subscribed") } isSubscribed = true } more, err := pubSocket.GetRcvmore() if err != nil { t.Fatal("pubSocket.GetRcvmore:", err) } if !more { break // Last message part } } break } } for _, socket := range sockets { if socket.Socket == subSocket { for _, exp := range []string{"foo", "this is foo!", "", ""} { msg, err := subSocket.Recv(0) if err != nil { t.Fatal("subSocket.Recv:", err) } if msg != exp { t.Errorf("subSocket.Recv: expected %q, got %q", exp, msg) } more, err := subSocket.GetRcvmore() if err != nil { t.Fatal("subSocket.GetRcvmore:", err) } if !more { publicationsReceived++ break // Last message part } } break } } if iteration == 1 { err := subSocket.Connect("inproc://someInProcDescriptor") if err != nil { t.Fatal("subSocket.Connect", err) } } if iteration == 4 { err := subSocket.Disconnect("inproc://someInProcDescriptor") if err != nil { t.Fatal("subSocket.Disconnect", err) } } if iteration > 4 && len(sockets) == 0 { break } _, err = pubSocket.Send("foo", zmq.SNDMORE) if err != nil { t.Fatal("pubSocket.Send 1", err) } _, err = pubSocket.Send("this is foo!", 0) if err != nil { t.Fatal("pubSocket.Send 2", err) } iteration++ } if publicationsReceived != 3 { t.Error("publicationsReceived != 3 ") } if isSubscribed { t.Error("isSubscribed") } err = pubSocket.Close() pubSocket = nil if err != nil { t.Error("pubSocket.Close:", err) } err = subSocket.Close() subSocket = nil if err != nil { t.Error("subSocket.Close:", err) } }
func TestPoller(t *testing.T) { var sb, sc *zmq.Socket defer func() { for _, s := range []*zmq.Socket{sb, sc} { if s != nil { s.SetLinger(0) s.Close() } } }() sb, err := zmq.NewSocket(zmq.PAIR) if err != nil { t.Fatal("NewSocket:", err) } err = sb.Bind("tcp://127.0.0.1:9737") if err != nil { t.Fatal("sb.Bind:", err) } sc, err = zmq.NewSocket(zmq.PAIR) if err != nil { t.Fatal("NewSocket:", err) } err = sc.Connect("tcp://127.0.0.1:9737") if err != nil { t.Fatal("sc.Connect:", err) } poller := zmq.NewPoller() idxb := poller.Add(sb, 0) idxc := poller.Add(sc, 0) if idxb != 0 || idxc != 1 { t.Errorf("idxb=%d idxc=%d", idxb, idxc) } if pa, err := poller.PollAll(100 * time.Millisecond); err != nil { t.Error("PollAll 1:", err) } else if len(pa) != 2 { t.Errorf("PollAll 1 len = %d", len(pa)) } else if pa[0].Events != 0 || pa[1].Events != 0 { t.Errorf("PollAll 1 events = %v, %v", pa[0], pa[1]) } poller.Update(idxb, zmq.POLLOUT) poller.UpdateBySocket(sc, zmq.POLLIN) if pa, err := poller.PollAll(100 * time.Millisecond); err != nil { t.Error("PollAll 2:", err) } else if len(pa) != 2 { t.Errorf("PollAll 2 len = %d", len(pa)) } else if pa[0].Events != zmq.POLLOUT || pa[1].Events != 0 { t.Errorf("PollAll 2 events = %v, %v", pa[0], pa[1]) } poller.UpdateBySocket(sb, 0) content := "12345678ABCDEFGH12345678ABCDEFGH" // Send message from client to server if rc, err := sb.Send(content, zmq.DONTWAIT); err != nil { t.Error("sb.Send DONTWAIT:", err) } else if rc != 32 { t.Error("sb.Send DONTWAIT:", err32) } if pa, err := poller.PollAll(100 * time.Millisecond); err != nil { t.Error("PollAll 3:", err) } else if len(pa) != 2 { t.Errorf("PollAll 3 len = %d", len(pa)) } else if pa[0].Events != 0 || pa[1].Events != zmq.POLLIN { t.Errorf("PollAll 3 events = %v, %v", pa[0], pa[1]) } // Receive message if msg, err := sc.Recv(zmq.DONTWAIT); err != nil { t.Error("sb.Recv DONTWAIT:", err) } else if msg != content { t.Error("sb.Recv msg != content") } poller.UpdateBySocket(sb, zmq.POLLOUT) poller.Update(idxc, zmq.POLLIN) if pa, err := poller.PollAll(100 * time.Millisecond); err != nil { t.Error("PollAll 4:", err) } else if len(pa) != 2 { t.Errorf("PollAll 4 len = %d", len(pa)) } else if pa[0].Events != zmq.POLLOUT || pa[1].Events != 0 { t.Errorf("PollAll 4 events = %v, %v", pa[0], pa[1]) } err = sc.Close() sc = nil if err != nil { t.Error("sc.Close:", err) } err = sb.Close() sb = nil if err != nil { t.Error("sb.Close:", err) } }
func TestRemoteEndpoint(t *testing.T) { if _, minor, _ := zmq.Version(); minor < 1 { t.Skip("RemoteEndpoint not avalable in ZeroMQ versions prior to 4.1.0") } addr := "tcp://127.0.0.1:9560" peer := "127.0.0.1" var rep, req *zmq.Socket defer func() { for _, s := range []*zmq.Socket{rep, req} { if s != nil { s.SetLinger(0) s.Close() } } }() rep, err := zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } req, err = zmq.NewSocket(zmq.REQ) if err != nil { t.Fatal("NewSocket:", err) } if err = rep.Bind(addr); err != nil { t.Fatal("rep.Bind:", err) } if err = req.Connect(addr); err != nil { t.Fatal("req.Connect:", err) } tmp := "test" if _, err = req.Send(tmp, 0); err != nil { t.Fatal("req.Send:", err) } // get message with peer address (remote endpoint) msg, props, err := rep.RecvWithMetadata(0, "Peer-Address") if err != nil { t.Fatal("rep.RecvWithMetadata:", err) return } if msg != tmp { t.Errorf("rep.RecvWithMetadata: expected %q, got %q", tmp, msg) } if p := props["Peer-Address"]; p != peer { t.Errorf("rep.RecvWithMetadata: expected Peer-Address == %q, got %q", peer, p) } err = rep.Close() rep = nil if err != nil { t.Fatal("rep.Close:", err) } err = req.Close() req = nil if err != nil { t.Fatal("req.Close:", err) } }
func (re *RouterElement) run(doRouting func(*RouterElement, *Peer, [][]byte) (*Peer, [][]byte, error), controlIn, controlOut *zmq.Socket) { var wg sync.WaitGroup controlChanInternal := make(chan *controlMessage, 1) wg.Add(1) // Start a goroutine to copy from the control channel to the internal // control channel and wake up the control socket pair on each message. // Quit the goroutine when the control channel itself is closed go func() { defer func() { controlIn.SetLinger(0) controlIn.Close() wg.Done() }() msg := [][]byte{[]byte{0}} for { select { case m, ok := <-re.controlChan: if !ok { close(controlChanInternal) // send a message to the control panel to wake it up controlIn.SendMessage(msg) // ensure we get a message back before closing it controlIn.RecvMessageBytes(0) return } controlChanInternal <- m controlIn.SendMessageDontwait(msg) } } }() defer func() { wg.Wait() controlOut.SetLinger(0) controlOut.Close() // Close() should already remove all the peers, so this is just belt & braces for _, p := range re.peers { p.sock.SetLinger(0) p.sock.Close() close(p.buffer) } re.wg.Done() }() for { poller := zmq.NewPoller() pollSource := make([]*Peer, len(re.peers), len(re.peers)) blockInput := false i := 0 for _, p := range re.peers { pollSource[i] = p i++ if p.xmit == nil { select { case p.xmit = <-p.buffer: default: } } buffered := len(p.buffer) if p.xmit != nil { buffered++ } if buffered >= cap(p.buffer) { log.Printf("Blocking input as %s cannot take more data", p.Name) blockInput = true } } for _, p := range pollSource { flags := zmq.State(0) if !blockInput { flags |= zmq.POLLIN } if p.xmit != nil { flags |= zmq.POLLOUT } poller.Add(p.sock, flags) } idxControl := poller.Add(controlOut, zmq.POLLIN) if polled, err := poller.PollAll(-1); err != nil { log.Printf("Cannot poll: %v", err) } else { for i, p := range pollSource { if (polled[i].Events&zmq.POLLOUT != 0) && (p.xmit != nil) { if _, err := p.sock.SendMessageDontwait(p.xmit); err != nil { log.Printf("Peer %s cannot send message: %v", p.Name, err) } p.xmit = nil } } for i, p := range pollSource { if polled[i].Events&zmq.POLLIN != 0 { if recv, err := p.sock.RecvMessageBytes(0); err != nil { log.Printf("Peer %s cannot receive message: %v", p.Name, err) } else { if dest, fwd, err := doRouting(re, p, recv); err != nil { log.Printf("Peer %s cannot route message: %v", p.Name, err) } else { if dest != nil && fwd != nil { dest.buffer <- fwd } } } } } if polled[idxControl].Events&zmq.POLLIN != 0 { // read from the control socket and discard. We don't care // if this errors as it's really only to make us read from our // own control socket controlOut.RecvMessageBytes(0) select { case msg, ok := <-controlChanInternal: if !ok { // control channel is closed // send a dummy message to handshake msg := [][]byte{[]byte{0}} controlOut.SendMessage(msg) return } msg.reply <- re.processControlMessage(msg) default: } } } } }