New versioning system, type ids and a few bug fixes

Changed the versioning system to a 4 number system that have the first 2
numbers as major.minor for the host application itself and the next 2
numbers (tcp_rev.mod_rev) used by clients and modules to determine
compatibility. A full description of this new system has been edited
into protocol.md. This new system offically starts at v3.0.0.0.

Added the PROMPT data type id that will work exactly like PRIV_TEXT except
it tells the client that the command is asking for non-private information
from the user.

Added PROG and PROG_LAST type ids that can be used by commands to notify
the client of the progress of the command if it is long running. The
long running fs_* commands were updated to use these instead of TEXT for
progress updates.

PUB_IPC, PRIV_IPC and PUB_IPC_WITH_FEEDBACK have all been combined into
one: ASYNC_PAYLOAD. This type id is now the only means at which module
commands can now run async commands. The command process object will
now determine where to direct the async payload (public, private or
public with feedback) based on the async command id being requested.

A description for TERM_CMD was missing in data_types.md so it was added.

Refactored HALT_CMD to YIELD_CMD. The new name just seems more appropriate
or the effect it has on the command.

Module commands can now do input hooking using the new ASYNC_HOOK_INPUT
and ASYNC_UNHOOK async commands. input hooking basically makes it so all
client data gets redirected to the module command that initiated the hook.
This can be used to implement something like a EULA agreement that blocks
all actions that can place during the session until the user accepts or
anything else to that effect.

The command process object will now check the open sub-channels list
being sent by ASYNC_CAST or ASYNC_LIMITED_CAST in any order and will not
be required match exactly to open sub-channels list in the session object.
It however cannot contain sub-channels not already listed in session's
list or else the async payload will be blocked.

Fixed the CmdProcess::validAsync() function that was comparing the input
aysnc command id with the process's command id in some places which is
invalid logic for this function.

Fixed the 'cast' core command that was outputting a malformed async
payload that didn't include the open writable sub-channels list.

Fixed a bug that caused all casted payloads to be forwared to the clients
even when the sub-channel(s) are closed.

Fixed the 'set_disp_name' core command so it can now see the -new_name
argument properly.
This commit is contained in:
Maurice ONeal 2020-03-08 14:58:51 -04:00
parent 4c1d13f8f8
commit 6e068a8e83
28 changed files with 479 additions and 330 deletions

View File

@ -9,33 +9,29 @@ Here is a describtion of what the keywords in the list mean:
client - this means the async command id will be used to forward client - this means the async command id will be used to forward
data of any type to client if needed. data of any type to client if needed.
internal - this means the async command will be responded by the internal - this means the async command used by internal host
session object but the data will not be forwarded to the objects only so it never gets forwarded to a client at
client or converted to an entirely different async any time.
command before sending to the client.
public - this means the session objects will respond to this async public - this means the aysnc command will be broadcasted to all
command if sent with PUB_IPC or PUB_IPC_WITH_FEEDBACK session objects currently connected to the host. which
from the module. sessions will resond to it depends on the data being
sent. some async's broadcasted this way will also feed
back to source session depending on the data.
private - this means only the session object that has a direct IPC private - this means the async command will only be sent to the
connection with the module that sends the async command local session.
via PRIV_IPC will respond to it.
none - this means none of the session objects will respond to retricted - this means the async command will be used by the local
this async command no matter which of the IPC data types session object only. any modules/commands sending it
are used. it is resevered for just the session object to will be ignored or blocked.
send to the client.
retricted - this means the session object will actively block this
async command from being sent from the module (any mode).
``` ```
``` ```
enum AsyncCommands : quint16 enum AsyncCommands : quint16
{ {
ASYNC_RDY = 1, // client | none ASYNC_RDY = 1, // client | retricted
ASYNC_SYS_MSG = 2, // client | none ASYNC_SYS_MSG = 2, // client | retricted
ASYNC_EXIT = 3, // internal | private ASYNC_EXIT = 3, // internal | private
ASYNC_CAST = 4, // client | public ASYNC_CAST = 4, // client | public
ASYNC_MAXSES = 5, // internal | private ASYNC_MAXSES = 5, // internal | private
@ -49,7 +45,7 @@ enum AsyncCommands : quint16
ASYNC_DISABLE_MOD = 13, // internal | public ASYNC_DISABLE_MOD = 13, // internal | public
ASYNC_END_SESSION = 14, // internal | private ASYNC_END_SESSION = 14, // internal | private
ASYNC_USER_LOGIN = 15, // internal | private ASYNC_USER_LOGIN = 15, // internal | private
ASYNC_TO_PEER = 16, // client | public | retricted ASYNC_TO_PEER = 16, // client | retricted
ASYNC_LIMITED_CAST = 17, // client | public ASYNC_LIMITED_CAST = 17, // client | public
ASYNC_RW_MY_INFO = 18, // internal | public ASYNC_RW_MY_INFO = 18, // internal | public
ASYNC_P2P = 19, // client | public ASYNC_P2P = 19, // client | public
@ -68,15 +64,17 @@ enum AsyncCommands : quint16
ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public
ASYNC_ADD_RDONLY = 33, // client | public ASYNC_ADD_RDONLY = 33, // client | public
ASYNC_RM_RDONLY = 34, // client | public ASYNC_RM_RDONLY = 34, // client | public
ASYNC_ADD_CMD = 35, // client | none ASYNC_ADD_CMD = 35, // client | retricted
ASYNC_RM_CMD = 36, // client | none ASYNC_RM_CMD = 36, // client | retricted
ASYNC_USER_RENAMED = 37, // internal | public ASYNC_USER_RENAMED = 37, // internal | public
ASYNC_PING_PEERS = 38, // internal | private ASYNC_PING_PEERS = 38, // internal | private
ASYNC_OPEN_SUBCH = 39, // internal | private ASYNC_OPEN_SUBCH = 39, // internal | private
ASYNC_CLOSE_SUBCH = 40, // internal | private ASYNC_CLOSE_SUBCH = 40, // internal | private
ASYNC_KEEP_ALIVE = 42, // internal | private ASYNC_KEEP_ALIVE = 42, // internal | private
ASYNC_SET_DIR = 43, // internal | private ASYNC_SET_DIR = 43, // internal | private
ASYNC_DEBUG_TEXT = 44 // internal | private ASYNC_DEBUG_TEXT = 44, // internal | private
ASYNC_HOOK_INPUT = 45, // internal | private
ASYNC_UNHOOK = 46 // internal | private
}; };
``` ```
@ -140,7 +138,7 @@ This internal only async commmand doesn't carry any data. It is used by modules
This command carries a 32byte user id hash. This can be used by modules to tell the session object to login as this user. 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)``` ```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. 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 it.
``` ```
from_module: [28bytes(sessionId)][1byte(typeId)][rest-of-bytes(payload)] from_module: [28bytes(sessionId)][1byte(typeId)][rest-of-bytes(payload)]
to_client: [type_id][cmd_id(16)][branch_id(0)][size_of_payload][payload] to_client: [type_id][cmd_id(16)][branch_id(0)][size_of_payload][payload]
@ -292,11 +290,17 @@ This is the other half to ASYNC_OPEN_SUBCH that tells the session to close the r
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. 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)``` ```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. This internal only async command carries a [TEXT](type_ids.md) path that sets the working directory for the local session. 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)``` ```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. 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.
```ASYNC_HOOK_INPUT (45)```
This async command doesn't carry any data. This just indicate to the local session that the module command is requesting to hook the tcp data input from the client. when the tcp input is hooked, all data sent from the client is redirected to the command object/process that initiated the hook until reqested to unhook. If the command that initiated the hook terminates in anyway with an active hook, the hook will automatically be removed.
```ASYNC_UNHOOK (46)```
This async command doesn't carry any data. Any module command that sends it tells the local session to unhook the tcp input data from the client if there is an active hook. This doesn't need to come from the command that initiated the hook.
### 5.3 Open Sub-Channel List ### ### 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: 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:

View File

@ -26,13 +26,34 @@ notes:
### 1.3 Versioning System ### ### 1.3 Versioning System ###
The host uses the typical 3 number versioning system: Major.Minor.Patch The host uses a 4 number versioning system that indicate rev numbers for the host application itself, the tcp interface and the module interface:
```
[Major][Minor][TCP_Rev][Mod_Rev]
3 . 0 . 0 . 0
Major - this indicate any changes to the host application that would cause
clients to need to change behaviour to maintain compatibility.
changes to the core command names, type id format changes, etc.
will cause the version major to increment.
Minor - this indicate any changes to the host application that clients will
not see and would not need behaviour changes to maintain
compatibility. documentation changes, bug fixes, security patches,
etc. will cause the version minor to increment.
TCP_Rev - this indicate any changes to the MRCI protocol that interface the
host with the clients via the TCP connection. any changes to the
MRCI frames, host/client headers, etc. will cause this rev to
increment.
Mod_Rev - this indicate any changes to the IPC protocol that interface the
host with the modules via named pipes. any changes to the IPC
frames, NEW_CMD/CMD_ID type ids, etc. will cause this rev to
increment.
```
* **Major** - this indicates any major changes to the code of the application that renders versions of different majors incompatible with each other. Any increments to the Major resets the Minor to 0. Any 3rd party client applications connecting to a MRCI host need to be aware of this versioning but does not need to adopt it as it's own version number.
* **Minor** - this indicates only minor changes to the code that may require a few conditional blocks to maintain compatibility.
* **Patch** - this indicates changes that won't require any behaviour changes at all to maintain compatibility.
Any increments to the major resets the minor and patch to 0. Any 3rd party client applications connecting to a MRCI host need to be aware of this versioning but does not need to adopt it as it's own version number.
### 1.4 Client Header ### ### 1.4 Client Header ###
@ -57,13 +78,14 @@ notes:
``` ```
Format: Format:
[reply][major][minor][patch][sesId] [reply][major][minor][tcp_rev][mod_rev][sesId]
reply - 1byte - 8bit little endian unsigned int reply - 1byte - 8bit little endian unsigned int
major - 2bytes - 16bit little endian unsigned int major - 2bytes - 16bit little endian unsigned int
minor - 2bytes - 16bit little endian unsigned int minor - 2bytes - 16bit little endian unsigned int
patch - 2bytes - 16bit little endian unsigned int tcp_rev - 2bytes - 16bit little endian unsigned int
sesId - 28bytes - 224bit sha3 hash mod_rev - 2bytes - 16bit little endian unsigned int
sesId - 28bytes - 224bit sha3 hash
``` ```
notes: notes:

View File

