func (sa *ServiceAdmin) Listen(addr *skynet.BindAddr, bindWait *sync.WaitGroup) { listener, err := addr.Listen() if err != nil { panic(err) } bindWait.Done() sa.service.Log.Trace(fmt.Sprintf("%+v", AdminListening{sa.service.Config})) for { conn, err := listener.AcceptTCP() if err != nil { panic(err) } go sa.rpc.ServeCodec(bsonrpc.NewServerCodec(conn)) } }
// this function is the goroutine that owns this service - all thread-sensitive data needs to // be manipulated only through here. func (s *Service) mux() { loop: for { select { case conn := <-s.connectionChan: atomic.AddInt32(&s.Stats.Clients, 1) clientID := skynet.UUID() s.clientMutex.Lock() s.clientInfo[clientID] = ClientInfo{ Address: conn.RemoteAddr(), } s.clientMutex.Unlock() // send the server handshake sh := skynet.ServiceHandshake{ Registered: s.Registered, ClientID: clientID, } encoder := bsonrpc.NewEncoder(conn) err := encoder.Encode(sh) if err != nil { s.Log.Error(err.Error()) atomic.AddInt32(&s.Stats.Clients, -1) break } if !s.Registered { conn.Close() atomic.AddInt32(&s.Stats.Clients, -1) break } // read the client handshake var ch skynet.ClientHandshake decoder := bsonrpc.NewDecoder(conn) err = decoder.Decode(&ch) if err != nil { s.Log.Error("Error calling bsonrpc.NewDecoder: " + err.Error()) atomic.AddInt32(&s.Stats.Clients, -1) break } // here do stuff with the client handshake go func() { s.RPCServ.ServeCodec(bsonrpc.NewServerCodec(conn)) atomic.AddInt32(&s.Stats.Clients, -1) }() case register := <-s.registeredChan: if register { s.register() } else { s.unregister() } case _ = <-s.doneChan: go func() { for _ = range s.doneChan { } }() s.RemoveFromCluster() s.doozerChan <- doozerFinish{} break loop case _ = <-s.updateTicker.C: s.UpdateDoozerStats() } } }