예제 #1
1
// 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
}
예제 #2
0
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
}
예제 #3
0
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
}
예제 #4
0
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
}
예제 #5
0
// 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
}
예제 #6
0
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
}
예제 #7
0
// 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
}
예제 #8
0
// 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
}