@ -5,35 +5,36 @@ All mrci frames transferred throughout this application have an 8bit numeric val
``` ```
enum TypeID : quint8 enum TypeID : quint8
{ {
GEN_FILE = 1, GEN_FILE = 1,
TEXT = 2, TEXT = 2,
ERR = 3, ERR = 3,
PRIV_TEXT = 4, PRIV_TEXT = 4,
IDLE = 5, IDLE = 5,
HOST_CERT = 6, HOST_CERT = 6,
FILE_INFO = 7, FILE_INFO = 7,
PEER_INFO = 8, PEER_INFO = 8,
MY_INFO = 9, MY_INFO = 9,
PEER_STAT = 10, PEER_STAT = 10,
P2P_REQUEST = 11, P2P_REQUEST = 11,
P2P_CLOSE = 12, P2P_CLOSE = 12,
P2P_OPEN = 13, P2P_OPEN = 13,
BYTES = 14, BYTES = 14,
SESSION_ID = 15, SESSION_ID = 15,
NEW_CMD = 16, NEW_CMD = 16,
CMD_ID = 17, CMD_ID = 17,
BIG_TEXT = 18, BIG_TEXT = 18,
TERM_CMD = 19, TERM_CMD = 19,
HOST_VER = 20, HOST_VER = 20,
PRIV_IPC = 21, PING_PEERS = 21,
PUB_IPC = 22, CH_MEMBER_INFO = 22,
PUB_IPC_WITH_FEEDBACK = 23, CH_ID = 23,
PING_PEERS = 24, KILL_CMD = 24,
CH_MEMBER_INFO = 25, YIELD_CMD = 25,
CH_ID = 26, RESUME_CMD = 26,
KILL_CMD = 27, PROMPT_TEXT = 27,
HALT_CMD = 28, PROG = 28,
RESUME_CMD = 29 PROG_LAST = 29,
ASYNC_PAYLOAD = 30
}; };
``` ```
@ -71,13 +72,16 @@ arguments:
This type id is similar to TEXT except it indicates that this is an error message that can be displayed directly to the user if needed. This type id is similar to TEXT except it indicates that this is an error message that can be displayed directly to the user if needed.
```PRIV_TEXT``` ```PRIV_TEXT```
This id can be treated exactly like TEXT except this should tell the client to hide or do not echo the next TEXT data that the host is expecting, like a password or other sensitive text data. This id can be treated exactly like TEXT except this tells the client that the command is prompting for private information from the user so it sould hide or do not echo the next TEXT data that the command is expecting, like a password or other sensitive data.
```PROMPT_TEXT```
This is similar to PRIV_TEXT expect it is not asking for private information. It is simply prompting for non-sensitive information from the user.
```BIG_TEXT``` ```BIG_TEXT```
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. 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``` ```IDLE```
All commands started during the session returns this type id when it has finished it's task. by default, it carries a 16bit unsigned integer indicating the result of the task that the command was running. All commands started during the session returns this type id when it has finished it's task. It carries a 16bit unsigned integer indicating the result of the task that the command was running.
``` ```
enum RetCode : quint16 enum RetCode : quint16
@ -94,35 +98,39 @@ enum RetCode : quint16
notes: notes:
1. the custom return code can be additional data added to the end of the 16bit 1. the custom return code can be additional data added to the end of the 16bit
integer that can carry additional data about the result of the task. it can integer that can carry additional data about the result of the task. it can
be any format that the module itself decides it should be. nothing is be any format that the module itself decides it can should be. nothing is
stopping modules from defining return codes beyond the value of 7 but it is stopping modules from defining return codes beyond the value of 7 but it is
advised not to because this enum might be expanded in the future. advised not to because this enum might be expanded in the future.
``` ```
```KILL_CMD``` ```TERM_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. This type id doesn't carry any actual data. It is used to tell the host to stop/terminate the command id and branch id that was used to send it. It does not actually terminate the module's process within the host, it only simply tells it to stop what it is currently doing. This will also terminate any commands in a prompt/more input state.
```HALT_CMD``` ```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 pause/halt the current task that the command is currently running. All modules are not obligated to support this feature but highly recommended. This works similarly to TERM_CMD except it will also terminate the module process. The module process will have 3 seconds to shutdown gracefully before it is force killed by the host session.
```YIELD_CMD```
This type id doesn't carry any actual data, instead can be used to tell the host to pause/yield the command id and branch id that was used to send it. All modules are not obligated to support this feature but it is highly recommended to do so.
```RESUME_CMD``` ```RESUME_CMD```
This is the other half of HALT_CMD that tells the module to resume the command task it was running. This is the other half of YIELD_CMD that tells the host to resume the command that was running.
```HOST_CERT``` ```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. 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``` ```HOST_VER```
This data structure carries 3 numeric values that represent the host version as described in section [1.3](protocol.md). This data structure carries 4 numeric values that represent the host version as described in section [1.3](protocol.md).
``` ```
format: format:
1. bytes[0-1] - version major (16bit little endian uint) 1. bytes[0-1] - version major (16bit little endian uint)
2. bytes[2-3] - version minor (16bit little endian uint) 2. bytes[2-3] - version minor (16bit little endian uint)
3. bytes[4-5] - version patch (16bit little endian uint) 3. bytes[4-5] - tcp interface rev (16bit little endian uint)
4. bytes[6-7] - module interface rev (16bit little endian uint)
``` ```
```PRIV_IPC``` ```ASYNC_PAYLOAD```
This is a data structure used to by modules to run async commands on the local session object only. This is a data structure that can be used by modules to run async commands. Each async command have a specific 16bit command id followed by a payload that can contain any data of any format depending on the async command id. A full discribtion of the async commands and the data they carry can found in section [5.1](async.md) and [5.2](async.md).
``` ```
format: format:
@ -130,12 +138,6 @@ This is a data structure used to by modules to run async commands on the local s
2. bytes[2-n] - payload (data to be processed by async command) 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 peer session objects in the host while avoiding a run on the local session object.
```PUB_IPC_WITH_FEEDBACK```
This has the same functionality as PUB_IPC except it is also feedback into the local session object.
```FILE_INFO``` ```FILE_INFO```
This is a data structure that carries information about a file system object (file,dir,link). This is a data structure that carries information about a file system object (file,dir,link).
@ -192,7 +194,7 @@ This carry some user account and session information about a peer client connect
``` ```
```PING_PEERS``` ```PING_PEERS```
This is 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 a PEER_INFO frame about you to their own clients and return PEER_INFO frames about themselves to you. This is formatted extactly as PEER_INFO except it is used by the ASYNC_LIMITED_CAST [async](async.md) command to tell all peer sessions that receive it to send a PEER_INFO frame about the local session to their own clients and return PEER_INFO frames about themselves to the local session.
```MY_INFO``` ```MY_INFO```
This contains all of the information found in ```PEER_INFO``` for the local session but also includes the following: This contains all of the information found in ```PEER_INFO``` for the local session but also includes the following:
@ -240,7 +242,7 @@ This type id carries a 64bit unsighed LE int indicating the channel id.
format: ```8bytes - 64bit LE unsigned int (channel id)``` format: ```8bytes - 64bit LE unsigned int (channel id)```
```SESSION_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. 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 changes upon re-connection.
format: ```28bytes - session id (224bit sha3 hash)``` format: ```28bytes - session id (224bit sha3 hash)```
@ -307,6 +309,14 @@ This contains public information about a channel member.
data type. data type.
``` ```
```PROG```
This is a 8bit integer value from 0-100 indicating the percentage progress of the command. All long running module commands are encouraged to use this to update the client on command progress; sending it in a 1-5 second pulse rate.
format: ```1byte - 8bit integer (0-100)```
```PROG_LAST```
This is formatted and treated exactly like PROG except it indicates to the client that this is the last progress update for the current string of progress updates. So at the client side, progress strings/pulses should appear with a single or multiple PROG frame(s) and then end with PROG_LAST. Receiving an IDLE should also end the progress string if seen before PROG_LAST.
### 3.3 GEN_FILE Example ### ### 3.3 GEN_FILE Example ###
Setup: Setup:

View File

@ -5,7 +5,7 @@ installer_file="$2"
src_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" src_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
bin_name="mrci" bin_name="mrci"
app_version="2.2.3" app_version="3.0.0.0"
app_name="MRCI" app_name="MRCI"
install_dir="/opt/$bin_name" install_dir="/opt/$bin_name"
var_dir="/var/opt/$bin_name" var_dir="/var/opt/$bin_name"

View File

