GUACAMOLE-860: [WIP] TN5250 adjustments.
This commit is contained in:
parent
22fe81913f
commit
30ec3be924
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user