GUACAMOLE-860: Add TN5250 packet processing.
This commit is contained in:
parent
b9330e5850
commit
0c8f79a6a0
@ -36,7 +36,8 @@ libguac_client_tn5250_la_SOURCES = \
|
||||
pipe.c \
|
||||
settings.c \
|
||||
tn5250.c \
|
||||
user.c
|
||||
user.c \
|
||||
lib5250/lib5250.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
argv.h \
|
||||
@ -46,7 +47,8 @@ noinst_HEADERS = \
|
||||
pipe.h \
|
||||
settings.h \
|
||||
tn5250.h \
|
||||
user.h
|
||||
user.h \
|
||||
lib5250/lib5250.h
|
||||
|
||||
libguac_client_tn5250_la_CFLAGS = \
|
||||
-Werror -Wall -Iinclude \
|
||||
|
105
src/protocols/tn5250/lib5250/lib5250.c
Normal file
105
src/protocols/tn5250/lib5250/lib5250.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "lib5250.h"
|
||||
#include "tn5250.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int guac_lib5250_process_packet(const char* data, guac_client* client) {
|
||||
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "%s: Processing expected TN5250 SNA data.", __func__);
|
||||
|
||||
guac_lib5250_packet* packet = (guac_lib5250_packet*) data;
|
||||
|
||||
if (ntohs(packet->type) != GUAC_LIB5250_SNA_GDS) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||
"%s: Unexpected SNA packet typing parsing TN5250 packet: 0x%x",
|
||||
__func__, ntohs(packet->type));
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (packet->opcode) {
|
||||
|
||||
case GUAC_LIB5250_OPCODE_NOOP:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode no-op.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_INVITE:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode invite.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_OUTPUT:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode output.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_PUTGET:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode put/get.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_SAVESCREEN:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode save screen.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_RESTORESCREEN:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode restore screen.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_READIMMEDIATE:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode read immediate.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_READSCREEN:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode read screen.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_CANCELINVITE:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode cancel invite.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_MSGON:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode msg on.", __func__);
|
||||
break;
|
||||
|
||||
case GUAC_LIB5250_OPCODE_MSGOFF:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received opcode msg off.", __func__);
|
||||
break;
|
||||
|
||||
default:
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Received unknown opcode.", __func__);
|
||||
|
||||
}
|
||||
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: SNA data length: %d bytes.", __func__, ntohs(packet->len));
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Packet type: 0x%x", __func__, ntohs(packet->type));
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Reserved space: 0x%x", __func__, ntohs(packet->reserved));
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Variable header length: 0x%x.", __func__, packet->varlen);
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: SNA Flags: 0x%x", __func__, packet->flags);
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: SNA Rerved flags: 0x%x", __func__, packet->reserved_flags);
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: SNA Opcode: 0x%x", __func__, packet->opcode);
|
||||
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: WHOLE ENCHILADA: 0x%x", __func__, packet);
|
||||
|
||||
guac_client_log(client, GUAC_LOG_WARNING, "%s: Everything else is unimplemented, now.", __func__);
|
||||
return 0;
|
||||
|
||||
}
|
207
src/protocols/tn5250/lib5250/lib5250.h
Normal file
207
src/protocols/tn5250/lib5250/lib5250.h
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_LIB5250_H
|
||||
#define GUAC_LIB5250_H
|
||||
|
||||
#include "config.h"
|
||||
#include "tn5250.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* The General Data Stream SNA packet type.
|
||||
*/
|
||||
#define GUAC_LIB5250_SNA_GDS 0x12a0
|
||||
|
||||
/**
|
||||
* An enum that represents all of the available terminal types according to
|
||||
* RFC1205, the specification that documents the Telnet 5250 (TN5250)
|
||||
* standard.
|
||||
*/
|
||||
typedef enum guac_lib5250_terminal {
|
||||
|
||||
/* 24 x 80 Double-Byte Character Set color display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_5555_C01,
|
||||
|
||||
/* 24 x 80 Double-Byte Character Set (DBCS) */
|
||||
GUAC_LIB5250_TERMINAL_IBM_5555_B01,
|
||||
|
||||
/* 27 x 132 color display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_3477_FC,
|
||||
|
||||
/* 27 x 132 monochrome display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_3477_FG,
|
||||
|
||||
/* 27 x 132 monochrome display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_3180_2,
|
||||
|
||||
/* 24 x 80 color display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_3179_2,
|
||||
|
||||
/* 24 x 80 monochrome display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_3196_A1,
|
||||
|
||||
/* 24 x 80 color display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_5292_2,
|
||||
|
||||
/* 24 x 80 monochrome display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_5291_1,
|
||||
|
||||
/* 24 x 80 monochrome display */
|
||||
GUAC_LIB5250_TERMINAL_IBM_5251_11
|
||||
|
||||
} guac_lib5250_terminal;
|
||||
|
||||
/**
|
||||
* A data type that captures a terminal type, from the guac_lib5250_terminal
|
||||
* enum, and the capabilities associated with that terminal.
|
||||
*/
|
||||
typedef struct guac_lib5250_terminal_cap {
|
||||
|
||||
/* The name of the terminal. */
|
||||
guac_lib5250_terminal name;
|
||||
|
||||
/* The number of rows supported on the terminal. */
|
||||
unsigned int rows;
|
||||
|
||||
/* The number of columns supports on the terminal. */
|
||||
unsigned int cols;
|
||||
|
||||
/* 1 if the terminal supports colors, 0 if it is monochrome. */
|
||||
unsigned int color;
|
||||
|
||||
/* The number of bytes-per-character the terminal supports. This must
|
||||
* be either 1 or 2. */
|
||||
unsigned int charbytes;
|
||||
|
||||
} guac_lib5250_terminal_cap;
|
||||
|
||||
/**
|
||||
* A list of the possible TN5250 opcodes, which can be sent to the client to
|
||||
* direct it to do something with the terminal. These are documented in RFC1205.
|
||||
*/
|
||||
typedef enum guac_lib5250_opcode {
|
||||
|
||||
/* No Operation */
|
||||
GUAC_LIB5250_OPCODE_NOOP = 0x00,
|
||||
|
||||
/* Invite terminal */
|
||||
GUAC_LIB5250_OPCODE_INVITE = 0x01,
|
||||
|
||||
/* Output only */
|
||||
GUAC_LIB5250_OPCODE_OUTPUT = 0x02,
|
||||
|
||||
/* Put/Get */
|
||||
GUAC_LIB5250_OPCODE_PUTGET = 0x03,
|
||||
|
||||
/* Save screen */
|
||||
GUAC_LIB5250_OPCODE_SAVESCREEN = 0x04,
|
||||
|
||||
/* Restore screen */
|
||||
GUAC_LIB5250_OPCODE_RESTORESCREEN = 0x05,
|
||||
|
||||
/* Read immediate */
|
||||
GUAC_LIB5250_OPCODE_READIMMEDIATE = 0x06,
|
||||
|
||||
/* Read screen */
|
||||
GUAC_LIB5250_OPCODE_READSCREEN = 0x08,
|
||||
|
||||
/* Cancel invite */
|
||||
GUAC_LIB5250_OPCODE_CANCELINVITE = 0x0A,
|
||||
|
||||
/* Message light on */
|
||||
GUAC_LIB5250_OPCODE_MSGON = 0x0B,
|
||||
|
||||
/* Message light off */
|
||||
GUAC_LIB5250_OPCODE_MSGOFF = 0x0C
|
||||
|
||||
} guac_lib5250_opcode;
|
||||
|
||||
/**
|
||||
* A data type that defines the structure of the packet for 5250 communication
|
||||
* across telnet. The structure of this packet is based off of the definition
|
||||
* in RFC1205.
|
||||
*/
|
||||
typedef struct guac_lib5250_packet {
|
||||
|
||||
/* The length of the entire logical record. */
|
||||
uint16_t len;
|
||||
|
||||
/* The SNA record type. This should always be 0x12A0, which is the
|
||||
* General Data Stream record. */
|
||||
uint16_t type;
|
||||
|
||||
/* Empty space, should be zerod. */
|
||||
uint16_t reserved;
|
||||
|
||||
/* The length of the variable portion of the header, in octets. According
|
||||
* to the RFC, this should always be 0x04. */
|
||||
uint8_t varlen;
|
||||
|
||||
/* Flags associated with the header, as documented in the RFC. The
|
||||
* bits are as follows:
|
||||
* Bit 0: ERR - Data stream output error.
|
||||
* Bit 1: ATN - Indicates Attention key was pressed.
|
||||
* Bit 2-4: Reserved, zeros.
|
||||
* Bit 5: SRQ - System Request key has been pressed.
|
||||
* Bit 6: TRQ - Test Request key has been pressed.
|
||||
* Bit 7: HLP - Help in Error State, with actual help code sent as data after
|
||||
* the header.
|
||||
*/
|
||||
uint8_t flags;
|
||||
|
||||
/* At present, the remaining 8 bits of flags are not used at all. As old
|
||||
* as RFC1205 is, I doubt that's likely to change. These bits should be
|
||||
* all zeroes.
|
||||
*/
|
||||
uint8_t reserved_flags;
|
||||
|
||||
/* The operation code, as requested by the sender. Valid values for this
|
||||
* are in the gauc_lib5250_opcode enum.
|
||||
*/
|
||||
uint8_t opcode;
|
||||
|
||||
/* What remains is the data in the packet, which should consume the
|
||||
* remainder of the space that the header did not take up. The packet
|
||||
* should also be terminated with a Telnet IAC EOR record, 0xffef.
|
||||
*/
|
||||
void* data;
|
||||
|
||||
} guac_lib5250_packet __attribute__ ((aligned));
|
||||
|
||||
/**
|
||||
* Parses the packet that libtelnet has received and then takes action
|
||||
* based on the contents of the packet.
|
||||
*
|
||||
* @param data
|
||||
* The data buffer delivered by libtelnet, which should be binary telnet
|
||||
* data that is the actual TN5250 protocol.
|
||||
*
|
||||
* @param client
|
||||
* The Guacamole client associated with this connection.
|
||||
*
|
||||
* @return
|
||||
* Zero if the data was successfully processed, non-zero otherwise.
|
||||
*/
|
||||
int guac_lib5250_process_packet(const char* data, guac_client* client);
|
||||
|
||||
#endif // GUAC_LIB5250_H
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "argv.h"
|
||||
#include "tn5250.h"
|
||||
#include "lib5250/lib5250.h"
|
||||
#include "terminal/terminal.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
@ -55,9 +56,6 @@ static const telnet_telopt_t __telnet_options[] = {
|
||||
{ TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO },
|
||||
{ TELNET_TELOPT_EOR, TELNET_WILL, TELNET_DO },
|
||||
{ TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT },
|
||||
{ TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO },
|
||||
{ TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO },
|
||||
{ TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT },
|
||||
{ TELNET_TELOPT_NEW_ENVIRON, TELNET_WILL, TELNET_DONT },
|
||||
{ -1, 0, 0 }
|
||||
};
|
||||
@ -65,12 +63,21 @@ static const telnet_telopt_t __telnet_options[] = {
|
||||
/**
|
||||
* Write the entire buffer given to the specified file descriptor, retrying
|
||||
* the write automatically if necessary. This function will return a value
|
||||
* not equal to the buffer's size iff an error occurs which prevents all
|
||||
* not equal to the buffer's size if an error occurs which prevents all
|
||||
* future writes.
|
||||
*
|
||||
* @param fd The file descriptor to write to.
|
||||
* @param buffer The buffer to write.
|
||||
* @param size The number of bytes from the buffer to write.
|
||||
* @param fd
|
||||
* The file descriptor to write to.
|
||||
*
|
||||
* @param buffer
|
||||
* The buffer to write.
|
||||
*
|
||||
* @param size
|
||||
* The number of bytes from the buffer to write.
|
||||
*
|
||||
* @return
|
||||
* Return a value equal to the buffer's size on success, or a value not
|
||||
* equal to the buffer's size or a negative value on failure.
|
||||
*/
|
||||
static int __guac_tn5250_write_all(int fd, const char* buffer, int size) {
|
||||
|
||||
@ -271,6 +278,15 @@ static void guac_tn5250_search(guac_client* client, const char* buffer, int size
|
||||
* Event handler, as defined by libtelnet. This function is passed to
|
||||
* telnet_init() and will be called for every event fired by libtelnet,
|
||||
* including feature enable/disable and receipt/transmission of data.
|
||||
*
|
||||
* @param tn5250
|
||||
* The telnet_t object associated with the event.
|
||||
*
|
||||
* @param event
|
||||
* The telnet_event_t that has fired.
|
||||
*
|
||||
* @param data
|
||||
* User data provided to the event.
|
||||
*/
|
||||
static void __guac_tn5250_event_handler(telnet_t* tn5250, telnet_event_t* event, void* data) {
|
||||
|
||||
@ -286,10 +302,15 @@ static void __guac_tn5250_event_handler(telnet_t* tn5250, telnet_event_t* event,
|
||||
"%s: Received %d bytes of data from remote side.", __func__, event->data.size);
|
||||
if (tn5250_client->binary_mode) {
|
||||
guac_client_log(client, GUAC_LOG_TRACE,
|
||||
"%s: Receiving binary data - it will not be printed to the screen.",
|
||||
"%s: Receiving binary data, which will not go directly to the terminal.",
|
||||
__func__);
|
||||
if (guac_lib5250_process_packet(event->data.buffer, client)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
guac_client_log(client, GUAC_LOG_TRACE,
|
||||
"%s: Writing ASCII output directly to terminal.", __func__);
|
||||
guac_terminal_write(tn5250_client->term, event->data.buffer, event->data.size);
|
||||
guac_tn5250_search(client, event->data.buffer, event->data.size);
|
||||
}
|
||||
@ -308,6 +329,7 @@ static void __guac_tn5250_event_handler(telnet_t* tn5250, telnet_event_t* event,
|
||||
case TELNET_EV_WILL:
|
||||
if (event->neg.telopt == TELNET_TELOPT_ECHO)
|
||||
tn5250_client->echo_enabled = 0; /* Disable local echo, as remote will echo */
|
||||
|
||||
if (event->neg.telopt == TELNET_TELOPT_EOR) {
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"%s: Received End of Record support from remote side.",
|
||||
@ -366,6 +388,14 @@ static void __guac_tn5250_event_handler(telnet_t* tn5250, telnet_event_t* event,
|
||||
if (event->ttype.cmd == TELNET_TTYPE_SEND) {
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"%s: Sending terminal type \"%s\" to remote side.", __func__, settings->terminal_type);
|
||||
|
||||
/* Apparently sending the TERMINAL TYPE to an IBMi system over
|
||||
* telnet requires both sending the TERM environment variable
|
||||
* and responding to the actual telnet TTYPE inquiry. */
|
||||
telnet_begin_newenviron(tn5250, TELNET_ENVIRON_IS);
|
||||
telnet_newenviron_value(tn5250, TELNET_ENVIRON_VAR, "TERM");
|
||||
telnet_newenviron_value(tn5250, TELNET_ENVIRON_VALUE, settings->terminal_type);
|
||||
telnet_finish_sb(tn5250);
|
||||
telnet_ttype_is(tn5250_client->tn5250, settings->terminal_type);
|
||||
}
|
||||
break;
|
||||
@ -376,8 +406,10 @@ static void __guac_tn5250_event_handler(telnet_t* tn5250, telnet_event_t* event,
|
||||
"%s: Received environment request from the remote side.",
|
||||
__func__);
|
||||
/* Only send USER if entire environment was requested */
|
||||
if (event->environ.size == 0)
|
||||
if (event->environ.size == 0) {
|
||||
guac_client_log(client, GUAC_LOG_TRACE, "%s: Sending username to remote server: %s", __func__, settings->username);
|
||||
guac_tn5250_send_user(tn5250, settings->username);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -427,8 +459,11 @@ static void __guac_tn5250_event_handler(telnet_t* tn5250, telnet_event_t* event,
|
||||
* continuously reads from the terminal's STDIN and transfers all read
|
||||
* data to the tn5250 connection.
|
||||
*
|
||||
* @param data The current guac_client instance.
|
||||
* @return Always NULL.
|
||||
* @param data
|
||||
* The current guac_client instance.
|
||||
*
|
||||
* @return
|
||||
* Always NULL.
|
||||
*/
|
||||
static void* __guac_tn5250_input_thread(void* data) {
|
||||
|
||||
@ -454,7 +489,8 @@ static void* __guac_tn5250_input_thread(void* data) {
|
||||
* with the given guac_client, which will have been populated by
|
||||
* guac_client_init.
|
||||
*
|
||||
* @return The connected tn5250 instance, if successful, or NULL if the
|
||||
* @return
|
||||
* The connected tn5250 instance, if successful, or NULL if the
|
||||
* connection fails for any reason.
|
||||
*/
|
||||
static telnet_t* __guac_tn5250_create_session(guac_client* client) {
|
||||
@ -553,8 +589,11 @@ static telnet_t* __guac_tn5250_create_session(guac_client* client) {
|
||||
* Sends a 16-bit value over the given tn5250 connection with the byte order
|
||||
* required by the tn5250 protocol.
|
||||
*
|
||||
* @param tn5250 The tn5250 connection to use.
|
||||
* @param value The value to send.
|
||||
* @param tn5250
|
||||
* The tn5250 connection to use.
|
||||
*
|
||||
* @param value
|
||||
* The value to send.
|
||||
*/
|
||||
/*
|
||||
static void __guac_tn5250_send_uint16(telnet_t* tn5250, uint16_t value) {
|
||||
@ -571,33 +610,32 @@ static void __guac_tn5250_send_uint16(telnet_t* tn5250, uint16_t value) {
|
||||
/**
|
||||
* Sends an 8-bit value over the given tn5250 connection.
|
||||
*
|
||||
* @param tn5250 The tn5250 connection to use.
|
||||
* @param value The value to send.
|
||||
* @param tn5250
|
||||
* The tn5250 connection to use.
|
||||
*
|
||||
* @param value
|
||||
* The value to send.
|
||||
*/
|
||||
/*
|
||||
static void __guac_tn5250_send_uint8(telnet_t* tn5250, uint8_t value) {
|
||||
telnet_send(tn5250, (char*) (&value), 1);
|
||||
}
|
||||
*/
|
||||
|
||||
void guac_tn5250_send_user(telnet_t* tn5250, const char* username) {
|
||||
|
||||
/* IAC SB NEW-ENVIRON IS */
|
||||
telnet_begin_sb(tn5250, TELNET_TELOPT_NEW_ENVIRON);
|
||||
__guac_tn5250_send_uint8(tn5250, TELNET_ENVIRON_IS);
|
||||
telnet_begin_newenviron(tn5250, TELNET_ENVIRON_IS);
|
||||
|
||||
/* Only send username if defined */
|
||||
if (username != NULL) {
|
||||
|
||||
/* VAR "USER" */
|
||||
__guac_tn5250_send_uint8(tn5250, TELNET_ENVIRON_VAR);
|
||||
telnet_send(tn5250, "USER", 4);
|
||||
|
||||
/* VALUE username */
|
||||
__guac_tn5250_send_uint8(tn5250, TELNET_ENVIRON_VALUE);
|
||||
telnet_send(tn5250, username, strlen(username));
|
||||
telnet_newenviron_value(tn5250, TELNET_ENVIRON_VAR, "USER");
|
||||
telnet_newenviron_value(tn5250, TELNET_ENVIRON_VALUE, username);
|
||||
|
||||
}
|
||||
|
||||
/* IAC SE */
|
||||
/* IAC SB */
|
||||
telnet_finish_sb(tn5250);
|
||||
|
||||
}
|
||||
@ -635,21 +673,6 @@ void* guac_tn5250_client_thread(void* data) {
|
||||
char buffer[8192];
|
||||
int wait_result;
|
||||
|
||||
/* If Wake-on-LAN is enabled, attempt to wake. */
|
||||
if (settings->wol_send_packet) {
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Sending Wake-on-LAN packet, "
|
||||
"and pausing for %d seconds.", settings->wol_wait_time);
|
||||
|
||||
/* Send the Wake-on-LAN request. */
|
||||
if (guac_wol_wake(settings->wol_mac_addr, settings->wol_broadcast_addr,
|
||||
settings->wol_udp_port))
|
||||
return NULL;
|
||||
|
||||
/* If wait time is specified, sleep for that amount of time. */
|
||||
if (settings->wol_wait_time > 0)
|
||||
guac_timestamp_msleep(settings->wol_wait_time * 1000);
|
||||
}
|
||||
|
||||
/* Set up screen recording, if requested */
|
||||
if (settings->recording_path != NULL) {
|
||||
tn5250_client->recording = guac_recording_create(client,
|
||||
|
Loading…
Reference in New Issue
Block a user