@ -78,13 +78,12 @@ void Session::castCatch(const QByteArray &data)
{ {
// format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)] // format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)]
if (matchChs(openSubChs, data.data())) if (matchAnyCh(openSubChs, data.data()))
{ {
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1; auto payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]); auto typeId = static_cast<quint8>(data[payloadOffs - 1]);
quint32 len = static_cast<quint32>(data.size() - payloadOffs); auto len = static_cast<quint32>(data.size() - payloadOffs);
auto *payload = data.data() + payloadOffs;
const char *payload = data.data() + payloadOffs;
asyncToClient(ASYNC_CAST, rdFromBlock(payload, len), typeId); asyncToClient(ASYNC_CAST, rdFromBlock(payload, len), typeId);
} }
@ -96,11 +95,10 @@ void Session::directDataFromPeer(const QByteArray &data)
if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0) if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0)
{ {
int payloadOffs = BLKSIZE_SESSION_ID + 1; auto payloadOffs = BLKSIZE_SESSION_ID + 1;
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]); auto typeId = static_cast<quint8>(data[payloadOffs - 1]);
quint32 len = static_cast<quint32>(data.size() - payloadOffs); auto len = static_cast<quint32>(data.size() - payloadOffs);
auto *payload = data.data() + payloadOffs;
const char *payload = data.data() + payloadOffs;
asyncToClient(ASYNC_TO_PEER, rdFromBlock(payload, len), typeId); asyncToClient(ASYNC_TO_PEER, rdFromBlock(payload, len), typeId);
} }
@ -112,13 +110,11 @@ void Session::p2p(const QByteArray &data)
if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0) if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0)
{ {
int payloadOffs = (BLKSIZE_SESSION_ID * 2) + 1; auto payloadOffs = (BLKSIZE_SESSION_ID * 2) + 1;
auto *src = data.data() + BLKSIZE_SESSION_ID;
const char *src = data.data() + BLKSIZE_SESSION_ID; auto *payload = data.data() + payloadOffs;
const char *payload = data.data() + payloadOffs; auto len = static_cast<quint32>(data.size() - payloadOffs);
auto typeId = static_cast<quint8>(data[payloadOffs - 1]);
quint32 len = static_cast<quint32>(data.size() - payloadOffs);
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]);
if (typeId == P2P_REQUEST) if (typeId == P2P_REQUEST)
{ {
@ -173,13 +169,12 @@ void Session::limitedCastCatch(const QByteArray &data)
{ {
// format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)] // format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)]
if (rd8BitFromBlock(activeUpdate) && matchChs(openSubChs, data.data())) if (rd8BitFromBlock(activeUpdate) && matchAnyCh(openSubChs, data.data()))
{ {
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1; auto payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
quint32 len = static_cast<quint32>(data.size() - payloadOffs); auto len = static_cast<quint32>(data.size() - payloadOffs);
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]); auto typeId = static_cast<quint8>(data[payloadOffs - 1]);
auto *payload = data.data() + payloadOffs;
const char *payload = data.data() + payloadOffs;
if (typeId == PING_PEERS) if (typeId == PING_PEERS)
{ {
@ -187,9 +182,9 @@ void Session::limitedCastCatch(const QByteArray &data)
// async command to also send PEER_INFO of this session to the session // async command to also send PEER_INFO of this session to the session
// that requested the ping using ASYNC_TO_PEER. // that requested the ping using ASYNC_TO_PEER.
QByteArray peerId = rdFromBlock(payload, BLKSIZE_SESSION_ID); auto peerId = rdFromBlock(payload, BLKSIZE_SESSION_ID);
QByteArray typeId = wrInt(PEER_INFO, 8); auto typeId = wrInt(PEER_INFO, 8);
QByteArray info = createPeerInfoFrame(); auto info = createPeerInfoFrame();
emit asyncToPeers(ASYNC_TO_PEER, peerId + typeId + info); emit asyncToPeers(ASYNC_TO_PEER, peerId + typeId + info);
@ -330,7 +325,7 @@ void Session::subChannelUpdated(quint16 cmdId, const QByteArray &data)
void Session::addModule(const QByteArray &data) void Session::addModule(const QByteArray &data)
{ {
QString modApp = fromTEXT(data); auto modApp = fromTEXT(data);
if (!modCmdNames.contains(modApp)) if (!modCmdNames.contains(modApp))
{ {
@ -340,7 +335,7 @@ void Session::addModule(const QByteArray &data)
void Session::rmModule(const QByteArray &data) void Session::rmModule(const QByteArray &data)
{ {
QString modApp = fromTEXT(data); auto modApp = fromTEXT(data);
if (modCmdNames.contains(modApp) && (modApp != QCoreApplication::applicationFilePath())) if (modCmdNames.contains(modApp) && (modApp != QCoreApplication::applicationFilePath()))
{ {
@ -362,7 +357,7 @@ void Session::rmModule(const QByteArray &data)
void Session::closeSubChannel(const QByteArray &data) void Session::closeSubChannel(const QByteArray &data)
{ {
QByteArray oldSubChs = QByteArray(openSubChs, MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL); auto oldSubChs = QByteArray(openSubChs, MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL);
if (rmBlockFromBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL)) if (rmBlockFromBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
{ {

View File

@ -82,6 +82,9 @@ CmdObject::CmdObject(QObject *parent) : MemShare(parent)
{ {
ipcWorker = new IPCWorker(pipe, nullptr); ipcWorker = new IPCWorker(pipe, nullptr);
keepAliveTimer = new QTimer(this); keepAliveTimer = new QTimer(this);
progTimer = new QTimer(this);
progCurrent = 0;
progMax = 0;
auto *thr = new QThread(nullptr); auto *thr = new QThread(nullptr);
@ -94,6 +97,7 @@ CmdObject::CmdObject(QObject *parent) : MemShare(parent)
connect(this, &CmdObject::procOut, ipcWorker, &IPCWorker::dataIn); connect(this, &CmdObject::procOut, ipcWorker, &IPCWorker::dataIn);
connect(keepAliveTimer, &QTimer::timeout, this, &CmdObject::keepAlive); connect(keepAliveTimer, &QTimer::timeout, this, &CmdObject::keepAlive);
connect(progTimer, &QTimer::timeout, this, &CmdObject::sendProg);
connect(ipcWorker, &IPCWorker::dataOut, this, &CmdObject::preProc); connect(ipcWorker, &IPCWorker::dataOut, this, &CmdObject::preProc);
connect(ipcWorker, &IPCWorker::termProc, this, &CmdObject::kill); connect(ipcWorker, &IPCWorker::termProc, this, &CmdObject::kill);
@ -102,6 +106,8 @@ CmdObject::CmdObject(QObject *parent) : MemShare(parent)
keepAliveTimer->setSingleShot(false); keepAliveTimer->setSingleShot(false);
keepAliveTimer->setInterval(30000); //30sec keep alive keepAliveTimer->setInterval(30000); //30sec keep alive
progTimer->setSingleShot(false);
progTimer->setInterval(1000); // 1sec progress updater
ipcWorker->moveToThread(thr); ipcWorker->moveToThread(thr);
thr->start(); thr->start();
} }
@ -113,7 +119,7 @@ CmdObject::CmdObject(QObject *parent) : MemShare(parent)
void CmdObject::term() void CmdObject::term()
{ {
if (flags & (MORE_INPUT | HALT_STATE | LOOPING)) if (flags & (MORE_INPUT | YIELD_STATE | LOOPING))
{ {
flags = 0; flags = 0;
retCode = ABORTED; retCode = ABORTED;
@ -140,20 +146,20 @@ void CmdObject::preProc(const QByteArray &data, quint8 typeId)
{ {
kill(); kill();
} }
else if (typeId == HALT_CMD) else if (typeId == YIELD_CMD)
{ {
if (flags & LOOPING) if (flags & LOOPING)
{ {
flags |= HALT_STATE; flags |= YIELD_STATE;
flags &= ~LOOPING; flags &= ~LOOPING;
} }
} }
else if (typeId == RESUME_CMD) else if (typeId == RESUME_CMD)
{ {
if (flags & HALT_STATE) if (flags & YIELD_STATE)
{ {
flags |= LOOPING; flags |= LOOPING;
flags &= ~HALT_STATE; flags &= ~YIELD_STATE;
} }
} }
else else
@ -174,7 +180,7 @@ void CmdObject::postProc()
{ {
preProc(QByteArray(), TEXT); preProc(QByteArray(), TEXT);
} }
else if (flags & (MORE_INPUT | HALT_STATE)) else if (flags & (MORE_INPUT | YIELD_STATE))
{ {
keepAliveTimer->start(); keepAliveTimer->start();
} }
@ -182,6 +188,11 @@ void CmdObject::postProc()
{ {
keepAliveTimer->stop(); keepAliveTimer->stop();
if (progTimer->isActive())
{
stopProgPulse();
}
emit procOut(wrInt(retCode, 16), IDLE); emit procOut(wrInt(retCode, 16), IDLE);
retCode = NO_ERRORS; retCode = NO_ERRORS;
@ -208,14 +219,50 @@ void CmdObject::bigTxt(const QString &txt)
emit procOut(toTEXT(txt), BIG_TEXT); emit procOut(toTEXT(txt), BIG_TEXT);
} }
void CmdObject::async(quint16 asyncId, quint8 asyncType, const QByteArray &data) void CmdObject::promptTxt(const QString &txt)
{ {
emit procOut(wrInt(asyncId, 16) + data, asyncType); emit procOut(toTEXT(txt), PROMPT_TEXT);
}
void CmdObject::async(quint16 asyncId, const QByteArray &data)
{
emit procOut(wrInt(asyncId, 16) + data, ASYNC_PAYLOAD);
} }
void CmdObject::keepAlive() void CmdObject::keepAlive()
{ {
async(ASYNC_KEEP_ALIVE, PRIV_IPC); async(ASYNC_KEEP_ALIVE);
}
void CmdObject::startProgPulse()
{
progCurrent = 0;
progTimer->start();
}
void CmdObject::stopProgPulse()
{
progTimer->stop();
emit procOut(wrInt(100, 8), PROG_LAST);
progCurrent = 0;
progMax = 0;
}
void CmdObject::sendProg()
{
quint8 percent = progCurrent / progMax * 100;
if ((progMax == 0) || (percent >= 100))
{
stopProgPulse();
}
else
{
emit procOut(wrInt(percent, 8), PROG);
}
} }
QString CmdObject::libName() QString CmdObject::libName()

View File

@ -65,15 +65,21 @@ class CmdObject : public MemShare
protected: protected:
QTimer *keepAliveTimer; QTimer *keepAliveTimer;
QTimer *progTimer;
IPCWorker *ipcWorker; IPCWorker *ipcWorker;
quint32 flags; quint32 flags;
quint16 retCode; quint16 retCode;
qint64 progCurrent;
qint64 progMax;
void mainTxt(const QString &txt); void mainTxt(const QString &txt);
void errTxt(const QString &txt); void errTxt(const QString &txt);
void privTxt(const QString &txt); void privTxt(const QString &txt);
void bigTxt(const QString &txt); void bigTxt(const QString &txt);
void async(quint16 asyncId, quint8 asyncType, const QByteArray &data = QByteArray()); void promptTxt(const QString &txt);
void async(quint16 asyncId, const QByteArray &data = QByteArray());
void startProgPulse();
void stopProgPulse();
void postProc(); void postProc();
QString libName(); QString libName();
@ -83,6 +89,7 @@ protected:
protected slots: protected slots:
void preProc(const QByteArray &data, quint8 typeId); void preProc(const QByteArray &data, quint8 typeId);
void sendProg();
void keepAlive(); void keepAlive();
void term(); void term();
void kill(); void kill();

View File

@ -128,13 +128,13 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
{ {
// a valid NEW_CMD must have a minimum of 259 bytes. // a valid NEW_CMD must have a minimum of 259 bytes.
QString cmdName = fromTEXT(data.mid(3, 128)).trimmed().toLower(); auto cmdName = fromTEXT(data.mid(3, 128)).trimmed().toLower();
if (isCmdLoaded(cmdName)) if (isCmdLoaded(cmdName))
{ {
if (!allowCmdLoad(cmdName)) if (!allowCmdLoad(cmdName))
{ {
quint16 cmdId = cmdRealNames->key(cmdName); auto cmdId = cmdRealNames->key(cmdName);
cmdIds->removeOne(cmdId); cmdIds->removeOne(cmdId);
cmdRealNames->remove(cmdId); cmdRealNames->remove(cmdId);
@ -152,9 +152,9 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
} }
else if (allowCmdLoad(cmdName)) else if (allowCmdLoad(cmdName))
{ {
quint16 cmdId = genCmdId(); auto cmdId = genCmdId();
QByteArray cmdIdBa = wrInt(cmdId, 16); auto cmdIdBa = wrInt(cmdId, 16);
QString unique = makeCmdUnique(cmdName); auto unique = makeCmdUnique(cmdName);
cmdIds->append(cmdId); cmdIds->append(cmdId);
cmdRealNames->insert(cmdId, cmdName); cmdRealNames->insert(cmdId, cmdName);
@ -167,12 +167,12 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
} }
else else
{ {
QStringList list = QStringList() << cmdName; auto list = QStringList() << cmdName;
modCmdNames->insert(program(), list); modCmdNames->insert(program(), list);
} }
QByteArray frame = cmdIdBa + data.mid(2, 1) + fixedToTEXT(unique, 128) + data.mid(131); auto frame = cmdIdBa + data.mid(2, 1) + fixedToTEXT(unique, 128) + data.mid(131);
emit dataToClient(toCmdId32(ASYNC_ADD_CMD, 0), frame, NEW_CMD); emit dataToClient(toCmdId32(ASYNC_ADD_CMD, 0), frame, NEW_CMD);
} }
@ -397,8 +397,9 @@ CmdProcess::CmdProcess(quint32 id, const QString &cmd, const QString &modApp, co
cmdIdle = false; cmdIdle = false;
} }
void CmdProcess::setSessionParams(QSharedMemory *mem, char *sesId, char *wrableSubChs) void CmdProcess::setSessionParams(QSharedMemory *mem, char *sesId, char *wrableSubChs, quint32 *hookCmd)
{ {
hook = hookCmd;
sesMem = mem; sesMem = mem;
sessionId = sesId; sessionId = sesId;
openWritableSubChs = wrableSubChs; openWritableSubChs = wrableSubChs;
@ -466,7 +467,7 @@ void CmdProcess::dataFromSession(quint32 id, const QByteArray &data, quint8 dTyp
bool CmdProcess::validAsync(quint16 async, const QByteArray &data, QTextStream &errMsg) bool CmdProcess::validAsync(quint16 async, const QByteArray &data, QTextStream &errMsg)
{ {
bool ret = true; auto ret = true;
if ((async == ASYNC_USER_DELETED) || (async == ASYNC_RW_MY_INFO) || (async == ASYNC_USER_LOGIN)) if ((async == ASYNC_USER_DELETED) || (async == ASYNC_RW_MY_INFO) || (async == ASYNC_USER_LOGIN))
{ {
@ -505,35 +506,31 @@ bool CmdProcess::validAsync(quint16 async, const QByteArray &data, QTextStream &
} }
else if ((async == ASYNC_CAST) || (async == ASYNC_LIMITED_CAST)) else if ((async == ASYNC_CAST) || (async == ASYNC_LIMITED_CAST))
{ {
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1; auto payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
sesMem->lock(); sesMem->lock();
if (data.size() < payloadOffs) if (data.size() < payloadOffs)
{ {
ret = false; errMsg << "cast header is not at least " << payloadOffs << " bytes long."; ret = false; errMsg << "the cast header is not at least " << payloadOffs << " bytes long.";
} }
else if (memcmp(data.data(), openWritableSubChs, static_cast<quint32>(payloadOffs - 1)) != 0) else if (!fullMatchChs(openWritableSubChs, data.data()))
{ {
ret = false; errMsg << "the open sub-channels (writable) does not match the actual open sub-channels."; ret = false; errMsg << "the sub-channels header contain a sub-channel that is not actually open for writing.";
} }
else if (rd8BitFromBlock(data.data() + (payloadOffs - 1)) == PING_PEERS) else if (rd8BitFromBlock(data.data() + (payloadOffs - 1)) == PING_PEERS)
{ {
// casting PING_PEERS to active update sessions are blocked. // casting PING_PEERS directly is blocked. command processes should use
// command processes should use ASYNC_PING_PEERS instead. // ASYNC_PING_PEERS instead.
ret = false; errMsg << "attempted to cast PING_PEERS which is forbidden for module commands."; ret = false; errMsg << "attempted to cast PING_PEERS which is forbidden for module commands.";
} }
sesMem->unlock(); sesMem->unlock();
} }
else if (async == ASYNC_TO_PEER)
{
ret = false; errMsg << "ASYNC_TO_PEER is forbidden for module commands.";
}
else if (async == ASYNC_P2P) else if (async == ASYNC_P2P)
{ {
int payloadOffs = ((BLKSIZE_SESSION_ID * 2) + 1); auto payloadOffs = ((BLKSIZE_SESSION_ID * 2) + 1);
if (data.size() < payloadOffs) if (data.size() < payloadOffs)
{ {
@ -578,62 +575,90 @@ bool CmdProcess::validAsync(quint16 async, const QByteArray &data, QTextStream &
ret = false; errMsg << "a 72bit sub-channel id header is not present."; ret = false; errMsg << "a 72bit sub-channel id header is not present.";
} }
} }
else if ((cmdId == ASYNC_NEW_CH_MEMBER) || (cmdId == ASYNC_INVITED_TO_CH) || else if ((async == ASYNC_NEW_CH_MEMBER) || (async == ASYNC_INVITED_TO_CH) ||
(cmdId == ASYNC_INVITE_ACCEPTED) || (cmdId == ASYNC_RM_CH_MEMBER) || (async == ASYNC_INVITE_ACCEPTED) || (async == ASYNC_RM_CH_MEMBER) ||
(cmdId == ASYNC_MEM_LEVEL_CHANGED)) (async == ASYNC_MEM_LEVEL_CHANGED))
{ {
if (data.size() < (BLKSIZE_USER_ID + BLKSIZE_CHANNEL_ID)) if (data.size() < (BLKSIZE_USER_ID + BLKSIZE_CHANNEL_ID))
{ {
ret = false; errMsg << "the channel member info header is not at least " << (BLKSIZE_USER_ID + BLKSIZE_CHANNEL_ID) << "bytes long."; ret = false; errMsg << "the channel member info header is not at least " << (BLKSIZE_USER_ID + BLKSIZE_CHANNEL_ID) << "bytes long.";
} }
} }
else if ((cmdId == ASYNC_RENAME_CH) || (cmdId == ASYNC_DEL_CH)) else if ((async == ASYNC_RENAME_CH) || (async == ASYNC_DEL_CH))
{ {
if (data.size() < BLKSIZE_CHANNEL_ID) if (data.size() < BLKSIZE_CHANNEL_ID)
{ {
ret = false; errMsg << "a 64bit channel id header was not found."; ret = false; errMsg << "a 64bit channel id header was not found.";
} }
} }
else if ((async == ASYNC_RDY) || (async == ASYNC_SYS_MSG) || (async == ASYNC_TO_PEER) ||
(async == ASYNC_ADD_CMD) || (async == ASYNC_RM_CMD))
{
ret = false; errMsg << "all modules are not allowed to send this async command directly.";
}
else if ((async < 1) || (async > 46))
{
ret = false; errMsg << "undefined async command id.";
}
return ret; return ret;
} }
void CmdProcess::asyncDirector(quint16 id, const QByteArray &payload)
{
if ((id == ASYNC_EXIT) || (id == ASYNC_MAXSES) || (id == ASYNC_LOGOUT) || (id == ASYNC_RESTART) ||
(id == ASYNC_END_SESSION) || (id == ASYNC_USER_LOGIN) || (id == ASYNC_OPEN_SUBCH) || (id == ASYNC_CLOSE_SUBCH) ||
(id == ASYNC_KEEP_ALIVE) || (id == ASYNC_SET_DIR) || (id == ASYNC_DEBUG_TEXT))
{
emit privIPC(id, payload);
}
else if ((id == ASYNC_CAST) || (id == ASYNC_LIMITED_CAST) || (id == ASYNC_P2P) || (id == ASYNC_CLOSE_P2P) ||
(id == ASYNC_PING_PEERS))
{
emit pubIPC(id, payload);
}
else if ((id == ASYNC_USER_DELETED) || (id == ASYNC_DISP_RENAMED) || (id == ASYNC_USER_RANK_CHANGED) || (id == ASYNC_CMD_RANKS_CHANGED) ||
(id == ASYNC_ENABLE_MOD) || (id == ASYNC_DISABLE_MOD) || (id == ASYNC_RW_MY_INFO) || (id == ASYNC_NEW_CH_MEMBER) ||
(id == ASYNC_DEL_CH) || (id == ASYNC_RENAME_CH) || (id == ASYNC_CH_ACT_FLAG) || (id == ASYNC_NEW_SUB_CH) ||
(id == ASYNC_RM_SUB_CH) || (id == ASYNC_RENAME_SUB_CH) || (id == ASYNC_INVITED_TO_CH) || (id == ASYNC_RM_CH_MEMBER) ||
(id == ASYNC_INVITE_ACCEPTED) || (id == ASYNC_MEM_LEVEL_CHANGED) || (id == ASYNC_SUB_CH_LEVEL_CHG) || (id == ASYNC_ADD_RDONLY) ||
(id == ASYNC_RM_RDONLY) || (id == ASYNC_USER_RENAMED))
{
emit pubIPCWithFeedBack(id, payload);
}
}
void CmdProcess::onDataFromProc(quint8 typeId, const QByteArray &data) void CmdProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
{ {
if ((typeId == PRIV_IPC) || (typeId == PUB_IPC) || (typeId == PUB_IPC_WITH_FEEDBACK)) if (typeId == ASYNC_PAYLOAD)
{ {
if (data.size() >= 2) if (data.size() >= 2)
{ {
quint16 async = rd16BitFromBlock(data.data()); auto async = rd16BitFromBlock(data.data());
// ASYNC_KEEP_ALIVE is blocked but not considered an error. it has already done // ASYNC_KEEP_ALIVE is blocked but not considered an error. it has already done
// it's job by getting transffered so it doesn't need to go any further. // it's job by getting transffered so it doesn't need to go any further.
if (async != ASYNC_KEEP_ALIVE) if (async != ASYNC_KEEP_ALIVE)
{ {
QByteArray payload = rdFromBlock(data.data() + 2, static_cast<quint32>(data.size() - 2)); auto payload = rdFromBlock(data.data() + 2, static_cast<quint32>(data.size() - 2));
QString errMsg; QString errMsg;
QTextStream errTxt(&errMsg); QTextStream errTxt(&errMsg);
if (async == ASYNC_DEBUG_TEXT)
{
typeId = PRIV_IPC;
}
if (validAsync(async, payload, errTxt)) if (validAsync(async, payload, errTxt))
{ {
if (typeId == PRIV_IPC) if (async == ASYNC_HOOK_INPUT)
{ {
emit privIPC(async, payload); *hook = cmdId;
} }
else if (typeId == PUB_IPC) else if (async == ASYNC_UNHOOK)
{ {
emit pubIPC(async, payload); *hook = 0;
} }
else else
{ {
emit pubIPCWithFeedBack(async, payload); asyncDirector(async, payload);
} }
} }
else else
@ -649,6 +674,11 @@ void CmdProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
{ {
cmdIdle = true; cmdIdle = true;
if (*hook == cmdId)
{
*hook = 0;
}
if (data.isEmpty()) if (data.isEmpty())
{ {
emit dataToClient(cmdId, wrInt(NO_ERRORS, 16), typeId); emit dataToClient(cmdId, wrInt(NO_ERRORS, 16), typeId);

View File

@ -107,12 +107,14 @@ private:
quint32 cmdId; quint32 cmdId;
QString cmdName; QString cmdName;
bool cmdIdle; bool cmdIdle;
quint32 *hook;
QSharedMemory *sesMem; QSharedMemory *sesMem;
char *sessionId; char *sessionId;
char *openWritableSubChs; char *openWritableSubChs;
void onReady(); void onReady();
void onFailToStart(); void onFailToStart();
void asyncDirector(quint16 id, const QByteArray &payload);
void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onDataFromProc(quint8 typeId, const QByteArray &data); void onDataFromProc(quint8 typeId, const QByteArray &data);
bool validAsync(quint16 async, const QByteArray &data, QTextStream &errMsg); bool validAsync(quint16 async, const QByteArray &data, QTextStream &errMsg);
@ -132,7 +134,7 @@ public:
explicit CmdProcess(quint32 id, const QString &cmd, const QString &modApp, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent = nullptr); explicit CmdProcess(quint32 id, const QString &cmd, const QString &modApp, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent = nullptr);
void dataFromSession(quint32 id, const QByteArray &data, quint8 dType); void dataFromSession(quint32 id, const QByteArray &data, quint8 dType);
void setSessionParams(QSharedMemory *mem, char *sesId, char *wrableSubChs); void setSessionParams(QSharedMemory *mem, char *sesId, char *wrableSubChs, quint32 *hookCmd);
bool startCmdProc(); bool startCmdProc();
signals: signals:

View File

@ -292,7 +292,7 @@ void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_RW_MY_INFO, PUB_IPC_WITH_FEEDBACK, uId); async(ASYNC_RW_MY_INFO, uId);
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
} }

View File

@ -36,7 +36,7 @@ void CloseHost::procIn(const QByteArray &binIn, quint8 dType)
{ {
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
async(ASYNC_EXIT, PRIV_IPC); async(ASYNC_EXIT);
} }
else if (input.isEmpty()) else if (input.isEmpty())
{ {
@ -46,14 +46,14 @@ void CloseHost::procIn(const QByteArray &binIn, quint8 dType)
else else
{ {
errTxt("err: Invalid response. you need to type 'CLOSE' exactly as shown without the quotes.\n"); errTxt("err: Invalid response. you need to type 'CLOSE' exactly as shown without the quotes.\n");
mainTxt("Enter 'CLOSE' to proceed or leave blank to cancel: "); promptTxt("Enter 'CLOSE' to proceed or leave blank to cancel: ");
} }
} }
else else
{ {
flags |= MORE_INPUT; flags |= MORE_INPUT;
mainTxt("You are about to shutdown the host instance, type: 'CLOSE' to proceed or leave blank to cancel: "); promptTxt("You are about to shutdown the host instance, type: 'CLOSE' to proceed or leave blank to cancel: ");
} }
} }
} }
@ -70,7 +70,7 @@ void RestartHost::procIn(const QByteArray &binIn, quint8 dType)
{ {
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
async(ASYNC_RESTART, PRIV_IPC); async(ASYNC_RESTART);
} }
else if (input.isEmpty()) else if (input.isEmpty())
{ {
@ -80,14 +80,14 @@ void RestartHost::procIn(const QByteArray &binIn, quint8 dType)
else if (!input.isEmpty()) else if (!input.isEmpty())
{ {
errTxt("err: Invalid response. you need to type 'RESTART' exactly as shown without the quotes.\n"); errTxt("err: Invalid response. you need to type 'RESTART' exactly as shown without the quotes.\n");
mainTxt("Enter 'RESTART' to proceed or leave blank to cancel: "); promptTxt("Enter 'RESTART' to proceed or leave blank to cancel: ");
} }
} }
else else
{ {
flags |= MORE_INPUT; flags |= MORE_INPUT;
mainTxt("You are about to re-start the host instance, type: 'RESTART' to proceed or leave blank to cancel: "); promptTxt("You are about to re-start the host instance, type: 'RESTART' to proceed or leave blank to cancel: ");
} }
} }
} }
@ -150,7 +150,7 @@ void ServSettings::printOptions()
level = 1; level = 1;
mainTxt(txt); promptTxt(txt);
} }
} }
@ -322,7 +322,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
txtOut << "" << endl << "Select an option: "; txtOut << "" << endl << "Select an option: ";
} }
mainTxt(txt); promptTxt(txt);
} }
else if (level == 2) else if (level == 2)
{ {
@ -343,12 +343,12 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if (!ok) if (!ok)
{ {
errTxt("err: Invalid 32bit unsigned integer. valid range: 1-4294967295.\n"); errTxt("err: Invalid 32bit unsigned integer. valid range: 1-4294967295.\n");
mainTxt("Enter a new value (leave blank to cancel): "); promptTxt("Enter a new value (leave blank to cancel): ");
} }
else if (num == 0) else if (num == 0)
{ {
errTxt("err: This value cannot be 0, valid range: 1-4294967295.\n"); errTxt("err: This value cannot be 0, valid range: 1-4294967295.\n");
mainTxt("Enter a new value (leave blank to cancel): "); promptTxt("Enter a new value (leave blank to cancel): ");
} }
else else
{ {
@ -364,7 +364,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if (select == 2) if (select == 2)
{ {
async(ASYNC_MAXSES, PRIV_IPC, wrInt(num, BLKSIZE_HOST_LOAD * 8)); async(ASYNC_MAXSES, wrInt(num, BLKSIZE_HOST_LOAD * 8));
} }
returnToStart(); returnToStart();
@ -375,7 +375,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if (!isBool(value)) if (!isBool(value))
{ {
errTxt("err: Invalid boolean value. must be 0 (false) or 1 (true).\n"); errTxt("err: Invalid boolean value. must be 0 (false) or 1 (true).\n");
mainTxt("Select an option (leave blank to cancel): "); promptTxt("Select an option (leave blank to cancel): ");
} }
else else
{ {
@ -400,7 +400,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if (!QFile::exists(expandEnvVariables(value))) if (!QFile::exists(expandEnvVariables(value)))
{ {
errTxt("err: The given file: '" + value + "' does not exists.\n"); errTxt("err: The given file: '" + value + "' does not exists.\n");
mainTxt("Enter a new path (leave blank to cancel): "); promptTxt("Enter a new path (leave blank to cancel): ");
} }
else else
{ {
@ -418,17 +418,17 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if (!value.contains(SUBJECT_SUB, Qt::CaseInsensitive)) if (!value.contains(SUBJECT_SUB, Qt::CaseInsensitive))
{ {
errTxt("err: The '" + QString(SUBJECT_SUB) + "' keyword is missing.\n"); errTxt("err: The '" + QString(SUBJECT_SUB) + "' keyword is missing.\n");
mainTxt("Enter a new command line (leave blank to cancel): "); promptTxt("Enter a new command line (leave blank to cancel): ");
} }
else if (!value.contains(TARGET_EMAIL_SUB, Qt::CaseInsensitive)) else if (!value.contains(TARGET_EMAIL_SUB, Qt::CaseInsensitive))
{ {
errTxt("err: The '" + QString(TARGET_EMAIL_SUB) + "' keyword is missing.\n"); errTxt("err: The '" + QString(TARGET_EMAIL_SUB) + "' keyword is missing.\n");
mainTxt("Enter a new command line (leave blank to cancel): "); promptTxt("Enter a new command line (leave blank to cancel): ");
} }
else if (!value.contains(MSG_SUB, Qt::CaseInsensitive)) else if (!value.contains(MSG_SUB, Qt::CaseInsensitive))
{ {
errTxt("err: The '" + QString(MSG_SUB) + "' keyword is missing.\n"); errTxt("err: The '" + QString(MSG_SUB) + "' keyword is missing.\n");
mainTxt("Enter a new command line (leave blank to cancel): "); promptTxt("Enter a new command line (leave blank to cancel): ");
} }
else else
{ {
@ -446,12 +446,12 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if (!isInt(value)) if (!isInt(value))
{ {
errTxt("err: '" + value + "' is not a valid integer.\n"); errTxt("err: '" + value + "' is not a valid integer.\n");
mainTxt("Enter a new value (leave blank to cancel): "); promptTxt("Enter a new value (leave blank to cancel): ");
} }
else if ((value.toInt() < 1) || (value.toInt() > 256)) else if ((value.toInt() < 1) || (value.toInt() > 256))
{ {
errTxt("err: A valid maximum sub-channels value ranges between 1-256.\n"); errTxt("err: A valid maximum sub-channels value ranges between 1-256.\n");
mainTxt("Enter a new value (leave blank to cancel): "); promptTxt("Enter a new value (leave blank to cancel): ");
} }
else else
{ {
@ -475,12 +475,12 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
else if (!validUserName(value)) else if (!validUserName(value))
{ {
errTxt("err: Invalid user name. it must be 2-24 chars long and contain no spaces.\n"); errTxt("err: Invalid user name. it must be 2-24 chars long and contain no spaces.\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (!userExists(value, &uId)) else if (!userExists(value, &uId))
{ {
errTxt("err: The requested user name does not exists.\n"); errTxt("err: The requested user name does not exists.\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else else
{ {

View File

@ -105,7 +105,7 @@ void Auth::confirmAuth()
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
async(ASYNC_USER_LOGIN, PRIV_IPC, uId); async(ASYNC_USER_LOGIN, uId);
mainTxt("Access granted.\n"); mainTxt("Access granted.\n");
} }
@ -150,7 +150,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
if (newUserName) if (newUserName)
{ {
mainTxt("Enter a new user name: "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else else
{ {
@ -170,27 +170,27 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
else if (noCaseMatch(DEFAULT_ROOT_USER, text)) else if (noCaseMatch(DEFAULT_ROOT_USER, text))
{ {
errTxt("err: '" + QString(DEFAULT_ROOT_USER) + "' is a reserved keyword. invalid for use as a user name.\n"); errTxt("err: '" + QString(DEFAULT_ROOT_USER) + "' is a reserved keyword. invalid for use as a user name.\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (validEmailAddr(text)) else if (validEmailAddr(text))
{ {
errTxt("err: Invaild use rname. it looks like an email address.\n"); errTxt("err: Invaild use rname. it looks like an email address.\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (!validUserName(text)) else if (!validUserName(text))
{ {
errTxt("err: Invalid user name. it must be 2-24 chars long and contain no spaces.\n\n"); errTxt("err: Invalid user name. it must be 2-24 chars long and contain no spaces.\n\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (noCaseMatch(text, uName)) else if (noCaseMatch(text, uName))
{ {
errTxt("err: You cannot re-apply your old user name.\n\n"); errTxt("err: You cannot re-apply your old user name.\n\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (userExists(text)) else if (userExists(text))
{ {
errTxt("err: The requested user name already exists.\n\n"); errTxt("err: The requested user name already exists.\n\n");
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else else
{ {
@ -202,7 +202,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_USER_RENAMED, PUB_IPC, uId + fixedToTEXT(text, BLKSIZE_USER_NAME)); async(ASYNC_USER_RENAMED, uId + fixedToTEXT(text, BLKSIZE_USER_NAME));
uName = text; uName = text;
newUserName = false; newUserName = false;
@ -236,7 +236,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (newUserName) else if (newUserName)
{ {
mainTxt("Enter a new user name (leave blank to cancel): "); promptTxt("Enter a new user name (leave blank to cancel): ");
} }
else else
{ {

View File

@ -73,7 +73,7 @@ int lowestAcessLevel(quint64 chId, quint8 subId)
void Cast::procIn(const QByteArray &binIn, quint8 dType) void Cast::procIn(const QByteArray &binIn, quint8 dType)
{ {
async(ASYNC_CAST, dType, binIn); async(ASYNC_CAST, rdFromBlock(openWritableSubChs, BLKSIZE_SUB_CHANNEL * MAX_OPEN_SUB_CHANNELS) + wrInt(dType, 8) + binIn);
} }
void OpenSubChannel::procIn(const QByteArray &binIn, quint8 dType) void OpenSubChannel::procIn(const QByteArray &binIn, quint8 dType)
@ -113,7 +113,7 @@ void OpenSubChannel::procIn(const QByteArray &binIn, quint8 dType)
{ {
retCode = NO_ERRORS; retCode = NO_ERRORS;
async(ASYNC_OPEN_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8)); async(ASYNC_OPEN_SUBCH, wrInt(chId, 64) + wrInt(subId, 8));
} }
} }
} }
@ -151,7 +151,7 @@ void CloseSubChannel::procIn(const QByteArray &binIn, quint8 dType)
{ {
retCode = NO_ERRORS; retCode = NO_ERRORS;
async(ASYNC_CLOSE_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8)); async(ASYNC_CLOSE_SUBCH, wrInt(chId, 64) + wrInt(subId, 8));
} }
} }
} }
@ -250,7 +250,7 @@ void PingPeers::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
async(ASYNC_PING_PEERS, PUB_IPC); async(ASYNC_PING_PEERS);
} }
} }
} }
@ -318,7 +318,7 @@ void AddRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_ACCESS_LEVEL, level.toInt()); db.addColumn(COLUMN_ACCESS_LEVEL, level.toInt());
db.exec(); db.exec();
async(ASYNC_ADD_RDONLY, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_ADD_RDONLY, frame);
} }
} }
} }
@ -386,7 +386,7 @@ void RemoveRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_ACCESS_LEVEL, level.toInt()); db.addCondition(COLUMN_ACCESS_LEVEL, level.toInt());
db.exec(); db.exec();
async(ASYNC_RM_RDONLY, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_RM_RDONLY, frame);
} }
} }
} }

View File

@ -95,7 +95,7 @@ void AddCert::ask()
{ {
flags |= MORE_INPUT; flags |= MORE_INPUT;
mainTxt("Common name: '" + coName + "' already exists. do you want to replace it? (y/n): "); promptTxt("Common name: '" + coName + "' already exists. do you want to replace it? (y/n): ");
} }
void AddCert::procIn(const QByteArray &binIn, quint8 dType) void AddCert::procIn(const QByteArray &binIn, quint8 dType)
@ -212,7 +212,7 @@ void RemoveCert::ask()
{ {
flags |= MORE_INPUT; flags |= MORE_INPUT;
mainTxt("Are you sure you want to remove the cert for common name: " + coName + "? (y/n): "); promptTxt("Are you sure you want to remove the cert for common name: " + coName + "? (y/n): ");
} }
void RemoveCert::procIn(const QByteArray &binIn, quint8 dType) void RemoveCert::procIn(const QByteArray &binIn, quint8 dType)

View File

@ -314,7 +314,7 @@ void CreateChannel::procIn(const QByteArray &binIn, uchar dType)
auto frame = createChMemberAsyncFrame(chId, uId, false, OWNER, uName, dName, chName); auto frame = createChMemberAsyncFrame(chId, uId, false, OWNER, uName, dName, chName);
async(ASYNC_NEW_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_NEW_CH_MEMBER, frame);
} }
} }
} }
@ -356,7 +356,7 @@ void RemoveChannel::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_CHANNEL_ID, chId); db.addCondition(COLUMN_CHANNEL_ID, chId);
db.exec(); db.exec();
async(ASYNC_DEL_CH, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64)); async(ASYNC_DEL_CH, wrInt(chId, 64));
} }
} }
} }
@ -414,7 +414,7 @@ void RenameChannel::procIn(const QByteArray &binIn, quint8 dType)
QByteArray frame = wrInt(chId, 64) + nullTermTEXT(newName); QByteArray frame = wrInt(chId, 64) + nullTermTEXT(newName);
async(ASYNC_RENAME_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_RENAME_CH, frame);
} }
} }
} }
@ -487,7 +487,7 @@ void SetActiveState::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
async(ASYNC_CH_ACT_FLAG, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + wrInt(subId, 8)); async(ASYNC_CH_ACT_FLAG, wrInt(chId, 64) + wrInt(subId, 8));
} }
} }
} }
@ -554,7 +554,7 @@ void CreateSubCh::procIn(const QByteArray &binIn, quint8 dType)
auto frame = wrInt(chId, 64) + wrInt(subId, 8) + wrInt(REGULAR, 8) + wrInt(0, 8) + nullTermTEXT(subName); auto frame = wrInt(chId, 64) + wrInt(subId, 8) + wrInt(REGULAR, 8) + wrInt(0, 8) + nullTermTEXT(subName);
async(ASYNC_NEW_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_NEW_SUB_CH, frame);
} }
} }
} }
@ -611,7 +611,7 @@ void RemoveSubCh::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_SUB_CH_ID, subId); db.addCondition(COLUMN_SUB_CH_ID, subId);
db.exec(); db.exec();
async(ASYNC_RM_SUB_CH, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + wrInt(subId, 8)); async(ASYNC_RM_SUB_CH, wrInt(chId, 64) + wrInt(subId, 8));
} }
} }
} }
@ -680,7 +680,7 @@ void RenameSubCh::procIn(const QByteArray &binIn, quint8 dType)
auto frame = wrInt(chId, 64) + wrInt(subId, 8) + nullTermTEXT(newName); auto frame = wrInt(chId, 64) + wrInt(subId, 8) + nullTermTEXT(newName);
async(ASYNC_RENAME_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_RENAME_SUB_CH, frame);
} }
} }
} }
@ -749,7 +749,7 @@ void InviteToCh::procIn(const QByteArray &binIn, quint8 dType)
auto frame = createChMemberAsyncFrame(chId, uId, true, REGULAR, uName, getDispName(uId), chName); auto frame = createChMemberAsyncFrame(chId, uId, true, REGULAR, uName, getDispName(uId), chName);
async(ASYNC_INVITED_TO_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_INVITED_TO_CH, frame);
} }
} }
} }
@ -788,7 +788,7 @@ void DeclineChInvite::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID)); db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID));
db.exec(); db.exec();
async(ASYNC_RM_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + rdFromBlock(userId, BLKSIZE_USER_ID)); async(ASYNC_RM_CH_MEMBER, wrInt(chId, 64) + rdFromBlock(userId, BLKSIZE_USER_ID));
} }
} }
} }
@ -828,7 +828,7 @@ void AcceptChInvite::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID)); db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID));
db.exec(); db.exec();
async(ASYNC_INVITE_ACCEPTED, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + rdFromBlock(userId, BLKSIZE_USER_ID)); async(ASYNC_INVITE_ACCEPTED, wrInt(chId, 64) + rdFromBlock(userId, BLKSIZE_USER_ID));
} }
} }
} }
@ -913,7 +913,7 @@ void RemoveChMember::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_RM_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + uId); async(ASYNC_RM_CH_MEMBER, wrInt(chId, 64) + uId);
} }
} }
} }
@ -997,7 +997,7 @@ void SetMemberLevel::procIn(const QByteArray &binIn, uchar dType)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_MEM_LEVEL_CHANGED, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + uId + wrInt(newLevel, 8)); async(ASYNC_MEM_LEVEL_CHANGED, wrInt(chId, 64) + uId + wrInt(newLevel, 8));
if (level.toInt() == OWNER) if (level.toInt() == OWNER)
{ {
@ -1007,7 +1007,7 @@ void SetMemberLevel::procIn(const QByteArray &binIn, uchar dType)
db.addCondition(COLUMN_USER_ID, owner); db.addCondition(COLUMN_USER_ID, owner);
db.exec(); db.exec();
async(ASYNC_MEM_LEVEL_CHANGED, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + owner + wrInt(ADMIN, 8)); async(ASYNC_MEM_LEVEL_CHANGED, wrInt(chId, 64) + owner + wrInt(ADMIN, 8));
} }
} }
} }
@ -1075,7 +1075,7 @@ void SetSubAcessLevel::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_CHANNEL_ID, chId); db.addCondition(COLUMN_CHANNEL_ID, chId);
db.exec(); db.exec();
async(ASYNC_SUB_CH_LEVEL_CHG, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + wrInt(subId, 8) + wrInt(level.toInt(), 8)); async(ASYNC_SUB_CH_LEVEL_CHG, wrInt(chId, 64) + wrInt(subId, 8) + wrInt(level.toInt(), 8));
} }
} }
} }

