From 39a1c25e9b4e886fa2d52bd286355e3c108fd655 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Sat, 17 Aug 2019 22:04:43 -0400 Subject: [PATCH] GUACAMOLE-860: [WIP] Interim changes for TN5250 support. --- .gitignore | 2 + src/protocols/tn5250/sna.h | 4 ++ src/protocols/tn5250/tn5250.c | 89 ++++++++++++++++++++++++++++---- src/protocols/tn5250/tn5250.h | 35 +++++++------ src/terminal/terminal/terminal.h | 12 +++++ 5 files changed, 117 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index e716ee0f..05ca7865 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ stamp-h1 # Generated docs doc/doxygen-output +# IDE Configuration +nbproject/ \ No newline at end of file diff --git a/src/protocols/tn5250/sna.h b/src/protocols/tn5250/sna.h index 10776d95..5ec5a877 100644 --- a/src/protocols/tn5250/sna.h +++ b/src/protocols/tn5250/sna.h @@ -126,6 +126,10 @@ struct sna_flags { } sna_flags; +/** + * Defines the structure of a TN5250 (SNA over Telnet) packet, including + * the fields and the length of each field, as described in RFC1205. + */ struct sna_packet { /** diff --git a/src/protocols/tn5250/tn5250.c b/src/protocols/tn5250/tn5250.c index 6aae7460..76d378c8 100644 --- a/src/protocols/tn5250/tn5250.c +++ b/src/protocols/tn5250/tn5250.c @@ -40,7 +40,8 @@ /** * Support levels for various telnet options, required for connection - * negotiation by telnet_init(), part of libtelnet. + * negotiation by telnet_init(), part of libtelnet. The TN5250 specification + * requires at EOR, BINARY, and TTYPE. */ static const telnet_telopt_t __telnet_options[] = { { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, @@ -55,6 +56,7 @@ static const telnet_telopt_t __telnet_options[] = { }; /** + * ***Should be abstracted to common telnet support.*** * Write the entire buffer given to the specified file descriptor, retrying * the write automatically if necessary. This function will return a value * not equal to the buffer's size iff an error occurs which prevents all @@ -74,7 +76,7 @@ static int __guac_telnet_write_all(int fd, const char* buffer, int size) { if (ret_val <= 0) return -1; - /* If successful, contine with what data remains (if any) */ + /* If successful, continue with what data remains (if any) */ remaining -= ret_val; buffer += ret_val; @@ -201,6 +203,7 @@ static void* __guac_tn5250_input_thread(void* data) { } /** + * ***Abstract to common telnet code.*** * Connects to the telnet server specified within the data associated * with the given guac_client, which will have been populated by * guac_client_init. @@ -328,13 +331,6 @@ static void __guac_tn5250_send_uint8(telnet_t* telnet, uint8_t value) { telnet_send(telnet, (char*) (&value), 1); } -void guac_tn5250_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) { - telnet_begin_sb(telnet, TELNET_TELOPT_NAWS); - __guac_tn5250_send_uint16(telnet, width); - __guac_tn5250_send_uint16(telnet, height); - telnet_finish_sb(telnet); -} - void guac_tn5250_send_user(telnet_t* telnet, const char* username) { /* IAC SB NEW-ENVIRON IS */ @@ -404,6 +400,8 @@ void* guac_tn5250_client_thread(void* data) { settings->recording_include_keys); } + /* Calculate required terminal size based on type. */ + /* Create terminal */ tn5250_client->term = guac_terminal_create(client, tn5250_client->clipboard, settings->disable_copy, @@ -476,10 +474,83 @@ void* guac_tn5250_client_thread(void* data) { void __guac_tn5250_send_sna_packet(void* data, tn5250_flags flags, unsigned char opcode, char* data) { + /** + * Things to do, here: + * - Put the TN5250 header on + * - Set any flags + * - Set the Opcode + * - Write data + * - Write EOR + */ + + } void __guac_tn5250_recv_sna_packet(guac_client* client, telnet_event_t* event) { + /** + * Things to do, here: + * - Check for TN5250 header + * - Take off flags and process + * - Examine Opcode and handle (switch) + * - Read data and handle it (while) + * - Look for EOR (while) + */ + + /* Look for TN5250 header - abort if not found. */ + + /* Grab flags */ + + /* Process Opcode */ + switch (opcode) { + + case OPCODE_NOOP: + + break; + + case OPCODE_INVITE: + + break; + + case OPCODE_OUTPUT: + + break; + + case OPCODE_PUT_GET: + + break; + + case OPCODE_SAVE_SCREEN: + + break; + + case OPCODE_RESTORE_SCREEN: + + break; + + case OPCODE_READ_IMMEDIATE: + + break: + + case OPCODE_READ_SCREEN: + + break; + + case OPCODE_CANCEL_INVITE: + + break; + + case OPCODE_MSG_ON: + + break; + + case OPCODE_MSG_OFF: + + break; + + default: + + } } diff --git a/src/protocols/tn5250/tn5250.h b/src/protocols/tn5250/tn5250.h index c7316891..4a5f8912 100644 --- a/src/protocols/tn5250/tn5250.h +++ b/src/protocols/tn5250/tn5250.h @@ -37,23 +37,23 @@ typedef struct guac_tn5250_client { /** - * Telnet connection settings. + * TN5250 connection settings. */ guac_tn5250_settings* settings; /** - * The telnet client thread. + * The tn5250 client thread. */ pthread_t client_thread; /** - * The file descriptor of the socket connected to the telnet server, + * The file descriptor of the socket connected to the tn5250 server, * or -1 if no connection has been established. */ int socket_fd; /** - * Telnet connection, used by the telnet client thread. + * telnet connection, used by the tn5250 client thread. */ telnet_t* telnet; @@ -74,7 +74,7 @@ typedef struct guac_tn5250_client { guac_common_clipboard* clipboard; /** - * The terminal which will render all output from the telnet client. + * The terminal which will render all output from the tn5250 client. */ guac_terminal* term; @@ -86,20 +86,23 @@ typedef struct guac_tn5250_client { } guac_tn5250_client; +/** + * Possible Opcodes that can be sent by the mainframe or the client. + */ unsigned char tn5250_opcodes[] = { - 0x00, /* No operation */ - 0x01, /* Invite */ - 0x02, /* Output only */ - 0x03, /* Put/Get */ - 0x04, /* Save screen */ - 0x05, /* Restore screen */ - 0x06, /* Read immediate */ + OPCODE_NOOP, /* No operation */ + OPCODE_INVITE, /* Invite */ + OPCODE_OUTPUT, /* Output only */ + OPCODE_PUT_GET, /* Put/Get */ + OPCODE_SAVE_SCREEN, /* Save screen */ + OPCODE_RESTORE_SCREEN, /* Restore screen */ + OPCODE_READ_IMMEDIATE, /* Read immediate */ 0x07, /* Reserved */ - 0x08, /* Read screen */ + OPCODE_READ_SCREEN, /* Read screen */ 0x09, /* Reserved */ - 0x0a, /* Cancel invite */ - 0x0b, /* Turn on message light */ - 0x0c, /* Turn off message light */ + OPCODE_CANCEL_INVITE, /* Cancel invite */ + OPCODE_MSG_ON, /* Turn on message light */ + OPCODE_MSG_OFF, /* Turn off message light */ NULL } diff --git a/src/terminal/terminal/terminal.h b/src/terminal/terminal/terminal.h index 28e69357..25e020a2 100644 --- a/src/terminal/terminal/terminal.h +++ b/src/terminal/terminal/terminal.h @@ -824,6 +824,18 @@ int guac_terminal_write(guac_terminal* term, const char* c, int size); /** * Sets the character at the given row and column to the specified value. + * + * @param term + * The guac_terminal to manipulate. + * + * @param row + * The row on which the character is located. + * + * @param col + * THe column in which the character is located. + * + * @param codepoint + * The value to set. */ int guac_terminal_set(guac_terminal* term, int row, int col, int codepoint);