示例#1
0
func sockHandler(d *Daemon, w *websocket.Conn) {
	r := w.Request()
	raddr := r.RemoteAddr
	if !d.isTrustedClient(r) {
		d.log.Warn("untrusted client connected", log.Ctx{"raddr": raddr})
		return
	}

	d.log.Debug("handing over client connection", log.Ctx{"raddr": raddr})

	clog := log.New(log.Ctx{"module": "socks", "raddr": raddr})
	handler := log.StdoutHandler

	if quiet {
		clog.SetHandler(log.DiscardHandler())
	} else if verbose {
		clog.SetHandler(log.LvlFilterHandler(log.LvlInfo, handler))
	} else if debug {
		clog.SetHandler(log.LvlFilterHandler(log.LvlDebug, handler))
	} else {
		clog.SetHandler(log.LvlFilterHandler(log.LvlError, handler))
	}

	client := &clientConnection{
		websocket: w,
		log:       clog,
		raddr:     raddr,
	}
	go client.run()
}
示例#2
0
文件: peer.go 项目: sisatech/cluster
// NewPeer returns a new peer, which can join a cluster
func NewPeer(config *PeerConfig) (*Peer, error) {

	advertise := config.Bind
	if len(config.Advertise) > 0 {
		advertise = config.Advertise
	}

	logger := log.New("module", "peer", "bind", config.Bind)
	peer := &Peer{
		config:            config,
		logger:            logger,
		pingChMap:         make(map[int64]chan *ackRequest),
		indirectPingChMap: make(map[int64]chan *indirectPingResponse),
		recentlyPinged:    make(map[string]*RemotePeer),
		store:             newStore(advertise, logger),
	}

	// create udp server
	udpServer := multiserver.NewUDPServer(config.Bind, peer.execUDP)
	udpServer.UDPBufferSizeSet(config.UDPBufferSize)
	peer.udpServer = udpServer

	// create tcp server
	tcpServer := multiserver.NewTCPServer(config.Bind, peer.handleTCPRequest, nil)
	peer.tcpServer = tcpServer

	// add callback if configured
	peer.store.peerEventCallback = config.PeerEventCallback

	return peer, nil
}
示例#3
0
文件: conn_pool.go 项目: rjammala/pgx
// NewConnPool creates a new ConnPool. config.ConnConfig is passed through to
// Connect directly.
func NewConnPool(config ConnPoolConfig) (p *ConnPool, err error) {
	p = new(ConnPool)
	p.config = config.ConnConfig
	p.maxConnections = config.MaxConnections
	if p.maxConnections == 0 {
		p.maxConnections = 5
	}
	if p.maxConnections < 2 {
		return nil, errors.New("MaxConnections must be at least 2")
	}

	p.afterConnect = config.AfterConnect
	if config.Logger != nil {
		p.logger = config.Logger
	} else {
		p.logger = log.New()
		p.logger.SetHandler(log.DiscardHandler())
	}

	p.allConnections = make([]*Conn, 0, p.maxConnections)
	p.availableConnections = make([]*Conn, 0, p.maxConnections)
	p.cond = sync.NewCond(new(sync.Mutex))

	// Initially establish one connection
	var c *Conn
	c, err = p.createConnection()
	if err != nil {
		return
	}
	p.allConnections = append(p.allConnections, c)
	p.availableConnections = append(p.availableConnections, c)

	return
}
示例#4
0
// NewBot creates a new instance of Bot
func NewBot(host, nick string, options ...func(*Bot)) (*Bot, error) {
	// Defaults are set here
	bot := Bot{
		Incoming:      make(chan *Message, 16),
		outgoing:      make(chan string, 16),
		started:       time.Now(),
		unixastr:      fmt.Sprintf("@%s-%s/bot", host, nick),
		Host:          host,
		Nick:          nick,
		ThrottleDelay: 200 * time.Millisecond,
		PingTimeout:   300 * time.Second,
		HijackSession: false,
		SSL:           false,
		SASL:          false,
		Channels:      []string{"#test"},
		Password:      "",
	}
	for _, option := range options {
		option(&bot)
	}
	// Discard logs by default
	bot.Logger = log.New("id", logext.RandId(8), "host", bot.Host, "nick", log.Lazy{bot.getNick})

	bot.Logger.SetHandler(log.DiscardHandler())
	bot.AddTrigger(pingPong)
	bot.AddTrigger(joinChannels)
	return &bot, nil
}
示例#5
0
func main() {
	flag.Parse()
	if helpflag {
		flag.Usage()
		return
	}

	logger = log.New()

	handler := log.StdoutHandler
	if quietflag {
		logger.SetHandler(log.DiscardHandler())
	} else if verboseflag {
		logger.SetHandler(log.LvlFilterHandler(log.LvlInfo, handler))
	} else if debugflag {
		logger.SetHandler(log.LvlFilterHandler(log.LvlDebug, handler))
	} else {
		logger.SetHandler(log.LvlFilterHandler(log.LvlError, handler))
	}

	ldifstore := &ldif.LdifBackend{
		Path: "./ldif",
		Log:  logger.New(log.Ctx{"type": "backend", "backend": "ldif"}),
	}

	if err := ldifstore.Start(); err != nil {
		logger.Error("error loading backend", log.Ctx{"error": err})
		os.Exit(1)
	}

	//Create a new LDAP Server
	server := ldap.NewServer(logger)

	fallback := &debug.DebugBackend{
		Log: logger.New(log.Ctx{"type": "backend", "backend": "debug"}),
	}

	//Create routes bindings
	routes := newRouter(fallback, logger)

	// backend specific routes
	routes.Bind(ldifstore).BaseDn("dc=enterprise,dc=org").Label("Bind LDIF")
	routes.Search(ldifstore).BaseDn("dc=enterprise,dc=org").Label("Search LDIF")
	routes.Add(ldifstore).BaseDn("dc=enterprise,dc=org").Label("Add LDIF")

	//Attach routes to server
	server.Handle(routes)

	// listen on 3389 and serve
	go server.ListenAndServe(":6389")

	// When CTRL+C, SIGINT and SIGTERM signal occurs
	// Then stop server gracefully
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	<-ch
	close(ch)

	server.Stop()
}
示例#6
0
文件: main.go 项目: seka17/bracelet
func main() {
	start := false
	logDir := flag.String("log", "./logs", "path to log directory")
	confPath := flag.String("config", "./config.json", "path to cofig file")
	// docker := flag.Bool("docker", false, "for docker")
	flag.Parse()

	// Create log directory
	if err := os.Mkdir(*logDir, 0777); err != nil && os.IsNotExist(err) {
		log.Fatal(err)
	}
	// Write log in file:
	// Change file every 24 hours
	go func() {
		Log = llog.New()
		t := time.Now()
		for {
			// Day_Month_Year
			name := fmt.Sprintf("%v.%v.%v", t.Month(), t.Day(), t.Year())
			h, f, err := MyFileHandler(path.Join(*logDir, name), llog.LogfmtFormat())
			if err != nil {
				log.Println(err)
				return
			}
			Log.SetHandler(llog.SyncHandler(h))
			if !start {
				start = true
			}
			t = <-time.After(24 * time.Second)
			Log.SetHandler(llog.DiscardHandler())
			f.Close()
		}
	}()
	// Wait for log setup
	for {
		if start {
			break
		}
		time.Sleep(time.Second * 5)
	}

	file, err := ioutil.ReadFile(*confPath)
	if err != nil {
		fmt.Println("No config.json provided, using default values!")
		os.Exit(1)
	}

	var conf proxy.Config
	if err := json.Unmarshal(file, &conf); err != nil {
		os.Exit(1)
	}
	// creates new server instance using config.json
	s := proxy.NewServer(Log, conf)

	if err := s.Listen(); err != nil {
		Log.Error("Listen", "error", err)
		os.Exit(1)
	}

}
示例#7
0
文件: main.go 项目: jgrossophoff/pgx
func main() {
	var err error
	connPoolConfig := pgx.ConnPoolConfig{
		ConnConfig: pgx.ConnConfig{
			Host:     "127.0.0.1",
			User:     "******",
			Password: "******",
			Database: "url_shortener",
			Logger:   log.New("module", "pgx"),
		},
		MaxConnections: 5,
		AfterConnect:   afterConnect,
	}
	pool, err = pgx.NewConnPool(connPoolConfig)
	if err != nil {
		log.Crit("Unable to create connection pool", "error", err)
		os.Exit(1)
	}

	http.HandleFunc("/", urlHandler)

	log.Info("Starting URL shortener on localhost:8080")
	err = http.ListenAndServe("localhost:8080", nil)
	if err != nil {
		log.Crit("Unable to start web server", "error", err)
		os.Exit(1)
	}
}
示例#8
0
文件: log.go 项目: sheenobu/quicklog
// Log gets the log from the context
func Log(ctx context.Context) log15.Logger {
	l, ok := FromContext(ctx)
	if !ok {
		l = log15.New()
	}
	return l
}
示例#9
0
func NewRouter() *mux.Router {
	var handler http.Handler

	logger := log.New("module", "web.router")
	router := mux.NewRouter().StrictSlash(true)
	for _, route := range routes {
		handler = route.HandlerFunc
		handler = Logger(handler, route.Name, logger)

		router.
			Methods(route.Method).
			Path(route.Pattern).
			Name(route.Name).
			Handler(handler)
	}

	currentFolder, err := osext.ExecutableFolder()
	if err != nil {
		panic(err)
	}

	handler = http.FileServer(http.Dir(currentFolder + "/html/lib/"))
	handler = http.StripPrefix("/resources/", handler)
	handler = Logger(handler, "Resources", logger)
	router.
		Methods("GET").
		PathPrefix("/resources/").
		Name("Resources").
		Handler(handler)

	return router
}
示例#10
0
func (d *Daemon) Init() error {

	/* Setup the TLS authentication */
	certf, keyf, err := shared.ReadMyCert("client.crt", "client.key")
	if err != nil {
		return err
	}
	d.certf = certf
	d.keyf = keyf
	d.tlsConfig, err = shared.GetTLSConfig(d.certf, d.keyf)
	if err != nil {
		return err
	}
	srvlog := log.New(log.Ctx{"module": "client"})
	d.log = srvlog

	handler := log.StdoutHandler

	if quiet {
		d.log.SetHandler(log.DiscardHandler())
	} else if verbose {
		d.log.SetHandler(log.LvlFilterHandler(log.LvlInfo, handler))
	} else if debug {
		d.log.SetHandler(log.LvlFilterHandler(log.LvlDebug, handler))
	} else {
		d.log.SetHandler(log.LvlFilterHandler(log.LvlError, handler))
	}

	d.Run()
	return nil
}
示例#11
0
文件: log.go 项目: rockstar/lxd
// SetLogger defines the *log.Logger where log messages are sent to.
func SetLogger(syslog string, logfile string, verbose bool, debug bool) error {
	Log = log.New()

	var handlers []log.Handler

	var syshandler log.Handler

	// System specific handler
	syshandler = GetSystemHandler(syslog, debug)
	if syshandler != nil {
		handlers = append(handlers, syshandler)
	}

	// FileHandler
	if logfile != "" {
		if !PathExists(filepath.Dir(logfile)) {
			return fmt.Errorf("Log file path doesn't exist: %s", filepath.Dir(logfile))
		}

		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlInfo,
					log.Must.FileHandler(logfile, log.LogfmtFormat()),
				),
			)
		} else {
			handlers = append(handlers, log.Must.FileHandler(logfile, log.LogfmtFormat()))
		}
	}

	// StderrHandler
	if verbose || debug {
		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlInfo,
					log.StderrHandler,
				),
			)
		} else {
			handlers = append(handlers, log.StderrHandler)
		}
	} else {
		handlers = append(
			handlers,
			log.LvlFilterHandler(
				log.LvlWarn,
				log.StderrHandler,
			),
		)
	}

	Log.SetHandler(log.MultiHandler(handlers...))

	return nil
}
示例#12
0
func Initialize(logOut string, lvl interface{}) error {
	if Log == nil {
		Log = &Logger{
			Logger: log.New(),
		}
	}
	return Log.InitializeWithContext("main", logOut, lvl)
}
示例#13
0
文件: log.go 项目: RuneTM/lxd
// SetLogger defines the *log.Logger where log messages are sent to.
func SetLogger(syslog string, logfile string, verbose bool, debug bool) error {
	Log = log.New()

	var handlers []log.Handler

	// SyslogHandler
	if syslog != "" {
		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlError,
					log.Must.SyslogHandler(syslog, log.LogfmtFormat()),
				),
			)
		} else {
			handlers = append(handlers, log.Must.SyslogHandler(syslog, log.LogfmtFormat()))
		}
	}

	// FileHandler
	if logfile != "" {
		if !PathExists(filepath.Dir(logfile)) {
			return fmt.Errorf("Log file path doesn't exist: %s\n", filepath.Dir(logfile))
		}

		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlError,
					log.Must.FileHandler(logfile, log.LogfmtFormat()),
				),
			)
		} else {
			handlers = append(handlers, log.Must.FileHandler(logfile, log.LogfmtFormat()))
		}
	}

	// StderrHandler
	if verbose || debug {
		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlError,
					log.StderrHandler,
				),
			)
		} else {
			handlers = append(handlers, log.StderrHandler)
		}
	}

	Log.SetHandler(log.MultiHandler(handlers...))

	return nil
}
示例#14
0
func log15LoggingMiddleware(next http.Handler) http.Handler {
	srvlog := log15.New("module", "app/server")
	fn := func(w http.ResponseWriter, r *http.Request) {
		t1 := time.Now()
		next.ServeHTTP(w, r)
		t2 := time.Now()
		srvlog.Info("access", "method", r.Method, "path", r.URL.String(), "req_time", t2.Sub(t1))
	}
	return http.HandlerFunc(fn)
}
示例#15
0
func TestMain(m *testing.M) {
	data, _ := ioutil.ReadFile("../simulation/test_data/demo.json")
	var s simulation.Simulation
	json.Unmarshal(data, &s)
	mainLogger := log.New()
	InitializeLogger(mainLogger)
	simulation.InitializeLogger(mainLogger)
	go Run(&s, "0.0.0.0", "22222")
	os.Exit(m.Run())
}
示例#16
0
文件: axiom.go 项目: postfix/axiom
func NewUpdater(equinoxAppId, publicKeyPEM string) *Updater {
	logger := log.New()
	logger.SetHandler(log.DiscardHandler())
	return &Updater{
		Logger:         logger,
		EquinoxAppId:   equinoxAppId,
		PublicKeyPEM:   publicKeyPEM,
		DefaultChannel: "stable",
	}
}
示例#17
0
文件: server.go 项目: sisatech/raft
func baseServerCreate(serverType string, addr string, tlsConfig *tls.Config) *baseServer {

	return &baseServer{
		address:      addr,
		logger:       log15.New("module", serverType, "addr", addr),
		stopCh:       make(chan chan struct{}, 1),
		serverStatus: stopped,
		tlsConfig:    tlsConfig,
	}

}
示例#18
0
文件: main.go 项目: jackc/tpr
func newLogger(conf ini.File) (log.Logger, error) {
	level, _ := conf.Get("log", "level")
	if level == "" {
		level = "warn"
	}

	logger := log.New()
	setFilterHandler(level, logger, log.StdoutHandler)

	return logger, nil
}
示例#19
0
// InitLog ...
func (logM *LogManager) InitLog() {

	var svrlog = log.New(logM.LogContext, logM.LogContext)
	svrlog.SetHandler(log.MultiHandler(log.StreamHandler(os.Stderr, log.LogfmtFormat()),
		log.LvlFilterHandler(log.LvlError, log.Must.FileHandler(logM.LogDir+logM.ErrorFile, log.JsonFormat())),
		log.LvlFilterHandler(log.LvlInfo, log.Must.FileHandler(logM.LogDir+logM.InfoFile, log.JsonFormat())),
		log.LvlFilterHandler(log.LvlCrit, log.Must.FileHandler(logM.LogDir+logM.CritFile, log.JsonFormat())),
		log.LvlFilterHandler(log.LvlDebug, log.Must.FileHandler(logM.LogDir+logM.DebugFile, log.JsonFormat()))))

	logM.Logger = svrlog

}
示例#20
0
文件: log.go 项目: joker042/lxd
// SetLogger defines the *log.Logger where log messages are sent to.
func SetLogger(syslog string, logfile string, verbose bool, debug bool) {
	Log = log.New()

	var handlers []log.Handler

	// SyslogHandler
	if syslog != "" {
		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlError,
					log.Must.SyslogHandler(syslog, log.LogfmtFormat()),
				),
			)
		} else {
			handlers = append(handlers, log.Must.SyslogHandler(syslog, log.LogfmtFormat()))
		}
	}

	// FileHandler
	if logfile != "" {
		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlError,
					log.Must.FileHandler(logfile, log.LogfmtFormat()),
				),
			)
		} else {
			handlers = append(handlers, log.Must.FileHandler(logfile, log.LogfmtFormat()))
		}
	}

	// StderrHandler
	if verbose || debug {
		if !debug {
			handlers = append(
				handlers,
				log.LvlFilterHandler(
					log.LvlError,
					log.StderrHandler,
				),
			)
		} else {
			handlers = append(handlers, log.StderrHandler)
		}
	}

	Log.SetHandler(log.MultiHandler(handlers...))
}
示例#21
0
文件: bench_test.go 项目: yunhor/pgx
func BenchmarkLog15Discard(b *testing.B) {
	logger := log.New()
	lvl, err := log.LvlFromString("error")
	if err != nil {
		b.Fatal(err)
	}
	logger.SetHandler(log.LvlFilterHandler(lvl, log.DiscardHandler()))

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		logger.Debug("benchmark", "i", i, "b.N", b.N)
	}
}
示例#22
0
func New() *Engine {
	// package instance of the helios type
	engine := &Engine{
		HTTPEngine: gin.Default(),
		Socket:     initSocket(),
		Logger:     log.New(),
	}

	fileHandler, _ := log.FileHandler("./log.debug", log.LogfmtFormat())
	engine.SetHandler(log.MultiHandler(log.LvlFilterHandler(log.LvlWarn, fileHandler), log.StreamHandler(os.Stdout, log.TerminalFormat())))

	return engine
}
示例#23
0
func BenchmarkLog15JSONPositive(b *testing.B) {
	stream := &blackholeStream{}
	logger := log.New()
	logger.SetHandler(log.StreamHandler(stream, log.JsonFormat()))
	b.ResetTimer()

	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("The quick brown fox jumps over the lazy dog", "rate", 15, "low", 16, "high", 123.2)
		}
	})

	if stream.WriteCount() != uint64(b.N) {
		b.Fatalf("Log write count")
	}
}
示例#24
0
文件: bench_test.go 项目: yunhor/pgx
func BenchmarkSelectWithLoggingErrorWithLog15(b *testing.B) {
	connConfig := *defaultConnConfig

	logger := log.New()
	lvl, err := log.LvlFromString("error")
	if err != nil {
		b.Fatal(err)
	}
	logger.SetHandler(log.LvlFilterHandler(lvl, log.DiscardHandler()))
	connConfig.Logger = logger
	connConfig.LogLevel = pgx.LogLevelError
	conn := mustConnect(b, connConfig)
	defer closeConn(b, conn)

	benchmarkSelectWithLog(b, conn)
}
示例#25
0
func TestSpeculativeHandler(t *testing.T) {
	t.Parallel()

	// test with an even multiple of the buffer size, less than full buffer size
	// and not a multiple of the buffer size
	for _, count := range []int{10000, 50, 432} {
		recs := make(chan *log.Record)
		done := make(chan int)
		spec := SpeculativeHandler(100, log.ChannelHandler(recs))

		go func() {
			defer close(done)
			expectedCount := int(math.Min(float64(count), float64(100)))
			expectedIdx := count - expectedCount
			for r := range recs {
				if r.Ctx[1] != expectedIdx {
					t.Errorf("Bad ctx 'i', got %d expected %d", r.Ctx[1], expectedIdx)
					return
				}
				expectedIdx++
				expectedCount--

				if expectedCount == 0 {
					// got everything we expected
					break
				}
			}

			select {
			case <-recs:
				t.Errorf("got an extra record we shouldn't have!")
			default:
			}
		}()

		lg := log.New()
		lg.SetHandler(spec)
		for i := 0; i < count; i++ {
			lg.Debug("test speculative", "i", i)
		}

		go spec.Flush()

		// wait for the go routine to finish
		<-done
	}
}
示例#26
0
func New(config *Config) *Matrix {
	cacheDir := config.CacheDir
	if cacheDir == "" {
		cacheDir = filepath.Join(config.OutputDir, ".cache")
	}
	l := log.New("component", "asset-matrix")
	m := &Matrix{
		Log:    l,
		config: config,
		cache:  &Cache{Dir: cacheDir, l: l.New("type", "cache")},
	}
	for _, r := range config.Paths {
		r.findAsset = m.findAsset
		r.assetURLPrefix = m.config.AssetURLPrefix
	}
	return m
}
示例#27
0
文件: logger.go 项目: grengojbo/ads
// Start Logger service
func (self *Logger) Start() {
	var err error
	self.Logger = log.New()
	if self.Release {
		self.Level, err = log.LvlFromString("error")
		if err != nil {
			fmt.Println(err)
		}
	} else {
		self.Level, err = log.LvlFromString("debug")
		if err != nil {
			fmt.Println(err)
		}
	}
	self.Logger.SetHandler(log.LvlFilterHandler(self.Level, log.StdoutHandler))
	// self.SetHandler(log.LvlFilterHandler(lvl, log.DiscardHandler()))
	self.Info("starting Logger service...")
}
示例#28
0
func BenchmarkLog15TextNegative(b *testing.B) {
	stream := &blackholeStream{}
	logger := log.New()
	logger.SetHandler(log.LvlFilterHandler(
		log.LvlError,
		log.StreamHandler(stream, log.LogfmtFormat())),
	)
	b.ResetTimer()

	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			logger.Info("The quick brown fox jumps over the lazy dog")
		}
	})

	if stream.WriteCount() != uint64(0) {
		b.Fatalf("Log write count")
	}
}
示例#29
0
func (l *Logger) Initialize(logOut string, lvl interface{}) error {
	var (
		level log.Lvl
		err   error
	)

	if l.Context == "" {
		r := rand.New(rand.NewSource(time.Now().UnixNano()))
		randInt := r.Int()
		t := time.Now()
		l.Context = fmt.Sprintf("%s#%d", t.Format(time.RFC3339), randInt)
	}

	if str, ok := lvl.(string); ok {
		level, err = log.LvlFromString(str)
		if err != nil {
			return err
		}
	} else {
		level = lvl.(log.Lvl)
	}
	l.Logger = log.New(log.Ctx{"context": l.Context})
	l.Level = level

	if logOut == "STDOUT" {
		normalHandler := log.LvlFilterHandler(level, log.StdoutHandler)
		errorHandler := log.LvlFilterHandler(level, log.CallerStackHandler("%+v", log.StdoutHandler))
		handler := errorMultiHandler(normalHandler, errorHandler)
		l.SetHandler(handler)
	} else if logOut == "NONE" {
		l.SetHandler(log.DiscardHandler())
	} else {
		fileHandler := log.Must.FileHandler(logOut, log.LogfmtFormat())
		normalHandler := log.LvlFilterHandler(level, fileHandler)
		errorHandler := log.LvlFilterHandler(level, log.CallerStackHandler("%+v", fileHandler))
		handler := errorMultiHandler(normalHandler, errorHandler)
		l.SetHandler(handler)
	}

	return nil
}
示例#30
0
func TestHotSwapHandler(t *testing.T) {
	t.Parallel()

	h1, r1 := testHandler()

	l := log.New()
	h := HotSwapHandler(h1)
	l.SetHandler(h)

	l.Info("to h1")
	if r1.Msg != "to h1" {
		t.Fatalf("didn't get expected message to h1")
	}

	h2, r2 := testHandler()
	h.Swap(h2)
	l.Info("to h2")
	if r2.Msg != "to h2" {
		t.Fatalf("didn't get expected message to h2")
	}
}