View File

@ -96,7 +96,7 @@ void AssignCmdRank::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_HOST_RANK, rank.toUInt()); db.addColumn(COLUMN_HOST_RANK, rank.toUInt());
db.exec(); db.exec();
async(ASYNC_CMD_RANKS_CHANGED, PUB_IPC_WITH_FEEDBACK); async(ASYNC_CMD_RANKS_CHANGED);
} }
} }
} }
@ -142,7 +142,7 @@ void RemoveCmdRank::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_MOD_MAIN, mod); db.addCondition(COLUMN_MOD_MAIN, mod);
db.exec(); db.exec();
async(ASYNC_CMD_RANKS_CHANGED, PUB_IPC_WITH_FEEDBACK); async(ASYNC_CMD_RANKS_CHANGED);
} }
} }
} }

View File

@ -48,7 +48,7 @@ QByteArray toFILE_INFO(const QFileInfo &info)
ret.append(wrInt(info.lastModified().toMSecsSinceEpoch(), 64)); ret.append(wrInt(info.lastModified().toMSecsSinceEpoch(), 64));
ret.append(wrInt(info.size(), 64)); ret.append(wrInt(info.size(), 64));
ret.append(toTEXT(info.fileName()) + strTerm); ret.append(toTEXT(info.fileName()) + strTerm);
ret.append(toTEXT(info.symLinkTarget() + strTerm)); ret.append(toTEXT(info.symLinkTarget()) + strTerm);
return ret; return ret;
} }
@ -91,8 +91,6 @@ void DownloadFile::onTerminate()
ssMode = false; ssMode = false;
paramsSet = false; paramsSet = false;
dataSent = 0;
len = 0;
flags = 0; flags = 0;
} }
@ -109,13 +107,11 @@ void DownloadFile::sendChunk()
} }
else else
{ {
dataSent += data.size(); progCurrent += data.size();
emit procOut(data, GEN_FILE); emit procOut(data, GEN_FILE);
mainTxt(QString::number(dataSent) + " / " + QString::number(len) + "\n"); if ((progCurrent >= progMax) || file->atEnd())
if ((dataSent >= len) || file->atEnd())
{ {
onTerminate(); onTerminate();
} }
@ -173,20 +169,24 @@ void DownloadFile::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
len = lenStr.toLongLong(); progMax = lenStr.toLongLong();
ssMode = argExists("-single_step", args); ssMode = argExists("-single_step", args);
paramsSet = true; paramsSet = true;
retCode = NO_ERRORS; retCode = NO_ERRORS;
flags |= MORE_INPUT; flags |= MORE_INPUT;
if ((len == 0) || (len > file->size())) if ((progMax == 0) || (progMax > file->size()))
{ {
len = file->size(); progMax = file->size();
} }
file->seek(offStr.toLongLong()); file->seek(offStr.toLongLong());
emit procOut(toTEXT("-len " + QString::number(len)), GEN_FILE); emit mainTxt("dl_file: " + path + "\n");
emit mainTxt("bytes: " + QString::number(progMax) + "\n");
emit procOut(toTEXT("-len " + QString::number(progMax)), GEN_FILE);
startProgPulse();
} }
} }
} }
@ -195,14 +195,12 @@ void UploadFile::onTerminate()
{ {
file->close(); file->close();
force = false; force = false;
confirm = false; confirm = false;
ssMode = false; ssMode = false;
dataReceived = 0; flags = 0;
len = 0; offs = 0;
flags = 0; mode = nullptr;
offs = 0;
mode = nullptr;
} }
void UploadFile::wrToFile(const QByteArray &data) void UploadFile::wrToFile(const QByteArray &data)
@ -218,11 +216,9 @@ void UploadFile::wrToFile(const QByteArray &data)
} }
else else
{ {
dataReceived += written; progCurrent += written;
mainTxt(QString::number(dataReceived) + " / " + QString::number(len) + "\n"); if (progCurrent >= progMax)
if (dataReceived >= len)
{ {
onTerminate(); onTerminate();
} }
@ -237,7 +233,7 @@ void UploadFile::ask()
{ {
confirm = true; confirm = true;
mainTxt("'" + file->fileName() + "' already exists, do you want to overwrite? (y/n): "); promptTxt("'" + file->fileName() + "' already exists, do you want to overwrite? (y/n): ");
} }
void UploadFile::run() void UploadFile::run()
@ -322,13 +318,15 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
force = argExists("-force", args); force = argExists("-force", args);
ssMode = argExists("-single_step", args); ssMode = argExists("-single_step", args);
len = lenStr.toLongLong(); progMax = lenStr.toLongLong();
offs = offStr.toLongLong(); offs = offStr.toLongLong();
retCode = NO_ERRORS; retCode = NO_ERRORS;
flags |= MORE_INPUT; flags |= MORE_INPUT;
file->setFileName(dst); file->setFileName(dst);
emit mainTxt("ul_file: " + dst + "\n");
emit mainTxt("bytes: " + QString::number(progMax) + "\n");
emit procOut(QByteArray(), GEN_FILE); emit procOut(QByteArray(), GEN_FILE);
if (QFileInfo(dst).exists() && !force) if (QFileInfo(dst).exists() && !force)
@ -347,7 +345,7 @@ void Delete::ask()
{ {
flags |= MORE_INPUT; flags |= MORE_INPUT;
mainTxt("Are you sure you want to delete the object? (y/n): "); promptTxt("Are you sure you want to delete the file/folder/symmlink? (y/n): ");
} }
void Delete::run() void Delete::run()
@ -419,7 +417,7 @@ void Delete::procIn(const QByteArray &binIn, uchar dType)
} }
else if (!QFileInfo(path).exists()) else if (!QFileInfo(path).exists())
{ {
errTxt("err: Object not found.\n"); errTxt("err: file/folder/symlink not found.\n");
} }
else if (!QFileInfo(path).isWritable()) else if (!QFileInfo(path).isWritable())
{ {
@ -435,11 +433,10 @@ void Delete::procIn(const QByteArray &binIn, uchar dType)
void Copy::onTerminate() void Copy::onTerminate()
{ {
fromQueue = false; fromQueue = false;
procedAFile = false; yToAll = false;
yToAll = false; nToAll = false;
nToAll = false; flags = 0;
flags = 0;
src->close(); src->close();
dst->close(); dst->close();
@ -459,7 +456,7 @@ void Copy::ask()
if (fromQueue) opts = "(y/n/y-all/n-all): "; if (fromQueue) opts = "(y/n/y-all/n-all): ";
else opts = "(y/n): "; else opts = "(y/n): ";
mainTxt("'" + dstPath + "' already exists, do you want to overwrite? " + opts); promptTxt("'" + dstPath + "' already exists, do you want to overwrite? " + opts);
} }
bool Copy::matchingVolumeMatters() bool Copy::matchingVolumeMatters()
@ -506,14 +503,10 @@ void Copy::run()
} }
else if (QFileInfo(srcPath).isSymLink()) else if (QFileInfo(srcPath).isSymLink())
{ {
if (procedAFile) mainTxt("\n");
mainTxt("mklink: '" + srcPath + "' --> '" + dstPath + "'\n"); mainTxt("mklink: '" + srcPath + "' --> '" + dstPath + "'\n");
if (QFile::link(QFileInfo(srcPath).symLinkTarget(), dstPath)) if (QFile::link(QFileInfo(srcPath).symLinkTarget(), dstPath))
{ {
procedAFile = true;
postProcFile(); postProcFile();
} }
else else
@ -528,6 +521,7 @@ void Copy::run()
} }
else if (QFileInfo(srcPath).isDir()) else if (QFileInfo(srcPath).isDir())
{ {
mainTxt("mkpath: '" + dstPath + "'\n");
mkPath(dstPath); mkPath(dstPath);
listDir(queue, srcPath, dstPath); listDir(queue, srcPath, dstPath);
@ -555,9 +549,8 @@ void Copy::run()
} }
else else
{ {
if (procedAFile) mainTxt("\n"); mainTxt("'" + srcPath + "' --> '" + dstPath + "'\n");
startProgPulse();
mainTxt("'" + srcPath + "' --> '" + dstPath + "'\n\n");
flags |= LOOPING; flags |= LOOPING;
} }
@ -572,15 +565,15 @@ void Copy::procIn(const QByteArray &binIn, uchar dType)
{ {
dst->write(src->read(LOCAL_BUFFSIZE)); dst->write(src->read(LOCAL_BUFFSIZE));
mainTxt(QString::number(src->pos()) + "/" + QString::number(src->size()) + "\n"); progMax = src->size();
progCurrent = src->pos();
if (src->atEnd()) if (src->atEnd())
{ {
procedAFile = true;
src->close(); src->close();
dst->close(); dst->close();
stopProgPulse();
postProcFile(); postProcFile();
} }
} }
@ -716,6 +709,8 @@ bool Move::matchingVolumeMatters()
void Move::runOnMatchingVolume() void Move::runOnMatchingVolume()
{ {
mainTxt("'" + srcPath + "' --> '" + dstPath + "'\n");
QFileInfo dstInfo(dstPath); QFileInfo dstInfo(dstPath);
if (dstInfo.exists()) if (dstInfo.exists())
@ -947,7 +942,7 @@ void ChangeDir::procIn(const QByteArray &binIn, quint8 dType)
QDir::setCurrent(path); QDir::setCurrent(path);
mainTxt(QDir::currentPath() + "\n"); mainTxt(QDir::currentPath() + "\n");
async(ASYNC_SET_DIR, PRIV_IPC, toTEXT(path)); async(ASYNC_SET_DIR, toTEXT(path));
} }
} }
} }

