// Starts listening for client connections. // When a new application connects, launches listeners in a goroutine. // Returns an error when error occurs. func StartListen(port int, useTls bool, crtPath string, keyPath string, sname string) error { // Create a listening address addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf(":%d", port)) if err != nil { return err } // start a new server and listen on the address var l net.Listener l, err = net.ListenTCP("tcp", addr) if err != nil { return err } // wrap with TLS if required if useTls { cert, err := tls.LoadX509KeyPair(crtPath, keyPath) if err != nil { return err } conf := tls.Config{} certs := make([]tls.Certificate, 1) certs[0] = cert conf.Certificates = certs cp := x509.NewCertPool() caCert, err := ioutil.ReadFile(crtPath) if err != nil { return err } if !cp.AppendCertsFromPEM(caCert) { return errors.New("Could not append PEM cert") } conf.RootCAs = cp conf.ServerName = sname conf.ClientAuth = tls.RequireAndVerifyClientCert conf.ClientCAs = cp l = tls.NewListener(l, &conf) } // at the end of this function close the server connection defer l.Close() logging.Debug("Starting listen loop") for { a, err := acceptApp(l) if err != nil { return err } else { logging.Debug("Got connection") go ListenForCommands(a) } } return nil }
func (c *commandStrategy) msgQuerySuccess() error { c.app.RWMutex.RLock() defer c.app.RWMutex.RUnlock() logging.Debug("Replying to message from app %s", c.app.Manifest.InstanceId) var id string if id_, ok := getString(c.body, "id"); ok { id = id_ } else { return errors.New("No id found") } ret := c.body["ret"] body := make(jsonData) body["fromInstanceId"] = c.app.Manifest.InstanceId body["id"] = id body["ret"] = ret if recipient, ok := msg_archive.GetMsg(id); ok { recipient.Send("MSG_QUERY_SUCCESS", body) } else { logging.Warning("unrecognized message query id %s from app %s", id, c.app.Manifest.InstanceId) } return nil }
func (c *commandStrategy) msgQueryFail() error { c.app.RWMutex.RLock() defer c.app.RWMutex.RUnlock() logging.Debug("Sending message query fail from %s", c.app.Manifest.InstanceId) var id, message string if id_, ok := getString(c.body, "id"); ok { id = id_ } else { return errors.New("No id found") } if message_, ok := getString(c.body, "message"); !ok { message = message_ } else { return errors.New("No message found") } body := make(jsonData) body["fromInstanceId"] = c.app.Manifest.InstanceId body["id"] = id body["message"] = message if recipient, ok := msg_archive.GetMsg(id); ok { recipient.Send("MSG_QUERY_FAIL", body) } else { logging.Warning("unrecognized message query id %s from app %s", id, c.app.Manifest.InstanceId) } return nil }
func (c *commandStrategy) msgBroadcast() error { c.app.RWMutex.RLock() defer c.app.RWMutex.RUnlock() var id string content := c.body["content"] logging.Debug("Sending message broadcast from %s", c.app.Manifest.InstanceId) if id_, ok := getString(c.body, "id"); ok { id = id_ } else { return errors.New("No id found") } msg_archive.RecordMsg(c.app, id) toSend := make(jsonData) toSend["fromInstanceId"] = c.app.Manifest.InstanceId toSend["id"] = id toSend["content"] = content for _, cpb := range c.app.Manifest.Capabilities { for _, dep := range registry.GetDependents(cpb) { dep.Send("MSG_BROADCAST", toSend) } } return nil }
// Parses a command given the command's message string // (verb and body, no message length) func ParseCommand(a *app.App, message string) (CommandStrategy, bool) { id := "NO_ID_FOUND" if a.Manifest != nil { id = a.Manifest.InstanceId } logging.Debug("Parsing from app %s: \n%s", id, message) ret, err := internalParseCommand(a, message) if err != nil { logging.Error("Parse failed from app %s: %s", id, err.Error()) return newFailedCommandStrategy(a, message, err.Error()), false } return ret, true }
func (a *App) Send(verb string, body map[string]interface{}) error { id := "NO_ID_FOUND" if a.Manifest != nil { id = a.Manifest.InstanceId } logging.Debug("Sending message %s to instance %s", verb, id) verb += " " bodyBytes, err := json.Marshal(body) if err != nil { return err } toSend := append([]byte(verb), bodyBytes...) length := fmt.Sprintf("%d\n", len(toSend)) toSend = append([]byte(length), toSend...) _, err = a.Connection.Write(toSend) return err }
// construct the app based on its manifest func (c *commandStrategy) appManifest() bool { c.app.RWMutex.Lock() defer c.app.RWMutex.Unlock() logging.Debug("Parsing application's manifest") man, err := decodeManifest(c.body) if err != nil { logging.Error("App's manifest is invalid: %s", err) sendManifestFail(c.app, err.Error()) return false } if _, exists := registry.GetInstance(man.InstanceId); exists { logging.Error("App's instance id is already taken: %s", man.InstanceId) sendManifestFail(c.app, fmt.Sprintf("instanceId %s is in use", man.InstanceId)) return false } c.app.Status = app.STATUS_DOWN c.app.Manifest = man registry.Register(c.app) sendManifestOkAndDependencies(c.app) logging.Info("App '%s' now connected with manifest parsed", c.app.Manifest.InstanceId) return true }
// send this message query to all targeted apps func (c *commandStrategy) msgQuery() error { c.app.RWMutex.RLock() defer c.app.RWMutex.RUnlock() logging.Debug("Processing query from %s", c.app.Manifest.InstanceId) mq, err := parseMsgQuery(c) if err != nil { return err } msg_archive.RecordMsg(c.app, mq.id) body := make(jsonData) body["fromInstanceId"] = c.app.Manifest.InstanceId body["id"] = mq.id body["priority"] = mq.priority body["data"] = mq.data body["instanceId"] = mq.instanceIds body["action"] = mq.action body["capability"] = mq.capability.Name // if this is an undirected query if len(mq.instanceIds) == 0 { // send to all providers of the capability for _, provider := range registry.GetProviders(mq.capability) { provider.Send("MSG_QUERY", body) } } else { // this is a directed query, send to all given instance ids for _, instName := range mq.instanceIds { if inst, ok := registry.GetInstance(instName); ok { inst.Send("MSG_QUERY", body) } } } return nil }