GUACAMOLE-860: [WIP] TN5250 adjustments.

This commit is contained in:
Nick Couchman 2019-08-03 17:15:02 -04:00
parent 22fe81913f
commit 30ec3be924
16 changed files with 431 additions and 308 deletions

View File

@ -30,50 +30,50 @@
#include <string.h>
/**
* All telnet connection settings which may be updated by unprivileged users
* All tn5250 connection settings which may be updated by unprivileged users
* through "argv" streams.
*/
typedef enum guac_telnet_argv_setting {
typedef enum guac_tn5250_argv_setting {
/**
* The color scheme of the terminal.
*/
GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME,
GUAC_TN5250_ARGV_SETTING_COLOR_SCHEME,
/**
* The name of the font family used by the terminal.
*/
GUAC_TELNET_ARGV_SETTING_FONT_NAME,
GUAC_TN5250_ARGV_SETTING_FONT_NAME,
/**
* The size of the font used by the terminal, in points.
*/
GUAC_TELNET_ARGV_SETTING_FONT_SIZE
GUAC_TN5250_ARGV_SETTING_FONT_SIZE
} guac_telnet_argv_setting;
} guac_tn5250_argv_setting;
/**
* The value or current status of a connection parameter received over an
* "argv" stream.
*/
typedef struct guac_telnet_argv {
typedef struct guac_tn5250_argv {
/**
* The specific setting being updated.
*/
guac_telnet_argv_setting setting;
guac_tn5250_argv_setting setting;
/**
* Buffer space for containing the received argument value.
*/
char buffer[GUAC_TELNET_ARGV_MAX_LENGTH];
char buffer[GUAC_TN5250_ARGV_MAX_LENGTH];
/**
* The number of bytes received so far.
*/
int length;
} guac_telnet_argv;
} guac_tn5250_argv;
/**
* Handler for "blob" instructions which appends the data from received blobs
@ -81,10 +81,10 @@ typedef struct guac_telnet_argv {
*
* @see guac_user_blob_handler
*/
static int guac_telnet_argv_blob_handler(guac_user* user,
static int guac_tn5250_argv_blob_handler(guac_user* user,
guac_stream* stream, void* data, int length) {
guac_telnet_argv* argv = (guac_telnet_argv*) stream->data;
guac_tn5250_argv* argv = (guac_tn5250_argv*) stream->data;
/* Calculate buffer size remaining, including space for null terminator,
* adjusting received length accordingly */
@ -106,40 +106,40 @@ static int guac_telnet_argv_blob_handler(guac_user* user,
*
* @see guac_user_end_handler
*/
static int guac_telnet_argv_end_handler(guac_user* user,
static int guac_tn5250_argv_end_handler(guac_user* user,
guac_stream* stream) {
int size;
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_terminal* terminal = telnet_client->term;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_terminal* terminal = tn5250_client->term;
/* Append null terminator to value */
guac_telnet_argv* argv = (guac_telnet_argv*) stream->data;
guac_tn5250_argv* argv = (guac_tn5250_argv*) stream->data;
argv->buffer[argv->length] = '\0';
/* Apply changes to chosen setting */
switch (argv->setting) {
/* Update color scheme */
case GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME:
case GUAC_TN5250_ARGV_SETTING_COLOR_SCHEME:
guac_terminal_apply_color_scheme(terminal, argv->buffer);
break;
/* Update font name */
case GUAC_TELNET_ARGV_SETTING_FONT_NAME:
case GUAC_TN5250_ARGV_SETTING_FONT_NAME:
guac_terminal_apply_font(terminal, argv->buffer, -1, 0);
break;
/* Update font size */
case GUAC_TELNET_ARGV_SETTING_FONT_SIZE:
case GUAC_TN5250_ARGV_SETTING_FONT_SIZE:
/* Update only if font size is sane */
size = atoi(argv->buffer);
if (size > 0) {
guac_terminal_apply_font(terminal, NULL, size,
telnet_client->settings->resolution);
tn5250_client->settings->resolution);
}
break;
@ -147,8 +147,8 @@ static int guac_telnet_argv_end_handler(guac_user* user,
}
/* Update terminal window size if connected */
if (telnet_client->telnet != NULL && telnet_client->naws_enabled)
guac_telnet_send_naws(telnet_client->telnet, terminal->term_width,
if (tn5250_client->tn5250 != NULL && tn5250_client->naws_enabled)
guac_tn5250_send_naws(tn5250_client->tn5250, terminal->term_width,
terminal->term_height);
free(argv);
@ -156,18 +156,18 @@ static int guac_telnet_argv_end_handler(guac_user* user,
}
int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
int guac_tn5250_argv_handler(guac_user* user, guac_stream* stream,
char* mimetype, char* name) {
guac_telnet_argv_setting setting;
guac_tn5250_argv_setting setting;
/* Allow users to update the color scheme and font details */
if (strcmp(name, "color-scheme") == 0)
setting = GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME;
setting = GUAC_TN5250_ARGV_SETTING_COLOR_SCHEME;
else if (strcmp(name, "font-name") == 0)
setting = GUAC_TELNET_ARGV_SETTING_FONT_NAME;
setting = GUAC_TN5250_ARGV_SETTING_FONT_NAME;
else if (strcmp(name, "font-size") == 0)
setting = GUAC_TELNET_ARGV_SETTING_FONT_SIZE;
setting = GUAC_TN5250_ARGV_SETTING_FONT_SIZE;
/* No other connection parameters may be updated */
else {
@ -177,13 +177,13 @@ int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
return 0;
}
guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv));
guac_tn5250_argv* argv = malloc(sizeof(guac_tn5250_argv));
argv->setting = setting;
argv->length = 0;
/* Prepare stream to receive argument value */
stream->blob_handler = guac_telnet_argv_blob_handler;
stream->end_handler = guac_telnet_argv_end_handler;
stream->blob_handler = guac_tn5250_argv_blob_handler;
stream->end_handler = guac_tn5250_argv_end_handler;
stream->data = argv;
/* Signal stream is ready */

View File

@ -18,8 +18,8 @@
*/
#ifndef GUAC_TELNET_ARGV_H
#define GUAC_TELNET_ARGV_H
#ifndef GUAC_TN5250_ARGV_H
#define GUAC_TN5250_ARGV_H
#include "config.h"
@ -29,13 +29,13 @@
* The maximum number of bytes to allow for any argument value received via an
* argv stream, including null terminator.
*/
#define GUAC_TELNET_ARGV_MAX_LENGTH 16384
#define GUAC_TN5250_ARGV_MAX_LENGTH 16384
/**
* Handles an incoming stream from a Guacamole "argv" instruction, updating the
* given connection parameter if that parameter is allowed to be updated.
*/
guac_user_argv_handler guac_telnet_argv_handler;
guac_user_argv_handler guac_tn5250_argv_handler;
#endif

View File

@ -21,7 +21,7 @@
#include "client.h"
#include "common/recording.h"
#include "settings.h"
#include "telnet.h"
#include "tn5250.h"
#include "terminal/terminal.h"
#include "user.h"
@ -36,23 +36,23 @@
int guac_client_init(guac_client* client) {
/* Set client args */
client->args = GUAC_TELNET_CLIENT_ARGS;
client->args = GUAC_TN5250_CLIENT_ARGS;
/* Allocate client instance data */
guac_telnet_client* telnet_client = calloc(1, sizeof(guac_telnet_client));
client->data = telnet_client;
guac_tn5250_client* tn5250_client = calloc(1, sizeof(guac_tn5250_client));
client->data = tn5250_client;
/* Init clipboard */
telnet_client->clipboard = guac_common_clipboard_alloc(GUAC_TELNET_CLIPBOARD_MAX_LENGTH);
tn5250_client->clipboard = guac_common_clipboard_alloc(GUAC_TN5250_CLIPBOARD_MAX_LENGTH);
/* Init telnet client */
telnet_client->socket_fd = -1;
telnet_client->naws_enabled = 0;
telnet_client->echo_enabled = 1;
/* Init tn5250 client */
tn5250_client->socket_fd = -1;
tn5250_client->naws_enabled = 0;
tn5250_client->echo_enabled = 1;
/* Set handlers */
client->join_handler = guac_telnet_user_join_handler;
client->free_handler = guac_telnet_client_free_handler;
client->join_handler = guac_tn5250_user_join_handler;
client->free_handler = guac_tn5250_client_free_handler;
/* Set locale and warn if not UTF-8 */
setlocale(LC_CTYPE, "");
@ -67,33 +67,33 @@ int guac_client_init(guac_client* client) {
}
int guac_telnet_client_free_handler(guac_client* client) {
int guac_tn5250_client_free_handler(guac_client* client) {
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Close telnet connection */
if (telnet_client->socket_fd != -1)
close(telnet_client->socket_fd);
/* Close tn5250 connection */
if (tn5250_client->socket_fd != -1)
close(tn5250_client->socket_fd);
/* Clean up recording, if in progress */
if (telnet_client->recording != NULL)
guac_common_recording_free(telnet_client->recording);
if (tn5250_client->recording != NULL)
guac_common_recording_free(tn5250_client->recording);
/* Kill terminal */
guac_terminal_free(telnet_client->term);
guac_terminal_free(tn5250_client->term);
/* Wait for and free telnet session, if connected */
if (telnet_client->telnet != NULL) {
pthread_join(telnet_client->client_thread, NULL);
telnet_free(telnet_client->telnet);
/* Wait for and free tn5250 session, if connected */
if (tn5250_client->telnet != NULL) {
pthread_join(tn5250_client->client_thread, NULL);
telnet_free(tn5250_client->telnet);
}
/* Free settings */
if (telnet_client->settings != NULL)
guac_telnet_settings_free(telnet_client->settings);
if (tn5250_client->settings != NULL)
guac_tn5250_settings_free(tn5250_client->settings);
guac_common_clipboard_free(telnet_client->clipboard);
free(telnet_client);
guac_common_clipboard_free(tn5250_client->clipboard);
free(tn5250_client);
return 0;
}

View File

@ -17,8 +17,8 @@
* under the License.
*/
#ifndef GUAC_TELNET__CLIENT_H
#define GUAC_TELNET__CLIENT_H
#ifndef GUAC_TN5250_CLIENT_H
#define GUAC_TN5250_CLIENT_H
#include "config.h"
#include "terminal/terminal.h"
@ -32,13 +32,13 @@
/**
* The maximum number of bytes to allow within the clipboard.
*/
#define GUAC_TELNET_CLIPBOARD_MAX_LENGTH 262144
#define GUAC_TN5250_CLIPBOARD_MAX_LENGTH 262144
/**
* Free handler. Required by libguac and called when the guac_client is
* disconnected and must be cleaned up.
*/
guac_client_free_handler guac_telnet_client_free_handler;
guac_client_free_handler guac_tn5250_client_free_handler;
#endif

View File

@ -20,40 +20,40 @@
#include "config.h"
#include "clipboard.h"
#include "common/clipboard.h"
#include "telnet.h"
#include "tn5250.h"
#include "terminal/terminal.h"
#include <guacamole/client.h>
#include <guacamole/stream.h>
#include <guacamole/user.h>
int guac_telnet_clipboard_handler(guac_user* user, guac_stream* stream,
int guac_tn5250_clipboard_handler(guac_user* user, guac_stream* stream,
char* mimetype) {
/* Clear clipboard and prepare for new data */
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_common_clipboard_reset(telnet_client->clipboard, mimetype);
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_common_clipboard_reset(tn5250_client->clipboard, mimetype);
/* Set handlers for clipboard stream */
stream->blob_handler = guac_telnet_clipboard_blob_handler;
stream->end_handler = guac_telnet_clipboard_end_handler;
stream->blob_handler = guac_tn5250_clipboard_blob_handler;
stream->end_handler = guac_tn5250_clipboard_end_handler;
return 0;
}
int guac_telnet_clipboard_blob_handler(guac_user* user, guac_stream* stream,
int guac_tn5250_clipboard_blob_handler(guac_user* user, guac_stream* stream,
void* data, int length) {
/* Append new data */
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_common_clipboard_append(telnet_client->clipboard, data, length);
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_common_clipboard_append(tn5250_client->clipboard, data, length);
return 0;
}
int guac_telnet_clipboard_end_handler(guac_user* user, guac_stream* stream) {
int guac_tn5250_clipboard_end_handler(guac_user* user, guac_stream* stream) {
/* Nothing to do - clipboard is implemented within client */

View File

@ -17,8 +17,8 @@
* under the License.
*/
#ifndef GUAC_TELNET_CLIPBOARD_H
#define GUAC_TELNET_CLIPBOARD_H
#ifndef GUAC_TN5250_CLIPBOARD_H
#define GUAC_TN5250_CLIPBOARD_H
#include "config.h"
@ -27,17 +27,17 @@
/**
* Handler for inbound clipboard streams.
*/
guac_user_clipboard_handler guac_telnet_clipboard_handler;
guac_user_clipboard_handler guac_tn5250_clipboard_handler;
/**
* Handler for data received along clipboard streams.
*/
guac_user_blob_handler guac_telnet_clipboard_blob_handler;
guac_user_blob_handler guac_tn5250_clipboard_blob_handler;
/**
* Handler for end-of-stream related to clipboard.
*/
guac_user_end_handler guac_telnet_clipboard_end_handler;
guac_user_end_handler guac_tn5250_clipboard_end_handler;
#endif

View File

@ -21,7 +21,7 @@
#include "common/recording.h"
#include "input.h"
#include "terminal/terminal.h"
#include "telnet.h"
#include "tn5250.h"
#include <guacamole/client.h>
#include <guacamole/user.h>
@ -32,20 +32,20 @@
#include <sys/types.h>
#include <unistd.h>
int guac_telnet_user_mouse_handler(guac_user* user, int x, int y, int mask) {
int guac_tn5250_user_mouse_handler(guac_user* user, int x, int y, int mask) {
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings;
guac_terminal* term = telnet_client->term;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_tn5250_settings* settings = tn5250_client->settings;
guac_terminal* term = tn5250_client->term;
/* Skip if terminal not yet ready */
if (term == NULL)
return 0;
/* Report mouse position within recording */
if (telnet_client->recording != NULL)
guac_common_recording_report_mouse(telnet_client->recording, x, y,
if (tn5250_client->recording != NULL)
guac_common_recording_report_mouse(tn5250_client->recording, x, y,
mask);
/* Send mouse if not searching for password or username */
@ -56,16 +56,16 @@ int guac_telnet_user_mouse_handler(guac_user* user, int x, int y, int mask) {
}
int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) {
int guac_tn5250_user_key_handler(guac_user* user, int keysym, int pressed) {
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings;
guac_terminal* term = telnet_client->term;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_tn5250_settings* settings = tn5250_client->settings;
guac_terminal* term = tn5250_client->term;
/* Report key state within recording */
if (telnet_client->recording != NULL)
guac_common_recording_report_key(telnet_client->recording,
if (tn5250_client->recording != NULL)
guac_common_recording_report_key(tn5250_client->recording,
keysym, pressed);
/* Skip if terminal not yet ready */
@ -104,7 +104,7 @@ int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) {
)) {
/* Send IAC BRK */
telnet_iac(telnet_client->telnet, TELNET_BREAK);
telnet_iac(tn5250_client->telnet, TELNET_BREAK);
return 0;
}
@ -116,12 +116,12 @@ int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) {
}
int guac_telnet_user_size_handler(guac_user* user, int width, int height) {
int guac_tn5250_user_size_handler(guac_user* user, int width, int height) {
/* Get terminal */
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_terminal* terminal = telnet_client->term;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_terminal* terminal = tn5250_client->term;
/* Skip if terminal not yet ready */
if (terminal == NULL)
@ -131,8 +131,8 @@ int guac_telnet_user_size_handler(guac_user* user, int width, int height) {
guac_terminal_resize(terminal, width, height);
/* Update terminal window size if connected */
if (telnet_client->telnet != NULL && telnet_client->naws_enabled)
guac_telnet_send_naws(telnet_client->telnet, terminal->term_width,
if (tn5250_client->telnet != NULL && tn5250_client->naws_enabled)
guac_tn5250_send_naws(tn5250_client->telnet, terminal->term_width,
terminal->term_height);
return 0;

View File

@ -17,8 +17,8 @@
* under the License.
*/
#ifndef GUAC_TELNET_INPUT_H
#define GUAC_TELNET_INPUT_H
#ifndef GUAC_TN5250_INPUT_H
#define GUAC_TN5250_INPUT_H
#include "config.h"
@ -28,19 +28,19 @@
* Handler for key events. Required by libguac and called whenever key events
* are received.
*/
guac_user_key_handler guac_telnet_user_key_handler;
guac_user_key_handler guac_tn5250_user_key_handler;
/**
* Handler for mouse events. Required by libguac and called whenever mouse
* events are received.
*/
guac_user_mouse_handler guac_telnet_user_mouse_handler;
guac_user_mouse_handler guac_tn5250_user_mouse_handler;
/**
* Handler for size events. Required by libguac and called whenever the remote
* display (window) is resized.
*/
guac_user_size_handler guac_telnet_user_size_handler;
guac_user_size_handler guac_tn5250_user_size_handler;
#endif

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "pipe.h"
#include "telnet.h"
#include "tn5250.h"
#include "terminal/terminal.h"
#include <guacamole/protocol.h>
@ -28,15 +28,15 @@
#include <string.h>
int guac_telnet_pipe_handler(guac_user* user, guac_stream* stream,
int guac_tn5250_pipe_handler(guac_user* user, guac_stream* stream,
char* mimetype, char* name) {
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Redirect STDIN if pipe has required name */
if (strcmp(name, GUAC_TELNET_STDIN_PIPE_NAME) == 0) {
guac_terminal_send_stream(telnet_client->term, user, stream);
if (strcmp(name, GUAC_TN5250_STDIN_PIPE_NAME) == 0) {
guac_terminal_send_stream(tn5250_client->term, user, stream);
return 0;
}

View File

@ -18,8 +18,8 @@
*/
#ifndef GUAC_TELNET_PIPE_H
#define GUAC_TELNET_PIPE_H
#ifndef GUAC_TN5250_PIPE_H
#define GUAC_TN5250_PIPE_H
#include "config.h"
@ -29,14 +29,14 @@
* The name reserved for the inbound pipe stream which forces the terminal
* emulator's STDIN to be received from the pipe.
*/
#define GUAC_TELNET_STDIN_PIPE_NAME "STDIN"
#define GUAC_TN5250_STDIN_PIPE_NAME "STDIN"
/**
* Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe
* is named "STDIN", the the contents of the pipe stream are redirected to
* STDIN of the terminal emulator for as long as the pipe is open.
*/
guac_user_pipe_handler guac_telnet_pipe_handler;
guac_user_pipe_handler guac_tn5250_pipe_handler;
#endif

View File

@ -33,6 +33,7 @@
const char* GUAC_TN5250_CLIENT_ARGS[] = {
"hostname",
"port",
"ssl",
"username",
"username-regex",
"password",
@ -60,7 +61,7 @@ const char* GUAC_TN5250_CLIENT_ARGS[] = {
NULL
};
enum TELNET_ARGS_IDX {
enum TN5250_ARGS_IDX {
/**
* The hostname to connect to. Required.
@ -71,6 +72,11 @@ enum TELNET_ARGS_IDX {
* The port to connect to. Optional.
*/
IDX_PORT,
/**
* Whether or not to use SSL. Optional.
*/
IDX_SSL,
/**
* The name of the user to login as. Optional.
@ -232,13 +238,13 @@ enum TELNET_ARGS_IDX {
*/
IDX_DISABLE_PASTE,
TELNET_ARGS_COUNT
TN5250_ARGS_COUNT
};
/**
* Compiles the given regular expression, returning NULL if compilation fails
* or of the given regular expression is NULL. The returned regex_t must be
* freed with regfree() AND free(), or with guac_telnet_regex_free().
* freed with regfree() AND free(), or with guac_tn5250_regex_free().
*
* @param user
* The user who provided the setting associated with the given regex
@ -251,7 +257,7 @@ enum TELNET_ARGS_IDX {
* The compiled regular expression, or NULL if compilation fails or NULL
* was originally provided for the pattern.
*/
static regex_t* guac_telnet_compile_regex(guac_user* user, char* pattern) {
static regex_t* guac_tn5250_compile_regex(guac_user* user, char* pattern) {
/* Nothing to compile if no pattern provided */
if (pattern == NULL)
@ -275,7 +281,7 @@ static regex_t* guac_telnet_compile_regex(guac_user* user, char* pattern) {
return regex;
}
void guac_telnet_regex_free(regex_t** regex) {
void guac_tn5250_regex_free(regex_t** regex) {
if (*regex != NULL) {
regfree(*regex);
free(*regex);
@ -283,100 +289,100 @@ void guac_telnet_regex_free(regex_t** regex) {
}
}
guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
guac_tn5250_settings* guac_tn5250_parse_args(guac_user* user,
int argc, const char** argv) {
/* Validate arg count */
if (argc != TELNET_ARGS_COUNT) {
if (argc != TN5250_ARGS_COUNT) {
guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection "
"parameters provided: expected %i, got %i.",
TELNET_ARGS_COUNT, argc);
TN5250_ARGS_COUNT, argc);
return NULL;
}
guac_telnet_settings* settings = calloc(1, sizeof(guac_telnet_settings));
guac_tn5250_settings* settings = calloc(1, sizeof(guac_tn5250_settings));
/* Read parameters */
/* Read hostname */
settings->hostname =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_HOSTNAME, "");
/* Read username */
settings->username =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_USERNAME, NULL);
/* Read username regex only if username is specified */
if (settings->username != NULL) {
settings->username_regex = guac_telnet_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_USERNAME_REGEX, GUAC_TELNET_DEFAULT_USERNAME_REGEX));
settings->username_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_USERNAME_REGEX, GUAC_TN5250_DEFAULT_USERNAME_REGEX));
}
/* Read password */
settings->password =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_PASSWORD, NULL);
/* Read password regex only if password is specified */
if (settings->password != NULL) {
settings->password_regex = guac_telnet_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_PASSWORD_REGEX, GUAC_TELNET_DEFAULT_PASSWORD_REGEX));
settings->password_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_PASSWORD_REGEX, GUAC_TN5250_DEFAULT_PASSWORD_REGEX));
}
/* Read optional login success detection regex */
settings->login_success_regex = guac_telnet_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
settings->login_success_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_LOGIN_SUCCESS_REGEX, NULL));
/* Read optional login failure detection regex */
settings->login_failure_regex = guac_telnet_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
settings->login_failure_regex = guac_tn5250_compile_regex(user,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_LOGIN_FAILURE_REGEX, NULL));
/* Both login success and login failure regexes must be provided if either
* is present at all */
if (settings->login_success_regex != NULL
&& settings->login_failure_regex == NULL) {
guac_telnet_regex_free(&settings->login_success_regex);
guac_tn5250_regex_free(&settings->login_success_regex);
guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for "
"\"%s\" as \"%s\" must also be provided.",
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX],
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX]);
GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX],
GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX]);
}
else if (settings->login_failure_regex != NULL
&& settings->login_success_regex == NULL) {
guac_telnet_regex_free(&settings->login_failure_regex);
guac_tn5250_regex_free(&settings->login_failure_regex);
guac_user_log(user, GUAC_LOG_WARNING, "Ignoring provided value for "
"\"%s\" as \"%s\" must also be provided.",
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX],
GUAC_TELNET_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX]);
GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_FAILURE_REGEX],
GUAC_TN5250_CLIENT_ARGS[IDX_LOGIN_SUCCESS_REGEX]);
}
/* Read-only mode */
settings->read_only =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_READ_ONLY, false);
/* Read maximum scrollback size */
settings->max_scrollback =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_SCROLLBACK, GUAC_TELNET_DEFAULT_MAX_SCROLLBACK);
guac_user_parse_args_int(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_SCROLLBACK, GUAC_TN5250_DEFAULT_MAX_SCROLLBACK);
/* Read font name */
settings->font_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_FONT_NAME, GUAC_TELNET_DEFAULT_FONT_NAME);
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_FONT_NAME, GUAC_TN5250_DEFAULT_FONT_NAME);
/* Read font size */
settings->font_size =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_FONT_SIZE, GUAC_TELNET_DEFAULT_FONT_SIZE);
guac_user_parse_args_int(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_FONT_SIZE, GUAC_TN5250_DEFAULT_FONT_SIZE);
/* Copy requested color scheme */
settings->color_scheme =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_COLOR_SCHEME, "");
/* Pull width/height/resolution directly from user */
@ -384,74 +390,84 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
settings->height = user->info.optimal_height;
settings->resolution = user->info.optimal_resolution;
/* Read SSL */
settings->ssl =
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_SSL, false);
int defualt_port = GUAC_TN5250_DEFAULT_PORT;
if (settings->ssl)
default_port = GUAC_TN5250_DEFAULT_SSL_PORT;
/* Read port */
settings->port =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_PORT, GUAC_TELNET_DEFAULT_PORT);
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_PORT, defualt_port);
/* Read typescript path */
settings->typescript_path =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_PATH, NULL);
/* Read typescript name */
settings->typescript_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_NAME, GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME);
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_TYPESCRIPT_NAME, GUAC_TN5250_DEFAULT_TYPESCRIPT_NAME);
/* Parse path creation flag */
settings->create_typescript_path =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_CREATE_TYPESCRIPT_PATH, false);
/* Read recording path */
settings->recording_path =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_PATH, NULL);
/* Read recording name */
settings->recording_name =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
IDX_RECORDING_NAME, GUAC_TELNET_DEFAULT_RECORDING_NAME);
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_NAME, GUAC_TN5250_DEFAULT_RECORDING_NAME);
/* Parse output exclusion flag */
settings->recording_exclude_output =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_EXCLUDE_OUTPUT, false);
/* Parse mouse exclusion flag */
settings->recording_exclude_mouse =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_EXCLUDE_MOUSE, false);
/* Parse key event inclusion flag */
settings->recording_include_keys =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_RECORDING_INCLUDE_KEYS, false);
/* Parse path creation flag */
settings->create_recording_path =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_CREATE_RECORDING_PATH, false);
/* Parse backspace key code */
settings->backspace =
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_int(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_BACKSPACE, 127);
/* Read terminal emulator type. */
settings->terminal_type =
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_string(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_TERMINAL_TYPE, "linux");
/* Parse clipboard copy disable flag */
settings->disable_copy =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_DISABLE_COPY, false);
/* Parse clipboard paste disable flag */
settings->disable_paste =
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
guac_user_parse_args_boolean(user, GUAC_TN5250_CLIENT_ARGS, argv,
IDX_DISABLE_PASTE, false);
/* Parsing was successful */
@ -459,7 +475,7 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
}
void guac_telnet_settings_free(guac_telnet_settings* settings) {
void guac_tn5250_settings_free(guac_tn5250_settings* settings) {
/* Free network connection information */
free(settings->hostname);
@ -470,10 +486,10 @@ void guac_telnet_settings_free(guac_telnet_settings* settings) {
free(settings->password);
/* Free various regexes */
guac_telnet_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex);
guac_telnet_regex_free(&settings->login_success_regex);
guac_telnet_regex_free(&settings->login_failure_regex);
guac_tn5250_regex_free(&settings->username_regex);
guac_tn5250_regex_free(&settings->password_regex);
guac_tn5250_regex_free(&settings->login_success_regex);
guac_tn5250_regex_free(&settings->login_failure_regex);
/* Free display preferences */
free(settings->font_name);

View File

@ -31,63 +31,170 @@
/**
* The name of the font to use for the terminal if no name is specified.
*/
#define GUAC_TELNET_DEFAULT_FONT_NAME "monospace"
#define GUAC_TN5250_DEFAULT_FONT_NAME "monospace"
/**
* The size of the font to use for the terminal if no font size is specified,
* in points.
*/
#define GUAC_TELNET_DEFAULT_FONT_SIZE 12
#define GUAC_TN5250_DEFAULT_FONT_SIZE 12
/**
* The port to connect to when initiating any telnet connection, if no other
* The port to connect to when initiating a 5250 telnet connection, if no other
* port is specified.
*/
#define GUAC_TELNET_DEFAULT_PORT "23"
#define GUAC_TN5250_DEFAULT_PORT "23"
/**
* The port to connect to when initiating a 5250 telnet connection over SSL,
* if no other port is specified.
*/
#define GUAC_TN5250_DEFAULT_SSL_PORT "992"
/**
* The filename to use for the typescript, if not specified.
*/
#define GUAC_TELNET_DEFAULT_TYPESCRIPT_NAME "typescript"
#define GUAC_TN5250_DEFAULT_TYPESCRIPT_NAME "typescript"
/**
* The filename to use for the screen recording, if not specified.
*/
#define GUAC_TELNET_DEFAULT_RECORDING_NAME "recording"
#define GUAC_TN5250_DEFAULT_RECORDING_NAME "recording"
/**
* The regular expression to use when searching for the username/login prompt
* if no other regular expression is specified.
*/
#define GUAC_TELNET_DEFAULT_USERNAME_REGEX "[Ll]ogin:"
#define GUAC_TN5250_DEFAULT_USERNAME_REGEX "[Ll]ogin:"
/**
* The regular expression to use when searching for the password prompt if no
* other regular expression is specified.
*/
#define GUAC_TELNET_DEFAULT_PASSWORD_REGEX "[Pp]assword:"
#define GUAC_TN5250_DEFAULT_PASSWORD_REGEX "[Pp]assword:"
/**
* The default maximum scrollback size in rows.
*/
#define GUAC_TELNET_DEFAULT_MAX_SCROLLBACK 1000
#define GUAC_TN5250_DEFAULT_MAX_SCROLLBACK 1000
/**
* Settings for the telnet connection. The values for this structure are parsed
* from the arguments given during the Guacamole protocol handshake using the
* guac_telnet_parse_args() function.
* The available terminal types for TN5250 connections. These are defined
* in RFC-1205, Section 2.
*/
typedef struct guac_telnet_settings {
typedef enum guac_tn5250_terminal_types {
/**
* IBM-3179-2, 24 x 80 color display
*/
IBM_3179_2,
/**
* The hostname of the telnet server to connect to.
* IBM-3180-2, 27 x 132 monochrome display
*/
IBM_3180_2,
/**
* IBM-3196-A1, 24 x 80 monochrome display
*/
IBM_3196_A1,
/**
* IBM-3477-FC, 27 x 132 color display
*/
IBM_3477_FC,
/**
* IBM-3477-FG, 27 x 132 monochrome display
*/
IBM_3477_FG,
/**
* IBM-5251-11, 24 x 80 monochrome display
*/
IBM_5251_11,
/**
* IBM-5291-1, 24 x 80 monochrome display
*/
IBM_5291_1,
/**
* IBM-5292-2, 24 x 80 color display
*/
IBM_5292_2,
/**
* IBM-5555-B01, 24 x 80 Double-Byte Character Set (DBCS)
*/
IBM_5555_B01,
/**
* IBM-5555-C01, 24 x 80 Double-Byte Character Set color display
*/
IBM_5555_C01
} guac_tn5250_terminal_type;
typedef struct __guac_tn5250_terminal_params {
/**
* The type of terminal, as defined in RFC-1205
*/
guac_tn5250_terminal_type terminal;
/**
* The number of rows in the terminal
*/
int rows;
/**
* The number of columns in the terminal
*/
int cols;
/**
* True if the terminal supports color, false if only monochrome.
*/
bool color;
} __guac_tn5250_terminal_params;
__guac_tn5250_terminal_params __guac_tn5250_terminals[] = {
{IBM_3179_2, 24, 80, true },
{IBM_3180_2, 27, 132, false},
{IBM_3196_A1, 24, 80, false},
{IBM_3477_FC, 27, 132, true },
{IBM_3477_FG, 27, 132, false},
{IBM_5251_11, 24, 80, false},
{IBM_5291_1, 24, 80, false},
{IBM_5292_2, 24, 80, true },
{IBM_5555_B01, 24, 80, false},
{IBM_5555_C01, 24, 80, true },
{NULL, -1, -1, false}
}
/**
* Settings for the TN5250 connection. The values for this structure are parsed
* from the arguments given during the Guacamole protocol handshake using the
* guac_tn5250_parse_args() function.
*/
typedef struct guac_tn5250_settings {
/**
* The hostname of the TN5250 server to connect to.
*/
char* hostname;
/**
* The port of the telnet server to connect to.
* The port of the TN5250 server to connect to.
*/
char* port;
/**
* Whether or not to use SSL.
*/
bool ssl;
/**
* The name of the user to login as, if any. If no username is specified,
@ -246,7 +353,7 @@ typedef struct guac_telnet_settings {
bool recording_include_keys;
/**
* The ASCII code, as an integer, that the telnet client will use when the
* The ASCII code, as an integer, that the 5250 client will use when the
* backspace key is pressed. By default, this is 127, ASCII delete, if
* not specified in the client settings.
*/
@ -255,9 +362,9 @@ typedef struct guac_telnet_settings {
/**
* The terminal emulator type that is passed to the remote system.
*/
char* terminal_type;
guac_tn5250_terminal_type terminal_type;
} guac_telnet_settings;
} guac_tn5250_settings;
/**
* Parses all given args, storing them in a newly-allocated settings object. If
@ -275,10 +382,10 @@ typedef struct guac_telnet_settings {
*
* @return
* A newly-allocated settings object which must be freed with
* guac_telnet_settings_free() when no longer needed. If the arguments fail
* guac_tn5250_settings_free() when no longer needed. If the arguments fail
* to parse, NULL is returned.
*/
guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
guac_tn5250_settings* guac_tn5250_parse_args(guac_user* user,
int argc, const char** argv);
/**
@ -289,21 +396,21 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
* @param regex
* The address of the pointer to the regex that should be freed.
*/
void guac_telnet_regex_free(regex_t** regex);
void guac_tn5250_regex_free(regex_t** regex);
/**
* Frees the given guac_telnet_settings object, having been previously
* allocated via guac_telnet_parse_args().
* Frees the given guac_tn5250_settings object, having been previously
* allocated via guac_tn5250_parse_args().
*
* @param settings
* The settings object to free.
*/
void guac_telnet_settings_free(guac_telnet_settings* settings);
void guac_tn5250_settings_free(guac_tn5250_settings* settings);
/**
* NULL-terminated array of accepted client args.
*/
extern const char* GUAC_TELNET_CLIENT_ARGS[];
extern const char* GUAC_TN5250_CLIENT_ARGS[];
#endif

View File

@ -88,13 +88,13 @@ static int __guac_telnet_write_all(int fd, const char* buffer, int size) {
* sent after the value is sent.
*
* @param client
* The guac_client associated with the telnet session.
* The guac_client associated with the tn5250 session.
*
* @param regex
* The regex to search for within the given line buffer.
*
* @param value
* The string value to send through STDIN of the telnet session if a
* The string value to send through STDIN of the tn5250 session if a
* match is found, or NULL if no value should be sent.
*
* @param line_buffer
@ -103,18 +103,18 @@ static int __guac_telnet_write_all(int fd, const char* buffer, int size) {
* @return
* true if a match is found, false otherwise.
*/
static bool guac_telnet_regex_exec(guac_client* client, regex_t* regex,
static bool guac_tn5250_regex_exec(guac_client* client, regex_t* regex,
const char* value, const char* line_buffer) {
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Send value upon match */
if (regexec(regex, line_buffer, 0, NULL, 0) == 0) {
/* Send value */
if (value != NULL) {
guac_terminal_send_string(telnet_client->term, value);
guac_terminal_send_string(telnet_client->term, "\x0D");
guac_terminal_send_string(tn5250_client->term, value);
guac_terminal_send_string(tn5250_client->term, "\x0D");
}
/* Stop searching for prompt */
@ -134,60 +134,60 @@ static bool guac_telnet_regex_exec(guac_client* client, regex_t* regex,
* completed, this function has no effect.
*
* @param client
* The guac_client associated with the telnet session.
* The guac_client associated with the tn5250 session.
*
* @param line_buffer
* The line of character data to test.
*/
static void guac_telnet_search_line(guac_client* client, const char* line_buffer) {
static void guac_tn5250_search_line(guac_client* client, const char* line_buffer) {
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_tn5250_settings* settings = tn5250_client->settings;
/* Continue search for username prompt */
if (settings->username_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->username_regex,
if (guac_tn5250_regex_exec(client, settings->username_regex,
settings->username, line_buffer)) {
guac_client_log(client, GUAC_LOG_DEBUG, "Username sent");
guac_telnet_regex_free(&settings->username_regex);
guac_tn5250_regex_free(&settings->username_regex);
}
}
/* Continue search for password prompt */
if (settings->password_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->password_regex,
if (guac_tn5250_regex_exec(client, settings->password_regex,
settings->password, line_buffer)) {
guac_client_log(client, GUAC_LOG_DEBUG, "Password sent");
/* Do not continue searching for username/password once password is sent */
guac_telnet_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex);
guac_tn5250_regex_free(&settings->username_regex);
guac_tn5250_regex_free(&settings->password_regex);
}
}
/* Continue search for login success */
if (settings->login_success_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->login_success_regex,
if (guac_tn5250_regex_exec(client, settings->login_success_regex,
NULL, line_buffer)) {
/* Allow terminal to render now that login has been deemed successful */
guac_client_log(client, GUAC_LOG_DEBUG, "Login successful");
guac_terminal_start(telnet_client->term);
guac_terminal_start(tn5250_client->term);
/* Stop all searches */
guac_telnet_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex);
guac_telnet_regex_free(&settings->login_success_regex);
guac_telnet_regex_free(&settings->login_failure_regex);
guac_tn5250_regex_free(&settings->username_regex);
guac_tn5250_regex_free(&settings->password_regex);
guac_tn5250_regex_free(&settings->login_success_regex);
guac_tn5250_regex_free(&settings->login_failure_regex);
}
}
/* Continue search for login failure */
if (settings->login_failure_regex != NULL) {
if (guac_telnet_regex_exec(client, settings->login_failure_regex,
if (guac_tn5250_regex_exec(client, settings->login_failure_regex,
NULL, line_buffer)) {
/* Advise that login has failed and connection should be closed */
@ -196,10 +196,10 @@ static void guac_telnet_search_line(guac_client* client, const char* line_buffer
"Login failed");
/* Stop all searches */
guac_telnet_regex_free(&settings->username_regex);
guac_telnet_regex_free(&settings->password_regex);
guac_telnet_regex_free(&settings->login_success_regex);
guac_telnet_regex_free(&settings->login_failure_regex);
guac_tn5250_regex_free(&settings->username_regex);
guac_tn5250_regex_free(&settings->password_regex);
guac_tn5250_regex_free(&settings->login_success_regex);
guac_tn5250_regex_free(&settings->login_failure_regex);
}
}
@ -214,7 +214,7 @@ static void guac_telnet_search_line(guac_client* client, const char* line_buffer
* have completed, this function has no effect.
*
* @param client
* The guac_client associated with the telnet session.
* The guac_client associated with the tn5250 session.
*
* @param buffer
* The buffer of received data to search through.
@ -222,7 +222,7 @@ static void guac_telnet_search_line(guac_client* client, const char* line_buffer
* @param size
* The size of the given buffer, in bytes.
*/
static void guac_telnet_search(guac_client* client, const char* buffer, int size) {
static void guac_tn5250_search(guac_client* client, const char* buffer, int size) {
static char line_buffer[1024] = {0};
static int length = 0;
@ -237,7 +237,7 @@ static void guac_telnet_search(guac_client* client, const char* buffer, int size
if (c == '\n') {
if (length > 0) {
line_buffer[length] = '\0';
guac_telnet_search_line(client, line_buffer);
guac_tn5250_search_line(client, line_buffer);
length = 0;
}
}
@ -252,7 +252,7 @@ static void guac_telnet_search(guac_client* client, const char* buffer, int size
/* Attempt pattern match if an unfinished line remains (may be a prompt) */
if (length > 0) {
line_buffer[length] = '\0';
guac_telnet_search_line(client, line_buffer);
guac_tn5250_search_line(client, line_buffer);
}
}
@ -262,23 +262,23 @@ static void guac_telnet_search(guac_client* client, const char* buffer, int size
* telnet_init() and will be called for every event fired by libtelnet,
* including feature enable/disable and receipt/transmission of data.
*/
static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event, void* data) {
static void __guac_tn5250_event_handler(telnet_t* telnet, telnet_event_t* event, void* data) {
guac_client* client = (guac_client*) data;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_tn5250_settings* settings = tn5250_client->settings;
switch (event->type) {
/* Terminal output received */
case TELNET_EV_DATA:
guac_terminal_write(telnet_client->term, event->data.buffer, event->data.size);
guac_telnet_search(client, event->data.buffer, event->data.size);
guac_terminal_write(tn5250_client->term, event->data.buffer, event->data.size);
guac_tn5250_search(client, event->data.buffer, event->data.size);
break;
/* Data destined for remote end */
case TELNET_EV_SEND:
if (__guac_telnet_write_all(telnet_client->socket_fd, event->data.buffer, event->data.size)
if (__guac_tn5250_write_all(tn5250_client->socket_fd, event->data.buffer, event->data.size)
!= event->data.size)
guac_client_stop(client);
break;
@ -286,27 +286,27 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event,
/* Remote feature enabled */
case TELNET_EV_WILL:
if (event->neg.telopt == TELNET_TELOPT_ECHO)
telnet_client->echo_enabled = 0; /* Disable local echo, as remote will echo */
tn5250_client->echo_enabled = 0; /* Disable local echo, as remote will echo */
break;
/* Remote feature disabled */
case TELNET_EV_WONT:
if (event->neg.telopt == TELNET_TELOPT_ECHO)
telnet_client->echo_enabled = 1; /* Enable local echo, as remote won't echo */
tn5250_client->echo_enabled = 1; /* Enable local echo, as remote won't echo */
break;
/* Local feature enable */
case TELNET_EV_DO:
if (event->neg.telopt == TELNET_TELOPT_NAWS) {
telnet_client->naws_enabled = 1;
guac_telnet_send_naws(telnet, telnet_client->term->term_width, telnet_client->term->term_height);
tn5250_client->naws_enabled = 1;
guac_tn5250_send_naws(telnet, tn5250_client->term->term_width, tn5250_client->term->term_height);
}
break;
/* Terminal type request */
case TELNET_EV_TTYPE:
if (event->ttype.cmd == TELNET_TTYPE_SEND)
telnet_ttype_is(telnet_client->telnet, settings->terminal_type);
tn5250_ttype_is(tn5250_client->telnet, settings->terminal_type);
break;
/* Environment request */
@ -314,7 +314,7 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event,
/* Only send USER if entire environment was requested */
if (event->environ.size == 0)
guac_telnet_send_user(telnet, settings->username);
guac_tn5250_send_user(telnet, settings->username);
break;
@ -345,19 +345,19 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event,
* @param data The current guac_client instance.
* @return Always NULL.
*/
static void* __guac_telnet_input_thread(void* data) {
static void* __guac_tn5250_input_thread(void* data) {
guac_client* client = (guac_client*) data;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
char buffer[8192];
int bytes_read;
/* Write all data read */
while ((bytes_read = guac_terminal_read_stdin(telnet_client->term, buffer, sizeof(buffer))) > 0) {
telnet_send(telnet_client->telnet, buffer, bytes_read);
if (telnet_client->echo_enabled)
guac_terminal_write(telnet_client->term, buffer, bytes_read);
while ((bytes_read = guac_terminal_read_stdin(tn5250_client->term, buffer, sizeof(buffer))) > 0) {
telnet_send(tn5250_client->telnet, buffer, bytes_read);
if (tn5250_client->echo_enabled)
guac_terminal_write(tn5250_client->term, buffer, bytes_read);
}
return NULL;
@ -372,7 +372,7 @@ static void* __guac_telnet_input_thread(void* data) {
* @return The connected telnet instance, if successful, or NULL if the
* connection fails for any reason.
*/
static telnet_t* __guac_telnet_create_session(guac_client* client) {
static telnet_t* __guac_tn5250_create_session(guac_client* client) {
int retval;
@ -383,8 +383,8 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
char connected_address[1024];
char connected_port[64];
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_tn5250_settings* settings = tn5250_client->settings;
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
@ -458,7 +458,7 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
}
/* Save file descriptor */
telnet_client->socket_fd = fd;
tn5250_client->socket_fd = fd;
return telnet;
@ -471,7 +471,7 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
* @param telnet The telnet connection to use.
* @param value The value to send.
*/
static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) {
static void __guac_tn5250_send_uint16(telnet_t* telnet, uint16_t value) {
unsigned char buffer[2];
buffer[0] = (value >> 8) & 0xFF;
@ -487,32 +487,32 @@ static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) {
* @param telnet The telnet connection to use.
* @param value The value to send.
*/
static void __guac_telnet_send_uint8(telnet_t* telnet, uint8_t value) {
static void __guac_tn5250_send_uint8(telnet_t* telnet, uint8_t value) {
telnet_send(telnet, (char*) (&value), 1);
}
void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) {
void guac_tn5250_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) {
telnet_begin_sb(telnet, TELNET_TELOPT_NAWS);
__guac_telnet_send_uint16(telnet, width);
__guac_telnet_send_uint16(telnet, height);
__guac_tn5250_send_uint16(telnet, width);
__guac_tn5250_send_uint16(telnet, height);
telnet_finish_sb(telnet);
}
void guac_telnet_send_user(telnet_t* telnet, const char* username) {
void guac_tn5250_send_user(telnet_t* telnet, const char* username) {
/* IAC SB NEW-ENVIRON IS */
telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON);
__guac_telnet_send_uint8(telnet, TELNET_ENVIRON_IS);
__guac_tn5250_send_uint8(telnet, TELNET_ENVIRON_IS);
/* Only send username if defined */
if (username != NULL) {
/* VAR "USER" */
__guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VAR);
__guac_tn5250_send_uint8(telnet, TELNET_ENVIRON_VAR);
telnet_send(telnet, "USER", 4);
/* VALUE username */
__guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VALUE);
__guac_tn5250_send_uint8(telnet, TELNET_ENVIRON_VALUE);
telnet_send(telnet, username, strlen(username));
}
@ -531,7 +531,7 @@ void guac_telnet_send_user(telnet_t* telnet, const char* username) {
* @return A value greater than zero on success, zero on timeout, and
* less than zero on error.
*/
static int __guac_telnet_wait(int socket_fd) {
static int __guac_tn5250_wait(int socket_fd) {
/* Build array of file descriptors */
struct pollfd fds[] = {{
@ -545,11 +545,11 @@ static int __guac_telnet_wait(int socket_fd) {
}
void* guac_telnet_client_thread(void* data) {
void* guac_tn5250_client_thread(void* data) {
guac_client* client = (guac_client*) data;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_telnet_settings* settings = telnet_client->settings;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
guac_tn5250_settings* settings = tn5250_client->settings;
pthread_t input_thread;
char buffer[8192];
@ -557,7 +557,7 @@ void* guac_telnet_client_thread(void* data) {
/* Set up screen recording, if requested */
if (settings->recording_path != NULL) {
telnet_client->recording = guac_common_recording_create(client,
tn5250_client->recording = guac_common_recording_create(client,
settings->recording_path,
settings->recording_name,
settings->create_recording_path,
@ -567,14 +567,14 @@ void* guac_telnet_client_thread(void* data) {
}
/* Create terminal */
telnet_client->term = guac_terminal_create(client,
telnet_client->clipboard, settings->disable_copy,
tn5250_client->term = guac_terminal_create(client,
tn5250_client->clipboard, settings->disable_copy,
settings->max_scrollback, settings->font_name, settings->font_size,
settings->resolution, settings->width, settings->height,
settings->color_scheme, settings->backspace);
/* Fail if terminal init failed */
if (telnet_client->term == NULL) {
if (tn5250_client->term == NULL) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
"Terminal initialization failed");
return NULL;
@ -582,46 +582,46 @@ void* guac_telnet_client_thread(void* data) {
/* Set up typescript, if requested */
if (settings->typescript_path != NULL) {
guac_terminal_create_typescript(telnet_client->term,
guac_terminal_create_typescript(tn5250_client->term,
settings->typescript_path,
settings->typescript_name,
settings->create_typescript_path);
}
/* Open telnet session */
telnet_client->telnet = __guac_telnet_create_session(client);
if (telnet_client->telnet == NULL) {
/* Already aborted within __guac_telnet_create_session() */
tn5250_client->telnet = __guac_tn5250_create_session(client);
if (tn5250_client->telnet == NULL) {
/* Already aborted within __guac_tn5250_create_session() */
return NULL;
}
/* Logged in */
guac_client_log(client, GUAC_LOG_INFO, "Telnet connection successful.");
guac_client_log(client, GUAC_LOG_INFO, "TN5250 connection successful.");
/* Allow terminal to render if login success/failure detection is not
* enabled */
if (settings->login_success_regex == NULL
&& settings->login_failure_regex == NULL)
guac_terminal_start(telnet_client->term);
guac_terminal_start(tn5250_client->term);
/* Start input thread */
if (pthread_create(&(input_thread), NULL, __guac_telnet_input_thread, (void*) client)) {
if (pthread_create(&(input_thread), NULL, __guac_tn5250_input_thread, (void*) client)) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
return NULL;
}
/* While data available, write to terminal */
while ((wait_result = __guac_telnet_wait(telnet_client->socket_fd)) >= 0) {
while ((wait_result = __guac_tn5250_wait(tn5250_client->socket_fd)) >= 0) {
/* Resume waiting of no data available */
if (wait_result == 0)
continue;
int bytes_read = read(telnet_client->socket_fd, buffer, sizeof(buffer));
int bytes_read = read(tn5250_client->socket_fd, buffer, sizeof(buffer));
if (bytes_read <= 0)
break;
telnet_recv(telnet_client->telnet, buffer, bytes_read);
telnet_recv(tn5250_client->telnet, buffer, bytes_read);
}
@ -629,7 +629,7 @@ void* guac_telnet_client_thread(void* data) {
guac_client_stop(client);
pthread_join(input_thread, NULL);
guac_client_log(client, GUAC_LOG_INFO, "Telnet connection ended.");
guac_client_log(client, GUAC_LOG_INFO, "TN5250 connection ended.");
return NULL;
}

View File

@ -33,12 +33,12 @@
/**
* Telnet-specific client data.
*/
typedef struct guac_telnet_client {
typedef struct guac_tn5250_client {
/**
* Telnet connection settings.
*/
guac_telnet_settings* settings;
guac_tn5250_settings* settings;
/**
* The telnet client thread.
@ -83,24 +83,24 @@ typedef struct guac_telnet_client {
*/
guac_common_recording* recording;
} guac_telnet_client;
} guac_tn5250_client;
/**
* Main telnet client thread, handling transfer of telnet output to STDOUT.
* Main tn5250 client thread, handling transfer of tn5250 output to STDOUT.
*/
void* guac_telnet_client_thread(void* data);
void* guac_tn5250_client_thread(void* data);
/**
* Send a telnet NAWS message indicating the given terminal window dimensions
* in characters.
*/
void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height);
void guac_tn5250_send_naws(telnet_t* telnet, uint16_t width, uint16_t height);
/**
* Sends the given username by setting the remote USER environment variable
* using the telnet NEW-ENVIRON option.
* using the tn5250 NEW-ENVIRON option.
*/
void guac_telnet_send_user(telnet_t* telnet, const char* username);
void guac_tn5250_send_user(telnet_t* telnet, const char* username);
#endif

View File

@ -35,13 +35,13 @@
#include <pthread.h>
#include <string.h>
int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
int guac_tn5250_user_join_handler(guac_user* user, int argc, char** argv) {
guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_tn5250_client* tn5250_client = (guac_tn5250_client*) client->data;
/* Parse provided arguments */
guac_telnet_settings* settings = guac_telnet_parse_args(user,
guac_tn5250_settings* settings = guac_tn5250_parse_args(user,
argc, (const char**) argv);
/* Fail if settings cannot be parsed */
@ -54,17 +54,17 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
/* Store settings at user level */
user->data = settings;
/* Connect via telnet if owner */
/* Connect via tn5250 if owner */
if (user->owner) {
/* Store owner's settings at client level */
telnet_client->settings = settings;
tn5250_client->settings = settings;
/* Start client thread */
if (pthread_create(&(telnet_client->client_thread), NULL,
guac_telnet_client_thread, (void*) client)) {
if (pthread_create(&(tn5250_client->client_thread), NULL,
guac_tn5250_client_thread, (void*) client)) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
"Unable to start telnet client thread");
"Unable to start tn5250 client thread");
return 1;
}
@ -72,7 +72,7 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
/* If not owner, synchronize with current display */
else {
guac_terminal_dup(telnet_client->term, user, user->socket);
guac_terminal_dup(tn5250_client->term, user, user->socket);
guac_socket_flush(user->socket);
}
@ -80,21 +80,21 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
if (!settings->read_only) {
/* General mouse/keyboard events */
user->key_handler = guac_telnet_user_key_handler;
user->mouse_handler = guac_telnet_user_mouse_handler;
user->key_handler = guac_tn5250_user_key_handler;
user->mouse_handler = guac_tn5250_user_mouse_handler;
/* Inbound (client to server) clipboard transfer */
if (!settings->disable_paste)
user->clipboard_handler = guac_telnet_clipboard_handler;
user->clipboard_handler = guac_tn5250_clipboard_handler;
/* STDIN redirection */
user->pipe_handler = guac_telnet_pipe_handler;
user->pipe_handler = guac_tn5250_pipe_handler;
/* Updates to connection parameters */
user->argv_handler = guac_telnet_argv_handler;
user->argv_handler = guac_tn5250_argv_handler;
/* Display size change events */
user->size_handler = guac_telnet_user_size_handler;
user->size_handler = guac_tn5250_user_size_handler;
}
@ -102,18 +102,18 @@ int guac_telnet_user_join_handler(guac_user* user, int argc, char** argv) {
}
int guac_telnet_user_leave_handler(guac_user* user) {
int guac_tn5250_user_leave_handler(guac_user* user) {
guac_telnet_client* telnet_client =
(guac_telnet_client*) user->client->data;
guac_tn5250_client* tn5250_client =
(guac_tn5250_client*) user->client->data;
/* Update shared cursor state */
guac_common_cursor_remove_user(telnet_client->term->cursor, user);
guac_common_cursor_remove_user(tn5250_client->term->cursor, user);
/* Free settings if not owner (owner settings will be freed with client) */
if (!user->owner) {
guac_telnet_settings* settings = (guac_telnet_settings*) user->data;
guac_telnet_settings_free(settings);
guac_tn5250_settings* settings = (guac_tn5250_settings*) user->data;
guac_tn5250_settings_free(settings);
}
return 0;

View File

@ -27,12 +27,12 @@
/**
* Handler for joining users.
*/
guac_user_join_handler guac_telnet_user_join_handler;
guac_user_join_handler guac_tn5250_user_join_handler;
/**
* Handler for leaving users.
*/
guac_user_leave_handler guac_telnet_user_leave_handler;
guac_user_leave_handler guac_tn5250_user_leave_handler;
#endif