View File

@ -31,8 +31,6 @@ class DownloadFile : public CmdObject
private: private:
QFile *file; QFile *file;
qint64 len;
qint64 dataSent;
bool ssMode; bool ssMode;
bool paramsSet; bool paramsSet;
@ -58,8 +56,6 @@ private:
QFile::OpenMode mode; QFile::OpenMode mode;
QFile *file; QFile *file;
qint64 len;
qint64 dataReceived;
qint64 offs; qint64 offs;
bool ssMode; bool ssMode;
bool confirm; bool confirm;
@ -115,7 +111,6 @@ protected:
QFile *src; QFile *src;
QFile *dst; QFile *dst;
bool procedAFile;
bool fromQueue; bool fromQueue;
bool yToAll; bool yToAll;
bool nToAll; bool nToAll;

View File

@ -71,7 +71,7 @@ void AddMod::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_MOD_MAIN, path); db.addColumn(COLUMN_MOD_MAIN, path);
db.exec(); db.exec();
async(ASYNC_ENABLE_MOD, PUB_IPC_WITH_FEEDBACK, toTEXT(path)); async(ASYNC_ENABLE_MOD, toTEXT(path));
} }
} }
} }
@ -107,7 +107,7 @@ void DelMod::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_MOD_MAIN, path); db.addCondition(COLUMN_MOD_MAIN, path);
db.exec(); db.exec();
async(ASYNC_DISABLE_MOD, PUB_IPC_WITH_FEEDBACK, toTEXT(path)); async(ASYNC_DISABLE_MOD, toTEXT(path));
} }
} }
} }

