green-screen-proxy 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +32 -0
- package/dist/hp6530/connection.d.ts +51 -0
- package/dist/hp6530/connection.js +258 -0
- package/dist/hp6530/constants.d.ts +64 -0
- package/dist/hp6530/constants.js +135 -0
- package/dist/hp6530/encoder.d.ts +37 -0
- package/dist/hp6530/encoder.js +89 -0
- package/dist/hp6530/parser.d.ts +45 -0
- package/dist/hp6530/parser.js +255 -0
- package/dist/hp6530/screen.d.ts +104 -0
- package/dist/hp6530/screen.js +252 -0
- package/dist/mock/mock-routes.d.ts +2 -0
- package/dist/mock/mock-routes.js +231 -0
- package/dist/protocols/hp6530-handler.d.ts +29 -0
- package/dist/protocols/hp6530-handler.js +64 -0
- package/dist/protocols/index.d.ts +11 -0
- package/dist/protocols/index.js +27 -0
- package/dist/protocols/tn3270-handler.d.ts +26 -0
- package/dist/protocols/tn3270-handler.js +61 -0
- package/dist/protocols/tn5250-handler.d.ts +26 -0
- package/dist/protocols/tn5250-handler.js +62 -0
- package/dist/protocols/types.d.ts +59 -0
- package/dist/protocols/types.js +7 -0
- package/dist/protocols/vt-handler.d.ts +30 -0
- package/dist/protocols/vt-handler.js +67 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.js +141 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +34 -0
- package/dist/session.d.ts +32 -0
- package/dist/session.js +88 -0
- package/dist/tn3270/connection.d.ts +31 -0
- package/dist/tn3270/connection.js +266 -0
- package/dist/tn3270/constants.d.ts +262 -0
- package/dist/tn3270/constants.js +261 -0
- package/dist/tn3270/encoder.d.ts +24 -0
- package/dist/tn3270/encoder.js +97 -0
- package/dist/tn3270/parser.d.ts +22 -0
- package/dist/tn3270/parser.js +284 -0
- package/dist/tn3270/screen.d.ts +89 -0
- package/dist/tn3270/screen.js +207 -0
- package/dist/tn5250/connection.d.ts +41 -0
- package/dist/tn5250/connection.js +254 -0
- package/dist/tn5250/constants.d.ts +128 -0
- package/dist/tn5250/constants.js +156 -0
- package/dist/tn5250/ebcdic.d.ts +10 -0
- package/dist/tn5250/ebcdic.js +89 -0
- package/dist/tn5250/encoder.d.ts +30 -0
- package/dist/tn5250/encoder.js +121 -0
- package/dist/tn5250/parser.d.ts +33 -0
- package/dist/tn5250/parser.js +412 -0
- package/dist/tn5250/screen.d.ts +80 -0
- package/dist/tn5250/screen.js +155 -0
- package/dist/vt/connection.d.ts +45 -0
- package/dist/vt/connection.js +229 -0
- package/dist/vt/constants.d.ts +97 -0
- package/dist/vt/constants.js +163 -0
- package/dist/vt/encoder.d.ts +30 -0
- package/dist/vt/encoder.js +55 -0
- package/dist/vt/parser.d.ts +36 -0
- package/dist/vt/parser.js +534 -0
- package/dist/vt/screen.d.ts +101 -0
- package/dist/vt/screen.js +424 -0
- package/dist/websocket.d.ts +6 -0
- package/dist/websocket.js +50 -0
- package/package.json +57 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
export { TELNET } from '../tn5250/constants.js';
|
|
2
|
+
export declare const CMD3270: {
|
|
3
|
+
readonly WRITE: 241;
|
|
4
|
+
readonly ERASE_WRITE: 245;
|
|
5
|
+
readonly ERASE_WRITE_ALTERNATE: 126;
|
|
6
|
+
readonly READ_BUFFER: 242;
|
|
7
|
+
readonly READ_MODIFIED: 246;
|
|
8
|
+
readonly READ_MODIFIED_ALL: 110;
|
|
9
|
+
readonly ERASE_ALL_UNPROTECTED: 111;
|
|
10
|
+
readonly WRITE_STRUCTURED_FIELD: 243;
|
|
11
|
+
readonly SNA_WRITE: 1;
|
|
12
|
+
readonly SNA_ERASE_WRITE: 5;
|
|
13
|
+
readonly SNA_ERASE_WRITE_ALTERNATE: 13;
|
|
14
|
+
readonly SNA_READ_BUFFER: 2;
|
|
15
|
+
readonly SNA_READ_MODIFIED: 6;
|
|
16
|
+
readonly SNA_READ_MODIFIED_ALL: 14;
|
|
17
|
+
readonly SNA_ERASE_ALL_UNPROTECTED: 15;
|
|
18
|
+
};
|
|
19
|
+
export declare const ORDER3270: {
|
|
20
|
+
readonly SBA: 17;
|
|
21
|
+
readonly SF: 29;
|
|
22
|
+
readonly SFE: 41;
|
|
23
|
+
readonly SA: 40;
|
|
24
|
+
readonly MF: 44;
|
|
25
|
+
readonly IC: 19;
|
|
26
|
+
readonly PT: 5;
|
|
27
|
+
readonly RA: 60;
|
|
28
|
+
readonly EUA: 18;
|
|
29
|
+
readonly GE: 8;
|
|
30
|
+
};
|
|
31
|
+
export declare const WCC: {
|
|
32
|
+
readonly RESET_MDT: 2;
|
|
33
|
+
readonly RESET_KEYBOARD: 64;
|
|
34
|
+
readonly SOUND_ALARM: 4;
|
|
35
|
+
readonly RESET_PARTITION: 1;
|
|
36
|
+
readonly START_PRINTER: 8;
|
|
37
|
+
};
|
|
38
|
+
export declare const AID3270: {
|
|
39
|
+
readonly ENTER: 125;
|
|
40
|
+
readonly PF1: 241;
|
|
41
|
+
readonly PF2: 242;
|
|
42
|
+
readonly PF3: 243;
|
|
43
|
+
readonly PF4: 244;
|
|
44
|
+
readonly PF5: 245;
|
|
45
|
+
readonly PF6: 246;
|
|
46
|
+
readonly PF7: 247;
|
|
47
|
+
readonly PF8: 248;
|
|
48
|
+
readonly PF9: 249;
|
|
49
|
+
readonly PF10: 122;
|
|
50
|
+
readonly PF11: 123;
|
|
51
|
+
readonly PF12: 124;
|
|
52
|
+
readonly PF13: 193;
|
|
53
|
+
readonly PF14: 194;
|
|
54
|
+
readonly PF15: 195;
|
|
55
|
+
readonly PF16: 196;
|
|
56
|
+
readonly PF17: 197;
|
|
57
|
+
readonly PF18: 198;
|
|
58
|
+
readonly PF19: 199;
|
|
59
|
+
readonly PF20: 200;
|
|
60
|
+
readonly PF21: 201;
|
|
61
|
+
readonly PF22: 74;
|
|
62
|
+
readonly PF23: 75;
|
|
63
|
+
readonly PF24: 76;
|
|
64
|
+
readonly PA1: 108;
|
|
65
|
+
readonly PA2: 110;
|
|
66
|
+
readonly PA3: 107;
|
|
67
|
+
readonly CLEAR: 109;
|
|
68
|
+
readonly STRUCTURED_FIELD: 136;
|
|
69
|
+
readonly NO_AID: 96;
|
|
70
|
+
};
|
|
71
|
+
export declare const KEY_TO_AID3270: Record<string, number>;
|
|
72
|
+
export declare const FIELD_ATTR: {
|
|
73
|
+
readonly PROTECTED: 32;
|
|
74
|
+
readonly NUMERIC: 16;
|
|
75
|
+
readonly DISPLAY_MASK: 12;
|
|
76
|
+
readonly DISPLAY_NORMAL: 0;
|
|
77
|
+
readonly DISPLAY_NORMAL_PEN: 4;
|
|
78
|
+
readonly DISPLAY_HIGH: 8;
|
|
79
|
+
readonly DISPLAY_NON: 12;
|
|
80
|
+
readonly MDT: 1;
|
|
81
|
+
};
|
|
82
|
+
export declare const EXTENDED_ATTR: {
|
|
83
|
+
readonly HIGHLIGHT: 65;
|
|
84
|
+
readonly COLOR: 66;
|
|
85
|
+
readonly CHARSET: 67;
|
|
86
|
+
readonly FIELD_OUTLINING: 197;
|
|
87
|
+
readonly TRANSPARENCY: 70;
|
|
88
|
+
readonly ALL: 0;
|
|
89
|
+
};
|
|
90
|
+
export declare const HIGHLIGHT: {
|
|
91
|
+
readonly DEFAULT: 0;
|
|
92
|
+
readonly NORMAL: 240;
|
|
93
|
+
readonly BLINK: 241;
|
|
94
|
+
readonly REVERSE: 242;
|
|
95
|
+
readonly UNDERSCORE: 244;
|
|
96
|
+
};
|
|
97
|
+
export declare const COLOR: {
|
|
98
|
+
readonly DEFAULT: 0;
|
|
99
|
+
readonly BLUE: 241;
|
|
100
|
+
readonly RED: 242;
|
|
101
|
+
readonly PINK: 243;
|
|
102
|
+
readonly GREEN: 244;
|
|
103
|
+
readonly TURQUOISE: 245;
|
|
104
|
+
readonly YELLOW: 246;
|
|
105
|
+
readonly WHITE: 247;
|
|
106
|
+
};
|
|
107
|
+
export declare const ADDRESS_TABLE: number[];
|
|
108
|
+
export declare const ADDRESS_REVERSE: Map<number, number>;
|
|
109
|
+
/**
|
|
110
|
+
* Decode a 3270 buffer address from 2 bytes.
|
|
111
|
+
* Supports 12-bit (bits 7-6 of first byte are 00) and 14-bit addressing.
|
|
112
|
+
*/
|
|
113
|
+
export declare function decodeBufferAddress(byte1: number, byte2: number): number;
|
|
114
|
+
/**
|
|
115
|
+
* Encode a buffer address into 2 bytes using 12-bit encoding.
|
|
116
|
+
*/
|
|
117
|
+
export declare function encodeBufferAddress12(address: number): [number, number];
|
|
118
|
+
/**
|
|
119
|
+
* Encode a buffer address into 2 bytes using 14-bit binary encoding.
|
|
120
|
+
*/
|
|
121
|
+
export declare function encodeBufferAddress14(address: number): [number, number];
|
|
122
|
+
export declare const SCREEN3270: {
|
|
123
|
+
readonly MODEL2_ROWS: 24;
|
|
124
|
+
readonly MODEL2_COLS: 80;
|
|
125
|
+
readonly MODEL3_ROWS: 32;
|
|
126
|
+
readonly MODEL3_COLS: 80;
|
|
127
|
+
readonly MODEL4_ROWS: 43;
|
|
128
|
+
readonly MODEL4_COLS: 80;
|
|
129
|
+
readonly MODEL5_ROWS: 27;
|
|
130
|
+
readonly MODEL5_COLS: 132;
|
|
131
|
+
};
|
|
132
|
+
export declare const TERMINAL_TYPE_3270 = "IBM-3278-2";
|
|
133
|
+
export declare const TERMINAL_TYPE_3270_M3 = "IBM-3278-3";
|
|
134
|
+
export declare const TERMINAL_TYPE_3270_M4 = "IBM-3278-4";
|
|
135
|
+
export declare const TERMINAL_TYPE_3270_M5 = "IBM-3278-5";
|
|
136
|
+
export declare const TERMINAL_TYPE_3270E = "IBM-3278-2-E";
|
|
137
|
+
export declare const OPT_TN3270E = 40;
|
|
138
|
+
export declare const CMD: {
|
|
139
|
+
readonly WRITE: 241;
|
|
140
|
+
readonly ERASE_WRITE: 245;
|
|
141
|
+
readonly ERASE_WRITE_ALTERNATE: 126;
|
|
142
|
+
readonly READ_BUFFER: 242;
|
|
143
|
+
readonly READ_MODIFIED: 246;
|
|
144
|
+
readonly READ_MODIFIED_ALL: 110;
|
|
145
|
+
readonly ERASE_ALL_UNPROTECTED: 111;
|
|
146
|
+
readonly WRITE_STRUCTURED_FIELD: 243;
|
|
147
|
+
readonly SNA_WRITE: 1;
|
|
148
|
+
readonly SNA_ERASE_WRITE: 5;
|
|
149
|
+
readonly SNA_ERASE_WRITE_ALTERNATE: 13;
|
|
150
|
+
readonly SNA_READ_BUFFER: 2;
|
|
151
|
+
readonly SNA_READ_MODIFIED: 6;
|
|
152
|
+
readonly SNA_READ_MODIFIED_ALL: 14;
|
|
153
|
+
readonly SNA_ERASE_ALL_UNPROTECTED: 15;
|
|
154
|
+
};
|
|
155
|
+
export declare const SNA_CMD: {
|
|
156
|
+
readonly WRITE: 1;
|
|
157
|
+
readonly ERASE_WRITE: 5;
|
|
158
|
+
readonly ERASE_WRITE_ALTERNATE: 13;
|
|
159
|
+
readonly READ_BUFFER: 2;
|
|
160
|
+
readonly READ_MODIFIED: 6;
|
|
161
|
+
readonly READ_MODIFIED_ALL: 14;
|
|
162
|
+
readonly ERASE_ALL_UNPROTECTED: 15;
|
|
163
|
+
readonly WRITE_STRUCTURED_FIELD: 243;
|
|
164
|
+
};
|
|
165
|
+
export declare const ORDER: {
|
|
166
|
+
readonly SBA: 17;
|
|
167
|
+
readonly SF: 29;
|
|
168
|
+
readonly SFE: 41;
|
|
169
|
+
readonly SA: 40;
|
|
170
|
+
readonly MF: 44;
|
|
171
|
+
readonly IC: 19;
|
|
172
|
+
readonly PT: 5;
|
|
173
|
+
readonly RA: 60;
|
|
174
|
+
readonly EUA: 18;
|
|
175
|
+
readonly GE: 8;
|
|
176
|
+
};
|
|
177
|
+
export declare const AID: {
|
|
178
|
+
readonly ENTER: 125;
|
|
179
|
+
readonly PF1: 241;
|
|
180
|
+
readonly PF2: 242;
|
|
181
|
+
readonly PF3: 243;
|
|
182
|
+
readonly PF4: 244;
|
|
183
|
+
readonly PF5: 245;
|
|
184
|
+
readonly PF6: 246;
|
|
185
|
+
readonly PF7: 247;
|
|
186
|
+
readonly PF8: 248;
|
|
187
|
+
readonly PF9: 249;
|
|
188
|
+
readonly PF10: 122;
|
|
189
|
+
readonly PF11: 123;
|
|
190
|
+
readonly PF12: 124;
|
|
191
|
+
readonly PF13: 193;
|
|
192
|
+
readonly PF14: 194;
|
|
193
|
+
readonly PF15: 195;
|
|
194
|
+
readonly PF16: 196;
|
|
195
|
+
readonly PF17: 197;
|
|
196
|
+
readonly PF18: 198;
|
|
197
|
+
readonly PF19: 199;
|
|
198
|
+
readonly PF20: 200;
|
|
199
|
+
readonly PF21: 201;
|
|
200
|
+
readonly PF22: 74;
|
|
201
|
+
readonly PF23: 75;
|
|
202
|
+
readonly PF24: 76;
|
|
203
|
+
readonly PA1: 108;
|
|
204
|
+
readonly PA2: 110;
|
|
205
|
+
readonly PA3: 107;
|
|
206
|
+
readonly CLEAR: 109;
|
|
207
|
+
readonly STRUCTURED_FIELD: 136;
|
|
208
|
+
readonly NO_AID: 96;
|
|
209
|
+
};
|
|
210
|
+
export declare const KEY_TO_AID: Record<string, number>;
|
|
211
|
+
export declare const FA: {
|
|
212
|
+
readonly PROTECTED: 32;
|
|
213
|
+
readonly NUMERIC: 16;
|
|
214
|
+
readonly DISPLAY_MASK: 12;
|
|
215
|
+
readonly DISPLAY_HIDDEN: 12;
|
|
216
|
+
readonly DISPLAY_INTENSIFIED: 8;
|
|
217
|
+
readonly MDT: 1;
|
|
218
|
+
};
|
|
219
|
+
export declare const EXT_ATTR: {
|
|
220
|
+
readonly HIGHLIGHT: 65;
|
|
221
|
+
readonly COLOR: 66;
|
|
222
|
+
readonly CHARSET: 67;
|
|
223
|
+
readonly FIELD_OUTLINING: 197;
|
|
224
|
+
readonly TRANSPARENCY: 70;
|
|
225
|
+
readonly ALL: 0;
|
|
226
|
+
};
|
|
227
|
+
export declare const decodeAddress: typeof decodeBufferAddress;
|
|
228
|
+
export declare function encodeAddress(addr: number, _screenSize: number): Buffer;
|
|
229
|
+
export declare const SCREEN: {
|
|
230
|
+
readonly MODEL_2_ROWS: 24;
|
|
231
|
+
readonly MODEL_2_COLS: 80;
|
|
232
|
+
};
|
|
233
|
+
export declare const TERMINAL_TYPE = "IBM-3278-2";
|
|
234
|
+
export declare const TN3270E: {
|
|
235
|
+
readonly CONNECT: 1;
|
|
236
|
+
readonly DEVICE_TYPE: 2;
|
|
237
|
+
readonly FUNCTIONS: 3;
|
|
238
|
+
readonly IS: 4;
|
|
239
|
+
readonly REASON: 5;
|
|
240
|
+
readonly REJECT: 6;
|
|
241
|
+
readonly REQUEST: 7;
|
|
242
|
+
readonly SEND: 8;
|
|
243
|
+
readonly FUNC_BIND_IMAGE: 0;
|
|
244
|
+
readonly FUNC_DATA_STREAM_CTL: 1;
|
|
245
|
+
readonly FUNC_RESPONSES: 2;
|
|
246
|
+
readonly FUNC_SCS_CTL_CODES: 3;
|
|
247
|
+
readonly FUNC_SYSREQ: 4;
|
|
248
|
+
readonly DT_3270_DATA: 0;
|
|
249
|
+
readonly DT_SCS_DATA: 1;
|
|
250
|
+
readonly DT_RESPONSE: 2;
|
|
251
|
+
readonly DT_BIND_IMAGE: 3;
|
|
252
|
+
readonly DT_UNBIND: 4;
|
|
253
|
+
readonly DT_NVT_DATA: 5;
|
|
254
|
+
readonly DT_REQUEST: 6;
|
|
255
|
+
readonly DT_SSCP_LU_DATA: 7;
|
|
256
|
+
readonly DT_PRINT_EOJ: 8;
|
|
257
|
+
readonly NO_RESPONSE: 0;
|
|
258
|
+
readonly ERROR_RESPONSE: 1;
|
|
259
|
+
readonly ALWAYS_RESPONSE: 2;
|
|
260
|
+
readonly POSITIVE_RESPONSE: 0;
|
|
261
|
+
readonly NEGATIVE_RESPONSE: 1;
|
|
262
|
+
};
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// === Telnet Constants (shared with TN5250) ===
|
|
2
|
+
export { TELNET } from '../tn5250/constants.js';
|
|
3
|
+
// === 3270 Command Codes ===
|
|
4
|
+
export const CMD3270 = {
|
|
5
|
+
WRITE: 0xF1, // Write
|
|
6
|
+
ERASE_WRITE: 0xF5, // Erase/Write
|
|
7
|
+
ERASE_WRITE_ALTERNATE: 0x7E, // Erase/Write Alternate
|
|
8
|
+
READ_BUFFER: 0xF2, // Read Buffer
|
|
9
|
+
READ_MODIFIED: 0xF6, // Read Modified
|
|
10
|
+
READ_MODIFIED_ALL: 0x6E, // Read Modified All
|
|
11
|
+
ERASE_ALL_UNPROTECTED: 0x6F, // Erase All Unprotected
|
|
12
|
+
WRITE_STRUCTURED_FIELD: 0xF3, // Write Structured Field
|
|
13
|
+
// SNA variants (without 0x40 bit set)
|
|
14
|
+
SNA_WRITE: 0x01,
|
|
15
|
+
SNA_ERASE_WRITE: 0x05,
|
|
16
|
+
SNA_ERASE_WRITE_ALTERNATE: 0x0D,
|
|
17
|
+
SNA_READ_BUFFER: 0x02,
|
|
18
|
+
SNA_READ_MODIFIED: 0x06,
|
|
19
|
+
SNA_READ_MODIFIED_ALL: 0x0E,
|
|
20
|
+
SNA_ERASE_ALL_UNPROTECTED: 0x0F,
|
|
21
|
+
};
|
|
22
|
+
// === 3270 Order Codes ===
|
|
23
|
+
export const ORDER3270 = {
|
|
24
|
+
SBA: 0x11, // Set Buffer Address
|
|
25
|
+
SF: 0x1D, // Start Field
|
|
26
|
+
SFE: 0x29, // Start Field Extended
|
|
27
|
+
SA: 0x28, // Set Attribute
|
|
28
|
+
MF: 0x2C, // Modify Field
|
|
29
|
+
IC: 0x13, // Insert Cursor
|
|
30
|
+
PT: 0x05, // Program Tab
|
|
31
|
+
RA: 0x3C, // Repeat to Address
|
|
32
|
+
EUA: 0x12, // Erase Unprotected to Address
|
|
33
|
+
GE: 0x08, // Graphic Escape
|
|
34
|
+
};
|
|
35
|
+
// === WCC (Write Control Character) bits ===
|
|
36
|
+
export const WCC = {
|
|
37
|
+
RESET_MDT: 0x02, // Reset Modified Data Tags
|
|
38
|
+
RESET_KEYBOARD: 0x40, // Reset keyboard lock
|
|
39
|
+
SOUND_ALARM: 0x04, // Sound audible alarm
|
|
40
|
+
RESET_PARTITION: 0x01, // Reset partition characteristics
|
|
41
|
+
START_PRINTER: 0x08, // Start printer
|
|
42
|
+
};
|
|
43
|
+
// === 3270 AID (Attention Identifier) bytes ===
|
|
44
|
+
export const AID3270 = {
|
|
45
|
+
ENTER: 0x7D,
|
|
46
|
+
PF1: 0xF1, PF2: 0xF2, PF3: 0xF3, PF4: 0xF4,
|
|
47
|
+
PF5: 0xF5, PF6: 0xF6, PF7: 0xF7, PF8: 0xF8,
|
|
48
|
+
PF9: 0xF9, PF10: 0x7A, PF11: 0x7B, PF12: 0x7C,
|
|
49
|
+
PF13: 0xC1, PF14: 0xC2, PF15: 0xC3, PF16: 0xC4,
|
|
50
|
+
PF17: 0xC5, PF18: 0xC6, PF19: 0xC7, PF20: 0xC8,
|
|
51
|
+
PF21: 0xC9, PF22: 0x4A, PF23: 0x4B, PF24: 0x4C,
|
|
52
|
+
PA1: 0x6C,
|
|
53
|
+
PA2: 0x6E,
|
|
54
|
+
PA3: 0x6B,
|
|
55
|
+
CLEAR: 0x6D,
|
|
56
|
+
STRUCTURED_FIELD: 0x88,
|
|
57
|
+
NO_AID: 0x60,
|
|
58
|
+
};
|
|
59
|
+
// Map key names (from frontend) to AID bytes
|
|
60
|
+
export const KEY_TO_AID3270 = {
|
|
61
|
+
'Enter': AID3270.ENTER,
|
|
62
|
+
'F1': AID3270.PF1, 'F2': AID3270.PF2, 'F3': AID3270.PF3, 'F4': AID3270.PF4,
|
|
63
|
+
'F5': AID3270.PF5, 'F6': AID3270.PF6, 'F7': AID3270.PF7, 'F8': AID3270.PF8,
|
|
64
|
+
'F9': AID3270.PF9, 'F10': AID3270.PF10, 'F11': AID3270.PF11, 'F12': AID3270.PF12,
|
|
65
|
+
'F13': AID3270.PF13, 'F14': AID3270.PF14, 'F15': AID3270.PF15, 'F16': AID3270.PF16,
|
|
66
|
+
'F17': AID3270.PF17, 'F18': AID3270.PF18, 'F19': AID3270.PF19, 'F20': AID3270.PF20,
|
|
67
|
+
'F21': AID3270.PF21, 'F22': AID3270.PF22, 'F23': AID3270.PF23, 'F24': AID3270.PF24,
|
|
68
|
+
'PA1': AID3270.PA1,
|
|
69
|
+
'PA2': AID3270.PA2,
|
|
70
|
+
'PA3': AID3270.PA3,
|
|
71
|
+
'Clear': AID3270.CLEAR,
|
|
72
|
+
'PageUp': AID3270.PF7, // Common mapping
|
|
73
|
+
'PageDown': AID3270.PF8, // Common mapping
|
|
74
|
+
};
|
|
75
|
+
// === 3270 Field Attribute Byte ===
|
|
76
|
+
// Bit layout (bit 7 = MSB):
|
|
77
|
+
// Bit 7: always 1 (attribute indicator, but occupies buffer position as 0x00 display)
|
|
78
|
+
// Bit 6: protected (1) / unprotected (0)
|
|
79
|
+
// Bit 5: numeric (1) / alphanumeric (0)
|
|
80
|
+
// Bits 4-3: display - 00=normal/pen-detectable, 01=normal/pen-detectable,
|
|
81
|
+
// 10=high-intensity/selector-pen, 11=non-display
|
|
82
|
+
// Bit 2: reserved
|
|
83
|
+
// Bit 1: MDT (Modified Data Tag)
|
|
84
|
+
// Bit 0: reserved
|
|
85
|
+
export const FIELD_ATTR = {
|
|
86
|
+
PROTECTED: 0x20, // Bit 5 in attribute byte (bit 6 of logical layout)
|
|
87
|
+
NUMERIC: 0x10, // Bit 4
|
|
88
|
+
DISPLAY_MASK: 0x0C, // Bits 3-2
|
|
89
|
+
DISPLAY_NORMAL: 0x00,
|
|
90
|
+
DISPLAY_NORMAL_PEN: 0x04,
|
|
91
|
+
DISPLAY_HIGH: 0x08,
|
|
92
|
+
DISPLAY_NON: 0x0C,
|
|
93
|
+
MDT: 0x01, // Bit 0 as stored (bit 1 of logical layout)
|
|
94
|
+
};
|
|
95
|
+
// === Extended Attribute Types (for SFE/SA/MF) ===
|
|
96
|
+
export const EXTENDED_ATTR = {
|
|
97
|
+
HIGHLIGHT: 0x41,
|
|
98
|
+
COLOR: 0x42,
|
|
99
|
+
CHARSET: 0x43,
|
|
100
|
+
FIELD_OUTLINING: 0xC5,
|
|
101
|
+
TRANSPARENCY: 0x46,
|
|
102
|
+
ALL: 0x00, // Reset all
|
|
103
|
+
};
|
|
104
|
+
// Highlight values
|
|
105
|
+
export const HIGHLIGHT = {
|
|
106
|
+
DEFAULT: 0x00,
|
|
107
|
+
NORMAL: 0xF0,
|
|
108
|
+
BLINK: 0xF1,
|
|
109
|
+
REVERSE: 0xF2,
|
|
110
|
+
UNDERSCORE: 0xF4,
|
|
111
|
+
};
|
|
112
|
+
// Color values
|
|
113
|
+
export const COLOR = {
|
|
114
|
+
DEFAULT: 0x00,
|
|
115
|
+
BLUE: 0xF1,
|
|
116
|
+
RED: 0xF2,
|
|
117
|
+
PINK: 0xF3,
|
|
118
|
+
GREEN: 0xF4,
|
|
119
|
+
TURQUOISE: 0xF5,
|
|
120
|
+
YELLOW: 0xF6,
|
|
121
|
+
WHITE: 0xF7,
|
|
122
|
+
};
|
|
123
|
+
// === 3270 Buffer Address Encoding ===
|
|
124
|
+
// 12-bit/14-bit/16-bit address encoding lookup table
|
|
125
|
+
// Each 6-bit value (0-63) maps to a specific byte value
|
|
126
|
+
export const ADDRESS_TABLE = [
|
|
127
|
+
0x40, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
|
|
128
|
+
0xC8, 0xC9, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
|
129
|
+
0x50, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
|
|
130
|
+
0xD8, 0xD9, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
|
131
|
+
0x60, 0x61, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
|
|
132
|
+
0xE8, 0xE9, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
|
133
|
+
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
|
|
134
|
+
0xF8, 0xF9, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
|
135
|
+
];
|
|
136
|
+
// Build reverse lookup: encoded byte -> 6-bit value
|
|
137
|
+
export const ADDRESS_REVERSE = new Map();
|
|
138
|
+
for (let i = 0; i < ADDRESS_TABLE.length; i++) {
|
|
139
|
+
ADDRESS_REVERSE.set(ADDRESS_TABLE[i], i);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Decode a 3270 buffer address from 2 bytes.
|
|
143
|
+
* Supports 12-bit (bits 7-6 of first byte are 00) and 14-bit addressing.
|
|
144
|
+
*/
|
|
145
|
+
export function decodeBufferAddress(byte1, byte2) {
|
|
146
|
+
// Check addressing mode from high bits of first byte
|
|
147
|
+
if ((byte1 & 0xC0) === 0x00) {
|
|
148
|
+
// 14-bit binary address
|
|
149
|
+
return ((byte1 & 0x3F) << 8) | byte2;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// 12-bit encoded address (standard for 24x80)
|
|
153
|
+
const high = ADDRESS_REVERSE.get(byte1) ?? 0;
|
|
154
|
+
const low = ADDRESS_REVERSE.get(byte2) ?? 0;
|
|
155
|
+
return (high << 6) | low;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Encode a buffer address into 2 bytes using 12-bit encoding.
|
|
160
|
+
*/
|
|
161
|
+
export function encodeBufferAddress12(address) {
|
|
162
|
+
const high = (address >> 6) & 0x3F;
|
|
163
|
+
const low = address & 0x3F;
|
|
164
|
+
return [ADDRESS_TABLE[high], ADDRESS_TABLE[low]];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Encode a buffer address into 2 bytes using 14-bit binary encoding.
|
|
168
|
+
*/
|
|
169
|
+
export function encodeBufferAddress14(address) {
|
|
170
|
+
return [(address >> 8) & 0x3F, address & 0xFF];
|
|
171
|
+
}
|
|
172
|
+
// === Screen Dimensions ===
|
|
173
|
+
export const SCREEN3270 = {
|
|
174
|
+
// Model 2: 24x80 (standard)
|
|
175
|
+
MODEL2_ROWS: 24,
|
|
176
|
+
MODEL2_COLS: 80,
|
|
177
|
+
// Model 3: 32x80
|
|
178
|
+
MODEL3_ROWS: 32,
|
|
179
|
+
MODEL3_COLS: 80,
|
|
180
|
+
// Model 4: 43x80
|
|
181
|
+
MODEL4_ROWS: 43,
|
|
182
|
+
MODEL4_COLS: 80,
|
|
183
|
+
// Model 5: 27x132
|
|
184
|
+
MODEL5_ROWS: 27,
|
|
185
|
+
MODEL5_COLS: 132,
|
|
186
|
+
};
|
|
187
|
+
// Terminal type strings
|
|
188
|
+
export const TERMINAL_TYPE_3270 = 'IBM-3278-2'; // Model 2 (24x80)
|
|
189
|
+
export const TERMINAL_TYPE_3270_M3 = 'IBM-3278-3'; // Model 3 (32x80)
|
|
190
|
+
export const TERMINAL_TYPE_3270_M4 = 'IBM-3278-4'; // Model 4 (43x80)
|
|
191
|
+
export const TERMINAL_TYPE_3270_M5 = 'IBM-3278-5'; // Model 5 (27x132)
|
|
192
|
+
export const TERMINAL_TYPE_3270E = 'IBM-3278-2-E'; // TN3270E variant
|
|
193
|
+
// TN3270E option code (RFC 2355)
|
|
194
|
+
export const OPT_TN3270E = 0x28;
|
|
195
|
+
// === Aliases used by connection.ts, encoder.ts, parser.ts, screen.ts ===
|
|
196
|
+
export const CMD = CMD3270;
|
|
197
|
+
export const SNA_CMD = {
|
|
198
|
+
WRITE: CMD3270.SNA_WRITE,
|
|
199
|
+
ERASE_WRITE: CMD3270.SNA_ERASE_WRITE,
|
|
200
|
+
ERASE_WRITE_ALTERNATE: CMD3270.SNA_ERASE_WRITE_ALTERNATE,
|
|
201
|
+
READ_BUFFER: CMD3270.SNA_READ_BUFFER,
|
|
202
|
+
READ_MODIFIED: CMD3270.SNA_READ_MODIFIED,
|
|
203
|
+
READ_MODIFIED_ALL: CMD3270.SNA_READ_MODIFIED_ALL,
|
|
204
|
+
ERASE_ALL_UNPROTECTED: CMD3270.SNA_ERASE_ALL_UNPROTECTED,
|
|
205
|
+
WRITE_STRUCTURED_FIELD: CMD3270.WRITE_STRUCTURED_FIELD,
|
|
206
|
+
};
|
|
207
|
+
export const ORDER = ORDER3270;
|
|
208
|
+
export const AID = AID3270;
|
|
209
|
+
export const KEY_TO_AID = KEY_TO_AID3270;
|
|
210
|
+
export const FA = {
|
|
211
|
+
PROTECTED: FIELD_ATTR.PROTECTED,
|
|
212
|
+
NUMERIC: FIELD_ATTR.NUMERIC,
|
|
213
|
+
DISPLAY_MASK: FIELD_ATTR.DISPLAY_MASK,
|
|
214
|
+
DISPLAY_HIDDEN: FIELD_ATTR.DISPLAY_NON,
|
|
215
|
+
DISPLAY_INTENSIFIED: FIELD_ATTR.DISPLAY_HIGH,
|
|
216
|
+
MDT: FIELD_ATTR.MDT,
|
|
217
|
+
};
|
|
218
|
+
export const EXT_ATTR = EXTENDED_ATTR;
|
|
219
|
+
export const decodeAddress = decodeBufferAddress;
|
|
220
|
+
export function encodeAddress(addr, _screenSize) {
|
|
221
|
+
const [b1, b2] = encodeBufferAddress12(addr);
|
|
222
|
+
return Buffer.from([b1, b2]);
|
|
223
|
+
}
|
|
224
|
+
export const SCREEN = {
|
|
225
|
+
MODEL_2_ROWS: SCREEN3270.MODEL2_ROWS,
|
|
226
|
+
MODEL_2_COLS: SCREEN3270.MODEL2_COLS,
|
|
227
|
+
};
|
|
228
|
+
export const TERMINAL_TYPE = TERMINAL_TYPE_3270;
|
|
229
|
+
// TN3270E subnegotiation types
|
|
230
|
+
export const TN3270E = {
|
|
231
|
+
CONNECT: 0x01,
|
|
232
|
+
DEVICE_TYPE: 0x02,
|
|
233
|
+
FUNCTIONS: 0x03,
|
|
234
|
+
IS: 0x04,
|
|
235
|
+
REASON: 0x05,
|
|
236
|
+
REJECT: 0x06,
|
|
237
|
+
REQUEST: 0x07,
|
|
238
|
+
SEND: 0x08,
|
|
239
|
+
// Function request flags
|
|
240
|
+
FUNC_BIND_IMAGE: 0x00,
|
|
241
|
+
FUNC_DATA_STREAM_CTL: 0x01,
|
|
242
|
+
FUNC_RESPONSES: 0x02,
|
|
243
|
+
FUNC_SCS_CTL_CODES: 0x03,
|
|
244
|
+
FUNC_SYSREQ: 0x04,
|
|
245
|
+
// Data header types (when TN3270E mode is active)
|
|
246
|
+
DT_3270_DATA: 0x00,
|
|
247
|
+
DT_SCS_DATA: 0x01,
|
|
248
|
+
DT_RESPONSE: 0x02,
|
|
249
|
+
DT_BIND_IMAGE: 0x03,
|
|
250
|
+
DT_UNBIND: 0x04,
|
|
251
|
+
DT_NVT_DATA: 0x05,
|
|
252
|
+
DT_REQUEST: 0x06,
|
|
253
|
+
DT_SSCP_LU_DATA: 0x07,
|
|
254
|
+
DT_PRINT_EOJ: 0x08,
|
|
255
|
+
// Response flags
|
|
256
|
+
NO_RESPONSE: 0x00,
|
|
257
|
+
ERROR_RESPONSE: 0x01,
|
|
258
|
+
ALWAYS_RESPONSE: 0x02,
|
|
259
|
+
POSITIVE_RESPONSE: 0x00,
|
|
260
|
+
NEGATIVE_RESPONSE: 0x01,
|
|
261
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ScreenBuffer3270 } from './screen.js';
|
|
2
|
+
/**
|
|
3
|
+
* Encodes 3270 client responses (AID key + modified field data)
|
|
4
|
+
* for sending back to the z/OS host.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TN3270Encoder {
|
|
7
|
+
private screen;
|
|
8
|
+
constructor(screen: ScreenBuffer3270);
|
|
9
|
+
/**
|
|
10
|
+
* Build a 3270 Read Modified response for an AID key press.
|
|
11
|
+
* Format: AID + cursor_addr(2) + [SBA(1) + addr(2) + field_data]... + IAC EOR
|
|
12
|
+
*/
|
|
13
|
+
buildAidResponse(keyName: string): Buffer | null;
|
|
14
|
+
/**
|
|
15
|
+
* Wrap data with Telnet IAC EOR framing.
|
|
16
|
+
* Escapes any 0xFF bytes in the data.
|
|
17
|
+
*/
|
|
18
|
+
private wrapWithEOR;
|
|
19
|
+
/**
|
|
20
|
+
* Insert text at the current cursor position in the current field.
|
|
21
|
+
* Returns true if text was successfully inserted.
|
|
22
|
+
*/
|
|
23
|
+
insertText(text: string): boolean;
|
|
24
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { TELNET } from '../tn5250/constants.js';
|
|
2
|
+
import { KEY_TO_AID, AID, ORDER, encodeAddress } from './constants.js';
|
|
3
|
+
import { charToEbcdic, EBCDIC_SPACE } from '../tn5250/ebcdic.js';
|
|
4
|
+
/**
|
|
5
|
+
* Encodes 3270 client responses (AID key + modified field data)
|
|
6
|
+
* for sending back to the z/OS host.
|
|
7
|
+
*/
|
|
8
|
+
export class TN3270Encoder {
|
|
9
|
+
screen;
|
|
10
|
+
constructor(screen) {
|
|
11
|
+
this.screen = screen;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build a 3270 Read Modified response for an AID key press.
|
|
15
|
+
* Format: AID + cursor_addr(2) + [SBA(1) + addr(2) + field_data]... + IAC EOR
|
|
16
|
+
*/
|
|
17
|
+
buildAidResponse(keyName) {
|
|
18
|
+
const aidByte = KEY_TO_AID[keyName];
|
|
19
|
+
if (aidByte === undefined)
|
|
20
|
+
return null;
|
|
21
|
+
const parts = [];
|
|
22
|
+
// AID byte
|
|
23
|
+
parts.push(Buffer.from([aidByte]));
|
|
24
|
+
// Cursor address (2 bytes)
|
|
25
|
+
parts.push(encodeAddress(this.screen.cursorAddr, this.screen.size));
|
|
26
|
+
// For short-read AIDs (PA keys, Clear), no field data
|
|
27
|
+
if (aidByte === AID.PA1 || aidByte === AID.PA2 || aidByte === AID.PA3 || aidByte === AID.CLEAR) {
|
|
28
|
+
return this.wrapWithEOR(Buffer.concat(parts));
|
|
29
|
+
}
|
|
30
|
+
// Collect modified fields
|
|
31
|
+
for (const field of this.screen.fields) {
|
|
32
|
+
if (!field.modified)
|
|
33
|
+
continue;
|
|
34
|
+
if (this.screen.isProtected(field))
|
|
35
|
+
continue;
|
|
36
|
+
// SBA order + field start address
|
|
37
|
+
const sba = Buffer.alloc(3);
|
|
38
|
+
sba[0] = ORDER.SBA;
|
|
39
|
+
const addrBuf = encodeAddress(field.startAddr, this.screen.size);
|
|
40
|
+
sba[1] = addrBuf[0];
|
|
41
|
+
sba[2] = addrBuf[1];
|
|
42
|
+
parts.push(sba);
|
|
43
|
+
// Field data in EBCDIC, trimmed
|
|
44
|
+
const value = this.screen.getFieldValue(field);
|
|
45
|
+
const ebcdicData = Buffer.alloc(value.length);
|
|
46
|
+
for (let i = 0; i < value.length; i++) {
|
|
47
|
+
ebcdicData[i] = charToEbcdic(value[i]);
|
|
48
|
+
}
|
|
49
|
+
// Trim trailing EBCDIC spaces
|
|
50
|
+
let trimLen = ebcdicData.length;
|
|
51
|
+
while (trimLen > 0 && ebcdicData[trimLen - 1] === EBCDIC_SPACE) {
|
|
52
|
+
trimLen--;
|
|
53
|
+
}
|
|
54
|
+
if (trimLen > 0) {
|
|
55
|
+
parts.push(ebcdicData.subarray(0, trimLen));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return this.wrapWithEOR(Buffer.concat(parts));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Wrap data with Telnet IAC EOR framing.
|
|
62
|
+
* Escapes any 0xFF bytes in the data.
|
|
63
|
+
*/
|
|
64
|
+
wrapWithEOR(data) {
|
|
65
|
+
const escaped = [];
|
|
66
|
+
for (let i = 0; i < data.length; i++) {
|
|
67
|
+
escaped.push(data[i]);
|
|
68
|
+
if (data[i] === TELNET.IAC) {
|
|
69
|
+
escaped.push(TELNET.IAC);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
escaped.push(TELNET.IAC, TELNET.EOR);
|
|
73
|
+
return Buffer.from(escaped);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Insert text at the current cursor position in the current field.
|
|
77
|
+
* Returns true if text was successfully inserted.
|
|
78
|
+
*/
|
|
79
|
+
insertText(text) {
|
|
80
|
+
const field = this.screen.getFieldAtCursor();
|
|
81
|
+
if (!field || this.screen.isProtected(field))
|
|
82
|
+
return false;
|
|
83
|
+
let cursorAddr = this.screen.cursorAddr;
|
|
84
|
+
const fieldEnd = (field.startAddr + field.length) % this.screen.size;
|
|
85
|
+
for (const ch of text) {
|
|
86
|
+
if (cursorAddr === fieldEnd)
|
|
87
|
+
break;
|
|
88
|
+
this.screen.buffer[cursorAddr] = ch;
|
|
89
|
+
cursorAddr = (cursorAddr + 1) % this.screen.size;
|
|
90
|
+
}
|
|
91
|
+
this.screen.cursorAddr = cursorAddr;
|
|
92
|
+
field.modified = true;
|
|
93
|
+
// Set MDT in the attribute
|
|
94
|
+
this.screen.attrBuffer[field.attrAddr] |= 0x01;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ScreenBuffer3270 } from './screen.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses 3270 data stream records and updates the screen buffer.
|
|
4
|
+
*/
|
|
5
|
+
export declare class TN3270Parser {
|
|
6
|
+
private screen;
|
|
7
|
+
constructor(screen: ScreenBuffer3270);
|
|
8
|
+
/**
|
|
9
|
+
* Parse a 3270 data stream record.
|
|
10
|
+
* Returns true if the screen was modified.
|
|
11
|
+
*/
|
|
12
|
+
parseRecord(record: Buffer): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Parse a Write or Erase/Write command body.
|
|
15
|
+
* Starts at `offset` which points to the WCC byte.
|
|
16
|
+
*/
|
|
17
|
+
private parseWrite;
|
|
18
|
+
/** Parse structured fields */
|
|
19
|
+
private parseStructuredFields;
|
|
20
|
+
/** Advance cursor to the start of the next unprotected field */
|
|
21
|
+
private advanceToNextUnprotected;
|
|
22
|
+
}
|