Skip to content

Commit

Permalink
Shell Handler functionality
Browse files Browse the repository at this point in the history
cli_ground_station
    - take a string as the message body
coms_handler
    - add server that listens to handler messages and sends to ground_station
    - clear message buffer properly
    - etc. typos, move constant declaration, mark unreachable code
shell_handler
    - execute command body from ground station and send back stdout
    - add client to talk to gs message server
    - switch to logging instead of println!
Msg
    - use msg_len in MsgHeader to construct message without trailing nulls
  • Loading branch information
shellbertt committed Oct 21, 2024
1 parent 502510b commit 8d7e937
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

# Vim swap files
# Vim files
.*.swp
Session.vim

# Used by editors to jump to definitions
tags
6 changes: 2 additions & 4 deletions ex3_ground_station/cli_ground_station/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ fn build_msg_from_operator_input(operator_str: String) -> Result<Msg, std::io::E
} else {
opcode = operator_str_split[1].parse::<u8>().unwrap();

for data_byte in operator_str_split[2..].iter() {
msg_body.push(data_byte.parse::<u8>().unwrap());
}
msg_body.extend(operator_str_split[2..].join(" ").bytes());
}

let msg = Msg::new(msg_type, 0, dest_id, component_ids::ComponentIds::GS as u8, opcode, msg_body);
Expand Down Expand Up @@ -318,7 +316,7 @@ async fn main() {
);

}
println!("Received Data: {:?}", read_buf);
println!("Received Message: {:?}, body {:?} = {}", recvd_msg.header, recvd_msg.msg_body,String::from_utf8(recvd_msg.msg_body.clone()).unwrap());
} else {
// Deallocate memory of these messages. Reconstructed version
// has been written to a file. This is slightly slower than .clear() though
Expand Down
2 changes: 1 addition & 1 deletion ex3_obc_fsw/handlers/coms_handler/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Coms Handler

The coms handler is the first and last part of the OBC FSW (aside from the interface the faciliates phsyical communication with the transceiver) for data communicated with the ground station (downlink and uplink).
The coms handler is the first and last part of the OBC FSW (aside from the interface that facilitates physical communication with the transceiver) for data communicated with the ground station (downlink and uplink).

## Scope of the Coms handler

Expand Down
24 changes: 20 additions & 4 deletions ex3_obc_fsw/handlers/coms_handler/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ use std::os::fd::OwnedFd;
use std::vec;
use tcp_interface::{Interface, TcpInterface};

// Something up with the slicing makes this number be the size that each packet ends up 128B
// const DONWLINK_MSG_BODY_SIZE: usize = 123; // 128B - 5 (header) - 2 (sequence number)

/// Setup function for decrypting incoming messages from the UHF transceiver
/// This just decrypts the bytes and does not return a message from the bytes
fn decrypt_bytes_from_gs(encrypted_bytes: &[u8]) -> Result<&[u8], std::io::Error> {
Expand Down Expand Up @@ -170,6 +167,8 @@ fn main() {
let mut bulk_msgs_read = 0;
let mut expected_msgs = 0;

let mut gs_interface_non_bulk: IpcServer = IpcServer::new("gs_non_bulk".to_string()).unwrap();

loop {
// Poll both the UHF transceiver and IPC unix domain socket for the GS channel
let mut clients = vec![&mut ipc_gs_interface];
Expand Down Expand Up @@ -299,7 +298,24 @@ fn main() {
// ERR -> If decryption fails or msg deserialization fails (inform sender what failed)
let ack_msg = Msg::new(0, ack_msg_id, GS, COMS, 200, ack_msg_body);
write_msg_to_uhf_for_downlink(&mut tcp_interface.as_mut().unwrap(), ack_msg);
// uhf_buf.clear(); //FOR SOME REASON CLEARING THE BUFFERS WOULD CAUSE THE CONNECTION TO DROP AFTER A SINGLE MSG IS READ
uhf_buf.fill(0);
}

// Handle regular messages for GS
let mut servers: Vec<&mut IpcServer> = vec![&mut gs_interface_non_bulk];
poll_ipc_server_sockets(&mut servers);

Check failure on line 306 in ex3_obc_fsw/handlers/coms_handler/src/main.rs

View workflow job for this annotation

GitHub Actions / build

mismatched types
if gs_interface_non_bulk.buffer != [0u8; IPC_BUFFER_SIZE] {
trace!("GS msg server \"{}\" received data", gs_interface_non_bulk.socket_path);
match deserialize_msg(&gs_interface_non_bulk.buffer) {
Ok(msg) => {
trace!("got {:?}", msg);
write_msg_to_uhf_for_downlink(&mut tcp_interface, msg);

Check failure on line 312 in ex3_obc_fsw/handlers/coms_handler/src/main.rs

View workflow job for this annotation

GitHub Actions / build

mismatched types
gs_interface_non_bulk.clear_buffer();
}
Err(err) => {
warn!("Error deserialising message for gs ({:?})", err);
}
}
}
}
}
Expand Down
49 changes: 46 additions & 3 deletions ex3_obc_fsw/handlers/shell_handler/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,40 @@ TODO - Setup a way to handle opcodes from messages passed to the handler
*/

use std::io::Error;
use ipc::{poll_ipc_clients, IpcClient, IPC_BUFFER_SIZE};
use std::process::{Command, Stdio};

use common::component_ids::ComponentIds::{GS, SHELL};
use common::constants::DONWLINK_MSG_BODY_SIZE;
use ipc::{ipc_write, poll_ipc_clients, IpcClient, IPC_BUFFER_SIZE};
use log::{debug, trace, warn};
use logging::*;
use message_structure::*;

struct ShellHandler {
msg_dispatcher_interface: Option<IpcClient>, // For communcation with other FSW components [internal to OBC]
gs_interface: Option<IpcClient>, // To send messages to the GS through the coms_handler
}

impl ShellHandler {
pub fn new(
msg_dispatcher_interface: Result<IpcClient, std::io::Error>,
gs_interface: Result<IpcClient, std::io::Error>,
) -> ShellHandler {
if msg_dispatcher_interface.is_err() {
warn!(
"Error creating dispatcher interface: {:?}",
msg_dispatcher_interface.as_ref().err().unwrap()
);
}
if gs_interface.is_err() {
warn!(
"Error creating gs interface: {:?}",
gs_interface.as_ref().err().unwrap()
);
}
ShellHandler {
msg_dispatcher_interface: msg_dispatcher_interface.ok(),
gs_interface: gs_interface.ok(),
}
}

Expand Down Expand Up @@ -69,18 +83,47 @@ impl ShellHandler {

fn handle_msg(&mut self, msg: Msg) -> Result<(), Error> {
self.msg_dispatcher_interface.as_mut().unwrap().clear_buffer();
println!("SHELL msg opcode: {} {:?}", msg.header.op_code, msg.msg_body);

trace!("SHELL msg opcode: {} {:?}", msg.header.op_code, msg.msg_body);

let body = String::from_utf8(msg.msg_body).unwrap();
let body_split = body.split(" ").collect::<Vec<_>>();

let mut command = Command::new(body_split[0]);
for arg in &body_split[1..] {
command.arg(arg);
}

// TODO K: commands should gracefully fail
let out = command.stdout(Stdio::piped())
.spawn()
.expect("Failed to start process")
.wait_with_output()
.expect("Failed to wait on child");

trace!("command outputted: {}", String::from_utf8(out.stdout.clone()).unwrap());

for chunk in out.stdout.chunks(DONWLINK_MSG_BODY_SIZE) {
let msg = Msg::new(MsgType::Cmd as u8, 0, GS as u8, SHELL as u8, 0, chunk.to_vec());
let _ = ipc_write(self.gs_interface.as_ref().unwrap().fd, &serialize_msg(&msg)?);
}

Ok(())
}
}

fn main() {
let log_path = "ex3_obc_fsw/handlers/shell_handler/logs";
init_logger(log_path);

trace!("Starting Shell Handler...");

// Create Unix domain socket interface for to talk to message dispatcher
let msg_dispatcher_interface = IpcClient::new("shell_handler".to_string());

let mut shell_handler = ShellHandler::new(msg_dispatcher_interface);
let gs_interface = IpcClient::new("gs_non_bulk".to_string());

let mut shell_handler = ShellHandler::new(msg_dispatcher_interface, gs_interface);

let _ = shell_handler.run();
}
3 changes: 3 additions & 0 deletions ex3_shared_libs/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ pub mod component_ids {
/// For constants that are used across the entire project
pub mod constants {
pub const UHF_MAX_MESSAGE_SIZE_BYTES: u8 = 128;

// Something up with the slicing makes this number be the size that each packet ends up 128B
pub const DONWLINK_MSG_BODY_SIZE: usize = 121; // 128 - 5 (header) - 2 (sequence number)
}

/// Here opcodes and their associated meaning are defined for each component
Expand Down
5 changes: 2 additions & 3 deletions ex3_shared_libs/message_structure/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,8 @@ impl Msg {
}

fn from_bytes(bytes: &[u8]) -> Result<Self, IoError> {
let header_bytes = &bytes[0..HEADER_SIZE];
let msg_body = bytes[HEADER_SIZE..].to_vec();
let header = MsgHeader::from_bytes(header_bytes)?;
let header = MsgHeader::from_bytes(&bytes[0..HEADER_SIZE])?;
let msg_body = bytes[HEADER_SIZE..header.msg_len as usize].to_vec(); // don't include trailing nulls in body
Ok(Msg { header, msg_body })
}
}
Expand Down

0 comments on commit 8d7e937

Please sign in to comment.