View File

@ -50,7 +50,7 @@ void ToPeer::procIn(const QByteArray &binIn, quint8 dType)
auto data = rdFromBlock(binIn.data() + BLKSIZE_SESSION_ID, len - BLKSIZE_SESSION_ID); auto data = rdFromBlock(binIn.data() + BLKSIZE_SESSION_ID, len - BLKSIZE_SESSION_ID);
auto typeBa = wrInt(dType, 8); auto typeBa = wrInt(dType, 8);
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + data); async(ASYNC_P2P, dst + src + typeBa + data);
} }
} }
@ -80,7 +80,7 @@ void P2PRequest::procIn(const QByteArray &binIn, quint8 dType)
auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto typeBa = wrInt(P2P_REQUEST, 8); auto typeBa = wrInt(P2P_REQUEST, 8);
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + createPeerInfoFrame()); async(ASYNC_P2P, dst + src + typeBa + createPeerInfoFrame());
} }
} }
} }
@ -111,7 +111,7 @@ void P2POpen::procIn(const QByteArray &binIn, quint8 dType)
auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto typeBa = wrInt(P2P_OPEN, 8); auto typeBa = wrInt(P2P_OPEN, 8);
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + dst); async(ASYNC_P2P, dst + src + typeBa + dst);
} }
} }
} }
@ -139,7 +139,7 @@ void P2PClose::procIn(const QByteArray &binIn, quint8 dType)
auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto typeBa = wrInt(P2P_CLOSE, 8); auto typeBa = wrInt(P2P_CLOSE, 8);
async(P2P_CLOSE, PUB_IPC, dst + src + typeBa + dst); async(P2P_CLOSE, dst + src + typeBa + dst);
} }
} }
} }

