コード例 #1
0
ファイル: game6.go プロジェクト: G-VAR/router
func main() {
	flag.Parse()
	if flag.NArg() < 1 {
		fmt.Println("Usage: game6 num_runs hideTrace")
		return
	} else if flag.NArg() > 1 {
		showPingPong = false
	}
	numRuns, _ := strconv.Atoi(flag.Arg(0))

	c0, c1 := net.Pipe()

	done := make(chan bool)

	//create router and connect it to io conn
	rot1 := router.New(router.StrID(), 32, router.BroadcastPolicy)
	go rot1.ConnectRemote(c0, router.GobMarshaling, router.XOnOffFlowController)

	//hook up Pinger and Ponger
	newPinger(rot1, done, numRuns)

	//create router and connect it to io conn
	rot2 := router.New(router.StrID(), 32, router.BroadcastPolicy)
	rot2.ConnectRemote(c1, router.GobMarshaling, router.XOnOffFlowController)

	//hook up Ponger
	newPonger(rot2, done)

	//wait for ping-pong to finish
	<-done
	<-done
}
コード例 #2
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_async_router() {
	//create a async router by setting buffer size to UnlimitedBuffer(-1) in router.New()
	rout1 := router.New(router.IntID(), router.UnlimitedBuffer, router.BroadcastPolicy /* , "router1", router.ScopeLocal*/)
	rout2 := router.New(router.IntID(), router.UnlimitedBuffer, router.BroadcastPolicy /* , "router2", router.ScopeLocal*/)
	rout1.Connect(rout2)
	chi1 := make(chan string)
	chi2 := make(chan string)
	chi3 := make(chan string)
	cho := make(chan string)
	bound := make(chan *router.BindEvent, 1)
	//when attaching sending chan, add a (chan BindEvent) for notifying recver connecting
	rout1.AttachSendChan(router.IntID(10), cho, bound)
	rout1.AttachRecvChan(router.IntID(10), chi1)
	rout2.AttachRecvChan(router.IntID(10), chi2)
	rout2.AttachRecvChan(router.IntID(10), chi3)
	//wait for some recvers connecting
	for {
		if (<-bound).Count == 2 {
			break
		}
	}
	//because we use async router, sending on those router attached channels
	//will never block. we do not need spawn goroutines in the following
	//go func() {
	cho <- "hello1"
	cho <- "hello2"
	cho <- "hello3"
	cho <- "from router1/src"
	close(cho)
	//}()
	//go func() {
	for v := range chi1 {
		fmt.Println("router1/sink1 got: ", v)
	}
	//}()
	//go func() {
	for v := range chi2 {
		fmt.Println("router2/sink2 got: ", v)
	}
	//}()
	//go func() {
	i := 0
	for v := range chi3 {
		fmt.Println("router2/sink3 got: ", v)
		i++
		if i == 2 {
			rout2.DetachChan(router.IntID(10), chi3)
		}
	}
	//}()
	rout1.Close()
	rout2.Close()
}
コード例 #3
0
ファイル: game4.go プロジェクト: G-VAR/router
func main() {
	flag.Parse()
	if flag.NArg() < 1 {
		fmt.Println("Usage: game4 num_runs hideTrace")
		return
	} else if flag.NArg() > 1 {
		showPingPong = false
	}
	//clean up test sock
	addr := "/tmp/pingpong.test"
	os.Remove(addr)
	//
	numRuns, _ := strconv.Atoi(flag.Arg(0))
	done := make(chan bool)
	connNow := make(chan bool)
	//start two goroutines to setup a unix sock connection
	//connect two routers thru unix sock
	//and then hook up Pinger and Ponger to the routers
	go func() { //setup Pinger sock conn
		//wait for ponger up
		<-connNow
		//set up an io conn to ponger thru unix sock
		addr := "/tmp/pingpong.test"
		conn, _ := net.Dial("unix", addr)
		fmt.Println("ping conn up")

		//create router and connect it to io conn
		rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "pinger", router.ScopeLocal*/)
		rot.ConnectRemote(conn, router.JsonMarshaling)

		//hook up Pinger and Ponger
		newPinger(rot, done, numRuns)
	}()
	go func() { //setup Ponger sock conn
		//wait to set up an io conn thru unix sock
		l, _ := net.Listen("unix", addr)
		connNow <- true //notify pinger that ponger's ready to accept
		conn, _ := l.Accept()
		fmt.Println("pong conn up")

		//create router and connect it to io conn
		rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "ponger", router.ScopeLocal*/)
		rot.ConnectRemote(conn, router.JsonMarshaling)

		//hook up Ponger
		newPonger(rot, done)
	}()
	//wait for ping-pong to finish
	<-done
	<-done
}
コード例 #4
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_StrId() {
	rout := router.New(router.StrID(), 32, router.BroadcastPolicy)
	chi1 := make(chan string)
	chi2 := make(chan string)
	cho := make(chan string)
	done := make(chan bool)
	rout.AttachSendChan(router.StrID("test"), cho)
	rout.AttachRecvChan(router.StrID("test"), chi1)
	rout.AttachRecvChan(router.StrID("test"), chi2)
	go func() {
		cho <- "hello"
		cho <- "from StrID"
		close(cho)
	}()
	go func() {
		for v := range chi1 {
			fmt.Println("StrId/sink1 got: ", v)
		}
		done <- true
	}()
	go func() {
		for v := range chi2 {
			fmt.Println("StrId/sink2 got: ", v)
		}
		done <- true
	}()
	<-done
	<-done
}
コード例 #5
0
ファイル: game5.go プロジェクト: G-VAR/router
func main() {
	flag.Parse()
	if flag.NArg() < 1 {
		fmt.Println("Usage: game5 num_runs hideTrace")
		return
	} else if flag.NArg() > 1 {
		showPingPong = false
	}
	numRuns, _ := strconv.Atoi(flag.Arg(0))
	done := make(chan bool)
	connNow := make(chan bool)
	//start two goroutines to setup a unix sock connection
	//connect two routers thru unix sock
	//and then hook up Pinger and Ponger to the routers
	go func() { //setup Pinger sock conn
		//wait for ponger up
		<-connNow
		//set up an io conn to ponger thru tcp sock
		conn, _ := net.Dial("tcp", "[::]:9099")
		fmt.Println("ping conn up")

		//create router and connect it to io conn
		rot := router.New(router.StrID(), 32, router.BroadcastPolicy)
		rot.ConnectRemote(conn, router.GobMarshaling, router.XOnOffFlowController)

		//hook up Pinger and Ponger
		newPinger(rot, done, numRuns)
	}()
	go func() { //setup Ponger sock conn
		//wait to set up an io conn thru tcp sock
		l, _ := net.Listen("tcp", ":9099")
		connNow <- true //notify pinger that ponger's ready to accept
		conn, _ := l.Accept()
		fmt.Println("pong conn up")

		//create router and connect it to io conn
		rot := router.New(router.StrID(), 32, router.BroadcastPolicy)
		rot.ConnectRemote(conn, router.GobMarshaling, router.XOnOffFlowController)

		//hook up Ponger
		newPonger(rot, done)
	}()
	//wait for ping-pong to finish
	<-done
	<-done
}
コード例 #6
0
ファイル: chatcli.go プロジェクト: G-VAR/router
func main() {
	flag.Parse()
	if flag.NArg() < 3 {
		fmt.Println("Usage: chatcli chatter_name srv_name srv_port")
		return
	}
	myName := flag.Arg(0)
	srvName := flag.Arg(1)
	srvPort := flag.Arg(2)

	dialaddr := srvName + ":" + srvPort
	conn, err := net.Dial("tcp", dialaddr)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("client connect")

	rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "client", router.ScopeLocal*/)
	_, err = rot.ConnectRemote(conn, router.JsonMarshaling)
	if err != nil {
		fmt.Println(err)
		return
	}

	chatter := newChatter(myName, rot)

	cont := true
	input := bufio.NewReader(os.Stdin)
	for cont {
		fmt.Println("action: 1 - Join, 2 - Leave, 3 - Send, 4 - Exit")
		action, _ := input.ReadString('\n')
		switch action[0] {
		case '1', '2', '3':
			fmt.Println("subject:")
			subj, _ := input.ReadString('\n')
			switch action[0] {
			case '1':
				chatter.Join(subj[0 : len(subj)-1])
			case '2':
				chatter.Leave(subj[0 : len(subj)-1])
			case '3':
				fmt.Println("message:")
				msg, _ := input.ReadString('\n')
				chatter.Send(subj[0:len(subj)-1], msg[0:len(msg)-1])
			default:
				fmt.Println("invalid action")
			}
		case '4':
			cont = false
		default:
			fmt.Println("invalid action")
		}
	}

	fmt.Println("client exit")
	conn.Close()
	rot.Close()
}
コード例 #7
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_notification() {
	rout := router.New(router.StrID(), 32, router.BroadcastPolicy)
	chi1 := make(chan string)
	chi2 := make(chan string)
	chiN := make(chan *router.ChanInfoMsg)
	cho := make(chan string)
	bound := make(chan *router.BindEvent, 1)
	done := make(chan bool)
	//subscribe to recver attach events
	rout.AttachRecvChan(rout.SysID(router.SubId), chiN)
	//
	rout.AttachSendChan(router.StrID("test"), cho, bound)
	rout.AttachRecvChan(router.StrID("test"), chi1)
	rout.AttachRecvChan(router.StrID("test"), chi2)
	//wait for two recvers to connect
	for {
		if (<-bound).Count == 2 {
			break
		}
	}
	go func() {
		cho <- "hello1"
		cho <- "hello2"
		cho <- "hello3"
		cho <- "from notif"
		close(cho)
	}()
	go func() {
		for v := range chi1 {
			fmt.Println("notif/sink1 got: ", v)
		}
		done <- true
	}()
	go func() {
		for v := range chi2 {
			fmt.Println("notif/sink2 got: ", v)
			rout.DetachChan(router.StrID("test"), chi2)
		}
		done <- true
	}()
	go func() {
		count := 0
		for m := range chiN {
			for _, v := range m.Info {
				fmt.Println("got sub notif: ", v.Id)
			}
			count++
			if count >= 2 {
				break
			}
		}
		done <- true
	}()
	<-done
	<-done
	<-done
	rout.Close()
}
コード例 #8
0
ファイル: client.go プロジェクト: G-VAR/router
func main() {
	flag.Parse()
	if flag.NArg() < 2 {
		fmt.Println("Usage: client ServiceName numRuns")
		return
	}
	svcName := flag.Arg(0)
	numRuns, _ := strconv.Atoi(flag.Arg(1))

	conn1, _ := net.Dial("unix", ServantAddr1)
	fmt.Println("conn to servant1 up")
	conn2, _ := net.Dial("unix", ServantAddr2)
	fmt.Println("conn to servant2 up")

	//create router and connect it to both active and standby servants
	rot := router.New(router.StrID(), 32, router.BroadcastPolicy /* , "cli", router.ScopeLocal*/)
	proxy1 := router.NewProxy(rot, "proxy1", nil, nil)
	proxy2 := router.NewProxy(rot, "proxy2", nil, nil)
	proxy1.ConnectRemote(conn1, router.GobMarshaling, router.XOnOffFlowController)
	proxy2.ConnectRemote(conn2, router.GobMarshaling, router.XOnOffFlowController)

	reqChan := make(chan string)
	rspChan := make(chan string)
	bindChan := make(chan *router.BindEvent, 1)
	rot.AttachSendChan(router.StrID("/App/"+svcName+"/Request"), reqChan, bindChan)
	rot.AttachRecvChan(router.StrID("/App/"+svcName+"/Response"), rspChan)
	//make sure client connect to 2 servants before sending requests
	for {
		if (<-bindChan).Count > 1 {
			break
		}
	}
	cont := true
	for i := 0; i < numRuns && cont; i++ {
		req := fmt.Sprintf("request %d", i)
		fmt.Printf("client sent request [%s] to serivce [%s]\n", req, svcName)
		reqChan <- req
		timer := time.NewTimer(6e8) //the wait for response will time out in less than 1 sec
		select {
		case rsp, chOpen := <-rspChan:
			if !chOpen {
				fmt.Println("client response closed, exit")
				cont = false
			} else {
				fmt.Printf("client recv response ( %s )\n", rsp)
			}
		case <-timer.C:
			fmt.Printf("time out for reqest [%s]\n", req)
			i-- //resend it
		}
		timer.Stop()
	}
	fmt.Printf("client exit\n")
	conn1.Close()
	conn2.Close()
	rot.Close()
}
コード例 #9
0
ファイル: game3.go プロジェクト: G-VAR/router
func main() {
	flag.Parse()
	if flag.NArg() < 1 {
		fmt.Println("Usage: game3 num_runs hideTrace")
		return
	} else if flag.NArg() > 1 {
		showPingPong = false
	}
	numRuns, _ := strconv.Atoi(flag.Arg(0))
	//alloc two routers to connect them
	rot1 := router.New(router.StrID(), 32, router.BroadcastPolicy)
	rot2 := router.New(router.StrID(), 32, router.BroadcastPolicy)
	rot1.Connect(rot2)
	done := make(chan bool)
	//hook up Pinger and Ponger
	newPinger(rot1, done, numRuns)
	newPonger(rot2, done)
	//wait for ping-pong to finish
	<-done
	<-done
}
コード例 #10
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_PathId() {
	rout := router.New(router.PathID(), 32, router.BroadcastPolicy)
	chi1 := make(chan string)
	chi2 := make(chan string)
	chi3 := make(chan string)
	cho1 := make(chan string)
	cho2 := make(chan string)
	cho3 := make(chan string)
	done := make(chan bool)
	rout.AttachSendChan(router.PathID("/sport/basketball"), cho1)
	rout.AttachSendChan(router.PathID("/sport/baseball"), cho2)
	rout.AttachSendChan(router.PathID("/sport/basketball/Jordan"), cho3)
	rout.AttachRecvChan(router.PathID("/sport/*"), chi1) //subscribe to all sports news
	rout.AttachRecvChan(router.PathID("/sport/baseball"), chi2)
	rout.AttachRecvChan(router.PathID("/sport/basketball*"), chi3) //subscribe to all basketball news
	go func() {
		cho1 <- "want to play"
		cho1 <- "basketball?"
		close(cho1)
	}()
	go func() {
		cho2 <- "want to watch"
		cho2 <- "baseball?"
		close(cho2)
	}()
	go func() {
		cho3 <- "hello there, anybody know"
		cho3 <- "will Michael Jordan play again?"
		close(cho3)
	}()
	go func() {
		for v := range chi1 {
			fmt.Println("sport fan read: ", v)
		}
		done <- true
	}()
	go func() {
		for v := range chi2 {
			fmt.Println("baseball fan read: ", v)
		}
		done <- true
	}()
	go func() {
		for v := range chi3 {
			fmt.Println("basketball fan read: ", v)
		}
		done <- true
	}()
	<-done
	<-done
	<-done
}
コード例 #11
0
ファイル: servant.go プロジェクト: G-VAR/router
func NewServant(n string, role ServantRole, done chan bool) *Servant {
	s := new(Servant)
	s.Rot = router.New(router.StrID(), 32, router.BroadcastPolicy /* , n, router.ScopeLocal*/)
	s.role = role
	s.name = n
	//start system tasks, ServiceTask will be created when clients connect
	NewSysMgrTask(s.Rot, n, role)
	NewDbTask(s.Rot, n, role)
	NewFaultMgrTask(s.Rot, n, role)
	//run Servant mainloop to wait for client connection
	go s.Run(done)
	return s
}
コード例 #12
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_IntId() {
	rout := router.New(router.IntID(), 32, router.BroadcastPolicy)
	chi1 := make(chan string)
	chi2 := make(chan string)
	cho1 := make(chan string)
	cho2 := make(chan string)
	done := make(chan bool)
	rout.AttachSendChan(router.IntID(10), cho1)
	rout.AttachSendChan(router.IntID(10), cho2)
	rout.AttachRecvChan(router.IntID(10), chi1)
	rout.AttachRecvChan(router.IntID(10), chi2)
	go func() {
		cho1 <- "hello"
		cho1 <- "from IntID/src1"
		close(cho1)
	}()
	go func() {
		for v := range chi1 {
			fmt.Println("IntId/sink1 got: ", v)
		}
		done <- true
	}()
	go func() {
		for v := range chi2 {
			fmt.Println("IntId/sink2 got: ", v)
		}
		done <- true
	}()
	go func() {
		cho2 <- "hello"
		cho2 <- "from IntID/src2"
		close(cho2)
	}()
	<-done
	<-done
}
コード例 #13
0
ファイル: router.go プロジェクト: Jaspper/gitchain
func init() {
	r = router.New(router.PathID(), -1, router.BroadcastPolicy)
}
コード例 #14
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_logger() {
	rout1 := router.New(router.IntID(), 32, router.BroadcastPolicy, "router1", router.ScopeLocal)
	rout2 := router.New(router.IntID(), 32, router.BroadcastPolicy, "router2", router.ScopeLocal)
	rout1.Connect(rout2)
	chi1 := make(chan string)
	chi2 := make(chan string)
	chi3 := make(chan string)
	chiN := make(chan *router.ChanInfoMsg)
	cho := make(chan string)
	done := make(chan bool)
	bound := make(chan *router.BindEvent, 1)
	//subscribe to recver attach events
	rout1.AttachRecvChan(rout1.SysID(router.SubId), chiN)
	//when attaching sending chan, add a (chan BindEvent) for notifying recver connecting
	rout1.AttachSendChan(router.IntID(10), cho, bound)
	rout1.AttachRecvChan(router.IntID(10), chi1)
	rout2.AttachRecvChan(router.IntID(10), chi2)
	rout2.AttachRecvChan(router.IntID(10), chi3)
	//wait for some recvers connecting
	for {
		if (<-bound).Count == 2 {
			break
		}
	}
	go func() {
		cho <- "hello1"
		cho <- "hello2"
		cho <- "from router1/src"
		close(cho)
	}()
	go func() {
		for v := range chi1 {
			fmt.Println("router1/sink1 got: ", v)
		}
		done <- true
	}()
	go func() {
		for v := range chi2 {
			fmt.Println("router2/sink2 got: ", v)
		}
		done <- true
	}()
	go func() {
		i := 0
		for v := range chi3 {
			fmt.Println("router2/sink3 got: ", v)
			i++
			if i == 2 {
				rout2.DetachChan(router.IntID(10), chi3)
			}
		}
		done <- true
	}()
	go func() {
		count := 0
		for m := range chiN {
			for _, v := range m.Info {
				fmt.Println("got sub notif: ", v.Id)
			}
			count++
			if count >= 2 {
				break
			}
		}
		done <- true
	}()
	//waiting goroutines can exit
	<-done
	<-done
	<-done
	<-done
	rout1.Close()
	rout2.Close()
}
コード例 #15
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_remote_conn() {
	listening := make(chan string)
	srvdone := make(chan int)
	clidone := make(chan int)
	//run server
	go func() {
		l, err := net.Listen("tcp", ":0")
		listening <- l.Addr().String()
		conn, err := l.Accept()
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println("server start")
		//
		rout1 := router.New(router.IntID(), 32, router.BroadcastPolicy /* , "router1", router.ScopeLocal*/)
		_, err = rout1.ConnectRemote(conn, router.JsonMarshaling)
		if err != nil {
			fmt.Println(err)
		} else {
			cho := make(chan string)
			chi1 := make(chan string)
			bound := make(chan *router.BindEvent, 1)
			done := make(chan bool)
			rout1.AttachSendChan(router.IntID(10), cho, bound)
			rout1.AttachRecvChan(router.IntID(10), chi1)
			//wait for recvers connecting
			for {
				if (<-bound).Count == 2 {
					break
				}
			}
			go func() {
				cho <- "hello1"
				cho <- "hello2"
				cho <- "hello3"
				cho <- "hello4"
				cho <- "from router1/src"
				close(cho)
			}()
			go func() {
				for v := range chi1 {
					fmt.Println("router1/sink1 got: ", v)
				}
				done <- true
			}()
			<-done
		}
		<-clidone
		conn.Close()
		l.Close()
		srvdone <- 1
		rout1.Close()
	}()
	//run client
	go func() {
		addr := <-listening // wait for server to start
		dialaddr := "127.0.0.1" + addr[strings.LastIndex(addr, ":"):]
		conn, err := net.Dial("tcp", dialaddr)
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println("client connect")
		//
		rout2 := router.New(router.IntID(), 32, router.BroadcastPolicy /* , "router2", router.ScopeLocal*/)
		_, err = rout2.ConnectRemote(conn, router.JsonMarshaling)
		if err != nil {
			fmt.Println(err)
		} else {
			chi2 := make(chan string)
			chi3 := make(chan string)
			done := make(chan bool)
			rout2.AttachRecvChan(router.IntID(10), chi2)
			rout2.AttachRecvChan(router.IntID(10), chi3)
			go func() {
				for v := range chi2 {
					fmt.Println("router2/sink2 got: ", v)
				}
				done <- true
			}()
			go func() {
				i := 0
				for v := range chi3 {
					fmt.Println("router2/sink3 got: ", v)
					i++
					if i == 2 {
						rout2.DetachChan(router.IntID(10), chi3)
					}
				}
				done <- true
			}()
			<-done
			<-done
		}
		clidone <- 1
		conn.Close()
		rout2.Close()
	}()
	<-srvdone
}
コード例 #16
0
ファイル: tests.go プロジェクト: G-VAR/router
func test_flow_control() {
	listening := make(chan string)
	srvdone := make(chan int)
	clidone := make(chan int)
	//run server
	go func() {
		l, err := net.Listen("tcp", ":0")
		listening <- l.Addr().String()
		conn, err := l.Accept()
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println("server start")
		rout1 := router.New(router.IntID(), 5, router.BroadcastPolicy /* , "router1", router.ScopeLocal*/)
		//set FlowControl to turn on flow control on connection stream
		_, err = rout1.ConnectRemote(conn, router.GobMarshaling, router.WindowFlowController)
		if err != nil {
			fmt.Println(err)
		} else {
			cho := make(chan int)
			bound := make(chan *router.BindEvent, 1)
			done := make(chan bool)
			rout1.AttachSendChan(router.IntID(10), cho, bound)
			//wait for recvers connecting
			<-bound
			//start sending msgs
			go func() {
				for i := 0; i < 30; i++ {
					cho <- i
					fmt.Println("client sent: ", i)
					time.Sleep(1e8)
				}
				close(cho)
				done <- true
			}()
			<-done
		}
		<-clidone
		conn.Close()
		l.Close()
		srvdone <- 1
		rout1.Close()
	}()
	//run client
	go func() {
		addr := <-listening // wait for server to start
		dialaddr := "127.0.0.1" + addr[strings.LastIndex(addr, ":"):]
		conn, err := net.Dial("tcp", dialaddr)
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println("client connect")
		rout2 := router.New(router.IntID(), 5, router.BroadcastPolicy /* , "router2", router.ScopeLocal*/)
		//turn on flow control
		_, err = rout2.ConnectRemote(conn, router.GobMarshaling, router.WindowFlowController)
		if err != nil {
			fmt.Println(err)
		} else {
			chi2 := make(chan int)
			chi3 := make(chan int)
			done := make(chan bool)
			rout2.AttachRecvChan(router.IntID(10), chi2, 3)
			rout2.AttachRecvChan(router.IntID(10), chi3)
			go func() {
				for v := range chi2 {
					fmt.Println("router2/sink2 got: ", v)
					if v < 10 {
						time.Sleep(1e9)
					}
				}
				done <- true
			}()
			go func() {
				i := 0
				for v := range chi3 {
					fmt.Println("router2/sink3 got: ", v)
					i++
					if i == 2 {
						rout2.DetachChan(router.IntID(10), chi3)
					}
				}
				done <- true
			}()
			<-done
			<-done
		}
		clidone <- 1
		conn.Close()
		rout2.Close()
	}()
	<-srvdone
}
コード例 #17
0
ファイル: chatsrv.go プロジェクト: G-VAR/router
func main() {
	l, err := net.Listen("tcp", ":0")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(l.Addr().String())

	subjMap := make(map[string]*Subject)

	rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "chatsrv", router.ScopeLocal*/)

	//start server mainloop in a separate goroutine, and recv client conn in main goroutine
	go func() {
		//subscribe to remote publications, so learn what subjects are created
		pubChan := make(chan *router.ChanInfoMsg)
		//attach a recv chan with a "chan BindEvent"
		//this recv chan will not be closed when all senders detach
		bindChan := make(chan *router.BindEvent, 1)
		rot.AttachRecvChan(rot.NewSysID(router.PubId, router.ScopeRemote), pubChan, bindChan)
		//stopChan to notify when all people leave a subject
		stopChan := make(chan string, 36)

		for {
			select {
			case idstr := <-stopChan:
				delete(subjMap, idstr)
			case pub := <-pubChan:
				//process recved client publication of subjects
				for _, v := range pub.Info {
					id := v.Id.(*router.StrId) //get the real id type
					subj, ok := subjMap[id.Val]
					if ok {
						continue
					}
					fmt.Printf("add subject: %v\n", id.Val)
					//add a new subject with ScopeRemote, so that msgs are forwarded
					//to peers in connected routers
					id.ScopeVal = router.ScopeRemote
					id.MemberVal = router.MemberLocal
					subj = newSubject()
					subjMap[id.Val] = subj
					//subscribe to new subjects, forward recved msgs to other
					rot.AttachSendChan(id, subj.sendChan)
					rot.AttachRecvChan(id, subj.recvChan)
					//start forwarding
					go func(subjname string) {
						for val := range subj.recvChan {
							fmt.Printf("chatsrv forward: subject[%v], msg[%s]\n", subjname, val)
							subj.sendChan <- val
						}
						stopChan <- subjname
						fmt.Printf("chatsrv stop forwarding for : %v\n", subjname)
					}(id.Val)
				}
			}
		}
	}()

	//keep accepting client conn and connect local router to it
	for {
		conn, err := l.Accept()
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println("one client connect")

		_, err = rot.ConnectRemote(conn, router.JsonMarshaling)
		if err != nil {
			fmt.Println(err)
			return
		}
	}

	//in fact never reach here
	rot.Close()
	l.Close()
}