Files
adcs_api
cbor_protocol
channel_protocol
clyde_3g_eps_api
clyde_3g_eps_service
comms_service
db_test
eps_api
example_rust_c_service
example_rust_service
extern_lib
file_protocol
file_service
iobc_supervisor_service
isis_ants
isis_ants_api
isis_ants_service
isis_imtq_api
isis_iobc_supervisor
kubos_app
kubos_app_service
kubos_build_helper
kubos_file_client
kubos_service
kubos_shell_client
kubos_system
kubos_telemetry_db
large_download
large_upload
local_comms_service
mai400
mai400_api
mai400_service
monitor_service
novatel_oem6_api
novatel_oem6_service
nsl_duplex_d2
nsl_duplex_d2_comms_service
obc_hs
radio_api
rust_i2c
rust_mission_app
rust_uart
scheduler_service
serial_comms_service
shell_protocol
shell_service
telemetry_service
uart_comms_client
udp_client
utils
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
// Copyright (C) 2018 Kubos Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use crate::error::ProtocolError;
use channel_protocol::ChannelMessage;
use serde_cbor::Value;
use std::collections::HashMap;

/// Messages available in shell protocol
#[derive(Debug, Eq, PartialEq)]
pub enum Message {
    /// This message is sent by the shell service when a process exits
    Exit {
        /// Channel ID of shell session
        channel_id: u32,
        /// Exit code
        code: u32,
        /// Exit signal
        signal: u32,
    },
    /// This message is sent when an error occurs within the shell protocol
    Error {
        /// Channel ID of shell session
        channel_id: u32,
        /// Error condition encountered
        message: String,
    },
    /// This message is sent to the shell service to send a kill signal to the child process
    Kill {
        /// Channel ID of shell session
        channel_id: u32,
        /// Optional signal to use. Default is SIGKILL
        signal: Option<u32>,
    },
    /// This message is used to request and respond with the lists of processes
    /// currently running under the shell service.
    List {
        /// Channel ID of shell session
        channel_id: u32,
        /// Optional list of processes. No list is sent when
        /// a request is sent.
        process_list: Option<HashMap<u32, (String, u32)>>,
    },
    /// This message is sent by the shell service after a process is spawned
    /// to indicate the process' PID
    Pid {
        /// Channel ID of shell session
        channel_id: u32,
        /// PID of remote process
        pid: u32,
    },
    /// This message is sent to the shell service to request a child process to be spawned.
    Spawn {
        /// Channel ID of shell session
        channel_id: u32,
        /// Process command to spawn
        command: String,
        /// Optional arguments to pass into command when spawning
        args: Option<Vec<String>>,
        // TODO: Add these options:
        // - pty - boolean specifying need for a pty
        // - env - list of environment variables
        // - cwd - current working directory of process
        // - uid - uid of process
        // - gid - gid of processs
        // - detached - boolean specifying if child process should be detached
    },
    /// This message is sent by the shell service when a process has produced stdout data.
    /// The shell service will send this message with no data when the stdout pipe is closed.
    Stdout {
        /// Channel ID of shell session
        channel_id: u32,
        /// Optional stdout data
        data: Option<String>,
    },
    /// This message is sent by the shell service when a process has produced stderr data.
    /// The shell service will send this message with no data when the stderr pipe is closed.
    Stderr {
        /// Channel ID of shell session
        channel_id: u32,
        /// Optional stdout data
        data: Option<String>,
    },
    /// This message is sent by the shell client with stdin for a shell process.
    /// If sent without any data the shell service will close the stdin pipe.
    Stdin {
        /// Channel ID of shell session
        channel_id: u32,
        /// Optional stdin data
        data: Option<String>,
    },
}

/// Helper functions for Message::Error
pub mod error;
/// Helper functions for Message::Exit
pub mod exit;
/// Helper functions for Message::Kill
pub mod kill;
/// Helper functions for Message::List
pub mod list;
/// Helper functions for Message::Pid
pub mod pid;
/// Helper functions for Message::Spawn
pub mod spawn;
/// Helper functions for Message::Stderr
pub mod stderr;
/// Helper functions for Message::Stdin
pub mod stdin;
/// Helper functions for Message::Stdout
pub mod stdout;

/// Parse a ChannelMessage into a ShellMessage
pub fn parse_message(message: &ChannelMessage) -> Result<Message, ProtocolError> {
    match message.name.as_ref() {
        "exit" => Ok(exit::from_cbor(&message)?),
        "error" => Ok(error::from_cbor(&message)?),
        "kill" => Ok(kill::from_cbor(&message)?),
        "list" => Ok(list::from_cbor(&message)?),
        "pid" => Ok(pid::from_cbor(&message)?),
        "spawn" => Ok(spawn::from_cbor(&message)?),
        "stderr" => Ok(stderr::from_cbor(&message)?),
        "stdin" => Ok(stdin::from_cbor(&message)?),
        "stdout" => Ok(stdout::from_cbor(&message)?),
        _ => Err(ProtocolError::MessageParseError {
            err: "No message found".to_owned(),
        }),
    }
}