View File

@ -122,11 +122,11 @@ void TableViewer::askDelete()
{ {
if (condAdded) if (condAdded)
{ {
mainTxt("This will delete rows from the table according to the parameters above. continue (y/n)?: "); promptTxt("This will delete rows from the table according to the parameters above. continue (y/n)?: ");
} }
else else
{ {
mainTxt("This will delete all rows in the table. continue (y/n)?: "); promptTxt("This will delete all rows in the table. continue (y/n)?: ");
} }
flags |= MORE_INPUT; flags |= MORE_INPUT;
@ -134,7 +134,7 @@ void TableViewer::askDelete()
void TableViewer::askPage() void TableViewer::askPage()
{ {
mainTxt("\nnext page (y/n)?: "); promptTxt("\nnext page (y/n)?: ");
flags |= MORE_INPUT; flags |= MORE_INPUT;
} }

View File

@ -226,14 +226,14 @@ void RemoveUser::rm()
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
async(ASYNC_USER_DELETED, PUB_IPC_WITH_FEEDBACK, uId); async(ASYNC_USER_DELETED, uId);
} }
void RemoveUser::ask() void RemoveUser::ask()
{ {
flags |= MORE_INPUT; flags |= MORE_INPUT;
mainTxt("Are you sure you want to permanently remove this user account? (y/n): "); promptTxt("Are you sure you want to permanently remove this user account? (y/n): ");
} }
void RemoveUser::procIn(const QByteArray &binIn, quint8 dType) void RemoveUser::procIn(const QByteArray &binIn, quint8 dType)
@ -365,7 +365,7 @@ void ChangeUserRank::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_USER_RANK_CHANGED, PUB_IPC_WITH_FEEDBACK, uId + wrInt(rank.toUInt(), 32)); async(ASYNC_USER_RANK_CHANGED, uId + wrInt(rank.toUInt(), 32));
} }
} }
} }
@ -449,7 +449,7 @@ void ChangeUsername::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID)); db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID));
db.exec(); db.exec();
async(ASYNC_USER_RENAMED, PUB_IPC_WITH_FEEDBACK, uId + newNameBa); async(ASYNC_USER_RENAMED, uId + newNameBa);
} }
} }
} }
@ -463,7 +463,7 @@ void ChangeDispName::procIn(const QByteArray &binIn, quint8 dType)
retCode = INVALID_PARAMS; retCode = INVALID_PARAMS;
if (argExists("-new_name", args)) if (!argExists("-new_name", args))
{ {
errTxt("err: New display name argument (-new_name) not found.\n"); errTxt("err: New display name argument (-new_name) not found.\n");
} }
@ -485,7 +485,7 @@ void ChangeDispName::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_DISP_RENAMED, PUB_IPC_WITH_FEEDBACK, uId + newNameBa); async(ASYNC_DISP_RENAMED, uId + newNameBa);
} }
} }
} }
@ -536,7 +536,7 @@ void OverWriteEmail::procArgs(const QString &uName, const QString &newEmail, boo
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
async(ASYNC_RW_MY_INFO, PUB_IPC_WITH_FEEDBACK, uId); async(ASYNC_RW_MY_INFO, uId);
} }
} }

View File

