Full documentation update and minor changes
-the add_mod command now requires the -mod_path argument as it should. -the session now filter out bad NEW_CMD frames based on bad command names and incorrect frame sizes. -modules running in list mode can now send ERR frames to the session to log error messages to the host database.
This commit is contained in:
parent
72d57a0b10
commit
e7ea316bc0
184
docs/Async.md
184
docs/Async.md
|
@ -1,184 +0,0 @@
|
|||
### 6.1 Async Commands ###
|
||||
|
||||
An async command is a virtual command that the host can use to send data to the client at any time while connected to the host. As the name implies, the occurance of a client receiving data from an async command is not always the result of running a regular command in the current session. This can occur for example when information in your account is changed by another client connected to the host; your client would not know about this change until an async command is sent notify it of the change. These commands cannot be called directly by a client or even a module command object.
|
||||
|
||||
Async commands are not only used send data to the client but also used internally within the host to help session objects operating in different processes to communicate with each other. Some async commands in fact are considered internal only because the client should never see any data come from them at anytime.
|
||||
|
||||
These are considered "virtual" commands because there is no defined command objects attached to them. Instead, async commands are best identified by command id values 1-255. Here is a list of currently "defined" async commands:
|
||||
|
||||
```
|
||||
#define ASYNC_RDY 1
|
||||
#define ASYNC_SYS_MSG 2
|
||||
#define ASYNC_EXE_CRASH 3
|
||||
#define ASYNC_EXIT 4 // internal only
|
||||
#define ASYNC_CAST 5 // internal only
|
||||
#define ASYNC_MAXSES 6 // internal only
|
||||
#define ASYNC_LOGOUT 7 // internal only
|
||||
#define ASYNC_USER_DELETED 8
|
||||
#define ASYNC_GROUP_RENAMED 9 // internal only
|
||||
#define ASYNC_DISP_RENAMED 10 // internal only
|
||||
#define ASYNC_GRP_TRANS 11 // internal only
|
||||
#define ASYNC_USER_GROUP_CHANGED 12 // internal only
|
||||
#define ASYNC_CMD_RANKS_CHANGED 13 // internal only
|
||||
#define ASYNC_RESTART 14 // internal only
|
||||
#define ASYNC_ENABLE_MOD 15 // internal only
|
||||
#define ASYNC_DISABLE_MOD 16 // internal only
|
||||
#define ASYNC_GROUP_UPDATED 17 // internal only
|
||||
#define ASYNC_END_SESSION 18 // internal only
|
||||
#define ASYNC_USER_LOGIN 19 // internal only
|
||||
#define ASYNC_RESTORE_AUTH 20 // internal only
|
||||
#define ASYNC_TO_PEER 21
|
||||
#define ASYNC_LIMITED_CAST 22
|
||||
#define ASYNC_RW_MY_INFO 23 // internal only
|
||||
#define ASYNC_P2P 24
|
||||
#define ASYNC_CLOSE_P2P 25 // internal only
|
||||
#define ASYNC_NEW_CH_MEMBER 26
|
||||
#define ASYNC_DEL_CH 27
|
||||
#define ASYNC_RENAME_CH 28
|
||||
#define ASYNC_CH_ACT_FLAG 29
|
||||
#define ASYNC_NEW_SUB_CH 30
|
||||
#define ASYNC_RM_SUB_CH 31
|
||||
#define ASYNC_RENAME_SUB_CH 32
|
||||
#define ASYNC_INVITED_TO_CH 33
|
||||
#define ASYNC_RM_CH_MEMBER 34
|
||||
#define ASYNC_INVITE_ACCEPTED 35
|
||||
#define ASYNC_MEM_LEVEL_CHANGED 36
|
||||
#define ASYNC_SUB_CH_LEVEL_CHG 37
|
||||
#define ASYNC_ADD_RDONLY 38
|
||||
#define ASYNC_RM_RDONLY 39
|
||||
#define ASYNC_ADD_CMD 40
|
||||
#define ASYNC_RM_CMD 41
|
||||
#define ASYNC_USER_RENAMED 42
|
||||
#define ASYNC_PUBLIC_AUTH 43 // internal only
|
||||
```
|
||||
|
||||
### 6.2 Async Data ###
|
||||
|
||||
```ASYNC_RDY (1)```
|
||||
This command signals to the client that your current session is now ready to start running commands. This is usually sent after successfully setting up the tcp connection ([protocol](Protocol.md)) or after successfully recovering from a session crash. It can carry ```TEXT``` data that can be displayed directly to the user if needed.
|
||||
|
||||
```ASYNC_SYS_MSG (2)```
|
||||
This command carry ```TEXT``` or ```ERR``` data that are system messages that can be directly displayed to the user of needed. It is also used to carry ```HOST_CERT``` data during the tcp connection setup and ```MY_INFO``` when local user account information has changed.
|
||||
|
||||
```ASYNC_EXE_CRASH (3)```
|
||||
This is used to send ```ERR``` messages to the client if your session crashes or fails to setup an IPC connection for any reason.
|
||||
|
||||
```ASYNC_EXIT (4)```
|
||||
This is an internal async command that doesn't carry any data. It is used to send a ```closeServer()``` signal to the ```TCPServer``` object in the main process. This will cause it stop listing for clients, close all sessions and then close the main process.
|
||||
|
||||
```ASYNC_CAST (5)```
|
||||
This is an internal only command that carries a 54byte open sub-channels list ```wrAbleChIds``` described in section [3.4](Command_Objects.md) and an embedded mrci frame that can then be sent to clients that have any of the matching open sub-channels. It drops that sub-channel list before arriving at the client so it will apppear like a regular mrci frame of any data type.
|
||||
|
||||
```ASYNC_MAXSES (6)```
|
||||
Internal only async command that is used by internal commands to send a ```BYTES``` frame to the main process to update the maximum amount the concurrent sessions for the ```TCPServer``` object. The data itself is actually a 32bit unsigned int.
|
||||
|
||||
```ASYNC_LOGOUT (7)```
|
||||
This internal only async command doesn't carry any data. This is just used to notify the main process ```Session``` object that the user has logged out and should not attempt to restore authentication in case of a session crash. This doesn't actually do the logout.
|
||||
|
||||
```ASYNC_USER_DELETED (8)```
|
||||
This async command carry ```TEXT``` data that is the user name of the user account that was deleted from the host database. All ```Session``` objects that get this command must read and match this to the user name that is currently logged in for that object. If the user name matches, the ```Session``` object must logout and forward this to the client since the user account no longer exists.
|
||||
|
||||
```ASYNC_GROUP_RENAMED (9)```
|
||||
Internal only async command that carry ```TEXT``` command line arguments to notify all ```Session``` objects that the a host group name has changed. Example: ```-src "old_group_name" -dst "new_group_name"```. All ```Session``` objects that have matching current group names to ```old_group_name``` must update that group name to ```new_group_name``` and also send a ```ASYNC_SYS_MSG``` containing an updated ```MY_INFO```.
|
||||
|
||||
```ASYNC_DISP_RENAMED (10)```
|
||||
Internal only async command that carry ```TEXT``` command line arguments to notify all ```Session``` objects that a user has changed the display name. Example: ```-name "new_display_name" -user "user_name"```. All ```Session``` objects that have matching current user names to ```user_name``` must update the display name to ```new_display_name``` and also send a ```ASYNC_SYS_MSG``` containing an updated ```MY_INFO```.
|
||||
|
||||
```ASYNC_GRP_TRANS (11)```
|
||||
Internal only async command that carry the same ```TEXT``` command line arguments as ```ASYNC_GROUP_RENAMED``` to notify all ```Session``` objects that the all users currently in the group given in ```-src``` must be updated to the group given in ```-dst```. This triggers a ```ASYNC_SYS_MSG``` to send an updated ```MY_INFO``` and the ```Session``` object will load all the commands that the user now have access to and remove any commands that lost access due to the group change.
|
||||
|
||||
```ASYNC_USER_GROUP_CHANGED (12)```
|
||||
This is an internal only command carry ```TEXT``` command line arguments to notify all ```Session``` objects that a user's group was changed to another group. example: ```-user "user_name" -group "new_group"```. All ```Session``` objects the have the matching user name need to update it's group to ```new_group```, send a ```ASYNC_SYS_MSG``` with an updated ```MY_INFO``` and load all the commands that the user now have access to and remove any commands that lost access due to the group change.
|
||||
|
||||
```ASYNC_CMD_RANKS_CHANGED (13)```
|
||||
This internal only async commmand doesn't carry any data. Instead, it notifies all ```Session``` objects that assigned command ranks have changed. This will cause all of the ```Session``` objects to re-check the currently loaded commands and determine if it needs to remove any commands that the user no longer have access to and add any commands that the user may have gained access to.
|
||||
|
||||
```ASYNC_RESTART (14)```
|
||||
This internal only async commmand doesn't carry any data. It is used to send a ```resServer()``` signal to the ```TCPServer``` object in the main process. This will cause it stop listing for clients, close all sessions, reload the host settings and start listening for clients again.
|
||||
|
||||
```ASYNC_ENABLE_MOD (15)```
|
||||
This internal only async commmand carry ```TEXT``` of a module name. All ```Session``` objects that receive this will then load the requested module.
|
||||
|
||||
```ASYNC_DISABLE_MOD (16)```
|
||||
This internal only async commmand carry ```TEXT``` of a module name. All ```Session``` objects that receive this will delete all commands associated with the with this module and then unload it.
|
||||
|
||||
```ASYNC_GROUP_UPDATED (17)```
|
||||
This is an internal only command that carry ```TEXT``` command line arguments to notify all ```Session``` objects that a group's host rank has changed. Example: ```-name "group_name" -rank 2```. All ```Session``` object that have matching group names to ```group_name``` will need to update the host rank to ```2```. When the session's host rank to adjusted this way, the session will need to re-check the currently loaded commands and determine if it needs to remove any commands that the user no longer have access to and add any commands that the user may have gained access to.
|
||||
|
||||
```ASYNC_END_SESSION (18)```
|
||||
This internal only async commmand doesn't carry any data. It is used to notify the main process that the ```CmdExecutor``` object is requesting to close the session. The main process ```Session``` object will then signal the slave process to close and close the tcp session.
|
||||
|
||||
```ASYNC_USER_LOGIN (19)```
|
||||
This is an internal only command that carry ```PRIV_IPC``` data containing the 256bit Keccak hash user id of the user that has successfully logged in. This is used by the ```CmdExecutor``` object to notify the main process ```Session``` object of the current user associated with the current session. The main process ```Session``` object will use this information to restore the user authorization in case of a session crash.
|
||||
|
||||
```ASYNC_RESTORE_AUTH (20)```
|
||||
This is an internal only command that carry ```PRIV_IPC``` data containing the 256bit Keccak hash user id of a user that has successfully logged in with the current session. It is used by the ```Session``` object in the main process to tell the ```CmdExecutor``` object in the slave process to authorize the user without a password. This is only used when attempting to restore the session from a crash and a user was logged in at the time.
|
||||
|
||||
```ASYNC_TO_PEER (21)```
|
||||
This is an async command that carry an embedded mrci frame directly to/from peer sessions without any restrictions. It is prepended with the 224bit sha3 hash of the target session id; however, it drops that session id before arriving at the client so it will apppear as a regular mrci frame of any data type. Users should not be given direct access to this for security reasons.
|
||||
|
||||
```ASYNC_LIMITED_CAST (22)```
|
||||
This operate exactly like ```ASYNC_CAST``` except only sessions with active update sub-channels will respond to it.
|
||||
|
||||
```ASYNC_RW_MY_INFO (23)```
|
||||
This internal only async command carry ```TEXT``` data of the user name to tell all ```Session``` objects that have the matching user name to send an update ```MY_INFO``` to the client. This is useful for when a host admin force updates user information of other lesser privileged users to make their clients aware of the changes.
|
||||
|
||||
```ASYNC_P2P (24)```
|
||||
This async command carry an embedded mrci frame directly to/from peer sessions following the p2p negotiation process as described in [Type_IDs](Type_IDs.md), section 4.2 at the P2P specific data types. It prepends the 224bit sha3 hash of the destination session id and source session id; however, it drops the destination id and source id for just the P2P specific data types before arriving at the client. For all other data types (if a p2p connection is estabished), the source id is prepend-moved to the payload of the mrci frame before arriving at the client.
|
||||
|
||||
```ASYNC_CLOSE_P2P (25)```
|
||||
This internal only async command carry a 224bit sha3 hash session id of a session that is about to close. This notifies all ```CmdExecutor``` objects that have matching hashes in ```p2pAccepted``` and ```p2pPending``` (section [3.4](Command_Objects.md)) to remove them now. It also triggers a ```ASYNC_P2P``` to send a ```P2P_CLOSE``` for the session id in question so the clients can also be made aware of this.
|
||||
|
||||
```ASYNC_NEW_CH_MEMBER (26)```
|
||||
```TEXT``` command line arguments when a new channel is created and the user that created it is added as the channel owner. Example: ```-user "user_name" -ch_name "new_channel" -ch_id 334 -level 1```.
|
||||
|
||||
```ASYNC_DEL_CH (27)```
|
||||
```TEXT``` command line arguments when a channel is deleted. Example: ```-ch_name "channel_name" -ch_id 426```. The host will automatically close all sub-channels related to this channel for all sessions that have them open.
|
||||
|
||||
```ASYNC_RENAME_CH (28)```
|
||||
```TEXT``` command line arguments when a channel is renamed. Example: ```-ch_name "old_name" -new_name "new_name"```.
|
||||
|
||||
```ASYNC_CH_ACT_FLAG (29)```
|
||||
```TEXT``` command line arguments when sub-channel's active update flag has been updated. Example: ```-ch_name "channel_name" -sub_name "sub_channel" -state 1```. (```-state``` 1 is true or ```-state``` 0 is false).
|
||||
|
||||
```ASYNC_NEW_SUB_CH (30)```
|
||||
```TEXT``` command line arguments when a new sub-channel is created. Example: ```-ch_name "channel_name" -sub_name "new_sub_channel" -ch_id 987 -sub_id 5 -level 2```.
|
||||
|
||||
```ASYNC_RM_SUB_CH (31)```
|
||||
```TEXT``` command line arguments when a sub-channel is deleted. Example: ```-ch_name "channel_name" -sub_name "sub_channel" -ch_id 987 -sub_id 5```. The host will automatically close this sub-channel for sessions that currently have it open.
|
||||
|
||||
```ASYNC_RENAME_SUB_CH (32)```
|
||||
```TEXT``` command line arguments when a sub-channel is renamed. Example: ```-ch_name "channel_name" -sub_name "sub_channel" -new_name "new_sub_name"```.
|
||||
|
||||
```ASYNC_INVITED_TO_CH (33)```
|
||||
```TEXT``` command line arguments when a new user is invited to join a channel. Example: ```-ch_name "channel_name" -user "user_name"```.
|
||||
|
||||
```ASYNC_RM_CH_MEMBER (34)```
|
||||
```TEXT``` command line arguments when a user is kicked from a channel, uninvited or has left the channel. Example: ```-ch_name "channel_name" -user "user_name" -ch_id 746```.
|
||||
|
||||
```ASYNC_INVITE_ACCEPTED (35)```
|
||||
```TEXT``` command line arguments when a user that was previously invite to join the channel has accepted the invite and should now be considered full member of the channel starting off at level ```REGULAR```. Example: ```-ch_name "channel_name" -user "user_name"```.
|
||||
|
||||
```ASYNC_MEM_LEVEL_CHANGED (36)```
|
||||
```TEXT``` command line arguments when a channel member's privilege level is changed. Example: ```-ch_name "channel_name" -user "user_name" -ch_id 774 -level 2```. The host automatically closes all sub-channels related to the channel for the affected user. It will be will up to the client to re-open the sub-channel(s) if the user still have access to it/them.
|
||||
|
||||
```ASYNC_SUB_CH_LEVEL_CHG (37)```
|
||||
```TEXT``` command line arguments when a sub-channel's lowest level of access is changed. Example: ```-ch_name "channel_name" -sub_name "sub_channel" -level 3 -ch_id 645 -sub_id 5```. The host will automatically close this sub-channel for sessions that currently have it open. It will be up to the client to reopen it if the current user still have access to it.
|
||||
|
||||
```ASYNC_ADD_RDONLY (38)```
|
||||
```TEXT``` command line arguments when a read only flag is added to a sub-channel's access level. Example: ```-ch_name "channel_name" -sub_id 5 -level 4```. The host will automatically close this sub-channel for sessions that currently have it open. It will be up to the client to reopen it if the current user still have access to it.
|
||||
|
||||
```ASYNC_RM_RDONLY (39)```
|
||||
```TEXT``` command line arguments when a read only flag is removed from a sub-channel's access level. Example: ```-ch_name "channel_name" -sub_id 5 -level 4```. The host will automatically close this sub-channel for sessions that currently have it open. It will be up to the client to reopen it if the current user still have access to it.
|
||||
|
||||
```ASYNC_ADD_CMD (40)```
|
||||
This async command carry ```NEW_CMD``` when the session's ```CmdExecutor``` loads a new command object and wants to notify the client of it.
|
||||
|
||||
```ASYNC_RM_CMD (41)```
|
||||
This async command carry ```CMD_ID``` when the session's ```CmdExecutor``` deletes a command object and wants to notify the client of it.
|
||||
|
||||
```ASYNC_USER_RENAMED (42)```
|
||||
```TEXT``` command line arguments when a user changes it's user name. Example: ```-old "old_user_name" -new_name "new_user_name"```.
|
||||
|
||||
```ASYNC_PUBLIC_AUTH (43)```
|
||||
This internal only async commmand doesn't carry any data. It just tells the ```CmdExecutor``` to load or reload commands without an authorized user so only public commands will be available until the client authorizes into a user account. This is used by the host when starting a session for the first time or if restoring the session after a crash and no user was logged in at the time.
|
|
@ -1,57 +0,0 @@
|
|||
### 2.1 Command Loaders ###
|
||||
|
||||
Every command object ([Command_Objects](Command_Objects.md)) defined in the host must have a unique command name atteched to it. Command loaders have the very simple job of creating these objects via the requested command name. The host use command names to determine if the current session is allowed to load them or not and command loaders are used to relate those command names with the command objects themselves.
|
||||
|
||||
When the host ```CmdExecutor``` determines that it can indeed load the commands based on the command names, it will then assign command ids to all command objects that were successfully built from the command loader. Each command loader can have a total of 256 command objects. Internally defined commands start at command id: 256 - 512 and module defined commands start at command id: 513 and up.
|
||||
|
||||
### 2.2 CommandLoader Class ###
|
||||
|
||||
The ```CommandLoader``` class itself defines a few virtual functions that make the command name to command object relationship possible:
|
||||
|
||||
```ExternCommand *cmdObj(QString cmdName)```
|
||||
This function is used to create the ```ExternCommand``` object associated with the command name passed by the ```QString``` parameter and return a pointer to it. If the command name is invalid, doesn't exists or fails to contruct the object for some reason, return ```nullptr```. The command object can have a parent or orphaned, just make sure it never gets deleted at any time; the host will handle that externally. It is safe to use the command loader itself as the parent.
|
||||
|
||||
```QStringList cmdList()```
|
||||
This function needs to return a ```QStringList``` of all of command names that this loader can actually load when the ```cmdObj()``` function is called. the host uses this list to enforce user access filtering of the command objects using the built in permission id system.
|
||||
|
||||
```QStringList pubCmdList()```
|
||||
This funtion needs to work the same way as ```cmdList()``` except the loader can this function to name any commands that can be accessed by un-logged in clients. aka, public commands. Note: the commands listed here must also be listed in ```cmdList()``` or else the commands will not get loaded at all.
|
||||
|
||||
```QStringList rankExemptList()```
|
||||
The loader can use this function to return a ```QStringList``` of all of command names that need to be exempt from host ranking system (section [5.2](Host_Features.md)). Commands listed here will be allowed to load/run regardless of what host rank the current user is.
|
||||
|
||||
```bool hostRevOk(quint64 importRev, quint16 hostMajor, quint16 hostMinor, quint16 hostPatch)```
|
||||
When the host calls this function, it will pass the import rev that it supports in the ```quint64``` parameter along with it's own version number in the next 3 ```quint16``` parameters. Use this function to return if this rev or host version is acceptable or not. The host will give up loading the module if it is not acceptable.
|
||||
|
||||
```quint64 rev()```
|
||||
Use this function to return the minimum import rev that the module supports. The host will decide if it is acceptable or not.
|
||||
|
||||
```QString lastError()```
|
||||
The host will call this function if a command object fails to load or if ```hostRevOk()``` returns false so it can log the error message returned by it to the host database.
|
||||
|
||||
```void modPath(QString path)```
|
||||
The host will call this function after successfully negotiating the import rev. The ```QString``` parameter passed into this will have the absolute path to the module's install directory. You can use this path to load additional files that came bundled with the module.
|
||||
|
||||
```void aboutToDelete()```
|
||||
The host will call this function before calling ```deleteLater()```. All command objects at this point should already be deleted, use this opportunity to free any resources related to the loader itself. Unload any additional lib files that the loader may have used.
|
||||
|
||||
Here's a few notes to consider when using this class:
|
||||
|
||||
* Never self delete or explicitly delete the command loader or any of the command objects it sucessfully creates at any time. The host ```CmdExecutor``` object will handle the life cycle of these objects externally.
|
||||
* Command ids are assigned in alphabetical order of the command names returned by ```cmdList()```. The command ids will remain constant as long as the command names also remain constant. All clients are recommended to rely on the ASYNC_ADD_CMD and ASYNC_RM_CMD async commands to keep track of the command ids and names (section [6.2](Async.md)).
|
||||
|
||||
### 2.3 Modules ###
|
||||
|
||||
External commands are added to the host through modules based on C/C++ style shared library files; see [this](https://doc.qt.io/qt-5/sharedlibrary.html) to learn how to create shared library files using the Qt API. The library must export a function named ```hostImport``` that returns a pointer to a new ```CommandLoader``` object when it is called by the host. Example:
|
||||
|
||||
```extern "C" LIB_EXPORT CommandLoader *hostImport();```
|
||||
|
||||
The ```CommandLoader``` returned by this function must never get deleted at anytime; the host will handle it's life cycle externally. Modules are installed using the *add_mod* internal command that supports extracting the module's library files from an archive file (.zip, .tar, etc...) or just a single library file (.so, .dll, .a, etc...).
|
||||
|
||||
In the case of an archive file, the host will extract all of the files from it while preserving the directory tree so you can bundle additional files that your module might depend on; however, the main library file that contains the ```hostImport``` function must be named 'main' (main.so, main.dll, etc..) and must be present in the root directory of the archive.
|
||||
|
||||
A template and an example of a module can be found in the 'modules/Tester' directory of the source code of this project. It provides the command.cpp and command.h files that contain the ```CommandLoader``` and ```ExternCommand``` classes that are needed to create a module. Also feel free to copy the command.cpp and command.h files from 'src/commands' if you prefer.
|
||||
|
||||
### 2.4 The Import Rev ###
|
||||
|
||||
The import rev is a single digit versioning system for external modules that help the host determine if it is compatible with the module it is attempting to load or not. Bumps to this rev is usually triggered by significant changes to the ```CommandLoader``` class or the method at which the host imports this object. Compatibility negotiation is a two way communication between the host ```CmdExecutor``` and the module itself using the virtual functions described in section 2.2.
|
|
@ -1,193 +0,0 @@
|
|||
### 3.1 Command Objects ###
|
||||
|
||||
```ExternCommand``` objects are QT/C++ classes used by the host to execute all logic related to the specific commands called by the client. It basically defines several QT signals and virtual functions that the host's internal ```CmdExecutor``` object uses to process input data from the client and return data to the client or to other peers connected to the host. Each command callable by the client defines a seperate ```ExternCommand``` object and it's life cycle is managed externally by the host's ```CmdExecutor``` object.
|
||||
|
||||
### 3.2 Defined Variables in ExternCommand ###
|
||||
|
||||
Aside from the virtual functions and QT signals, the ```ExternCommand``` object also defines a few public variables that can be of interest:
|
||||
|
||||
```cmdId```
|
||||
This is a ```quint16``` command id that the command object was assigned to when it was built. Changing it at any time does nothing upstream but it is reset to it's proper value every time the ```procBin()``` function is called. the MRCI protocol use assigned command ids to call certain command objects currently loaded into the ```CmdExecutor``` object. It is unique to each command object and makes it possible for the client to call a command with only 2 bytes of data instead of a variable number of bytes for a command name. This variable exist to make it possible for the internal logic of the command object to be made aware of it's assigned command id.
|
||||
|
||||
```internCommands```
|
||||
This is a ```QHash<QString, ExternCommand*>``` containing a list of pointers to internal command objects built to be used from within this command object. It is filled by the ```internRequest()``` function (section 3.3). Internal commands differ from external commands like this by having direct access to the host database and less restrictive access to various host functions. This variable is useful if you want access to such functions without the chance of causing a session crash or database corruption.
|
||||
|
||||
```errSent```
|
||||
This is a ```bool``` that simply indicates if the command has sent error message to the client using the ```errTxt()``` non-virtual function. This is useful if you want to determine of the last run of the command was successful or not but only if the internal logic used the aforementioned function to send the error. The ```CmdExecutor``` does reset it to false before calling the ```procBin()``` function.
|
||||
|
||||
```inLoopMode```
|
||||
This is a ```bool``` that indicates if the command object is currently in loop mode. This basically retains what was passed into the ```enableLoop()``` signal when it is called. more info on this can be found in section 3.5.
|
||||
|
||||
```inMoreInputMode```
|
||||
This is a ```bool``` that indicates if the command object is currently in the more input state. It retains what was passed into the ```enableMoreInput()``` signal when it is called. see section 3.5 for more info.
|
||||
|
||||
```QString QObject::objectName()```
|
||||
This is not a variable but it is a function available to the ```ExternCommand``` object from the QT API. The ```CmdExecutor``` assigns the unique command name to this property that was assigned to this command when it was built. Just like ```cmdId``` this makes the internal logic aware of it's assigned command name. Changing it using ```QObject::setObjectName()``` does nothing upstream but also unlike ```cmdId``` it is not reset upon calling ```procBin()```.
|
||||
|
||||
### 3.3 ExternCommand Virtual Functions ###
|
||||
|
||||
```void procBin(SharedObjs,QByteArray,uchar)```
|
||||
This function is called by the host to process input data from the client passed in the form of a ```QByteArray```. Look at this as the main execution function of the command that can be called more than once if the loop state is enabled. The ```SharedObjs``` parameter is passed by the ```CmdExecutor``` to share information about the session with the command object as described in section 3.4 of this document. It is passed as a const because changing any of the objects within ```SharedObjs``` in an unexpected way may cause undesired behaviour. The third ```uchar``` parameter indicate what type of data is in the ```QByteArray```. Details on type ids can be found in the [Type_IDs.md](Type_IDs.md) document.
|
||||
|
||||
```bool handlesGenfile()```
|
||||
Command objects should return true on this function if your command object handles the ```GEN_FILE``` data type in anyway. The host will use this to tell the client which commands support this data type which ones don't. The reason for this is because the ```GEN_FILE``` data type require structured 2 way communication in a way between the host and client (see [Type_IDs.md](Type_IDs.md)). This function is called only once shortly after the command is contructed.
|
||||
|
||||
```QString shortText()```
|
||||
Command objects must return a short summary on what this command actually does. The host will use this to send help text to the client. How this text is displayed to the user depends entirely on the client.
|
||||
|
||||
```QString ioText()```
|
||||
Just like shortText(), this is a help text function that describes what input/output data to expected to/from the command object. It follows a specific text format:
|
||||
|
||||
```
|
||||
[] Brackets are used to indicate a block of data (text,binary,etc..).
|
||||
Example: [text]
|
||||
|
||||
/ Seperates input and output data blocks to/from the command.
|
||||
Example: [input_text]/[output_text]
|
||||
|
||||
- Indicates a argument.
|
||||
Example: [-arg]/[text]
|
||||
|
||||
() Brackets indicate argument parameters/values.
|
||||
Example: [-arg (text)]/[text]
|
||||
|
||||
{} Brackets indicate optional arguments or parameters.
|
||||
Example: [-arg {(text)} {-optional}]/[text]
|
||||
|
||||
'or' Indicates optional input data blocks and/or possible output blocks.
|
||||
Example: [-arg1 (text)] or [-arg2 (text)]/[output_text1] or [output_text2]
|
||||
```
|
||||
|
||||
```QString longText()```
|
||||
This is a help text function that is used by the host to send full detailed information about the command and it's usage. It's recommended to be as thorough as possible to help users understand proper usage of your command. The host will send it as ```BIG_TEXT``` so it will be up to the client if it should word-wrap the text when displaying to the user.
|
||||
|
||||
```QString libText()```
|
||||
Command objects can use this function to return the library/module name and version that the command object belongs to. This can also contain extra information that clients can use to further identify the command object; however, the text is limited to 64 chars or less. Any text returned by this function that is larger than 64 chars will be truncated.
|
||||
|
||||
```QStringList internRequest()```
|
||||
After the command is successfully built, this function is called by the ```CmdExecutor``` to fulfil any request to build internal command objects that can be used from within the object that was built. the ```QStringList``` returned by this function just need to list any of the known internal command names and the ```CmdExecutor``` will build them and add them to the ```internCommands``` ```QHash``` defined inside the ```ExternCommand``` object (section 3.2). Here's a few notes to consider if you want to build internal commands within your own command.
|
||||
|
||||
* Your command object is assigned the parent of the internal commands.
|
||||
* The internal commands built into internCommands have full access to the internal host batabase and functions that normal ExternCommands would otherwise not have access to.
|
||||
* The output from the internal commands go directly to the client, peers or other objects. Nothing is passed through the parent object by default.
|
||||
* Clients do not have direct access to these specific internal commands. Instead, they can only be called by running the ```procBin()``` function directly from within the parent object.
|
||||
* The internal commands inherit the parent command object's command id/name so output from these internal commands will appear as if it came from the parent object. This also includes the ```enableLoop()``` and ```enableMoreInput()``` signals (section 3.5).
|
||||
* It will be up to the parent object to detect and execute the loop mode for these internal commands since ```CmdExecutor::exeCmd()``` will not call these objects directly.
|
||||
* Terminating the parent object also terminates all of the internal commands within it.
|
||||
* It is safe to delete the internals commands but be sure to remove the deleted commands from the ```internCommands``` ```QHash``` or it will must likely cause the session to crash. You normally should never have to do this anyway, the ```CmdExecutor``` will safely delete these internal commands when the parent is about to get deleted.
|
||||
|
||||
```void term()```
|
||||
This function is called by the host when the command needs to terminate what it is currently doing. Use this opportunity to reset and clean up any reasources so the command object can be ready to be called again in a reset state.
|
||||
|
||||
```void aboutToDelete()```
|
||||
The host will call this function before calling the command object's ```deleteLater()``` function. Use this opportunity to clean up anything the host may not be aware of in preparation for deletion. Avoid self deleting any ```ExternCommand``` object at any time, doing so will must certainly cause the session to crash.
|
||||
|
||||
```bool errState();```
|
||||
Return true or false on this function to indicate if the command object is currently in an error state. The default logic simply returns ```errSent``` (section 3.2).
|
||||
|
||||
### 3.4 Shared Objects ###
|
||||
|
||||
The ```SharedObjs``` class is used by the host's ```Session``` and ```CmdExecutor``` objects to share data with all command objects. It contains pointers to various objects related to the user's current session and command states. It is passed into the command via the ```ExternCommand::procBin()``` function as a read only const. Below are all of the pointers defined within it:
|
||||
|
||||
```sessionId```
|
||||
This is a ```QByteArray``` containing the 224bit (28byte) sha3 hash id unique to the current session only. this does change upon reconnecting to the host.
|
||||
|
||||
```p2pAccepted```
|
||||
This is a ```QList<QByteArray>``` object that list all peer session ids that the user has accepted to be allowed to send/receive data when using the ```toPeer()``` signal.
|
||||
|
||||
```p2pPending```
|
||||
This is a ```QList<QByteArray>``` object that list all peer session ids that sent a ```P2P_REQUEST``` to/from the session and are awaiting a ```P2P_OPEN```. When a ```P2P_OPEN``` is received, the session id sent by it is removed from this list and then added to ```p2pAccepted```.
|
||||
|
||||
```chIds```
|
||||
This is a ```QByteArray``` object that string togeather up to 6 channel-sub combinations that indicate which channel id and sub id combinations are currently open. Each channel-sub are 9bytes long and chIds itself maintians a fixed length of 54bytes. It is padded with 0x00 chars to maintain the fixed length (this padding can appear anywhere in 9byte increments within chIds). Channel-sub is formatted like this:
|
||||
|
||||
```
|
||||
bytes[0-7] - 64bit LE unsigned int (channel id)
|
||||
bytes[8] - 8bit LE unsigned int (sub id)
|
||||
|
||||
note: channel id 0 is not a valid id and the sub id cannot
|
||||
be valid without a valid channel id.
|
||||
```
|
||||
|
||||
```wrAbleChIds```
|
||||
This is a ```QByteArray``` object formatted exactly like ```chIds```. It however list all channel-subs from ```chIds``` that are 'writable.' This is what is actually used when casting data to peers while ```chIds``` is used when receiving data from peers. This cannot list any channel-subs that are not also listed in ```chIds```.
|
||||
|
||||
```chList```
|
||||
This is a ```QList<QString>``` of channel names that the currently logged user is a member of. Unlike ```chIds```, this list doesn't care if the channel is open or not.
|
||||
|
||||
```activeUpdate```
|
||||
This is a ```bool``` object that indicate if the above ```chIds``` contains an open active update channel. When a session is active updating it will respond to peer pings, ```PEER_INFO``` and ```PEER_STAT``` frames related to just the active update sub-channels.
|
||||
|
||||
```chOwnerOverride```
|
||||
This is a ```bool``` object that indicates if the user currently have the channel owner override flag active or not. The owner override flag allows the user to do anything a channel owner could do in a channel without actually being the owner of the channel. This is usually reserved for host administrators.
|
||||
|
||||
```sessionAddr```
|
||||
This is a ```QString``` representation of the IPv4 or IPv6 address of the TCP client.
|
||||
|
||||
```userName```
|
||||
This is a ```QString``` of the current user that is logged in on the current session. This is empty if no user is currently logged in.
|
||||
|
||||
```groupName```
|
||||
This is a ```QString``` of the group that the above ```userName``` is a member of. it is also blank if no user is currently logged in.
|
||||
|
||||
```displayName```
|
||||
This is a ```QString``` of the user's desired display name. Clients are encouraged put more emphasis on this if displaying the user to the public.
|
||||
|
||||
```appName```
|
||||
This is a ```QString``` of the client's application name. It can also contain the application's version depending on the application itself. This is updated upon connecting to the host and normally does not change while the session is active.
|
||||
|
||||
```clientMajor```
|
||||
This is a ```ushort``` version major of the mrci protocol that the client is using.
|
||||
|
||||
```clientMinor```
|
||||
This is a ```ushort``` version minor of the mrci protocol that the client is using.
|
||||
|
||||
```clientPatch```
|
||||
This is a ```ushort``` version patch of the mrci protocol that the client is using.
|
||||
|
||||
```userId```
|
||||
This is a ```QByteArray``` containing the 256bit (32byte) Keccak hash unique to the current user. This is empty if no user is currently logged in. This remains constant even when the user name, or any other user information changes.
|
||||
|
||||
```moreInputCmds```
|
||||
This is a ```QList<quint16>``` of command ids that are currently in the more input state. Command objects in this state are simply requesting more input data from the client and should not be considered finished.
|
||||
|
||||
```activeLoopCmds```
|
||||
This is a ```QList<quint16>``` of command ids that are currently in the loop state. Command objects in this state will cause the ```CmdExecutor``` to call ```ExternCommand::procBin()``` in a loop until it is removed from this list.
|
||||
|
||||
```pausedCmds```
|
||||
This is a ```QList<quint16>``` containing a list of command ids that are blocked from looping. The commands listed here must also be listed in activeLoopCmds.
|
||||
|
||||
```hostRank```
|
||||
This is a ```uint``` that indicates the currently logged in user's host rank. The host rank determines the level of access to the host commands the user currently have. what those commands could be depends on how the host is configured. The lower the rank value, the higher the privilege level with 1 being the highest level. 0 is not considered a valid rank and it will initialized as that if no user is currently logged in.
|
||||
|
||||
```cmdNames```
|
||||
This is a ```QHash<quint16,QString>``` with command id ```quint16``` keys that relate to ```QString``` command names that are currently loaded for the session.
|
||||
|
||||
### 3.5 ExternCommand Signals ###
|
||||
|
||||
```dataToClient(QByteArray data, uchar typeId)```
|
||||
This signal sends the data to ```CmdExecutor``` passed as a ```QByteArray``` with a ```uchar``` indicating what [TypeID](Type_IDs.md) is stored in that ```QByteArray```. The ```CmdExecutor``` object inspects the type id and stops external commands from sending the following data types: ```PRIV_IPC```, ```PUB_IPC```, ```NEW_CMD```, ```PEER_STAT```, ```MY_INFO```, ```PEER_INFO```, ```HOST_CERT```, ```IDLE```, ```PING_PEERS```, ```P2P_REQUEST```, ```P2P_OPEN```, ```P2P_CLOSE```. If none of these type ids are caught, the data is then sent to the client as a mrci frame.
|
||||
|
||||
```castToPeers(QByteArray data, uchar typeId)```
|
||||
This is used to broadcast data to all clients that have any matching sub-channels open. It takes the same parameters and have the same retrictions as ```dataToClient()```.
|
||||
|
||||
```toPeer(QByteArray sessionId, QByteArray data, uchar typeId)```
|
||||
This signal is used to send data directly to a peer client without the need to open any sub-channels. Instead, the data is routed via the target peer's session id, given in the 1st ```QByteArray``` parameter as 224bit (28byte) sha3 hash. The next 2 parameters are the same as ```dataToClient()```, however only the following data types are allowed until a connection is negotiated with the peer: ```P2P_REQUEST```, ```P2P_OPEN``` or ```P2P_CLOSE```. More info on this can be found in [Type_IDs.md](Type_IDs.md), section 4.2. Except the P2P specific data types, the same retrictions for ```dataToClient()``` also apply here.
|
||||
|
||||
```closeChById(quint64 channelId, uchar subId), closeChByName(QString channelName, QString subName), openChById(quint64 channelId, uchar subId), openChByName(QString channelName, QString subName)```
|
||||
These signals open/close sub-channels via the channel and sub-channel names or ids. The ```CmdExecutor``` does error checking on these so errors are returned to the client if the channel or sub-channel does not exists, is invalid or if the user doesn't have access to it.
|
||||
|
||||
```enableLoop(bool state)```
|
||||
This takes a ```bool``` value that enables or disables the command object's loop state. If the loop state is enabled, the ```procBin()``` function will be called by the ```CmdExecutor``` within it's own loop until the loop state is disabled. 3rd party module devs are highly recommended to use this rather than implementing their own long term loops. By letting the ```CmdExecutor``` handle the looping structure it would be possible for it terminate/interrupt the command more gracefully from the outside.
|
||||
|
||||
```enableMoreInput(bool state)```
|
||||
This takes a ```bool``` value that enables or disables the command object's more input state. This state tells the ```CmdExecutor``` that the command is requesting more data from the client and should hold off sending an ```IDLE``` frame to the client because the command is not yet finished. if both loop and more input states are disabled, an ```IDLE``` frame is sent to indicate to the client that the command is finished.
|
||||
|
||||
```closeSession()```
|
||||
This closes the session from the host side. The TCP connection also closes.
|
||||
|
||||
```cmdFinished()```
|
||||
This signal disables both loop and more input states. It also immediately sends the IDLE frame to the client to indicate that the command is finished. Normally, you should not have to emit this signal directly because the ```CmdExecutor``` will automatically send the ```IDLE``` frame if it detects that both the loop and more inputs states are disabled after calling ```procBin()```. This signal is only useful if you need to indicate that the command is finished outside of the ```procBin()``` function.
|
||||
|
||||
```logout()```
|
||||
This clears parameters in ```SharedObjs``` related to the currently logged in user and puts the session in a reset state with no user currently logged in. Unlike ```closeSession()```, this does not close the TCP connection.
|
|
@ -1,80 +0,0 @@
|
|||
### 5.1 Host Features ###
|
||||
|
||||
Other than transporting data to be processed by command objects, the host have a few other built in features such as data broadcasting to/from clients connected to the host, a multi-process architecture and full user account management. The following concepts needed to be created to facilitate these specific features:
|
||||
|
||||
### 5.2 Host Groups And Ranks ###
|
||||
|
||||
Host groups are used to manage the access level of all users. Each user registered in the host must be assigned a group and each group must be assigned a host rank. The rank is numeric integer that indicates the value of the group's rank. The lower it's numeric value, the higher the level of access the users in that group have in the host with 0 being invalid. By default, the host defines the ```root``` user into a group also called ```root``` and that group has a host rank of 1; giving it the highest level of access possible in the host.
|
||||
|
||||
The host also defines a default ```users``` group assigned a rank of 2 and that group is also assigned as the ```initial group``` for all new accounts that are created in the host. This can be re-configured at any time using the ```host_settings``` internal command.
|
||||
|
||||
Some internal commands have the ability to change the user account information of other accounts. The host will in general not allow users of a lower level of access to any user information of higher access level. For example: a user of host rank ```1``` can force change another user's email address if that user's rank is ```2``` or higher but the rank ```2``` can't do the same in reverse.
|
||||
|
||||
Host ranks can also be assigned to the commands themselves via the command names. The ```CmdExecutor``` object uses this to determine if it's allowed to load the command object or not. By doing this, the host can be configured to allow users of certain ranks or higher access to running certain commands. For example: if a command named ```this_cmd``` is assigned a host rank of ```6```, all users with a host rank value of ```6``` or lower will have access to loading/running this command. All commands that don't have an assigned rank will be assumed a rank of 1 but all commands that define itself as rank exempt can bypass this and allow the user to load/run it regardless of the user's host rank. This would also disregard the assigned rank of the command.
|
||||
|
||||
### 5.3 Channels And Sub-channels ###
|
||||
|
||||
Channels are used to manage sub-channels and sub-channels are used to determine which clients can send/receive broadcast data. When a client broadcast data to a open sub-channel, the clients that want to receive that data will also need to have the matching sub-channel open. Channels and sub-channels can be identified by a string name or integer id. When a channel is created, the user only needs to provide a unique channel name because the host will auto generate a unique channel id attached to that name. This id is a 64bit unsigned integer and it remains constant for as long as the channel exists, even when the name changes. The channel however can't broadcast any data until a sub-channel is created with the user providing a sub-channel name unique to the channel and the host will auto generate a sub-channel id also unique to the channel. The sub-id is a 8bit unsigned integer and it also remains constant for as long as the sub-channel exists. When brocasting data, a combination of the channel and sub-channel ids are used in the ```SharedObjs``` class (```chIds``` variable) as described in section [3.4](Command_Objects.md) to route the data.
|
||||
|
||||
Access to opening sub-channels are managed in a way similar to the host groups and ranks. All channels have a list of host user accounts that are members of the channel, each having managed levels of access to what they can do as a member of the channel. Host users are added via invitation and the users themselves have the option to accept or decline the invitation to join the channel. Like the host rank, access levels to the channels are a numeric integer value where the lower it's value is the higher level of access the channel member will have but unlike the host rank, the access levels are not user defined. Instead, all levels are host defined and what each level can do is also host defined.
|
||||
|
||||
```
|
||||
enum ChannelMemberLevel
|
||||
{
|
||||
OWNER = 1,
|
||||
ADMIN = 2,
|
||||
OFFICER = 3,
|
||||
REGULAR = 4,
|
||||
PUBLIC = 5
|
||||
};
|
||||
```
|
||||
|
||||
Below is a description of what each of these levels can do within the channel:
|
||||
|
||||
owner-level(1):
|
||||
|
||||
1. delete or rename the channel.
|
||||
2. delete, create or rename sub-channels within the channel.
|
||||
3. invite new users to the channel or cancel invites.
|
||||
4. remove any member of the channel except your self.
|
||||
5. set sub-channels' level of access.
|
||||
6. add/remove read only flags to/from sub-channels.
|
||||
7. update the privilege level of any member in the channel.
|
||||
8. open/close sub-channels.
|
||||
|
||||
admin-level(2):
|
||||
|
||||
1. delete, create or rename sub-channels within the channel.
|
||||
2. invite new users to the channel or cancel invites.
|
||||
3. remove any member of channel except the owner and other admins.
|
||||
4. set sub-channels' level of access.
|
||||
5. add/remove read only flags to/from sub-channels.
|
||||
6. update the privilege level of members up to your own level but not above.
|
||||
7. open/close sub-channels.
|
||||
|
||||
officer-level(3):
|
||||
|
||||
1. invite new users to the channel or cancel invites.
|
||||
2. can only remove regular members of the channel.
|
||||
3. update the privilege level of members up to your own level but not above.
|
||||
4. open/close sub-channels.
|
||||
|
||||
regular-level(4):
|
||||
|
||||
1. open/close sub-channels.
|
||||
|
||||
public-level(5):
|
||||
|
||||
1. open/close public sub-channels.
|
||||
|
||||
All sub-channels can be configured with it's own "lowest level of access" level that can make it so only certain channel members can open it. For example, the channel owner or admin can set a sub-channel's minimum level to 4 to make it so only channel regular members and above can open the sub-channel or it can be set to 5 to make it so anybody can open/close the sub-channel, affectively making it a public sub-channel.
|
||||
|
||||
There can only be one channel owner so if the owner decides change the privilege of any other member in the channel to owner, the current owner will automatically step down to level 2 (admin). Also note that privilege level 5 is reserved for users that are not a member of the channel and cannot be assigned to any user that are currently members of the channel.
|
||||
|
||||
Sub-channels can also be assigned what is called *read-only* flags. These flags are attached to the sub-channel id and privilege level. It is decoupled from all changes that could occur with the sub-channel so this means the sub-channel can get renamed or even deleted but the read-only flag would still remain. What a read-only flag actual does is make it so certain users of the matching level can listen for broadcast data but cannot send out broadcast data to the sub-channel. So a read-only flag for example can be added to a sub-channel id for privilege 5 to make it so public users can listen to the sub-channel but cannot send out anything to it.
|
||||
|
||||
### 5.4 Multi-Process Architecture ###
|
||||
|
||||
The host uses what's called a multi-process architecture which basically means each session operate in seperated processes and threads. This makes it possible for a session to crash due to a faultly command without taking down the entire host. In fact, the main process can detect this crash and attempt to restore the session automatically, up to a limited amount of attempts just so it doesn't infinite loop on crash-restore attempts.
|
||||
|
||||
In the code, this is done mainly in the ```Session``` class. When a client connects, a version of this class is created to operate in the main process and in it's own thread. It will then create another instance of the host and that new instance will create another ```Session``` class to operate in slave mode. The slave ```Session``` class will then start communicating with the main process ```Session``` via named pipes (```QLocalSocket```) using the same mrci frame protocol as with the client (section [1.1](Protocol.md)). The class that handles running the commands is the ```CmdExecutor``` object and that lives in the slave process where it is safe to crash without causing the host to go down.
|
|
@ -1,26 +1,37 @@
|
|||
# MRCI #
|
||||
|
||||
(Modular Remote Command Interpreter) is a command interpreter primarily designed to provide remote service to connected clients, whether text based or any kind of data. As the name implies, it is expandable via 3rd party modules by adding addtional commands that remote clients can run on the host. It has a fully feasured user account management system with access control to certain commands for certain user groups. All persistent data is handled by a SQLite database and all remote connections are handled via TCP and encrypted in SSL/TLS.
|
||||
(Modular Remote Command Interpreter) is a command interpreter primarily designed to provide remote service to connected clients, whether text based or any kind of data. As the name implies, it is expandable via 3rd party modules by adding addtional commands that remote clients can run on the host. It has a fully feasured user account management system with access control to certain commands for certain users. All persistent data is handled by a SQLite database and all remote connections are handled via TCP and encrypted in SSL/TLS.
|
||||
|
||||
### Usage ###
|
||||
|
||||
```
|
||||
Usage: mrci <arguments>
|
||||
Usage: mrci <argument>
|
||||
|
||||
<Arguments>
|
||||
|
||||
-help : display usage information about this application.
|
||||
-start : start a new host instance in the background.
|
||||
-stop : stop the current host instance if one is currently running.
|
||||
-about : display versioning/warranty information about this application.
|
||||
-addr {ip_address:port} : set the listening address and port for TCP clients.
|
||||
-status : display status information about the host instance if it is currently running.
|
||||
-reset_root : reset the root account password to default.
|
||||
-executor : this starts a command executor instance. this is normally for internal use only.
|
||||
-host : this starts a blocking host instance. this is normally for internal use only.
|
||||
|
||||
-help : display usage information about this application.
|
||||
-start : start a new host instance in the background. (non-blocking)
|
||||
-stop : stop the current host instance if one is currently running.
|
||||
-about : display versioning/warranty information about this application.
|
||||
-addr {ip_address:port} : set the listening address and port for TCP clients.
|
||||
-status : display status information about the host instance if it is currently running.
|
||||
-reset_root : reset the root account password to the default password.
|
||||
-host : this starts a blocking host instance. for internal use only.
|
||||
-public_cmds : run the internal module to list it's public commands. for internal use only.
|
||||
-exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only.
|
||||
-user_cmds : run the internal module to list it's user commands. for internal use only.
|
||||
-run_cmd {command_name} : run an internal module command. for internal use only.
|
||||
|
||||
Internal module | -public_cmds, -user_cmds, -exempt_cmds, -run_cmd |:
|
||||
|
||||
-pipe {pipe_name/path} : the named pipe used to establish a data connection with the session.
|
||||
-mem_ses {key_name} : the shared memory key for the session.
|
||||
-mem_host {key_name} : the shared memory key for the host main process.
|
||||
```
|
||||
|
||||
Other than that, the host can only be managed via a connected client that supports text input/output so the host application is always listening for clients while running entirely in the background. By default, the host listen for clients on address 127.0.0.1 and port 35516. Just like any linux OS, the host will have an administrative user called root along with a group also called root. This account can be used to modify anything on the host without restriction. The default password set to (R00tPa$$w0rd) when logging in for the first time as root, the host will require you to change the password before continuing.
|
||||
Other than that, the host can only be managed via a connected client that supports text input/output so the host application is always listening for clients while running entirely in the background. By default the host listen for clients on address 0.0.0.0 and port 35516, effectively making it reachable on any network interface of the host platform via that specific port.
|
||||
|
||||
Just like any linux based OS, the host will have an administrative user called root. This account can be used to modify anything on the host without restriction. The default password is randomized and set on the root user account on running the host for the first time. To find out what the default password is, run -help or -about. When logging in as root with the default password, the host will require you to change the password before continuing.
|
||||
|
||||
### More Than Just a Command Interpreter ###
|
||||
|
||||
|
@ -30,7 +41,7 @@ Typical use for a MRCI host is to run commands that clients ask it to run, very
|
|||
* Run remote commands on connected peers.
|
||||
* Host object positioning data for peers (online games do this).
|
||||
* Send data to/from a peer client directly.
|
||||
* Fully feasured builtin user account management.
|
||||
* Fully feasured user account management system.
|
||||
* Built in permissions and command access management.
|
||||
* Host limits management (max concurrent users, max failed password attempts, etc...).
|
||||
* Account recovery emailing in case of forgotten passwords. **
|
||||
|
@ -44,13 +55,12 @@ Because the host is modular, the things you can customize it to do is almost lim
|
|||
|
||||
### Documentation ###
|
||||
|
||||
* [1.1 The Protocol](Protocol.md)
|
||||
* [2.1 Command Loaders](Command_Loaders.md)
|
||||
* [3.1 Command Objects](Command_Objects.md)
|
||||
* [4.1 Type IDs](Type_IDs.md)
|
||||
* [5.1 Host Features](Host_Features.md)
|
||||
* [6.1 Async Commands](Async.md)
|
||||
* [7.1 Internal Commands](Internal_Commands.md)
|
||||
* [1.1 The Protocol](protocol.md)
|
||||
* [2.1 Modules](modules.md)
|
||||
* [3.1 Type IDs](type_ids.md)
|
||||
* [4.1 Host Features](host_features.md)
|
||||
* [5.1 Async Commands](async.md)
|
||||
* [6.1 Shared Memory](shared_data.md)
|
||||
|
||||
### Development Setup ###
|
||||
|
||||
|
|
316
docs/async.md
Normal file
316
docs/async.md
Normal file
|
@ -0,0 +1,316 @@
|
|||
### 5.1 Async Commands ###
|
||||
|
||||
An async command is a virtual command that the host can use to send data to the client at any time while connected to the host. As the name implies, the occurance of a client receiving data from an async command is not always the result of running a regular command in the current session. This can occur for example when information in your account is changed by another client connected to the host; your client would not know about this change until an async command is sent notify it of the change. These commands can called directly or indirectly by a module.
|
||||
|
||||
Async commands are not only used send data to the client but also used internally within the host to help objects operating in different processes to communicate with each other. Some async commands in fact are considered internal only because the client should never see any data come from them at anytime. There is also data flow contriants for aysnc commands, meaning some gets blocked or has no effect if sent from a module when not expected to or sent using the [PRIV_IPC](type_ids.md) data type when expected to be sent via [PUB_IPC](type_ids.md). The list below shows the various data flow contriants each of these async commands have.
|
||||
|
||||
Here is a describtion of what those keywords mean:
|
||||
```
|
||||
client - this means the async command id will be used to forward
|
||||
data of any type to client if needed.
|
||||
|
||||
internal - this means the async command will be responded by the
|
||||
session object but the data will not be forwarded to the
|
||||
client or converted to an entirely different async
|
||||
command.
|
||||
|
||||
public - this means the session objects will respond to this async
|
||||
command if sent with PUB_IPC or PUB_IPC_WITH_FEEDBACK
|
||||
from the module.
|
||||
|
||||
private - this means only the session object that has a direct IPC
|
||||
connection with the module that sends the async command
|
||||
via PRIV_IPC will respond to it.
|
||||
|
||||
none - this means none of the session objects will respond to
|
||||
this async command no matter which of the IPC data types
|
||||
are used. it is resevered for just the session object to
|
||||
send to the client.
|
||||
|
||||
retricted - this means the session object will actively block this
|
||||
async command from being sent from the module (any mode).
|
||||
```
|
||||
|
||||
These are considered "virtual" commands because there is no defined command objects attached to them. Instead, async commands are best identified by command id values 1-255.
|
||||
|
||||
```
|
||||
enum AsyncCommands : quint16
|
||||
{
|
||||
ASYNC_RDY = 1, // client | none
|
||||
ASYNC_SYS_MSG = 2, // client | none
|
||||
ASYNC_EXIT = 3, // internal | private
|
||||
ASYNC_CAST = 4, // client | public
|
||||
ASYNC_MAXSES = 5, // internal | private
|
||||
ASYNC_LOGOUT = 6, // internal | private
|
||||
ASYNC_USER_DELETED = 7, // client | public
|
||||
ASYNC_DISP_RENAMED = 8, // internal | public
|
||||
ASYNC_USER_RANK_CHANGED = 9, // internal | public
|
||||
ASYNC_CMD_RANKS_CHANGED = 10, // internal | public
|
||||
ASYNC_RESTART = 11, // internal | private
|
||||
ASYNC_ENABLE_MOD = 12, // internal | public
|
||||
ASYNC_DISABLE_MOD = 13, // internal | public
|
||||
ASYNC_END_SESSION = 14, // internal | private
|
||||
ASYNC_USER_LOGIN = 15, // internal | private
|
||||
ASYNC_TO_PEER = 16, // client | public | retricted
|
||||
ASYNC_LIMITED_CAST = 17, // client | public
|
||||
ASYNC_RW_MY_INFO = 18, // internal | public
|
||||
ASYNC_P2P = 19, // client | public
|
||||
ASYNC_CLOSE_P2P = 20, // internal | public
|
||||
ASYNC_NEW_CH_MEMBER = 21, // client | public
|
||||
ASYNC_DEL_CH = 22, // client | public
|
||||
ASYNC_RENAME_CH = 23, // client | public
|
||||
ASYNC_CH_ACT_FLAG = 24, // internal | public
|
||||
ASYNC_NEW_SUB_CH = 25, // client | public
|
||||
ASYNC_RM_SUB_CH = 26, // client | public
|
||||
ASYNC_RENAME_SUB_CH = 27, // client | public
|
||||
ASYNC_INVITED_TO_CH = 28, // client | public
|
||||
ASYNC_RM_CH_MEMBER = 29, // client | public
|
||||
ASYNC_INVITE_ACCEPTED = 30, // client | public
|
||||
ASYNC_MEM_LEVEL_CHANGED = 31, // client | public
|
||||
ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public
|
||||
ASYNC_ADD_RDONLY = 33, // client | public
|
||||
ASYNC_RM_RDONLY = 34, // client | public
|
||||
ASYNC_ADD_CMD = 35, // client | none
|
||||
ASYNC_RM_CMD = 36, // client | none
|
||||
ASYNC_USER_RENAMED = 37, // internal | public
|
||||
ASYNC_PING_PEERS = 38, // internal | private
|
||||
ASYNC_OPEN_SUBCH = 39, // internal | private
|
||||
ASYNC_CLOSE_SUBCH = 40, // internal | private
|
||||
ASYNC_UPDATE_BANS = 41, // internal | private
|
||||
ASYNC_KEEP_ALIVE = 42, // internal | private
|
||||
ASYNC_SET_DIR = 43, // internal | private
|
||||
ASYNC_DEBUG_TEXT = 44 // internal | private
|
||||
};
|
||||
```
|
||||
|
||||
### 5.2 Async Data ###
|
||||
|
||||
```ASYNC_RDY (1)```
|
||||
This command signals to the client that your current session is now ready to start running commands. This is sent to the client after successfully setting up the tcp connection ([protocol](protocol.md)). It can carry [TEXT](type_ids.md) data that can be displayed directly to the user if needed.
|
||||
|
||||
```ASYNC_SYS_MSG (2)```
|
||||
This command carry [TEXT](type_ids.md) or [ERR](type_ids.md) data that are system messages that can be directly displayed to the user of needed. It is also used to carry [HOST_CERT](type_ids.md) data during the tcp connection setup and MY_INFO when local user account information has changed.
|
||||
|
||||
```ASYNC_EXIT (3)```
|
||||
This is an internal async command that doesn't carry any data. It is used to send a ```closeServer()``` signal to the TCPServer object in the main process. This will cause it stop listing for clients, close all sessions and then close the main process.
|
||||
|
||||
```ASYNC_CAST (4)```
|
||||
This is an internal only command that carries a 54byte open sub-channels list described in section 5.3 and an embedded frame that can then be sent to clients that have any of the matching open sub-channels. It drops that sub-channel list before arriving at the client so it will apppear like a regular [mrci frame](protocol.md) of any data type.
|
||||
```
|
||||
from_module: [54bytes(sub_channel_list)][1byte(type_id)][rest-of-bytes(pay_load)]
|
||||
to_client: [type_id][cmd_id(4)][branch_id(0)][size_of_payload][payload]
|
||||
```
|
||||
|
||||
```ASYNC_MAXSES (5)```
|
||||
Internal only async command can used by modules to send a 4byte unsigned 32bit int to the session object to change the maximum amount the concurrent sessions for the TCPServer object.
|
||||
|
||||
```ASYNC_LOGOUT (6)```
|
||||
This internal only async command doesn't carry any data. This can be used by modules to tell the session object to logout the current user.
|
||||
|
||||
```ASYNC_USER_DELETED (7)```
|
||||
This command carries a 32byte user id hash of the user account that was delete from the host database. All sessions that are currently logged into this account will force logout.
|
||||
|
||||
```ASYNC_DISP_RENAMED (8)```
|
||||
This command carries a combination of the 32byte user id hash and the 64byte new display name (UTF-16LE, padded with 0x00) of the user account that changed it's display name. This will trigger all sessions that are currently logged into this account to send an updated [MY_INFO](type_ids.md) frame via ASYNC_SYS_MSG to the clients.
|
||||
```
|
||||
from_module: [32bytes(user_id)][64bytes(new_disp_name)]
|
||||
to_client: [type_id(9)][cmd_id(2)][branch_id(0)][size_of_payload][payload(MY_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_USER_RANK_CHANGED (9)```
|
||||
This command carries a combination of the 32byte user id hash and 4byte new rank (32bit uint_le) of the user account that changed it's host rank. This will trigger all sessions that are currently logged into this account to send an updated [MY_INFO](type_ids.md) frame via ASYNC_SYS_MSG to the clients.
|
||||
```
|
||||
from_module: [32bytes(userId)][4bytes(newRank)]
|
||||
to_client: [type_id(9)][cmd_id(2)][branch_id(0)][size_of_payload][payload(MY_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_CMD_RANKS_CHANGED (10)```
|
||||
This internal only command doesn't carry any data, it just triggers all sessions to re-load runable commands.
|
||||
|
||||
```ASYNC_RESTART (11)```
|
||||
This internal only async commmand doesn't carry any data. It is used to send a ```resServer()``` signal to the TCPServer object in the main process. This will cause it stop listing for clients, close all sessions, reload the host settings and start listening for clients again.
|
||||
|
||||
```ASYNC_ENABLE_MOD (12)```
|
||||
This internal only async commmand that carry a [TEXT](type_ids.md) path to a module executable. All session objects that receive this will then attempt to load the module.
|
||||
|
||||
```ASYNC_DISABLE_MOD (13)```
|
||||
This is the other half to ASYNC_ENABLE_MOD. All session objects that receive this will remove and terminate all commands associated with this module.
|
||||
|
||||
```ASYNC_END_SESSION (14)```
|
||||
This internal only async commmand doesn't carry any data. It is used by modules to logout the current user.
|
||||
|
||||
```ASYNC_USER_LOGIN (15)```
|
||||
This command carries a 32byte user id hash. This can be used by modules to tell the session object to login as this user.
|
||||
|
||||
```ASYNC_TO_PEER (16)```
|
||||
This is an async command that carry an embedded data frame directly to/from peer sessions without any restrictions. It is prepended with the 224bit hash of the target session id; however, it drops that session id before arriving at the client so it will apppear as a regular mrci frame of any data type. Modules do not have direct access to this, the host internal objects will handle this.
|
||||
```
|
||||
from_module: [28bytes(sessionId)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
to_client: [type_id][cmd_id(16)][branch_id(0)][size_of_payload][payload]
|
||||
```
|
||||
|
||||
```ASYNC_LIMITED_CAST (17)```
|
||||
This operate exactly like ASYNC_CAST except only sessions with active update sub-channels open will respond to it.
|
||||
|
||||
```ASYNC_RW_MY_INFO (18)```
|
||||
This command carries a 32byte user id hash of a user account who's data has been overwritten by another user. This will trigger all sessions that are currently logged into this account to send an updated [MY_INFO](type_ids.md) frame via ASYNC_SYS_MSG to the clients.
|
||||
```
|
||||
from_module: [32bytes(user_id)]
|
||||
to_client: [type_id(9)][cmd_id(2)][branch_id(0)][size_of_payload][payload(MY_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_P2P (19)```
|
||||
This async command carry an embedded data frames directly to/from peer sessions following the p2p negotiation process as described in [Type_IDs](type_ids.md), section 3.2 at the P2P specific data types. It prepends the 28byte hash of the destination session id and source session id; however, it drops the destination id and source id for just the P2P specific data types before arriving at the client. For all other data types (if a p2p connection is estabished), the source id is prepend-moved to the payload of the mrci frame before arriving at the client.
|
||||
```
|
||||
from_module: [28bytes(dst_sessionId)][28bytes(src_sessionId)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
to_client (P2P): [type_id][cmd_id(19)][branch_id(0)][size_of_payload][payload(src_sessionId)]
|
||||
to_client: [type_id][cmd_id(19)][branch_id(0)][size_of_payload + 28][src_sessionId + payload]
|
||||
```
|
||||
|
||||
```ASYNC_CLOSE_P2P (20)```
|
||||
This internal only async command carry the 28byte hash session id of a session that is about to close. All sessions that receive this will close the p2p connection with this session if such a connection exists. If such a connection did exist, the session will convert the frame into a P2P_CLOSE mrci frame and send it to the client via ASYNC_P2P.
|
||||
```
|
||||
from_module: [28bytes(src_sessionId)]
|
||||
to_client: [type_id(12)][cmd_id(19)][branch_id(0)][size_of_payload][payload(src_sessionId)]
|
||||
```
|
||||
|
||||
```ASYNC_NEW_CH_MEMBER (21)```
|
||||
This async command carries a [CH_MEMBER_INFO](type_ids.md) frame containing public information about a user that has been added to a channel member list. All sessions that are logged in as a member of the channel will forward the frame (unchanged) to the clients.
|
||||
```
|
||||
to_client: [type_id(25)][cmd_id(21)][branch_id(0)][size_of_payload][payload(CH_MEMBER_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_DEL_CH (22)```
|
||||
This async command carries a [CH_ID](type_ids.md) frame of a channel that has been deleted. All sessions that receive will forward the frame to the client (unchanged) and close all sub-channels related to the channel.
|
||||
```
|
||||
to_client: [type_id(26)][cmd_id(22)][branch_id(0)][size_of_payload][payload(CH_ID)]
|
||||
```
|
||||
|
||||
```ASYNC_RENAME_CH (23)```
|
||||
This async command carries a combination of the channel id and a 16bit null terminated UTF-16LE string containing the new name of the channel that has been renamed. This command desn't use any of the standard frame formats so it sends a [BYTES](type_ids.md) frame to the client.
|
||||
```
|
||||
to_client: [type_id(14)][cmd_id(28)][branch_id(0)][size_of_payload][payload(channel_id + new_channel_name)]
|
||||
```
|
||||
|
||||
```ASYNC_CH_ACT_FLAG (24)```
|
||||
This internal only async command carries a combination of the channel id and and sub-channel id to tell sessions that the sub-channel has changed it's active update flag. All sessions that have this sub-channel open will re-check this flag and determine if it should continue active updating.
|
||||
```
|
||||
format: [8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
||||
```
|
||||
|
||||
```ASYNC_NEW_SUB_CH (25)```
|
||||
This async command carries a comination of the channel id, sub-channel id, access level and a 16bit null terminated UTF-16LE string containing the sub-channel name when a new sub-channel is created. All sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame.
|
||||
```
|
||||
to_client: [type_id(14)][cmd_id(25)][branch_id(0)][8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
||||
[1byte(8bit_access_level)][16bit_null_term_sub-channel_name]
|
||||
```
|
||||
|
||||
```ASYNC_RM_SUB_CH (26)```
|
||||
This is the other half to ASYNC_NEW_SUB_CH. It carries just a combination of the channel id and and sub-channel id to tell all sessions that the sub-channel was deleted. All sessions that have the sub-channel open will close it.
|
||||
```
|
||||
to_client: [type_id(14)][cmd_id(26)][branch_id(0)][8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
||||
```
|
||||
|
||||
```ASYNC_RENAME_SUB_CH (27)```
|
||||
This async command carries a combination of the channel id, sub-channel id, access level and a 16bit null terminated UTF-16LE string containing the new sub-channel name. All sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame.
|
||||
```
|
||||
to_client: [type_id(14)][cmd_id(27)][branch_id(0)][8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
||||
[16bit_null_term_sub-channel_name]
|
||||
```
|
||||
|
||||
```ASYNC_INVITED_TO_CH (28)```
|
||||
This async command carries a [CH_MEMBER_INFO](type_ids.md) frame containing public information about a user that has been invited to a channel. All sessions that are logged in as a member of the channel will forward the frame (unchanged) to the clients.
|
||||
```
|
||||
to_client: [type_id(25)][cmd_id(28)][branch_id(0)][size_of_payload][payload(CH_MEMBER_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_RM_CH_MEMBER (29)```
|
||||
This async command carries a combination of the channel id and the 32byte user id of the channel member that has left or kicked from the channel member list. All sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame.
|
||||
```
|
||||
from_module: [8bytes(chId)][32bytes(userId)]
|
||||
to_client: [type_id(14)][cmd_id(29)][branch_id(0)][size_of_payload][payload(64bit_ch_id + 256bit_user_id)]
|
||||
```
|
||||
|
||||
```ASYNC_INVITE_ACCEPTED (30)```
|
||||
This async command carries a [CH_MEMBER_INFO](type_ids.md) frame containing public information about a user that has accepted an invite to a channel. All sessions that are logged in as a member of the channel will forward the frame (unchanged) to the clients.
|
||||
```
|
||||
to_client: [type_id(25)][cmd_id(30)][branch_id(0)][size_of_payload][payload(CH_MEMBER_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_MEM_LEVEL_CHANGED (31)```
|
||||
This async command carries a combination of the channel id, new level and the 32byte user id of the channel member that changed it's level of privilege in the channel. All sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame. All sessions that are currently logged in as this user also closes all sub-channels related to the channel.
|
||||
```
|
||||
from_module: [8bytes(chId)][32bytes(userId)][1byte(newLevel)]
|
||||
to_client: [type_id(14)][cmd_id(31)][branch_id(0)][size_of_payload][payload(64bit_ch_id + 256bit_user_id + 8bit_new_level)]
|
||||
```
|
||||
|
||||
```ASYNC_SUB_CH_LEVEL_CHG (32)```
|
||||
This async command carries a combination of the channel id and sub-channel id of a sub-channel that has changed it's level of access. All sessions that have this sub-channel open will close the sub-channel and/or all sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame.
|
||||
```
|
||||
from_module: [8bytes(chId)][1byte(subId)]
|
||||
to_client: [type_id(14)][cmd_id(32)][branch_id(0)][size_of_payload][payload(64bit_ch_id + 8bit_sub_id)]
|
||||
```
|
||||
|
||||
```ASYNC_ADD_RDONLY (33)```
|
||||
This async command carries exactly the same data as ASYNC_SUB_CH_LEVEL_CHG and has the same effect on the session sub-channels except it tells the clients that a read-only flag was added to the sub-channel.
|
||||
|
||||
```ASYNC_RM_RDONLY (34)```
|
||||
This is the other half to ASYNC_ADD_RDONLY except if tells the clients that a read-only was removed from the sub-channel.
|
||||
|
||||
```ASYNC_ADD_CMD (35)```
|
||||
This async command is used indirectly by modules to send [NEW_CMD](type_ids.md) frames to the session object. The session object will decide which frame gets forwarded to the client and which doesn't. Both this or ASYNC_RM_CMD sent directly to the session object does nothing. Instead, for modules called in listing mode [2.3](modules.md) (public_cmds, exempt_cmds or user_cmds); the session will detect the [NEW_CMD](type_ids.md) frames from the module and forward them to the client with this async command.
|
||||
```
|
||||
to_client: [type_id(16)][cmd_id(35)][branch_id(0)][size_of_payload][payload(NEW_CMD)]
|
||||
```
|
||||
|
||||
```ASYNC_RM_CMD (36)```
|
||||
This is the other half to ASYNC_ADD_CMD expect it is used to tell the client that the command was removed from the session and it carries a [CMD_ID](type_ids.md) frame instead.
|
||||
```
|
||||
to_client: [type_id(17)][cmd_id(36)][branch_id(0)][size_of_payload][payload(CMD_ID)]
|
||||
```
|
||||
|
||||
```ASYNC_USER_RENAMED (37)```
|
||||
This command carries a combination of the 32byte user id hash and the 48byte new user name (UTF-16LE, padded with 0x00) of the user account that changed it's user name. This will trigger all sessions that are currently logged into this account to send an updated [MY_INFO](type_ids.md) frame via ASYNC_SYS_MSG to the clients.
|
||||
```
|
||||
from_module: [32bytes(user_id)][48bytes(new_user_name)]
|
||||
to_client: [type_id(9)][cmd_id(2)][branch_id(0)][size_of_payload][payload(MY_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_PING_PEERS (38)```
|
||||
This internal only async commmand doesn't carry any data. It can be used by modules to request all peer sessions that have matching active update sub-channels open to return [PEER_INFO](type_ids.md) frames via ASYNC_TO_PEER directly to the session that has sent it. The session that receives these frames will in turn forward them to the client via ASYNC_LIMITED_CAST.
|
||||
```
|
||||
to_client: [type_id(8)][cmd_id(17)][branch_id(0)][size_of_payload][payload(PEER_INFO)]
|
||||
```
|
||||
|
||||
```ASYNC_OPEN_SUBCH (39)```
|
||||
This internal only async command carries a combination of the channel id and sub-channel id. it can be used by modules to tell the session object open a sub-channel.
|
||||
```
|
||||
format: [8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
||||
```
|
||||
|
||||
```ASYNC_CLOSE_SUBCH (40)```
|
||||
This is the other half to ASYNC_OPEN_SUBCH that tells the session to close the requested sub-channel.
|
||||
|
||||
```ASYNC_UPDATE_BANS (41)```
|
||||
This internal only async command doesn't carry any data. It can be use by modules to tell the TCPServer object to update it's ip ban list cache from the database. This generally only needs to be used if the ip ban list in the database has changed in anyway.
|
||||
|
||||
```ASYNC_KEEP_ALIVE (42)```
|
||||
This internal only async command doesn't carry any data. The session object normally sends a [KILL_CMD](type_ids.md) to the module when it detects that the module process has not sent an IPC frame in 2 minutes to terminate the module process. If desired, the module can send this async command in regular intervals to reset this 2 minute idle timer to prevent auto termination.
|
||||
|
||||
```ASYNC_SET_DIR (43)```
|
||||
This internal only async command carries a [TEXT](type_ids.md) path that sets the working directory for the session object. All module processes started by the session will use this directory as the working directory and it is not shared among peer sessions. nothing happens if the path is invalid or does not exists.
|
||||
|
||||
```ASYNC_DEBUG_TEXT (44)```
|
||||
This internal only async command carries a [TEXT](type_ids.md) debug message to be logged into the host debug log from the module. Modules can use this to help with debugging issues if it doesn't have direct access to the host database.
|
||||
|
||||
### 5.3 Open Sub-Channel List ###
|
||||
|
||||
An open sub-channel list is a binary data structure that string togeather up to 6 channel-sub combinations that indicate which channel id and sub id combinations are currently open. Each sub-channel are 9bytes long and the list itself maintians a fixed length of 54bytes so it is padded with 0x00 chars to maintain the fixed length (this padding can appear anywhere in 9byte increments within the list). Each sub-channel is formatted like this:
|
||||
|
||||
```
|
||||
bytes[0-7] - 64bit LE unsigned int (channel id)
|
||||
bytes[8] - 8bit LE unsigned int (sub id)
|
||||
|
||||
note: channel id 0 is not a valid id and the sub id cannot
|
||||
be valid without a valid channel id.
|
||||
```
|
76
docs/host_features.md
Normal file
76
docs/host_features.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
### 4.1 Host Features ###
|
||||
|
||||
Other than transporting data to be processed by modules, the host have a few other built in features such as data broadcasting to/from clients connected to the host and full user account management. The following concepts needed to be created to facilitate these specific features:
|
||||
|
||||
### 4.2 Host Ranks ###
|
||||
|
||||
Each user registered in the host must be assigned a host rank. The lower it's numeric value, the higher the level of access the user has in the host with 0 being invalid. By default, the host defines the ```root``` user with a host rank of 1; giving it the highest level of access possible in the host. The host also defines a default initial host rank of 2 for all new accounts that are created in the host. This can be re-configured at any time using the [host_config](internal_commands.md) internal command.
|
||||
|
||||
Some internal commands have the ability to change the user account information of other accounts. The host will in general not allow users of a lower level of access to any user information of higher access level. For example: a user of host rank ```1``` can force change another user's email address if that user's rank is ```2``` or higher but the rank ```2``` user can't do the same in reverse.
|
||||
|
||||
Host ranks can also be assigned to the commands themselves via the command names of specific modules. By doing this, the host can be configured to allow users of certain ranks or higher access to running certain commands. For example: if a command named ```this_cmd``` is assigned a host rank of ```6```, all users with a host rank value of ```6``` or lower will have access to running this command. All commands that don't have an assigned rank will be assumed a rank of ```1``` but all commands that define itself as rank exempt can bypass this and allow the user to run it regardless of the user's host rank. Exemptions would also disregard the assigned rank of the command.
|
||||
|
||||
### 4.3 Channels And Sub-channels ###
|
||||
|
||||
Channels are used to manage sub-channels and sub-channels are used to determine which clients can send/receive broadcast data. When a client broadcast data to a open sub-channel, the clients that want to receive that data will also need to have the matching sub-channel open. Channels and sub-channels can be identified by a string name or integer id.
|
||||
|
||||
When a channel is created, the user only needs to provide a unique channel name because the host will auto generate a unique channel id attached to that name. This id is a 64bit unsigned integer and it remains constant for as long as the channel exists, even when the name changes. The channel however can't broadcast any data until a sub-channel is created with the user providing a sub-channel name unique to the channel and the host will auto generate a sub-channel id also unique to the channel. The sub-id is a 8bit unsigned integer and it also remains constant for as long as the sub-channel exists.
|
||||
|
||||
When brocasting data, a combination of the channel and sub-channel ids are used as described in [ASYNC_CAST](async.md) or [ASYNC_LIMITED_CAST](async.md).
|
||||
|
||||
Access to opening sub-channels are managed in a way similar to the host ranks. All channels have a list of host user accounts that are members of the channel, each having managed levels of access to what they can do as a member of the channel. Host users are added via invitation and the users themselves have the option to accept or decline the invitation to join the channel. Like the host rank, access levels to the channels are a numeric integer value where the lower it's value is the higher level of access the channel member will have but unlike the host rank, the access levels are not user defined. Instead, all levels are host defined and what each level can do is also host defined.
|
||||
|
||||
```
|
||||
enum ChannelMemberLevel
|
||||
{
|
||||
OWNER = 1,
|
||||
ADMIN = 2,
|
||||
OFFICER = 3,
|
||||
REGULAR = 4,
|
||||
PUBLIC = 5
|
||||
};
|
||||
```
|
||||
|
||||
Below is a description of what each of these levels can do within the channel:
|
||||
|
||||
owner-level(1):
|
||||
|
||||
1. delete or rename the channel.
|
||||
2. delete, create or rename sub-channels within the channel.
|
||||
3. invite new users to the channel or cancel invites.
|
||||
4. remove any member of the channel except your self.
|
||||
5. set sub-channels' level of access.
|
||||
6. add/remove read only flags to/from sub-channels.
|
||||
7. update the privilege level of any member in the channel.
|
||||
8. open/close sub-channels.
|
||||
|
||||
admin-level(2):
|
||||
|
||||
1. delete, create or rename sub-channels within the channel.
|
||||
2. invite new users to the channel or cancel invites.
|
||||
3. remove any member of channel except the owner and other admins.
|
||||
4. set sub-channels' level of access.
|
||||
5. add/remove read only flags to/from sub-channels.
|
||||
6. update the privilege level of members up to your own level but not above.
|
||||
7. open/close sub-channels.
|
||||
|
||||
officer-level(3):
|
||||
|
||||
1. invite new users to the channel or cancel invites.
|
||||
2. can only remove regular members of the channel.
|
||||
3. update the privilege level of members up to your own level but not above.
|
||||
4. open/close sub-channels.
|
||||
|
||||
regular-level(4):
|
||||
|
||||
1. open/close sub-channels.
|
||||
|
||||
public-level(5):
|
||||
|
||||
1. open/close public sub-channels.
|
||||
|
||||
All sub-channels can be configured with it's own "lowest level of access" level that can make it so only certain channel members can open it. For example, the channel owner or admin can set a sub-channel's minimum level to 4 to make it so only channel regular members and above can open the sub-channel or it can be set to 5 to make it so anybody can open/close the sub-channel, affectively making it a public sub-channel.
|
||||
|
||||
There can only be one channel owner so if the owner decides change the privilege of any other member in the channel to owner, the current owner will automatically step down to level 2 (admin). Also note that privilege level 5 is reserved for users that are not a member of the channel and cannot be assigned to any user that are currently members of the channel.
|
||||
|
||||
Sub-channels can also be assigned what is called *read-only* flags. These flags are attached to the sub-channel id and privilege level. It is decoupled from all changes that could occur with the sub-channel so this means the sub-channel can get renamed or even deleted but the read-only flag would still remain. What a read-only flag actual does is make it so certain users of the matching level can listen for broadcast data but cannot send out broadcast data to the sub-channel. So a read-only flag for example can be added to a sub-channel id for privilege 5 to make it so public users can listen to the sub-channel but cannot send out anything to it.
|
48
docs/modules.md
Normal file
48
docs/modules.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
### 2.1 Modules ###
|
||||
|
||||
Modules in this project are independent applications that communicate with the host application's session objects via named pipes and/or shared memory segments. The host will call multiple instances of these modules if needed using the command line options described in section 2.3 depending on session activity. The format for data transport between the session and module via the named pipe is a modified version of the MRCI frame described in section 2.2 called the IPC frame.
|
||||
|
||||
Basically the module's main job is to input and output IPC frames with the session object with the option to read session data from shared memory.
|
||||
|
||||
### 2.2 IPC Frame ###
|
||||
|
||||
```
|
||||
[type_id][data_len][payload]
|
||||
|
||||
type_id - 1byte - 8bit little endian integer type id of the payload.
|
||||
data_len - 3bytes - 24bit little endian integer size of the payload.
|
||||
payload - variable - the actual data to be processed.
|
||||
```
|
||||
|
||||
A full description of the type id's can be found in the [Type_IDs.md](type_ids.md) document.
|
||||
|
||||
### 2.3 Module Command Line Options ###
|
||||
|
||||
```
|
||||
The host will call the module with just one of these options:
|
||||
|
||||
-public_cmds : send a NEW_CMD frame for all public commands the module can run.
|
||||
-exempt_cmds : send a NEW_CMD frame all rank exempt commands the module can run.
|
||||
-user_cmds : send a NEW_CMD frame for all user rank enforced commands the module can run.
|
||||
-run_cmd {command_name} : run a module command based on the command name.
|
||||
|
||||
The host will include all 3 of these options with the above option:
|
||||
|
||||
-pipe {pipe_name/path} : the named pipe used to establish a data connection with the session.
|
||||
-mem_ses {key_name} : the shared memory key for the session object.
|
||||
-mem_host {key_name} : the shared memory key for the host main process.
|
||||
```
|
||||
|
||||
notes:
|
||||
|
||||
* When the session calls the module in list mode (-public_cmds, -exempt_cmds or -user_cmds), it will only respond to frame type ids: [NEW_CMD](type_ids.md) or [ERR](type_ids.md) from the module; all other data types are ignored. Modules called in run mode (-run_cmd) on the other hand will open up all frame type ids.
|
||||
|
||||
* When the session detects that the module successfully established a pipe connection, it will send a [HOST_VER](type_ids.md) frame to the module so the module can decide if it supports the host. If the host is not compatible or the module fails for what ever other reason, the module can send a useful error message ([ERR](type_ids.md) frame) and then terminate if needed. The error message will be added to the host debug log where it can be used by host admins to find out what went wrong. The HOST_VER frame is sent only when the module is called with the -public_cmds, -exempt_cmds or -user_cmds options.
|
||||
|
||||
* When the module sends a [NEW_CMD](type_ids.md) frame, the 16bit command id is needed but does not need to be valid, it just needs to be there as a place holder. The session will auto fill a valid ccommand id before sending the data to the client. A valid NEW_CMD frame must have a minimum of 259 bytes and a valid command name. the session will ignore all NEW_CMD frames the doesn't meet these requirements. See section [6.3](shared_data.md) for what would be considered a valid command name.
|
||||
|
||||
* All modules are encouraged to terminate after sending all [NEW_CMD](type_ids.md) frames for the -public_cmds, -exempt_cmds or -user_cmds options. The session will force kill the module after 2 mins of being idle but it is still desired to terminate gracefully when finished.
|
||||
|
||||
* The session will call all modules with the -public_cmds when created for the first time or when the user logout so it doesn't matter if the command names returned to the session overlap with -exempt_cmd or -user_cmds. When a user is logged in, it will then call 2 instances of each module with the -exempt_cmds and -user_cmds options so the command names should not overlap when these options are active.
|
||||
|
||||
* Modules called with -run_cmd does not need to terminate after running the requested command, instead it must send an [IDLE](type_ids.md) frame to indicate that the command is finished. This is desired because not only it tells the client that the command is finished but it also makes it so the session doesn't need to recreate the module process on every subsequent call to the module. The session will send a [KILL_CMD](type_ids.md) to the module after 2 mins of being idle to give the module a chance to terminate gracefully; The module will have 3 seconds to do this before it is force killed.
|
|
@ -1,25 +1,22 @@
|
|||
### 1.1 The Protocol ###
|
||||
|
||||
The main goal of this application is to transport data from remote TCP clients to the [Command_Objects](Command_Objects.md) defined in the host. How the data processed and/or returned back to the client depends entirely on the type of data being transported or the command object itself. The format that the host understands for data transport is referred to as MRCI frames as described below in section 1.2.
|
||||
The main goal of this application is to transport data from remote TCP clients to the [Modules](modules.md) defined in the host. How the data is processed and/or returned back to the client depends entirely on the type of data being transported or the module itself. The data format that the host understands for data transport is referred to as MRCI frames described below in section 1.2.
|
||||
|
||||
Before any MRCI frames can be transported, the host need to be made aware of the version of the host that the client supports and the client needs to be made aware of the host current version. This is done by having the client send a fixed length client header when it successfully connects to the host and the host will reply with it's own fixed length host header. Descriptions of these headers can be found in sections 1.4 and 1.5.
|
||||
Before any MRCI frames can be transported, both the host and client need basic information about each other. This is done by having the client send a fixed length client header when it successfully connects to the host and the host will reply with it's own fixed length host header. Descriptions of these headers can be found in sections 1.4 and 1.5.
|
||||
|
||||
### 1.2 MRCI Frames ###
|
||||
|
||||
MRCI frames are a data structure that allow the TCP clients to communicate with commands objects and various other objects defined in the MRCI host.
|
||||
|
||||
```
|
||||
Format:
|
||||
[type_id][cmd_id][branch_id][data_len][payload]
|
||||
|
||||
[type_id][cmd_id][data_len][payload]
|
||||
|
||||
type_id - 1byte - 8bit little endian integer type id of the payload.
|
||||
cmd_id - 2bytes - 16bit little endian integer command object id.
|
||||
data_len - 3bytes - 24bit little endian integer size of the payload.
|
||||
payload - variable - the actual data to be processed.
|
||||
type_id - 1byte - 8bit little endian integer type id of the payload.
|
||||
cmd_id - 2bytes - 16bit little endian integer command id.
|
||||
branch_id - 2bytes - 16bit little endian integer branch id.
|
||||
data_len - 3bytes - 24bit little endian integer size of the payload.
|
||||
payload - variable - the actual data to be processed.
|
||||
```
|
||||
|
||||
A full description of the type id's can be found in the [Type_IDs.md](Type_IDs.md) document.
|
||||
A full description of the type id's can be found in the [Type_IDs.md](type_ids.md) document.
|
||||
|
||||
### 1.3 Versioning System ###
|
||||
|
||||
|
@ -34,23 +31,18 @@ Any increments to the major resets the minor and patch to 0. Any 3rd party clien
|
|||
### 1.4 Client Header ###
|
||||
|
||||
```
|
||||
Format:
|
||||
|
||||
[tag][major][minor][patch][appName][coName]
|
||||
[tag][appName][coName]
|
||||
|
||||
tag - 4bytes - 0x4D, 0x52, 0x43, 0x49 (MRCI)
|
||||
major - 2bytes - 16bit little endian unsigned int
|
||||
minor - 2bytes - 16bit little endian unsigned int
|
||||
patch - 2bytes - 16bit little endian unsigned int
|
||||
appName - 128bytes - UTF16LE string (padded with spaces)
|
||||
coName - 272bytes - UTF16LE string (padded with spaces)
|
||||
appName - 134bytes - UTF16LE string (padded with 0x00)
|
||||
coName - 272bytes - UTF16LE string (padded with 0x00)
|
||||
```
|
||||
|
||||
notes:
|
||||
|
||||
* The **tag** is just a fixed ascii string "MRCI" that indicates to the host that the client is indeed attempting to use the MRCI protocol.
|
||||
|
||||
* The **appName** is the name of the client application that is connected to the host. It can also contain the client's app version if needed because it doesn't follow any particular standard. This string is accessable to all command objects so the commands themselves can be made aware of what app the user is currently using.
|
||||
* The **appName** is the name of the client application that is connected to the host. It can also contain the client's app version if needed because it doesn't follow any particular standard. This string is accessable to all modules so the commands themselves can be made aware of what app the user is currently using.
|
||||
|
||||
* The **coName** is the common name of a SSL certificate that is currently installed in the host. Depending on how the host is configured, it can contain more than one installed SSL cert so coName can be used by clients as a way to request which one of the SSL certs to use during the SSL handshake.
|
||||
|
||||
|
@ -74,7 +66,6 @@ notes:
|
|||
|
||||
* reply = 1, means the client version is acceptable and it does not need to take any further action.
|
||||
* reply = 2, means the client version is acceptable but the host will now send it's Pem formatted SSL cert data in a ```HOST_CERT``` mrci frame just after sending it's header. After receiving the cert, the client will then need to send a STARTTLS signal using this cert.
|
||||
* reply = 3, means the client version is not supported by the host and the session will end shortly.
|
||||
* reply = 4, means the host was unable to load the SSL cert associated with the common name sent by the client. The session will auto close at this point.
|
||||
|
||||
* **sesId** is the session id. It is a unique 224bit sha3 hash generated against the current date and time of session creation (down to the msec) and the machine id. This can be used by the host and client to uniquely identify the current session or past sessions.
|
64
docs/shared_data.md
Normal file
64
docs/shared_data.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
### 6.1 Session/Host Shared Memory ###
|
||||
|
||||
The host use shared shared memory segments to share data with the module processes so the modules can be made aware of various session data points like the currently logged in user id, user name, display name, etc. A shared memory segment is basically a block of memory where multiple processes have access to reading/writing data. The use of shared memory segments is entire optional so it does not need to be implemented to have a fully functional module.
|
||||
|
||||
The session object creates the shared memory segment and assigns a text key unique to just the session. When the session object calls a new module process, it will pass the [-mem_ses](modules.md) option with the shared memory key that the module can then use to attach to the segment. The session will also pass the [-mem_host](modules.md) option unique to the TCPServer object to get data relevant to the sever object.
|
||||
|
||||
As mentioned before, the share memory segments are just blocks of memory. sections 6.2 and 6.3 describes the format of the shared memory and where to find the data based on the memory offset.
|
||||
|
||||
### 6.2 Session Shared Memory Offsets ###
|
||||
|
||||
| Offset | Data | Type | Bytes | Descrition |
|
||||
| ------ | ---------------------- | --------------- | ----- | ---------------------------------------------------------------------------- |
|
||||
| 0 | Session ID | Hash | 28 | a unique hash for the current session. |
|
||||
| 28 | User ID | Hash | 32 | a unique hash for the currently logged in user account. |
|
||||
| 60 | Client IP | String | 78 | the ip address of user's client in string form. |
|
||||
| 138 | Client App | String | 134 | the name of the application the user is currently using. |
|
||||
| 272 | User Name | String | 48 | current user name. |
|
||||
| 320 | Disp Name | String | 64 | current display name. |
|
||||
| 384 | Host Rank | uint32 | 4 | current host rank. |
|
||||
| 388 | Active Update | uint8 | 1 | a bool value 0x00 or 0x01 if the session has an active update sub-ch open. |
|
||||
| 389 | Owner Override | uint8 | 1 | also a bool value if the session has the channel owner override flag active. |
|
||||
| 390 | Channel List | uint64 (x200) | 1600 | a list of up to 200 channel ids that the current user is a member of. |
|
||||
| 1990 | Open Sub-channels | [5.3](async.md) | 54 | a list of sub-channels the session currently have open. |
|
||||
| 2044 | Writeable Sub-channels | [5.3](async.md) | 54 | same as the list above except the sub-channels do not have read-only flags. |
|
||||
| 2098 | Pending P2P Request | Hash (x100) | 2800 | a list of up to 100 session ids that have pending p2p request. |
|
||||
| 4898 | Accepted P2P Request | Hash (x100) | 2800 | same as above except this list p2p request that was accepted. |
|
||||
|
||||
notes:
|
||||
|
||||
* The "String" data type is [TEXT](type_ids.md) padded with 0x00.
|
||||
* The list data types are also padded to strings of 0x00 based on the size of each sub-unit.
|
||||
|
||||
### 6.3 Host Shared Memory Offsets ###
|
||||
|
||||
| Offset | Data | Type | Bytes | Descrition |
|
||||
| ------ | ---------------------- | --------------- | ----- | ---------------------------------------------------------------------------- |
|
||||
| 0 | Number Of Sessions | uint32 | 4 | the number of active concurrent sessions. |
|
||||
|
||||
### 6.4 Data Constraints Table ###
|
||||
|
||||
| Data | Type | Vaild Size Range | Forbidden Chars | Must Contain |
|
||||
| ---------------------- | ------ | ---------------- | ------------------ | ----------------------------------------------------------- |
|
||||
| Module Executable Path | String | 1-512 | ```|*:\"?<>``` | |
|
||||
| User Name | String | 2-24 | spaces or newlines | |
|
||||
| Email Address | String | 4-64 | spaces or newlines | ```@``` and ```.``` |
|
||||
| Password | String | 8-200 | | special chars, numbers, capital letters and common letters. |
|
||||
| Command Name | String | 1-64 | spaces or newlines | |
|
||||
| Common Name | String | 1-136 | spaces or newlines | |
|
||||
| Display Name | String | 0-32 | newlines | |
|
||||
| Channel Name | String | 4-32 | spaces or newlines | |
|
||||
| Sub-channel Name | String | 4-32 | spaces or newlines | |
|
||||
| Client App Name | String | 0-67 | | |
|
||||
| Command Lib Name | String | 0-64 | | |
|
||||
| IP Address (string) | String | 3-39 | spaces or newlines | numbers and ```.``` or numbers, A-F and ```:``` |
|
||||
| User ID | Hash | 32-32 | | |
|
||||
| Session ID | Hash | 28-28 | | |
|
||||
| Host Rank | int32 | 1-4x10^9 | non-numeric chars | |
|
||||
| Max Sessions | int32 | 1-4x10^9 | non-numeric chars | |
|
||||
| Channel ID | int64 | 1-18x10^18 | non-numeric chars | |
|
||||
| Command ID | int16 | 256-65535 | non-numeric chars | |
|
||||
| Async Command ID | int16 | 1-255 | non-numeric chars | |
|
||||
| Sub-channel ID | int8 | 0-255 | non-numeric chars | |
|
||||
| Channel Level | int8 | 1-5 | non-numeric chars | |
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
### 4.1 Type IDs ###
|
||||
### 3.1 Type IDs ###
|
||||
|
||||
All mrci frames transferred throughout this application are usually passed into various functions using a ```uchar``` numeric value to indicate the type of data being passed with the ```QByteArray``` that are also usually passed into the functions. The type id enum values are as follows:
|
||||
All mrci frames transferred throughout this application have an 8bit numeric value to indicate the type of data being passed with the binary data. The type id enum values are as follows:
|
||||
|
||||
```
|
||||
enum TypeID : quint8
|
||||
|
@ -30,21 +30,24 @@ enum TypeID : quint8
|
|||
PUB_IPC_WITH_FEEDBACK = 23,
|
||||
PING_PEERS = 24,
|
||||
CH_MEMBER_INFO = 25,
|
||||
CH_ID = 26
|
||||
CH_ID = 26,
|
||||
KILL_CMD = 27,
|
||||
HALT_CMD = 28,
|
||||
RESUME_CMD = 29
|
||||
};
|
||||
```
|
||||
|
||||
### 4.2 Type Descriptions ###
|
||||
### 3.2 Type Descriptions ###
|
||||
|
||||
```TEXT```
|
||||
This is text that can be displayed directly to the user or pass arguments for the command object to process.
|
||||
This is text that can be displayed directly to the user, pass command line arguments to be processed or used to carry text data within other data types.
|
||||
|
||||
format: ```[UTF-16LE_string] (no BOM)```
|
||||
|
||||
```GEN_FILE```
|
||||
This is a file transfer type id that can be used to transfer any type of file type (music, photos, documents, etc...). It operates in its own protocol of sorts. The 1st GEN_FILE frame received by the host or client is TEXT parameters similar to what you see in terminal command lines with at least one of the arguments listed below. The next set of GEN_FILE frames received by the host or client is then the binary data that needs to be written to an open file or streamed until the limit defined in -len is meet.
|
||||
This is a file transfer type id that can be used to transfer any file type (music, photos, documents, etc...). It operates in its own protocol of sorts. The 1st GEN_FILE frame received by the host or client is TEXT parameters similar to what you see in terminal command lines with at least one of the arguments listed below. The next set of GEN_FILE frames received by the host or client is then the binary data that needs to be written to an open file or streamed until the limit defined in -len is meet.
|
||||
|
||||
The host or the client can be set as the sender or receiver of the GEN_FILE binary data. Which ever is designated as the receiver by the TEXT parameters need to send an empty GEN_FILE frame to start the process. An example if this can be found in section 4.3.
|
||||
The host or the client can be set as the sender or receiver of the GEN_FILE binary data. Which ever is designated as the receiver by the TEXT parameters need to send an empty GEN_FILE frame to start the process. An example if this can be found in section 3.3.
|
||||
|
||||
arguments:
|
||||
|
||||
|
@ -76,22 +79,56 @@ This id can be treated exactly like TEXT except this should tell the client to h
|
|||
Also formatted exactly like TEXT but this indicates to the client that this is a large body of text that is recommended to be word wrapped when displaying to the user. It can contain line breaks so clients are also recommended to honor those line breaks.
|
||||
|
||||
```IDLE```
|
||||
This doesn't carry any actual data, instead this indicates that the command id that sent it has finished it's task. Commands objects are not allowed to send this directly, the ```CmdExecutor``` will handle it.
|
||||
This doesn't carry any actual data, instead this indicates that the command-branch id that sent it has finished it's task. Modules that send this doesn't need to terminate it's process.
|
||||
|
||||
```KILL_CMD```
|
||||
This doesn't carry any actual data, instead can be sent by the client or session object to tell the command-branch id sent in the frame to terminate the module process. Modules that receive this need to send a IDLE frame if a command is still running and then terminate itself. The module will have 3 seconds to do this before it is force killed by the session.
|
||||
|
||||
```HALT_CMD```
|
||||
This doesn't carry any actual data, instead can be sent by the client or session object to tell the command-branch id sent in the frame to pause/halt the current task that the command is currently running. All modules are not obligated to support this feature but highly recommended.
|
||||
|
||||
```RESUME_CMD```
|
||||
This is the other half of HALT_CMD that tells the module to resume the command task it was running.
|
||||
|
||||
```HOST_CERT```
|
||||
Just as the name implies, this data type is used by the host to send the host SSL certificate while setting up an SSL connection.
|
||||
|
||||
```HOST_VER```
|
||||
This data structure carries 3 numeric values that represent the host version as described in section [1.3](protocol.md).
|
||||
|
||||
```
|
||||
format:
|
||||
1. bytes[0-1] - version major (16bit little endian uint)
|
||||
2. bytes[2-3] - version minor (16bit little endian uint)
|
||||
3. bytes[4-5] - version patch (16bit little endian uint)
|
||||
```
|
||||
|
||||
```PRIV_IPC```
|
||||
This is a data structure used to by modules to run async commands on the local session object only.
|
||||
|
||||
```
|
||||
format:
|
||||
1. bytes[0-1] - async command id (16bit little endian uint)
|
||||
2. bytes[2-n] - payload (data to be processed by async command)
|
||||
```
|
||||
|
||||
```PUB_IPC```
|
||||
This is formatted exactly like PRIV_IPC except it is used by modules to run async commands on all connected peers in the host while avoiding a run on the local session object.
|
||||
|
||||
```PUB_IPC_WITH_FEEDBACK```
|
||||
This combines the functionality of PUB_IPC and PRIV_IPC. It runs async commands on all connected peers and on the local session object.
|
||||
|
||||
```FILE_INFO```
|
||||
This is a data structure that carries information about a file system object (file,dir,link).
|
||||
|
||||
```
|
||||
format:
|
||||
1. bytes[0] - flags (8bit little endian uint)
|
||||
2. bytes[1-8] - creation time in msec since Epoch UTC (64bit little endian uint)
|
||||
3. bytes[9-16] - modification time in msec since Epoch UTC (64bit little endian uint)
|
||||
4. bytes[17-24] - file size (64bit little endian uint)
|
||||
5. bytes[25-variable] - file name (UTF16-LE string, 16bit terminated)
|
||||
6. bytes[variable] - symmlink target if it is a symmlink (UTF16-LE string, 16bit terminated)
|
||||
1. bytes[0] - flags (8bit little endian uint)
|
||||
2. bytes[1-8] - creation time in msec since Epoch UTC (64bit little endian uint)
|
||||
3. bytes[9-16] - modification time in msec since Epoch UTC (64bit little endian uint)
|
||||
4. bytes[17-24] - file size (64bit little endian uint)
|
||||
5. bytes[25-n] - file name (UTF16-LE string, 16bit terminated)
|
||||
6. bytes[n-n] - symmlink target if it is a symmlink (UTF16-LE string, 16bit terminated)
|
||||
|
||||
notes:
|
||||
1. 16bit terminated UTF-16LE strings are basically
|
||||
|
@ -117,9 +154,9 @@ This carry some user account and session information about a peer client connect
|
|||
format:
|
||||
1. bytes[0-27] 28bytes - session id (224bit hash)
|
||||
2. bytes[28-59] 32bytes - user id (256bit hash)
|
||||
3. bytes[60-107] 48bytes - user name (TEXT - padded with empty spaces)
|
||||
4. bytes[108-235] 128bytes - app name (TEXT - padded with empty spaces)
|
||||
5. bytes[236-299] 64bytes - disp name (TEXT - padded with empty spaces)
|
||||
3. bytes[60-107] 48bytes - user name (TEXT - padded with 0x00)
|
||||
4. bytes[108-235] 128bytes - app name (TEXT - padded with 0x00)
|
||||
5. bytes[236-299] 64bytes - disp name (TEXT - padded with 0x00)
|
||||
|
||||
notes:
|
||||
1. the session id is unique to the peer's session connection only. it
|
||||
|
@ -133,12 +170,15 @@ This carry some user account and session information about a peer client connect
|
|||
name.
|
||||
```
|
||||
|
||||
```PING_PEERS```
|
||||
This formatted extactly as PEER_INFO except it can be used the ASYNC_LIMITED_CAST [async](async.md) command to tell all peer sessions that receive it to send PEER_INFO frame about you to their own clients and to return PEER_INFO frames about themselves to you.
|
||||
|
||||
```MY_INFO```
|
||||
This contains all of the information found in ```PEER_INFO``` for the local session but also includes the following:
|
||||
|
||||
```
|
||||
format:
|
||||
1. bytes[300-427] 128bytes - email (TEXT - padded with empty spaces)
|
||||
1. bytes[300-427] 128bytes - email (TEXT - padded with 0x00)
|
||||
2. bytes[428-431] 4bytes - host rank (32bit unsigned int)
|
||||
3. bytes[432] 1byte - is email confirmed? (0x00 false, 0x01 true)
|
||||
```
|
||||
|
@ -170,6 +210,16 @@ This type id carries a 16bit unsigned LE int representing a command id.
|
|||
|
||||
format: ```2bytes - 16bit LE unsigned int (command id)```
|
||||
|
||||
```CH_ID```
|
||||
This type id carries a 64bit unsighed LE int indicating the channel id.
|
||||
|
||||
format: ```8bytes - 64bit LE unsigned int (channel id)```
|
||||
|
||||
```SESSION_ID```
|
||||
This is a fixed length 28byte(224bit) sha3 hash of a client's session id connected to the host. This is unique to just the client's tcp connection with the host. This can change upon re-connection.
|
||||
|
||||
format: ```28bytes - session id (224bit sha3 hash)```
|
||||
|
||||
```PEER_STAT```
|
||||
This contain status information of a peer client when the peer changes sub-channels or disconnects from the host.
|
||||
|
||||
|
@ -190,26 +240,21 @@ This contain status information of a peer client when the peer changes sub-chann
|
|||
disconnected since you will no longer send/receive data with this peer.
|
||||
```
|
||||
|
||||
```SESSION_ID```
|
||||
This is a fixed length 28byte(224bit) sha3 hash of a client's session id connected to the host. This is unique to just the client's tcp connection with the host. This can change upon re-connection.
|
||||
|
||||
format: ```28bytes - session id (224bit sha3 hash)```
|
||||
|
||||
```P2P_REQUEST```
|
||||
This is formatted extactly like ```PEER_INFO``` except this is allowed to be sent directly to the target peer without restriction when using the ```ExternCommand::toPeer()``` signal ([Command_Objects.md](Command_Objects.md), section 2.5). It will be up to the target peer to respond with a ```P2P_OPEN``` for the host to then unrestrict ```toPeer()``` so it will then be able to send/received other TypeIDs with this peer until ```P2P_CLOSE``` is sent/received. ```P2P_CLOSE``` can also be sent to decline the request. When sending this TypeID, the ```CmdExecutor``` will ignore the data passed into ```toPeer()``` from the command object and substitute with it's own generated ```P2P_REQUEST``` to prevent fraudulent request from getting sent out to all sessions; because of this, it is ok and preferable to send an empty ```P2P_REQUEST``` with the ```toPeer()``` signal.
|
||||
This is formatted extactly like PEER_INFO except it is allowed to be sent directly to a peer session without retriction via the ASYNC_P2P [async](async.md) command. It will be up to the target peer to respond with a P2P_OPEN for the session to then unrestrict ASYNC_P2P so it will then be able to send/received other TypeIDs with this peer until P2P_CLOSE is sent/received. P2P_CLOSE can also be sent to decline the request.
|
||||
|
||||
```P2P_OPEN```
|
||||
This contains a 28byte session id hash of the peer session that you or the peer will allow direct communication with when using the ```ExternCommand::toPeer()``` signal.
|
||||
This contains a 28byte session id hash of the peer session that you or the peer will allow direct communication with ASYNC_P2P.
|
||||
|
||||
format: ```28bytes - session id (224bit sha3 hash)```
|
||||
|
||||
```P2P_CLOSE```
|
||||
This contains a 28byte session id hash of the peer session that you or the peer want to close direct communication with when using the ```ExternCommand::toPeer()``` signal.
|
||||
This is the other half of P2P_OPEN that will close direct communication with ASYNC_P2P.
|
||||
|
||||
format: ```28bytes - session id (224bit sha3 hash)```
|
||||
|
||||
```BYTES```
|
||||
This contains arbitrary binary data of any format that is not specialized for any internal objects in the host.
|
||||
This contains arbitrary binary data of any format.
|
||||
|
||||
```CH_MEMBER_INFO```
|
||||
This contains public information about a channel member.
|
||||
|
@ -228,14 +273,14 @@ This contains public information about a channel member.
|
|||
1. a 16bit null terminated TEXT formatted string ended with 2 bytes of
|
||||
(0x00) to indicate the end of the string data.
|
||||
2. the member's privilege level can be any of the values discribed in
|
||||
section [5.3](Host_Features.md).
|
||||
section [4.3](host_features.md).
|
||||
3. is invite? indicates if this user has received an invite to join
|
||||
that channel by has not accepted yet. if, accepted the user will
|
||||
become a full member of the channel at the level indicated by this
|
||||
data type.
|
||||
```
|
||||
|
||||
### 4.3 GEN_FILE Example ###
|
||||
### 3.3 GEN_FILE Example ###
|
||||
|
||||
Setup:
|
||||
|
118
src/cmd_proc.cpp
118
src/cmd_proc.cpp
|
@ -101,17 +101,20 @@ bool ModProcess::allowCmdLoad(const QString &cmdName)
|
|||
{
|
||||
bool ret = false;
|
||||
|
||||
if (flags & (LOADING_PUB_CMDS | LOADING_EXEMPT_CMDS))
|
||||
if (validCommandName(cmdName))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if (!cmdRanks.contains(cmdName))
|
||||
{
|
||||
ret = (hostRank == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (cmdRanks[cmdName] >= hostRank);
|
||||
if (flags & (LOADING_PUB_CMDS | LOADING_EXEMPT_CMDS))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if (!cmdRanks.contains(cmdName))
|
||||
{
|
||||
ret = (hostRank == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (cmdRanks[cmdName] >= hostRank);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -121,55 +124,64 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
|
|||
{
|
||||
if ((typeId == NEW_CMD) && (flags & SESSION_PARAMS_SET))
|
||||
{
|
||||
QString cmdName = fromTEXT(data.mid(3, 128)).trimmed().toLower();
|
||||
|
||||
if (isCmdLoaded(cmdName))
|
||||
if (data.size() >= 259)
|
||||
{
|
||||
if (!allowCmdLoad(cmdName))
|
||||
{
|
||||
quint16 cmdId = cmdRealNames->key(cmdName);
|
||||
// a valid NEW_CMD must have a minimum of 259 bytes.
|
||||
|
||||
cmdIds->removeOne(cmdId);
|
||||
cmdRealNames->remove(cmdId);
|
||||
cmdUniqueNames->remove(cmdId);
|
||||
cmdAppById->remove(cmdId);
|
||||
QString cmdName = fromTEXT(data.mid(3, 128)).trimmed().toLower();
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
modCmdNames->operator[](program()).removeOne(cmdName);
|
||||
}
|
||||
if (isCmdLoaded(cmdName))
|
||||
{
|
||||
if (!allowCmdLoad(cmdName))
|
||||
{
|
||||
quint16 cmdId = cmdRealNames->key(cmdName);
|
||||
|
||||
emit cmdUnloaded(cmdId);
|
||||
emit dataToClient(toCmdId32(ASYNC_RM_CMD, 0), wrInt(cmdId, 16), CMD_ID);
|
||||
}
|
||||
}
|
||||
else if (allowCmdLoad(cmdName))
|
||||
{
|
||||
quint16 cmdId = genCmdId();
|
||||
QByteArray cmdIdBa = wrInt(cmdId, 16);
|
||||
QString unique = makeCmdUnique(cmdName);
|
||||
|
||||
cmdIds->append(cmdId);
|
||||
cmdRealNames->insert(cmdId, cmdName);
|
||||
cmdUniqueNames->insert(cmdId, unique);
|
||||
cmdAppById->insert(cmdId, program());
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
modCmdNames->operator[](program()).append(cmdName);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList list = QStringList() << cmdName;
|
||||
|
||||
modCmdNames->insert(program(), list);
|
||||
}
|
||||
|
||||
QByteArray frame = cmdIdBa + data.mid(2, 1) + fixedToTEXT(unique, 128) + data.mid(131);
|
||||
|
||||
emit dataToClient(toCmdId32(ASYNC_ADD_CMD, 0), frame, NEW_CMD);
|
||||
cmdIds->removeOne(cmdId);
|
||||
cmdRealNames->remove(cmdId);
|
||||
cmdUniqueNames->remove(cmdId);
|
||||
cmdAppById->remove(cmdId);
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
modCmdNames->operator[](program()).removeOne(cmdName);
|
||||
}
|
||||
|
||||
emit cmdUnloaded(cmdId);
|
||||
emit dataToClient(toCmdId32(ASYNC_RM_CMD, 0), wrInt(cmdId, 16), CMD_ID);
|
||||
}
|
||||
}
|
||||
else if (allowCmdLoad(cmdName))
|
||||
{
|
||||
quint16 cmdId = genCmdId();
|
||||
QByteArray cmdIdBa = wrInt(cmdId, 16);
|
||||
QString unique = makeCmdUnique(cmdName);
|
||||
|
||||
cmdIds->append(cmdId);
|
||||
cmdRealNames->insert(cmdId, cmdName);
|
||||
cmdUniqueNames->insert(cmdId, unique);
|
||||
cmdAppById->insert(cmdId, program());
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
modCmdNames->operator[](program()).append(cmdName);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList list = QStringList() << cmdName;
|
||||
|
||||
modCmdNames->insert(program(), list);
|
||||
}
|
||||
|
||||
QByteArray frame = cmdIdBa + data.mid(2, 1) + fixedToTEXT(unique, 128) + data.mid(131);
|
||||
|
||||
emit dataToClient(toCmdId32(ASYNC_ADD_CMD, 0), frame, NEW_CMD);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeId == ERR)
|
||||
{
|
||||
qDebug() << fromTEXT(data);
|
||||
}
|
||||
}
|
||||
|
||||
void ModProcess::rdFromIPC()
|
||||
|
|
|
@ -62,6 +62,10 @@ void AssignCmdRank::procIn(const QByteArray &binIn, quint8 dType)
|
|||
{
|
||||
errTxt("err: The rank (-rank) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (mod.isEmpty())
|
||||
{
|
||||
errTxt("err: The module path (-mod) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (!isInt(rank))
|
||||
{
|
||||
errTxt("err: The given rank is not a valid 32bit unsigned integer.\n");
|
||||
|
@ -72,7 +76,7 @@ void AssignCmdRank::procIn(const QByteArray &binIn, quint8 dType)
|
|||
}
|
||||
else if (!validModPath(mod))
|
||||
{
|
||||
errTxt("err: Invalid module path. it cannot contain any of the following chars '|*:\"?<>'\n");
|
||||
errTxt("err: Invalid module path. it must be less than 512 chars long and it cannot contain any of the following chars '|*:\"?<>'\n");
|
||||
}
|
||||
else if (commandHasRank(mod, cmdName))
|
||||
{
|
||||
|
@ -105,6 +109,10 @@ void RemoveCmdRank::procIn(const QByteArray &binIn, quint8 dType)
|
|||
{
|
||||
errTxt("err: The command name (-command) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (mod.isEmpty())
|
||||
{
|
||||
errTxt("err: The module path (-mod) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (!validCommandName(cmdName))
|
||||
{
|
||||
errTxt("err: Invalid command name.\n");
|
||||
|
|
|
@ -49,7 +49,7 @@ void UploadMod::procIn(const QByteArray &binIn, quint8 dType)
|
|||
}
|
||||
else if (!validModPath(path))
|
||||
{
|
||||
errTxt("err: The module path cannot contain the following chars: :*?\"<>|\n");
|
||||
errTxt("err: The module path must be less then 512 chars long and cannot contain the following chars: :*?\"<>|\n");
|
||||
}
|
||||
else if (modExists(path))
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ void DelMod::procIn(const QByteArray &binIn, quint8 dType)
|
|||
}
|
||||
else if (!validModPath(path))
|
||||
{
|
||||
errTxt("err: The module path cannot contain the following chars: :*?\"<>|\n");
|
||||
errTxt("err: Invalid module path.\n");
|
||||
}
|
||||
else if (!modExists(path))
|
||||
{
|
||||
|
|
|
@ -72,7 +72,7 @@ void P2PRequest::procIn(const QByteArray &binIn, quint8 dType)
|
|||
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
|
||||
QByteArray typeBa = wrInt(P2P_REQUEST, 8);
|
||||
|
||||
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + dst);
|
||||
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + createPeerInfoFrame());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,13 +210,16 @@ bool validModPath(const QString &modPath)
|
|||
bool ret = true;
|
||||
QString forbidden = "|*:\"?<>";
|
||||
|
||||
for (auto&& chr : forbidden)
|
||||
if ((modPath.size() > 512) || modPath.isEmpty())
|
||||
{
|
||||
if (modPath.contains(chr))
|
||||
for (auto&& chr : forbidden)
|
||||
{
|
||||
ret = false;
|
||||
if (modPath.contains(chr))
|
||||
{
|
||||
ret = false;
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
4
src/db.h
4
src/db.h
|
@ -37,7 +37,7 @@
|
|||
#include "shell.h"
|
||||
|
||||
#define APP_NAME "MRCI"
|
||||
#define APP_VER "2.0.0"
|
||||
#define APP_VER "2.0.1"
|
||||
#define APP_TARGET "mrci"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -67,7 +67,7 @@
|
|||
#define INTERN_MOD_NAME ":internal_mod"
|
||||
#define DEFAULT_CONFIRM_SUBJECT "Email Verification"
|
||||
#define DEFAULT_TEMP_PW_SUBJECT "Password Reset"
|
||||
#define DEFAULT_LISTEN_ADDRESS "127.0.0.1"
|
||||
#define DEFAULT_LISTEN_ADDRESS "0.0.0.0"
|
||||
#define DEFAULT_LISTEN_PORT 35516
|
||||
#define DEFAULT_BAN_LIMIT 30
|
||||
#define DEFAULT_LOCK_LIMIT 20
|
||||
|
|
|
@ -351,7 +351,6 @@ bool MemShare::createSharedMem(const QByteArray &sesId, const QString &hostKey)
|
|||
len += BLKSIZE_APP_NAME; // appName
|
||||
len += BLKSIZE_USER_NAME; // userName
|
||||
len += BLKSIZE_DISP_NAME; // displayName
|
||||
len += BLKSIZE_GROUP_NAME; // groupName
|
||||
len += BLKSIZE_HOST_RANK; // hostRank
|
||||
len += BLKSIZE_ACT_UPDATE; // activeUpdate
|
||||
len += BLKSIZE_CH_OVERRIDE; // chOwnerOverride
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#define BLKSIZE_APP_NAME 134
|
||||
#define BLKSIZE_USER_ID 32
|
||||
#define BLKSIZE_USER_NAME 48
|
||||
#define BLKSIZE_GROUP_NAME 24
|
||||
#define BLKSIZE_DISP_NAME 64
|
||||
#define BLKSIZE_CHANNEL_ID 8
|
||||
#define BLKSIZE_HOST_RANK 4
|
||||
|
|
Loading…
Reference in New Issue
Block a user