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 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 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 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") }
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: } } } } }