@ -469,17 +469,40 @@ bool isInt(const QString &str)
return ret; return ret;
} }
bool matchChs(const char *chsA, const char *chsB) bool matchAnyCh(const char *chsA, const char *chsB)
{ {
bool ret = false; bool ret = false;
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL) for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
{ {
if (posOfBlock(chsA + i, chsB, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) != -1) if (!isEmptyBlock(chsA + i, BLKSIZE_SUB_CHANNEL))
{ {
ret = true; if (posOfBlock(chsA + i, chsB, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) != -1)
{
ret = true;
break; break;
}
}
}
return ret;
}
bool fullMatchChs(const char *openChs, const char *comp)
{
bool ret = true;
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
{
if (!isEmptyBlock(comp + i, BLKSIZE_SUB_CHANNEL))
{
if (posOfBlock(comp + i, openChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) == -1)
{
ret = false;
break;
}
} }
} }

View File

@ -90,8 +90,8 @@
enum AsyncCommands : quint16 enum AsyncCommands : quint16
{ {
ASYNC_RDY = 1, // client | none ASYNC_RDY = 1, // client | retricted
ASYNC_SYS_MSG = 2, // client | none ASYNC_SYS_MSG = 2, // client | retricted
ASYNC_EXIT = 3, // internal | private ASYNC_EXIT = 3, // internal | private
ASYNC_CAST = 4, // client | public ASYNC_CAST = 4, // client | public
ASYNC_MAXSES = 5, // internal | private ASYNC_MAXSES = 5, // internal | private
@ -105,7 +105,7 @@ enum AsyncCommands : quint16
ASYNC_DISABLE_MOD = 13, // internal | public ASYNC_DISABLE_MOD = 13, // internal | public
ASYNC_END_SESSION = 14, // internal | private ASYNC_END_SESSION = 14, // internal | private
ASYNC_USER_LOGIN = 15, // internal | private ASYNC_USER_LOGIN = 15, // internal | private
ASYNC_TO_PEER = 16, // client | public | retricted ASYNC_TO_PEER = 16, // client | retricted
ASYNC_LIMITED_CAST = 17, // client | public ASYNC_LIMITED_CAST = 17, // client | public
ASYNC_RW_MY_INFO = 18, // internal | public ASYNC_RW_MY_INFO = 18, // internal | public
ASYNC_P2P = 19, // client | public ASYNC_P2P = 19, // client | public
@ -124,15 +124,17 @@ enum AsyncCommands : quint16
ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public
ASYNC_ADD_RDONLY = 33, // client | public ASYNC_ADD_RDONLY = 33, // client | public
ASYNC_RM_RDONLY = 34, // client | public ASYNC_RM_RDONLY = 34, // client | public
ASYNC_ADD_CMD = 35, // client | none ASYNC_ADD_CMD = 35, // client | retricted
ASYNC_RM_CMD = 36, // client | none ASYNC_RM_CMD = 36, // client | retricted
ASYNC_USER_RENAMED = 37, // internal | public ASYNC_USER_RENAMED = 37, // internal | public
ASYNC_PING_PEERS = 38, // internal | private ASYNC_PING_PEERS = 38, // internal | private
ASYNC_OPEN_SUBCH = 39, // internal | private ASYNC_OPEN_SUBCH = 39, // internal | private
ASYNC_CLOSE_SUBCH = 40, // internal | private ASYNC_CLOSE_SUBCH = 40, // internal | private
ASYNC_KEEP_ALIVE = 42, // internal | private ASYNC_KEEP_ALIVE = 42, // internal | private
ASYNC_SET_DIR = 43, // internal | private ASYNC_SET_DIR = 43, // internal | private
ASYNC_DEBUG_TEXT = 44 // internal | private ASYNC_DEBUG_TEXT = 44, // internal | private
ASYNC_HOOK_INPUT = 45, // internal | private
ASYNC_UNHOOK = 46 // internal | private
}; };
enum Flags : quint32 enum Flags : quint32
@ -153,7 +155,7 @@ enum Flags : quint32
MORE_INPUT = 1 << 13, MORE_INPUT = 1 << 13,
LOOPING = 1 << 14, LOOPING = 1 << 14,
SINGLE_STEP_MODE = 1 << 15, SINGLE_STEP_MODE = 1 << 15,
HALT_STATE = 1 << 16 YIELD_STATE = 1 << 16
}; };
enum FileInfoFlags : quint8 enum FileInfoFlags : quint8
@ -169,35 +171,36 @@ enum FileInfoFlags : quint8
enum TypeID : quint8 enum TypeID : quint8
{ {
GEN_FILE = 1, GEN_FILE = 1,
TEXT = 2, TEXT = 2,
ERR = 3, ERR = 3,
PRIV_TEXT = 4, PRIV_TEXT = 4,
IDLE = 5, IDLE = 5,
HOST_CERT = 6, HOST_CERT = 6,
FILE_INFO = 7, FILE_INFO = 7,
PEER_INFO = 8, PEER_INFO = 8,
MY_INFO = 9, MY_INFO = 9,
PEER_STAT = 10, PEER_STAT = 10,
P2P_REQUEST = 11, P2P_REQUEST = 11,
P2P_CLOSE = 12, P2P_CLOSE = 12,
P2P_OPEN = 13, P2P_OPEN = 13,
BYTES = 14, BYTES = 14,
SESSION_ID = 15, SESSION_ID = 15,
NEW_CMD = 16, NEW_CMD = 16,
CMD_ID = 17, CMD_ID = 17,
BIG_TEXT = 18, BIG_TEXT = 18,
TERM_CMD = 19, TERM_CMD = 19,
HOST_VER = 20, HOST_VER = 20,
PRIV_IPC = 21, PING_PEERS = 21,
PUB_IPC = 22, CH_MEMBER_INFO = 22,
PUB_IPC_WITH_FEEDBACK = 23, CH_ID = 23,
PING_PEERS = 24, KILL_CMD = 24,
CH_MEMBER_INFO = 25, YIELD_CMD = 25,
CH_ID = 26, RESUME_CMD = 26,
KILL_CMD = 27, PROMPT_TEXT = 27,
HALT_CMD = 28, PROG = 28,
RESUME_CMD = 29 PROG_LAST = 29,
ASYNC_PAYLOAD = 30
}; };
enum RetCode : quint16 enum RetCode : quint16
@ -265,7 +268,8 @@ bool matchedFsObjTypes(const QString &pathA, const QString &pathB);
bool matchedVolume(const QString &pathA, const QString &pathB); bool matchedVolume(const QString &pathA, const QString &pathB);
bool noCaseMatch(const QString &strA, const QString &strB); bool noCaseMatch(const QString &strA, const QString &strB);
bool argExists(const QString &key, const QStringList &args); bool argExists(const QString &key, const QStringList &args);
bool matchChs(const char *chsA, const char *chsB); bool matchAnyCh(const char *chsA, const char *chsB);
bool fullMatchChs(const char *openChs, const char *comp);
bool globalActiveFlag(); bool globalActiveFlag();
bool genSubId(quint64 chId, quint8 *newId); bool genSubId(quint64 chId, quint8 *newId);
bool isChOwner(const QByteArray &uId); bool isChOwner(const QByteArray &uId);

View File

@ -37,7 +37,7 @@
#include "shell.h" #include "shell.h"
#define APP_NAME "MRCI" #define APP_NAME "MRCI"
#define APP_VER "2.2.3" #define APP_VER "3.0.0.0"
#define APP_TARGET "mrci" #define APP_TARGET "mrci"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@ -110,7 +110,7 @@ int main(int argc, char *argv[])
qInstallMessageHandler(msgHandler); qInstallMessageHandler(msgHandler);
//args.append("-default_pw"); // debug //args.append("-host"); // debug
if (args.contains("-help", Qt::CaseInsensitive)) if (args.contains("-help", Qt::CaseInsensitive))
{ {

View File

@ -30,6 +30,7 @@ Session::Session(const QString &hostKey, QSslSocket *tcp, QObject *parent) : Mem
currentDir = QDir::currentPath(); currentDir = QDir::currentPath();
hostMemKey = hostKey; hostMemKey = hostKey;
tcpSocket = tcp; tcpSocket = tcp;
hookCmdId32 = 0;
tcpFrameCmdId = 0; tcpFrameCmdId = 0;
tcpPayloadSize = 0; tcpPayloadSize = 0;
tcpFrameType = 0; tcpFrameType = 0;
@ -123,6 +124,11 @@ void Session::cmdProcFinished(quint32 cmdId)
cmdProcesses.remove(cmdId); cmdProcesses.remove(cmdId);
frameQueue.remove(cmdId); frameQueue.remove(cmdId);
if (hookCmdId32 == cmdId)
{
hookCmdId32 = 0;
}
if (flags & END_SESSION_EMPTY_PROC) if (flags & END_SESSION_EMPTY_PROC)
{ {
endSession(); endSession();
@ -184,7 +190,7 @@ void Session::startCmdProc(quint32 cmdId)
auto *proc = new CmdProcess(cmdId, cmdRealNames[cmdId16], modApp, sesMemKey, hostMemKey, pipe, this); auto *proc = new CmdProcess(cmdId, cmdRealNames[cmdId16], modApp, sesMemKey, hostMemKey, pipe, this);
proc->setWorkingDirectory(currentDir); proc->setWorkingDirectory(currentDir);
proc->setSessionParams(sharedMem, sessionId, openWritableSubChs); proc->setSessionParams(sharedMem, sessionId, openWritableSubChs, &hookCmdId32);
connect(proc, &CmdProcess::cmdProcFinished, this, &Session::cmdProcFinished); connect(proc, &CmdProcess::cmdProcFinished, this, &Session::cmdProcFinished);
connect(proc, &CmdProcess::cmdProcReady, this, &Session::cmdProcStarted); connect(proc, &CmdProcess::cmdProcReady, this, &Session::cmdProcStarted);
@ -287,8 +293,15 @@ void Session::dataFromClient()
if (flags & FRAME_RDY) if (flags & FRAME_RDY)
{ {
if (tcpSocket->bytesAvailable() >= tcpPayloadSize) if (tcpSocket->bytesAvailable() >= tcpPayloadSize)
{ {
dataToCmd(tcpFrameCmdId, tcpSocket->read(tcpPayloadSize), tcpFrameType); if (hookCmdId32 != 0)
{
dataToCmd(hookCmdId32, tcpSocket->read(tcpPayloadSize), tcpFrameType);
}
else
{
dataToCmd(tcpFrameCmdId, tcpSocket->read(tcpPayloadSize), tcpFrameType);
}
flags ^= FRAME_RDY; flags ^= FRAME_RDY;
@ -323,6 +336,7 @@ void Session::dataFromClient()
servHeader.append(wrInt(ver[0].toULongLong(), 16)); servHeader.append(wrInt(ver[0].toULongLong(), 16));
servHeader.append(wrInt(ver[1].toULongLong(), 16)); servHeader.append(wrInt(ver[1].toULongLong(), 16));
servHeader.append(wrInt(ver[2].toULongLong(), 16)); servHeader.append(wrInt(ver[2].toULongLong(), 16));
servHeader.append(wrInt(ver[3].toULongLong(), 16));
servHeader.append(sessionId, BLKSIZE_SESSION_ID); servHeader.append(sessionId, BLKSIZE_SESSION_ID);
addIpAction("Session Active"); addIpAction("Session Active");

View File

@ -40,6 +40,7 @@ private:
QHash<quint16, QString> cmdAppById; QHash<quint16, QString> cmdAppById;
QList<quint16> cmdIds; QList<quint16> cmdIds;
quint32 flags; quint32 flags;
quint32 hookCmdId32;
quint32 tcpPayloadSize; quint32 tcpPayloadSize;
quint32 tcpFrameCmdId; quint32 tcpFrameCmdId;
quint8 tcpFrameType; quint8 tcpFrameType;