2021-03-01 16:08:40 +00:00
|
|
|
// The structure of how to add new method types to the system.
|
|
|
|
// -----------------------------------------------------------
|
|
|
|
// All methods need 3 things:
|
|
|
|
// - A type definition
|
|
|
|
// - The type needs a getKind method
|
|
|
|
// - The type needs a handler method
|
|
|
|
// Overall structure example shown below.
|
|
|
|
//
|
|
|
|
// ---
|
2021-04-04 05:33:18 +00:00
|
|
|
// type methodCommandCLICommandRequest struct {
|
2021-03-01 16:08:40 +00:00
|
|
|
// commandOrEvent CommandOrEvent
|
|
|
|
// }
|
|
|
|
//
|
2021-04-04 05:33:18 +00:00
|
|
|
// func (m methodCommandCLICommandRequest) getKind() CommandOrEvent {
|
2021-03-01 16:08:40 +00:00
|
|
|
// return m.commandOrEvent
|
|
|
|
// }
|
|
|
|
//
|
2021-04-04 05:33:18 +00:00
|
|
|
// func (m methodCommandCLICommandRequest) handler(s *server, message Message, node string) ([]byte, error) {
|
2021-03-01 16:08:40 +00:00
|
|
|
// ...
|
|
|
|
// ...
|
2021-03-11 05:34:36 +00:00
|
|
|
// ackMsg := []byte(fmt.Sprintf("confirmed from node: %v: messageID: %v\n---\n%s---", node, message.ID, out))
|
|
|
|
// return ackMsg, nil
|
2021-03-01 16:08:40 +00:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// You also need to make a constant for the Method, and add
|
2022-06-14 05:05:38 +00:00
|
|
|
// that constant as the key in the MethodsAvailable map, where
|
|
|
|
// the value is the actual type you want to map it to with a
|
|
|
|
// handler method. You also specify if it is a Command or Event,
|
|
|
|
// and if it is ACK or NACK.
|
|
|
|
//
|
|
|
|
// Requests used in sub processes should always start with the
|
|
|
|
// naming REQSUB. Since the method of a sub process are defined
|
|
|
|
// within the method handler of the owning reqest type we should
|
|
|
|
// use the methodREQSUB for these types. The methodREQSUB handler
|
|
|
|
// does nothing.
|
|
|
|
//
|
2021-03-01 16:08:40 +00:00
|
|
|
// Check out the existing code below for more examples.
|
2021-02-11 14:39:19 +00:00
|
|
|
|
2023-10-04 20:58:42 +00:00
|
|
|
package ctrl
|
2021-02-11 14:39:19 +00:00
|
|
|
|
|
|
|
import (
|
2021-03-26 15:04:01 +00:00
|
|
|
"context"
|
2021-02-11 14:39:19 +00:00
|
|
|
"fmt"
|
2021-03-02 12:46:02 +00:00
|
|
|
"path/filepath"
|
2022-06-14 05:05:38 +00:00
|
|
|
"strings"
|
2021-03-11 11:07:09 +00:00
|
|
|
"time"
|
2021-02-11 14:39:19 +00:00
|
|
|
)
|
|
|
|
|
2021-03-11 16:14:43 +00:00
|
|
|
// Method is used to specify the actual function/method that
|
|
|
|
// is represented in a typed manner.
|
|
|
|
type Method string
|
|
|
|
|
2021-02-11 14:39:19 +00:00
|
|
|
// ------------------------------------------------------------
|
2021-03-01 16:08:40 +00:00
|
|
|
// The constants that will be used throughout the system for
|
|
|
|
// when specifying what kind of Method to send or work with.
|
|
|
|
const (
|
2021-08-16 11:01:12 +00:00
|
|
|
// Initial parent method used to start other processes.
|
2021-04-08 11:43:47 +00:00
|
|
|
REQInitial Method = "REQInitial"
|
2021-09-20 04:40:34 +00:00
|
|
|
// Get a list of all the running processes.
|
|
|
|
REQOpProcessList Method = "REQOpProcessList"
|
|
|
|
// Start up a process.
|
|
|
|
REQOpProcessStart Method = "REQOpProcessStart"
|
2021-09-20 09:53:17 +00:00
|
|
|
// Stop up a process.
|
|
|
|
REQOpProcessStop Method = "REQOpProcessStop"
|
2021-03-11 16:14:43 +00:00
|
|
|
// Execute a CLI command in for example bash or cmd.
|
|
|
|
// This is an event type, where a message will be sent to a
|
|
|
|
// node with the command to execute and an ACK will be replied
|
|
|
|
// if it was delivered succesfully. The output of the command
|
|
|
|
// ran will be delivered back to the node where it was initiated
|
|
|
|
// as a new message.
|
|
|
|
// The data field is a slice of strings where the first string
|
|
|
|
// value should be the command, and the following the arguments.
|
2021-04-04 09:19:17 +00:00
|
|
|
REQCliCommand Method = "REQCliCommand"
|
2021-09-17 08:17:10 +00:00
|
|
|
// REQCliCommandCont same as normal Cli command, but can be used
|
2021-06-08 18:52:45 +00:00
|
|
|
// when running a command that will take longer time and you want
|
|
|
|
// to send the output of the command continually back as it is
|
2021-09-17 08:17:10 +00:00
|
|
|
// generated, and not wait until the command is finished.
|
|
|
|
REQCliCommandCont Method = "REQCliCommandCont"
|
2021-04-05 06:17:04 +00:00
|
|
|
// Send text to be logged to the console.
|
2021-03-11 16:14:43 +00:00
|
|
|
// The data field is a slice of strings where the first string
|
|
|
|
// value should be the command, and the following the arguments.
|
2021-04-13 15:22:25 +00:00
|
|
|
REQToConsole Method = "REQToConsole"
|
2021-04-05 06:17:04 +00:00
|
|
|
// Send text logging to some host by appending the output to a
|
|
|
|
// file, if the file do not exist we create it.
|
2021-03-11 16:14:43 +00:00
|
|
|
// A file with the full subject+hostName will be created on
|
|
|
|
// the receiving end.
|
|
|
|
// The data field is a slice of strings where the values of the
|
|
|
|
// slice will be written to the log file.
|
2021-04-13 13:54:04 +00:00
|
|
|
REQToFileAppend Method = "REQToFileAppend"
|
2021-04-06 12:05:47 +00:00
|
|
|
// Send text to some host by overwriting the existing content of
|
|
|
|
// the fileoutput to a file. If the file do not exist we create it.
|
|
|
|
// A file with the full subject+hostName will be created on
|
|
|
|
// the receiving end.
|
|
|
|
// The data field is a slice of strings where the values of the
|
|
|
|
// slice will be written to the file.
|
2021-04-13 15:15:13 +00:00
|
|
|
REQToFile Method = "REQToFile"
|
2022-03-04 14:02:43 +00:00
|
|
|
// REQToFileNACK same as REQToFile but NACK.
|
|
|
|
REQToFileNACK Method = "REQToFileNACK"
|
2022-06-14 05:05:38 +00:00
|
|
|
// Initiated by the user.
|
2022-06-09 03:29:41 +00:00
|
|
|
REQCopySrc Method = "REQCopySrc"
|
2022-06-14 05:05:38 +00:00
|
|
|
// Initial request for file copying.
|
|
|
|
// Generated by the source to send initial information to the destination.
|
2022-06-09 03:29:41 +00:00
|
|
|
REQCopyDst Method = "REQCopyDst"
|
2022-06-14 05:05:38 +00:00
|
|
|
// Read the source file to be copied to some node.
|
2022-06-14 05:09:20 +00:00
|
|
|
REQSUBCopySrc Method = "REQSUBCopySrc"
|
2022-06-14 05:05:38 +00:00
|
|
|
// Write the destination copied to some node.
|
2022-06-14 05:09:20 +00:00
|
|
|
REQSUBCopyDst Method = "REQSUBCopyDst"
|
2022-06-09 03:29:41 +00:00
|
|
|
// Send Hello I'm here message.
|
2021-04-06 03:46:07 +00:00
|
|
|
REQHello Method = "REQHello"
|
2021-03-11 16:14:43 +00:00
|
|
|
// Error log methods to centralError node.
|
2021-04-06 05:56:49 +00:00
|
|
|
REQErrorLog Method = "REQErrorLog"
|
2021-04-06 17:42:03 +00:00
|
|
|
// Http Get
|
|
|
|
REQHttpGet Method = "REQHttpGet"
|
2022-02-11 06:27:51 +00:00
|
|
|
// Http Get Scheduled
|
|
|
|
// The second element of the MethodArgs slice holds the timer defined in seconds.
|
|
|
|
REQHttpGetScheduled Method = "REQHttpGetScheduled"
|
2021-04-13 09:28:52 +00:00
|
|
|
// Tail file
|
|
|
|
REQTailFile Method = "REQTailFile"
|
2022-01-05 07:47:06 +00:00
|
|
|
// REQNone is used when there should be no reply.
|
|
|
|
REQNone Method = "REQNone"
|
2022-05-22 04:36:02 +00:00
|
|
|
// REQTest is used only for testing to be able to grab the output
|
|
|
|
// of messages.
|
|
|
|
REQTest Method = "REQTest"
|
|
|
|
|
2022-04-07 07:34:06 +00:00
|
|
|
// REQPublicKey will get the public ed25519 key from a node.
|
2022-02-08 10:49:32 +00:00
|
|
|
REQPublicKey Method = "REQPublicKey"
|
2022-05-24 10:00:38 +00:00
|
|
|
// REQKeysRequestUpdate will get all the public keys from central if an update is available.
|
2022-05-24 05:21:48 +00:00
|
|
|
REQKeysRequestUpdate Method = "REQKeysRequestUpdate"
|
|
|
|
// REQKeysDeliverUpdate will deliver the public from central to a node.
|
|
|
|
REQKeysDeliverUpdate Method = "REQKeysDeliverUpdate"
|
|
|
|
// REQKeysAllow
|
|
|
|
REQKeysAllow Method = "REQKeysAllow"
|
2022-06-01 05:29:25 +00:00
|
|
|
// REQKeysDelete
|
|
|
|
REQKeysDelete Method = "REQKeysDelete"
|
2022-05-22 04:36:02 +00:00
|
|
|
|
2022-05-24 10:00:38 +00:00
|
|
|
// REQAclRequestUpdate will get all node acl's from central if an update is available.
|
|
|
|
REQAclRequestUpdate Method = "REQAclRequestUpdate"
|
2022-05-24 13:51:36 +00:00
|
|
|
// REQAclDeliverUpdate will deliver the acl from central to a node.
|
|
|
|
REQAclDeliverUpdate Method = "REQAclDeliverUpdate"
|
2022-05-24 10:00:38 +00:00
|
|
|
|
2022-05-18 12:43:35 +00:00
|
|
|
// REQAclAddCommand
|
|
|
|
REQAclAddCommand = "REQAclAddCommand"
|
|
|
|
// REQAclDeleteCommand
|
|
|
|
REQAclDeleteCommand = "REQAclDeleteCommand"
|
2022-05-19 19:35:14 +00:00
|
|
|
// REQAclDeleteSource
|
|
|
|
REQAclDeleteSource = "REQAclDeleteSource"
|
2022-05-19 20:19:22 +00:00
|
|
|
// REQGroupNodesAddNode
|
|
|
|
REQAclGroupNodesAddNode = "REQAclGroupNodesAddNode"
|
|
|
|
// REQAclGroupNodesDeleteNode
|
|
|
|
REQAclGroupNodesDeleteNode = "REQAclGroupNodesDeleteNode"
|
2022-05-20 03:18:26 +00:00
|
|
|
// REQAclGroupNodesDeleteGroup
|
|
|
|
REQAclGroupNodesDeleteGroup = "REQAclGroupNodesDeleteGroup"
|
2022-05-20 03:59:34 +00:00
|
|
|
// REQAclGroupCommandsAddCommand
|
|
|
|
REQAclGroupCommandsAddCommand = "REQAclGroupCommandsAddCommand"
|
2022-05-20 04:27:46 +00:00
|
|
|
// REQAclGroupCommandsDeleteCommand
|
|
|
|
REQAclGroupCommandsDeleteCommand = "REQAclGroupCommandsDeleteCommand"
|
2022-05-20 11:56:17 +00:00
|
|
|
// REQAclGroupCommandsDeleteGroup
|
|
|
|
REQAclGroupCommandsDeleteGroup = "REQAclGroupCommandsDeleteGroup"
|
2022-05-21 05:09:35 +00:00
|
|
|
// REQAclExport
|
|
|
|
REQAclExport = "REQAclExport"
|
2022-05-21 05:26:36 +00:00
|
|
|
// REQAclImport
|
|
|
|
REQAclImport = "REQAclImport"
|
2021-03-01 16:08:40 +00:00
|
|
|
)
|
2021-02-11 14:39:19 +00:00
|
|
|
|
2023-10-04 20:58:42 +00:00
|
|
|
type HandlerFunc func(proc process, message Message, node string) ([]byte, error)
|
|
|
|
|
2021-03-01 16:08:40 +00:00
|
|
|
// The mapping of all the method constants specified, what type
|
2023-10-04 20:58:42 +00:00
|
|
|
// it references.
|
2022-05-20 11:56:17 +00:00
|
|
|
// The primary use of this table is that messages are not able to
|
|
|
|
// pass the actual type of the request since it is sent as a string,
|
|
|
|
// so we use the below table to find the actual type based on that
|
|
|
|
// string type.
|
2021-02-11 14:39:19 +00:00
|
|
|
func (m Method) GetMethodsAvailable() MethodsAvailable {
|
2021-04-03 05:14:39 +00:00
|
|
|
|
2021-02-11 14:39:19 +00:00
|
|
|
ma := MethodsAvailable{
|
2023-10-04 20:58:42 +00:00
|
|
|
Methodhandlers: map[Method]HandlerFunc{
|
|
|
|
REQInitial: HandlerFunc(methodREQInitial),
|
|
|
|
REQOpProcessList: HandlerFunc(methodREQOpProcessList),
|
|
|
|
REQOpProcessStart: HandlerFunc(methodREQOpProcessStart),
|
|
|
|
REQOpProcessStop: HandlerFunc(methodREQOpProcessStop),
|
|
|
|
REQCliCommand: HandlerFunc(methodREQCliCommand),
|
|
|
|
REQCliCommandCont: HandlerFunc(methodREQCliCommandCont),
|
|
|
|
REQToConsole: HandlerFunc(methodREQToConsole),
|
|
|
|
REQToFileAppend: HandlerFunc(methodREQToFileAppend),
|
|
|
|
REQToFile: HandlerFunc(methodREQToFile),
|
|
|
|
REQToFileNACK: HandlerFunc(methodREQToFile),
|
|
|
|
REQCopySrc: HandlerFunc(methodREQCopySrc),
|
|
|
|
REQCopyDst: HandlerFunc(methodREQCopyDst),
|
|
|
|
REQSUBCopySrc: HandlerFunc(methodREQSUB),
|
|
|
|
REQSUBCopyDst: HandlerFunc(methodREQSUB),
|
|
|
|
REQHello: HandlerFunc(methodREQHello),
|
|
|
|
REQErrorLog: HandlerFunc(methodREQErrorLog),
|
|
|
|
REQHttpGet: HandlerFunc(methodREQHttpGet),
|
|
|
|
REQHttpGetScheduled: HandlerFunc(methodREQHttpGetScheduled),
|
|
|
|
REQTailFile: HandlerFunc(methodREQTailFile),
|
|
|
|
REQPublicKey: HandlerFunc(methodREQPublicKey),
|
|
|
|
REQKeysRequestUpdate: HandlerFunc(methodREQKeysRequestUpdate),
|
|
|
|
REQKeysDeliverUpdate: HandlerFunc(methodREQKeysDeliverUpdate),
|
|
|
|
REQKeysAllow: HandlerFunc(methodREQKeysAllow),
|
|
|
|
REQKeysDelete: HandlerFunc(methodREQKeysDelete),
|
|
|
|
|
|
|
|
REQAclRequestUpdate: HandlerFunc(methodREQAclRequestUpdate),
|
|
|
|
REQAclDeliverUpdate: HandlerFunc(methodREQAclDeliverUpdate),
|
|
|
|
|
|
|
|
REQAclAddCommand: HandlerFunc(methodREQAclAddCommand),
|
|
|
|
REQAclDeleteCommand: HandlerFunc(methodREQAclDeleteCommand),
|
|
|
|
REQAclDeleteSource: HandlerFunc(methodREQAclDeleteSource),
|
|
|
|
REQAclGroupNodesAddNode: HandlerFunc(methodREQAclGroupNodesAddNode),
|
|
|
|
REQAclGroupNodesDeleteNode: HandlerFunc(methodREQAclGroupNodesDeleteNode),
|
|
|
|
REQAclGroupNodesDeleteGroup: HandlerFunc(methodREQAclGroupNodesDeleteGroup),
|
|
|
|
REQAclGroupCommandsAddCommand: HandlerFunc(methodREQAclGroupCommandsAddCommand),
|
|
|
|
REQAclGroupCommandsDeleteCommand: HandlerFunc(methodREQAclGroupCommandsDeleteCommand),
|
|
|
|
REQAclGroupCommandsDeleteGroup: HandlerFunc(methodREQAclGroupCommandsDeleteGroup),
|
|
|
|
REQAclExport: HandlerFunc(methodREQAclExport),
|
|
|
|
REQAclImport: HandlerFunc(methodREQAclImport),
|
|
|
|
REQTest: HandlerFunc(methodREQTest),
|
2021-02-11 14:39:19 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return ma
|
|
|
|
}
|
|
|
|
|
2021-03-01 16:08:40 +00:00
|
|
|
// getHandler will check the methodsAvailable map, and return the
|
|
|
|
// method handler for the method given
|
|
|
|
// as input argument.
|
2023-10-04 20:58:42 +00:00
|
|
|
func (m Method) getHandler(method Method) HandlerFunc {
|
2021-03-01 16:08:40 +00:00
|
|
|
ma := m.GetMethodsAvailable()
|
2022-06-14 06:45:34 +00:00
|
|
|
mh, _ := ma.CheckIfExists(method)
|
|
|
|
// mh := ma.Methodhandlers[method]
|
2021-03-01 16:08:40 +00:00
|
|
|
|
|
|
|
return mh
|
|
|
|
}
|
2021-02-11 14:39:19 +00:00
|
|
|
|
2022-01-26 14:35:31 +00:00
|
|
|
// getContextForMethodTimeout, will return a context with cancel function
|
|
|
|
// with the timeout set to the method timeout in the message.
|
|
|
|
// If the value of timeout is set to -1, we don't want it to stop, so we
|
|
|
|
// return a context with a timeout set to 200 years.
|
|
|
|
func getContextForMethodTimeout(ctx context.Context, message Message) (context.Context, context.CancelFunc) {
|
|
|
|
// If methodTimeout == -1, which means we don't want a timeout, set the
|
|
|
|
// time out to 200 years.
|
|
|
|
if message.MethodTimeout == -1 {
|
|
|
|
return context.WithTimeout(ctx, time.Hour*time.Duration(8760*200))
|
|
|
|
}
|
|
|
|
|
|
|
|
return context.WithTimeout(ctx, time.Second*time.Duration(message.MethodTimeout))
|
|
|
|
}
|
2021-04-08 11:43:47 +00:00
|
|
|
|
|
|
|
// ----
|
|
|
|
|
2021-08-16 11:01:12 +00:00
|
|
|
// Initial parent method used to start other processes.
|
2023-10-04 20:58:42 +00:00
|
|
|
func methodREQInitial(proc process, message Message, node string) ([]byte, error) {
|
2021-04-08 11:43:47 +00:00
|
|
|
// proc.procFuncCh <- message
|
|
|
|
ackMsg := []byte("confirmed from: " + node + ": " + fmt.Sprint(message.ID))
|
|
|
|
return ackMsg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----
|
2021-08-16 11:01:12 +00:00
|
|
|
|
2022-06-14 05:05:38 +00:00
|
|
|
// place holder method used for sub processes.
|
|
|
|
// Methods used in sub processes are defined within the the requests
|
|
|
|
// they are spawned in, so this type is primarily for us to use the
|
|
|
|
// same logic with sub process requests as we do with normal requests.
|
2023-10-04 20:58:42 +00:00
|
|
|
func methodREQSUB(proc process, message Message, node string) ([]byte, error) {
|
2022-06-14 05:05:38 +00:00
|
|
|
// proc.procFuncCh <- message
|
|
|
|
ackMsg := []byte("confirmed from: " + node + ": " + fmt.Sprint(message.ID))
|
|
|
|
return ackMsg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----
|
|
|
|
|
2021-08-16 11:01:12 +00:00
|
|
|
// MethodsAvailable holds a map of all the different method types and the
|
|
|
|
// associated handler to that method type.
|
2021-02-11 14:39:19 +00:00
|
|
|
type MethodsAvailable struct {
|
2023-10-04 20:58:42 +00:00
|
|
|
Methodhandlers map[Method]HandlerFunc
|
2021-02-11 14:39:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if exists will check if the Method is defined. If true the bool
|
|
|
|
// value will be set to true, and the methodHandler function for that type
|
|
|
|
// will be returned.
|
2023-10-04 20:58:42 +00:00
|
|
|
func (ma MethodsAvailable) CheckIfExists(m Method) (HandlerFunc, bool) {
|
2022-06-14 05:05:38 +00:00
|
|
|
// First check if it is a sub process.
|
2022-06-14 05:09:20 +00:00
|
|
|
if strings.HasPrefix(string(m), "REQSUB") {
|
2022-06-14 05:05:38 +00:00
|
|
|
// Strip of the uuid after the method name.
|
|
|
|
sp := strings.Split(string(m), ".")
|
|
|
|
m = Method(sp[0])
|
|
|
|
}
|
|
|
|
|
2021-06-29 06:21:42 +00:00
|
|
|
mFunc, ok := ma.Methodhandlers[m]
|
2021-02-11 14:39:19 +00:00
|
|
|
if ok {
|
|
|
|
return mFunc, true
|
|
|
|
} else {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-22 03:24:15 +00:00
|
|
|
// newReplyMessage will create and send a reply message back to where
|
|
|
|
// the original provided message came from. The primary use of this
|
|
|
|
// function is to report back to a node who sent a message with the
|
|
|
|
// result of the request method of the original message.
|
|
|
|
//
|
|
|
|
// The method to use for the reply message when reporting back should
|
|
|
|
// be specified within a message in the replyMethod field. We will
|
2021-08-16 11:01:12 +00:00
|
|
|
// pick up that value here, and use it as the method for the new
|
|
|
|
// request message. If no replyMethod is set we default to the
|
|
|
|
// REQToFileAppend method type.
|
2021-11-22 03:24:15 +00:00
|
|
|
//
|
|
|
|
// There will also be a copy of the original message put in the
|
|
|
|
// previousMessage field. For the copy of the original message the data
|
|
|
|
// field will be set to nil before the whole message is put in the
|
|
|
|
// previousMessage field so we don't copy around the original data in
|
|
|
|
// the reply response when it is not needed anymore.
|
2021-08-16 11:01:12 +00:00
|
|
|
func newReplyMessage(proc process, message Message, outData []byte) {
|
2022-01-05 07:47:06 +00:00
|
|
|
// If REQNone is specified, we don't want to send a reply message
|
|
|
|
// so we silently just return without sending anything.
|
2023-01-10 08:29:24 +00:00
|
|
|
if message.ReplyMethod == "REQNone" || message.IsReply {
|
2022-01-05 07:47:06 +00:00
|
|
|
return
|
|
|
|
}
|
2021-08-16 11:01:12 +00:00
|
|
|
|
|
|
|
// If no replyMethod is set we default to writing to writing to
|
|
|
|
// a log file.
|
|
|
|
if message.ReplyMethod == "" {
|
|
|
|
message.ReplyMethod = REQToFileAppend
|
|
|
|
}
|
|
|
|
|
2021-11-22 03:24:15 +00:00
|
|
|
// Make a copy of the message as it is right now to use
|
|
|
|
// in the previous message field, but set the data field
|
|
|
|
// to nil so we don't copy around the original data when
|
|
|
|
// we don't need to for the reply message.
|
|
|
|
thisMsg := message
|
|
|
|
thisMsg.Data = nil
|
|
|
|
|
2021-08-16 11:01:12 +00:00
|
|
|
// Create a new message for the reply, and put it on the
|
|
|
|
// ringbuffer to be published.
|
|
|
|
newMsg := Message{
|
2022-06-22 12:32:58 +00:00
|
|
|
ToNode: message.FromNode,
|
2022-06-22 12:43:01 +00:00
|
|
|
// The ToNodes field is not needed since it is only a concept that exists when messages
|
2022-06-22 12:32:58 +00:00
|
|
|
// are injected f.ex. on a socket, and there they are directly converted into separate
|
|
|
|
// node messages. With other words a message in the system are only for single nodes,
|
|
|
|
// so we don't have to worry about the ToNodes field when creating reply messages.
|
2021-09-22 13:25:40 +00:00
|
|
|
FromNode: message.ToNode,
|
2022-01-31 07:49:46 +00:00
|
|
|
Data: outData,
|
2021-09-16 10:37:46 +00:00
|
|
|
Method: message.ReplyMethod,
|
|
|
|
MethodArgs: message.ReplyMethodArgs,
|
|
|
|
MethodTimeout: message.ReplyMethodTimeout,
|
2021-09-22 14:08:55 +00:00
|
|
|
IsReply: true,
|
2022-06-16 22:39:15 +00:00
|
|
|
RetryWait: message.RetryWait,
|
2021-09-16 10:37:46 +00:00
|
|
|
ACKTimeout: message.ReplyACKTimeout,
|
|
|
|
Retries: message.ReplyRetries,
|
2021-09-22 13:25:40 +00:00
|
|
|
Directory: message.Directory,
|
|
|
|
FileName: message.FileName,
|
2021-08-16 11:01:12 +00:00
|
|
|
|
|
|
|
// Put in a copy of the initial request message, so we can use it's properties if
|
|
|
|
// needed to for example create the file structure naming on the subscriber.
|
2021-11-22 03:24:15 +00:00
|
|
|
PreviousMessage: &thisMsg,
|
2021-08-16 11:01:12 +00:00
|
|
|
}
|
|
|
|
|
2021-08-25 06:56:44 +00:00
|
|
|
sam, err := newSubjectAndMessage(newMsg)
|
2021-08-16 11:01:12 +00:00
|
|
|
if err != nil {
|
|
|
|
// In theory the system should drop the message before it reaches here.
|
2021-09-23 06:19:53 +00:00
|
|
|
er := fmt.Errorf("error: newSubjectAndMessage : %v, message: %v", err, message)
|
2023-01-11 07:38:15 +00:00
|
|
|
proc.errorKernel.errSend(proc, message, er, logError)
|
2021-08-16 11:01:12 +00:00
|
|
|
}
|
2022-01-03 09:40:27 +00:00
|
|
|
|
2021-08-25 06:56:44 +00:00
|
|
|
proc.toRingbufferCh <- []subjectAndMessage{sam}
|
2021-08-16 11:01:12 +00:00
|
|
|
}
|
|
|
|
|
2021-09-07 04:24:21 +00:00
|
|
|
// selectFileNaming will figure out the correct naming of the file
|
|
|
|
// structure to use for the reply data.
|
|
|
|
// It will return the filename, and the tree structure for the folders
|
|
|
|
// to create.
|
|
|
|
func selectFileNaming(message Message, proc process) (string, string) {
|
|
|
|
var fileName string
|
2022-06-22 09:03:59 +00:00
|
|
|
// As default we set the folder tree to what is specified in the
|
|
|
|
// message.Directory field. If we don't want that in the checks
|
|
|
|
// done later we then replace the value with what we want.
|
|
|
|
folderTree := message.Directory
|
|
|
|
|
|
|
|
checkPrefix := func(s string) bool {
|
|
|
|
if strings.HasPrefix(s, "./") || strings.HasPrefix(s, "/") {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
2021-09-07 04:24:21 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
case message.PreviousMessage == nil:
|
|
|
|
// If this was a direct request there are no previous message to take
|
|
|
|
// information from, so we use the one that are in the current mesage.
|
|
|
|
fileName = message.FileName
|
2022-06-22 09:03:59 +00:00
|
|
|
if !checkPrefix(message.Directory) {
|
|
|
|
folderTree = filepath.Join(proc.configuration.SubscribersDataFolder, message.Directory, string(message.ToNode))
|
|
|
|
}
|
2021-09-07 04:24:21 +00:00
|
|
|
case message.PreviousMessage.ToNode != "":
|
|
|
|
fileName = message.PreviousMessage.FileName
|
2022-06-22 09:03:59 +00:00
|
|
|
if !checkPrefix(message.PreviousMessage.Directory) {
|
|
|
|
folderTree = filepath.Join(proc.configuration.SubscribersDataFolder, message.PreviousMessage.Directory, string(message.PreviousMessage.ToNode))
|
|
|
|
}
|
2021-09-07 04:24:21 +00:00
|
|
|
case message.PreviousMessage.ToNode == "":
|
|
|
|
fileName = message.PreviousMessage.FileName
|
2022-06-22 09:03:59 +00:00
|
|
|
if !checkPrefix(message.PreviousMessage.Directory) {
|
|
|
|
folderTree = filepath.Join(proc.configuration.SubscribersDataFolder, message.PreviousMessage.Directory, string(message.FromNode))
|
|
|
|
}
|
2021-09-07 04:24:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return fileName, folderTree
|
|
|
|
}
|
|
|
|
|
2021-02-18 13:27:53 +00:00
|
|
|
// ------------------------------------------------------------
|
|
|
|
// Subscriber method handlers
|
2021-02-11 14:39:19 +00:00
|
|
|
// ------------------------------------------------------------
|