func main() { // routing requests between server 1 and server 2 server1 := gomsg.NewServer() server1.SetTimeout(time.Second) server1.Listen(":7777") server2 := gomsg.NewServer() server2.SetTimeout(time.Second) server2.Listen(":7778") // all (*) messages arriving to server 1 are routed to server 2 gomsg.Route("*", server1, server2, time.Second, func(ctx *gomsg.Request) bool { fmt.Println("===>routing incoming msg:", string(ctx.Request())) return true }, nil) // client 1 connects to server 1 cli := gomsg.NewClient() cli.Connect("localhost:7777") cli2 := gomsg.NewClient() cli2.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) { if m != MESSAGE { fmt.Printf("###> EXPECTED '%s'. RECEIVED '%s'.\n", MESSAGE, m) } fmt.Println("<=== processing:", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("Hello %s", m), nil }) // client 2 connects to server 2 cli2.Connect("localhost:7778") var err error /* err = <-cli.Push("XPTO", "PUSH: One") if err != nil { fmt.Println("W: error:", err) } */ err = <-cli.Request("HELLO", MESSAGE, func(ctx gomsg.Response, r string, e error) { if r != REPLY { fmt.Printf("###> EXPECTED '%s'. RECEIVED '%s'.\n", REPLY, r) } fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) if err != nil { fmt.Println("===> error:", err) } time.Sleep(time.Second * 3) cli.Destroy() time.Sleep(time.Millisecond * 100) }
func main() { server := gomsg.NewServer() server.Listen(":7777") cli := gomsg.NewClient() cli.Connect("localhost:7777") // this late server handler must propagate to the client server.Handle("XPTO", func(m string) { fmt.Println("<=== handling pull:", m) }) time.Sleep(time.Millisecond * 100) e := <-cli.Publish("XPTO", "teste") if e != nil { fmt.Println("===> XPTO error:", e) } // this late client handler must propagate to the server cli.Handle("SUB", func(m string) { fmt.Println("<=== handling pub-sub:", m) }) time.Sleep(time.Millisecond * 100) e = <-server.Publish("SUB", "teste") if e != nil { fmt.Println("===> SUB error:", e) } time.Sleep(time.Millisecond * 100) }
func main() { cli := gomsg.NewClient().Connect("localhost:7777") time.Sleep(time.Millisecond * 100) // THE SERVER SHOWS UP AFTER THE CLIENT server := gomsg.NewServer() server.Handle("XPTO", func(m string) { fmt.Println("<=== handling pull:", m) }) server.Listen(":7777") time.Sleep(time.Second) e := <-cli.Publish("XPTO", "teste") if e != nil { fmt.Println("===> error:", e) } /* cli.Handle("SUB", func(m string) { fmt.Println("<=== handling pub-sub:", m) }) time.Sleep(time.Millisecond * 100) <-server.Publish("SUB", "teste") */ time.Sleep(time.Second) }
func main() { server := gomsg.NewServer() server.SetTimeout(time.Second) server.Listen(":7777") cli := gomsg.NewClient() cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing (1):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[1]=%s", reverse(m)), nil }) cli.Connect("localhost:7777") cli2 := gomsg.NewClient() cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing (2):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[2]=%s", reverse(m)), nil }) cli2.Connect("localhost:7777") time.Sleep(time.Millisecond * 100) // Warning: when requesting many in a server, the last response (end mark) will have a null connection server.RequestAll("REVERSE", "hello", func(ctx gomsg.Response, r string) { fmt.Println("===> reply:", r, ", last?", ctx.Last()) }, time.Second) time.Sleep(time.Second * 2) fmt.Println("I: close...") cli.Destroy() time.Sleep(time.Second * 5) }
// This is our main task. First we bind/connect our sockets with our // peer and make sure we will get state messages correctly. We use // three sockets; one to publish state, one to subscribe to state, and // one for client requests/replies: func NewBStar(primary bool, frontentAddr string, stateLocalAddr string, stateRemoteAddr string) *BStar { this := &BStar{} if primary { fmt.Println("I: Primary active, waiting for backup (passive)") this.state = STATE_PRIMARY } else { fmt.Println("I: Backup passive, waiting for primary (active)") this.state = STATE_BACKUP } this.quit = make(chan bool, 1) this.statepub = gomsg.NewClient().SetCodec(codec) this.statesub = gomsg.NewServer() this.statesub.SetCodec(codec) this.statesub.Handle("STATE", func(ctx *gomsg.Request) { state, _ := ctx.Reader().ReadUI8() // Have state from our peer, execute as event if this.stateMachine(Event(state)) { this.quit <- true // Error, so exit } else { this.updatePeerExpiry() } }) this.frontend = gomsg.NewServer() this.frontend.SetCodec(codec) this.frontend.Handle("*", func(ctx *gomsg.Request) { // Have a client request ok := !this.stateMachine(CLIENT_REQUEST) if ok { this.frontendHandler(this, ctx) } else { // rejects request ctx.Terminate() } }) this.stateRemoteAddr = stateRemoteAddr this.stateLocalAddr = stateLocalAddr this.frontentAddr = frontentAddr return this }
func main() { server := gomsg.NewServer() server.Listen(":7777") ungrouped := 0 cli := gomsg.NewClient() cli.Handle("HELLO", func(m string) { fmt.Println("<=== [0] processing:", m) ungrouped++ }) <-cli.Connect("localhost:7777") group1 := 0 // Group HA subscriber cli1 := gomsg.NewClient() cli1.SetGroupId("HA") cli1.Handle("HELLO", func(m string) { fmt.Println("<=== [1] processing:", m) group1++ }) <-cli1.Connect("localhost:7777") // Group HA subscriber group2 := 0 cli2 := gomsg.NewClient() cli2.SetGroupId("HA") cli2.Handle("HELLO", func(m string) { fmt.Println("<=== [2] processing:", m) group2++ }) <-cli2.Connect("localhost:7777") // Only one element of the group HA will process each message, alternately (round robin). server.Publish("HELLO", "one") wait() server.Publish("HELLO", "two") wait() server.Publish("HELLO", "three") wait() server.Publish("HELLO", "four") wait() if ungrouped != 4 { fmt.Println("ERROR: RECEIVED", ungrouped, "UNGROUPED EVENTS. EXPECTED 4.") } if group1 != 2 { fmt.Println("ERROR: RECEIVED", group1, "GROUP EVENTS. EXPECTED 2.") } if group2 != 2 { fmt.Println("ERROR: RECEIVED", group2, "GROUP EVENTS. EXPECTED 2.") } wait() server.Destroy() wait() }
func main() { server := gomsg.NewServer() server.Listen(SERVER_PORT_1) defer server.Destroy() // client #1 var received1 = 0 cli1 := gomsg.NewClient() cli1.Handle(CONSUMER, func(m string) { fmt.Println("<<< client #1: received", m) if m == MESSAGE { received1++ } }) cli1.Connect(SERVER_1) defer cli1.Destroy() // client #2 var received2 = 0 cli2 := gomsg.NewClient() cli2.Handle(CONSUMER, func(m string) { fmt.Println("<<< client #2: received", m) if m == MESSAGE { received2++ } }) cli2.Connect(SERVER_1) defer cli2.Destroy() // give time to connect wait() // only one client will receive the message e := <-server.Push(CONSUMER, MESSAGE) if e != nil { fmt.Printf("Error: %s\n", e) } // a different client from before (round-robin) // will receive the message e = <-server.Push(CONSUMER, MESSAGE) if e != nil { fmt.Printf("Error: %s\n", e) } if received1 != 1 { fmt.Printf("Expected '%v', got '%v'\n", 1, received1) } if received2 != 1 { fmt.Printf("Expected '%v', got '%v'\n", 1, received2) } }
// NewDirectory creates a peer directory where all the clients connect to know about their peers func NewDirectory(addr string, codec gomsg.Codec) *Directory { dir := &Directory{ peers: make(map[net.Conn]string), } dir.server = gomsg.NewServer() dir.server.SetCodec(codec) dir.server.OnClose = func(c net.Conn) { // this will be called if a peer stops pinging fmt.Println("< Dir: peer", c.RemoteAddr(), "exited") dir.mu.Lock() defer dir.mu.Unlock() delete(dir.peers, c) dir.server.Publish("DROP", dir.peers[c]) } // returns all the peer addresses dir.server.Handle("DIR", func(ctx *gomsg.Request) []string { fmt.Println("< Dir: DIRECTORY LIST") dir.mu.RLock() defer dir.mu.RUnlock() addrs := make([]string, len(dir.peers)) i := 0 for _, v := range dir.peers { addrs[i] = v i++ } return addrs }) dir.server.Handle("READY", func(ctx *gomsg.Request, port int) { c := ctx.Connection() addr := fmt.Sprint(c.RemoteAddr().(*net.TCPAddr).IP, ":", port) fmt.Println("< Dir: peer", addr, "PEER READY") dir.mu.Lock() defer dir.mu.Unlock() dir.peers[c] = addr dir.server.Publish("NEW", addr) }) dir.server.Listen(addr) return dir }
func main() { server := gomsg.NewServer() server.SetTimeout(time.Second) server.Listen(":7777") cli := gomsg.NewClient() cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing (1):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[1]=%s", reverse(m)), nil }) cli.Connect("localhost:7777") /* cli2 := gomsg.NewClient() cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing (2):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[2]=%s", reverse(m)), nil }) cli2.Connect("localhost:7777") // just to get in the way cli3 := gomsg.NewClient() cli3.Connect("localhost:7777") */ // =============== //time.Sleep(time.Millisecond * 100) fmt.Println("====> requesting...") <-server.Request("REVERSE", "hello", func(ctx gomsg.Response, r string) { fmt.Println("===> reply:", r) }) /* server.RequestAll("REVERSE", "hello", func(ctx gomsg.Response, r string) { fmt.Println("===> reply:", ctx.Kind, r) }, time.Second) */ time.Sleep(time.Second * 2) fmt.Println("I: close...") cli.Destroy() time.Sleep(time.Second * 5) }
// NewNode creates a new Node func NewNode() *Node { node := &Node{ Wires: gomsg.NewWires(gomsg.JsonCodec{}), dirs: gomsg.NewWires(gomsg.JsonCodec{}), remoteDirs: make([]*gomsg.Client, 0), peers: make(map[string]*gomsg.Client), PingInterval: time.Second, PingFailures: 2, provides: make(map[string]bool), providers: make(map[string]*Provider), } node.local = gomsg.NewServer() // consecutive calls under 500 ms to "DIR/*" // will be consumed by the same directory node node.dirs.Stick("DIR/*", time.Millisecond*500) node.AddSendListener(0, func(event gomsg.SendEvent) { node.lazyConnect(event.Name) }) return node }
func NewPeer(dirAddr string, bindAddr string, codec gomsg.Codec) *Peer { this := &Peer{ codec: codec, peers: NewPeers(), } this.local = gomsg.NewServer() this.local.SetTimeout(time.Second) this.local.SetCodec(codec) this.local.Listen(bindAddr) this.dir = gomsg.NewClient().SetCodec(codec) this.dir.SetTimeout(time.Second) this.dir.OnConnect = func(w *gomsg.Wired) { this.dir.Handle("NEW", func(peerAddr string) { if peerAddr != this.self { fmt.Println("====>", bindAddr, ": new peer at", peerAddr) cli := gomsg.NewClient().SetCodec(codec) cli.Connect(peerAddr) this.peers.Put(peerAddr, cli) } }) this.dir.Handle("DROP", func(peerAddr string) { this.peers.Remove(peerAddr) }) port := this.local.Port() <-this.dir.Request("DIR", nil, func(ctx gomsg.Response, addrs []string) { this.self = fmt.Sprint(ctx.Connection().LocalAddr().(*net.TCPAddr).IP, ":", port) for _, v := range addrs { cli := gomsg.NewClient().SetCodec(this.codec) cli.Connect(v) this.peers.Put(v, cli) } }) this.dir.Push("READY", port) } this.dir.Connect(dirAddr) return this }
func main() { server := gomsg.NewServer() server.SetTimeout(time.Second) server.Listen(":7777") cli := gomsg.NewClient() cli2 := gomsg.NewClient() fmt.Println("=========== STICKY PUSH =============") cli.Handle("PUSHING", func(ctx *gomsg.Request, m string) { fmt.Println("<=== processing PUSHING (1):", m, "from", ctx.Connection().RemoteAddr()) }) cli.Handle("NOISE", func(ctx *gomsg.Request, m string) { fmt.Println("<=== processing NOISE (21):", m, "from", ctx.Connection().RemoteAddr()) }) cli2.Handle("PUSHING", func(ctx *gomsg.Request, m string) { fmt.Println("<=== processing PUSHING (2):", m, "from", ctx.Connection().RemoteAddr()) }) cli2.Handle("NOISE", func(ctx *gomsg.Request, m string) { fmt.Println("<=== processing NOISE (22):", m, "from", ctx.Connection().RemoteAddr()) }) cli.Connect("localhost:7777") cli2.Connect("localhost:7777") wait() // note the FILTER_TOKEN at the end. This way we can define a range of Stickyness server.Stick("PUSH"+gomsg.FILTER_TOKEN, time.Millisecond*500) server.Push("PUSHING", "ping") wait() server.Push("PUSHING", "ping") wait() server.Push("NOISE", "---noise--- will provoque the rotation of the general cursor") wait() server.Push("PUSHING", "ping") wait() server.Push("NOISE", "---noise--- will provoque the rotation of the general cursor") wait() server.Push("PUSHING", "ping") time.Sleep(time.Second) server.Push("PUSHING", "change wire") wait() fmt.Println("=========== STICKY REQUEST =============") cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing REVERSE (1):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[1]=%s", reverse(m)), nil }) cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing REVERSE (2):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[2]=%s", reverse(m)), nil }) wait() server.Stick("REVERSE", time.Millisecond*500) // Warning: when requesting many in a server, the last response (end mark) will have a null connection var resultFn = func(ctx gomsg.Response, r string) { fmt.Println("===> reply:", r, ", last?", ctx.Last()) } server.Request("REVERSE", "hello", resultFn) wait() server.Request("REVERSE", "world", resultFn) wait() server.Request("REVERSE", "ola", resultFn) wait() server.Request("REVERSE", "mundo", resultFn) time.Sleep(time.Second) server.Request("REVERSE", "change wire", resultFn) wait() time.Sleep(time.Second * 2) fmt.Println("I: close...") cli.Destroy() time.Sleep(time.Second * 5) }
func main() { server := gomsg.NewServer() server.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing:", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("Hello %s", m), nil }) server.Handle("XPTO", func(m string) { fmt.Println("<=== handling pull:", m) }) server.Listen(":7777") cli := gomsg.NewClient() cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing (1):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[1]=%s", reverse(m)), nil }) cli.Handle("SUB", func(m string) { fmt.Println("<=== handling pub-sub:", m) }) cli.Connect("localhost:7777") cli2 := gomsg.NewClient() cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== processing (2):", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[2]=%s", reverse(m)), nil }) cli2.Handle("SUB", func(m string) { fmt.Println("<=== handling pub-sub:", m) }) cli2.Connect("localhost:7777") //var err error /* messages := []string{"Hello", "World", "Paulo"} for _, m := range messages { err = <-cli.Request("HELLO", m, func(ctx gomsg.IResponse, r string) { fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr()) }) if err != nil { fmt.Println("===> error:", err) } } */ time.Sleep(time.Millisecond * 100) // Warning: when requesting many in a server, the last response (end mark) will have a null connection server.RequestAll("REVERSE", "hello", func(ctx gomsg.Response, r string) { fmt.Println("===> reply:", r) }, time.Second) /* server.Request("REVERSE", "hello", func(ctx gomsg.IResponse, r string) { fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr()) }) server.Request("REVERSE", "hello", func(ctx gomsg.IResponse, r string) { fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr()) }) server.Request("REVERSE", "hello", func(ctx gomsg.IResponse, r string) { fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr()) }) */ //server.Publish("SUB", "PUB: La") /* err = <-cli.Publish("XPTO", "PUB: La") err = <-cli.Publish("XPTO", "PUB: Vida") err = <-cli.Publish("XPTO", "PUB: Loca") */ //cli.Push("XPTO", "One") /* err = <-cli.Push("XPTO", "PUSH: Two") err = <-cli.Push("XPTO", "PUSH: Three") err = <-cli.Push("XPTO", "PUSH: Four") time.Sleep(time.Millisecond * 100) err = <-cli.Push("FAIL", 123) fmt.Println("I: error:", err) if err == nil { fmt.Println("E: Should have returned an error") } */ time.Sleep(time.Millisecond * 100) fmt.Println("I: close...") cli.Destroy() time.Sleep(time.Millisecond * 100) }
func main() { server := gomsg.NewServer() // keep alive var timeout = gomsg.NewTimeout(CLEAN_CYCLE, time.Second, func(o interface{}) { c := o.(net.Conn) fmt.Println("=====> killing connection from", c.RemoteAddr()) server.Wires.Kill(c) }) server.OnConnect = func(w *gomsg.Wired) { // starts monitoring timeout.Delay(w.Conn()) } // for PING messages the server will reply immediatly, // without relaying the message to the clients. server.Route("*", time.Second, func(ctx *gomsg.Request) bool { // any message received, delays the timeout timeout.Delay(ctx.Connection()) if ctx.Name == "PING" { ctx.SetReply([]byte("PONG")) return false } return true }, nil) server.Listen(":7777") cli := gomsg.NewClient() cli.SetReconnectInterval(0) cli.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== [1] processing:", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[1] Hello %s", m), nil }) cli.Connect("localhost:7777") // just to get in the way cli3 := gomsg.NewClient() cli3.SetReconnectInterval(0) cli3.Connect("localhost:7777") cli2 := gomsg.NewClient() cli2.SetReconnectInterval(0) cli2.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== [2] processing:", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[2] Hello %s", m), nil }) cli2.Connect("localhost:7777") <-cli3.RequestAll("HELLO", "World!", func(ctx gomsg.Response, r string, e error) { fmt.Println("===HELLO===> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) time.Sleep(time.Millisecond * 2000) <-cli3.RequestAll("HELLO", "World!", func(ctx gomsg.Response, r string, e error) { fmt.Println("===HELLO===> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) time.Sleep(time.Millisecond * 1000) }
func main() { // all messages arriving to the server are routed to the clients server := gomsg.NewServer() server.Listen(":7777") server.Route("*", time.Second, nil, nil) cli := gomsg.NewClient() cli.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== [1] processing:", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[1] Hello %s", m), nil }) // sends multi reply cli.Handle("PIPE", func(ctx *gomsg.Request) { ctx.SendReply([]byte("\"Pipe #1\"")) ctx.SendReply([]byte("\"Pipe #2\"")) ctx.Terminate() }) cli.Connect("localhost:7777") // just to get in the way cli3 := gomsg.NewClient() cli3.Connect("localhost:7777") cli2 := gomsg.NewClient() cli2.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) { fmt.Println("<=== [2] processing:", m, "from", ctx.Connection().RemoteAddr()) return fmt.Sprintf("[2] Hello %s", m), nil }) cli2.Handle("PIPE", func(ctx *gomsg.Request) string { return "Pipe #201" }) cli2.Connect("localhost:7777") <-cli3.RequestAll("HELLO", "World!", func(ctx gomsg.Response, r string, e error) { fmt.Println("===HELLO===> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) fmt.Println("===============") <-cli3.RequestAll("PIPE", nil, func(ctx gomsg.Response, s string) { fmt.Println("===PIPE===> reply:", ctx.Kind, string(ctx.Reply()), s) }) fmt.Println("===============") <-cli3.Request("PIPE", nil, func(ctx gomsg.Response, s string) { fmt.Println("===PIPE===> reply:", ctx.Kind, string(ctx.Reply()), s) }) /* cli.Request("HELLO", "World!", func(ctx gomsg.IResponse, r string, e error) { fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) // check to see if the server is working server.Request("HELLO", "World!", func(ctx gomsg.IResponse, r string, e error) { fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) server.Request("HELLO", "World!", func(ctx gomsg.IResponse, r string, e error) { fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr()) }) */ time.Sleep(time.Millisecond * 100) cli.Destroy() time.Sleep(time.Millisecond * 100) }
func main() { // all messages arriving to the server are routed to the clients server := gomsg.NewServer() server.Listen(":7777") server.Route("*", time.Second, nil, nil) ungrouped := 0 cli := gomsg.NewClient() cli.Handle("HELLO", func(m string) { fmt.Println("<=== [0] processing:", m) ungrouped++ }) <-cli.Connect("localhost:7777") group1 := 0 // Group HA subscriber cli1 := gomsg.NewClient() cli1.SetGroupId("HA") cli1.Handle("HELLO", func(m string) { fmt.Println("<=== [1] processing:", m) group1++ }) <-cli1.Connect("localhost:7777") // Group HA subscriber group2 := 0 cli2 := gomsg.NewClient() cli2.SetGroupId("HA") cli2.Handle("HELLO", func(m string) { fmt.Println("<=== [2] processing:", m) group2++ }) <-cli2.Connect("localhost:7777") // publisher cli3 := gomsg.NewClient() <-cli3.Connect("localhost:7777") // Only one element of the group HA will process each message, alternately (round robin). // cli3.Publish("HELLO", "Hello World!") // cli3.Publish("HELLO", "Olá Mundo!") // cli3.Publish("HELLO", "YESSSS!") cli3.Publish("HELLO", "one") wait() cli3.Publish("HELLO", "two") wait() cli3.Publish("HELLO", "three") wait() cli3.Publish("HELLO", "four") wait() if ungrouped != 4 { fmt.Println("ERROR: RECEIVED", ungrouped, "UNGROUPED EVENTS. EXPECTED 4.") } if group1 != 2 { fmt.Println("ERROR: RECEIVED", group1, "GROUP EVENTS. EXPECTED 2.") } if group2 != 2 { fmt.Println("ERROR: RECEIVED", group2, "GROUP EVENTS. EXPECTED 2.") } wait() cli.Destroy() wait() }
// NewServiceDirectory creates a peer ServiceDirectory where all the clients connect // to know about service providers func NewServiceDirectory(codec gomsg.Codec) *ServiceDirectory { dir := &ServiceDirectory{ providers: make(map[net.Conn]*Provider), PingInterval: time.Second, PingFailures: 2, } dir.server = gomsg.NewServer() dir.server.SetCodec(codec) dir.server.SetTimeout(time.Second * 5) dir.server.OnClose = func(c net.Conn) { dir.mu.Lock() defer dir.mu.Unlock() var provider = dir.providers[c] if provider != nil { fmt.Println("I: < Dir: peer", provider.Endpoint, "exited") delete(dir.providers, c) dir.server.Publish(C_DROPPEER, provider.Endpoint) } else { fmt.Println("I: < Dir: closing connection", c.RemoteAddr(), "for inexistente provider") } } // returns a list of endpoints (addresses) by service dir.server.Handle(S_ADDSERVICE, func(r *gomsg.Request, service string) error { var c = r.Connection() dir.mu.Lock() var provider = dir.providers[c] if provider != nil { fmt.Println("I: < Dir: S_ADDSERVICE service", provider.Endpoint, "->", service) provider.AddService(service) } dir.mu.Unlock() if provider != nil { var w = dir.server.Get(c) // notifies all nodes, but caller dir.server.SendSkip(w.Wire(), gomsg.REQALL, C_ADDSERVICE, Service{provider.Endpoint, service}, nil, time.Second) } return nil }) dir.server.Handle(S_CANCELSERVICE, func(r *gomsg.Request, service string) error { var c = r.Connection() dir.mu.Lock() var provider = dir.providers[c] if provider != nil { fmt.Println("I: < Dir: S_CANCELSERVICE service", provider.Endpoint, "->", service) provider.RemoveService(service) } dir.mu.Unlock() if provider != nil { var w = dir.server.Get(c) // notifies all nodes, but caller dir.server.SendSkip(w.Wire(), gomsg.REQALL, C_CANCELSERVICE, Service{provider.Endpoint, service}, nil, time.Second) } return nil }) dir.server.Handle(S_PEERREADY, func(r *gomsg.Request, provider Provider) []*Provider { var c = r.Connection() fmt.Println("< Dir: peer", c.RemoteAddr(), " S_PEERREADY:", provider) // will be using the IP from where the connection came provider.Endpoint = fmt.Sprintf("%s:%s", c.RemoteAddr().(*net.TCPAddr).IP, provider.Endpoint) dir.mu.Lock() defer dir.mu.Unlock() // Creates a shallow copy of all existing providers var copy = make([]*Provider, len(dir.providers)) var i = 0 for _, v := range dir.providers { copy[i] = v i++ } // update directory dir.providers[c] = &provider // notifies all peers, but the caller var w = dir.server.Get(c) dir.server.SendSkip(w.Wire(), gomsg.REQALL, C_PEERREADY, provider, nil, time.Second) return copy }) return dir }