1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.telnet;
19
20 import java.io.BufferedInputStream;
21 import java.io.BufferedOutputStream;
22 import java.io.OutputStream;
23 import java.io.IOException;
24 import org.apache.commons.net.SocketClient;
25
26
27
28
29
30
31 class Telnet extends SocketClient
32 {
33 static final boolean debug =
34
35 static final boolean debugoptions =
36
37 static final byte[] _COMMAND_DO = {
38 (byte)TelnetCommand.IAC, (byte)TelnetCommand.DO
39 };
40
41 static final byte[] _COMMAND_DONT = {
42 (byte)TelnetCommand.IAC, (byte)TelnetCommand.DONT
43 };
44
45 static final byte[] _COMMAND_WILL = {
46 (byte)TelnetCommand.IAC, (byte)TelnetCommand.WILL
47 };
48
49 static final byte[] _COMMAND_WONT = {
50 (byte)TelnetCommand.IAC, (byte)TelnetCommand.WONT
51 };
52
53 static final byte[] _COMMAND_SB = {
54 (byte)TelnetCommand.IAC, (byte)TelnetCommand.SB
55 };
56
57 static final byte[] _COMMAND_SE = {
58 (byte)TelnetCommand.IAC, (byte)TelnetCommand.SE
59 };
60
61 static final int _WILL_MASK = 0x01, _DO_MASK = 0x02,
62 _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08;
63
64
65 static final int DEFAULT_PORT = 23;
66
67 int[] _doResponse, _willResponse, _options;
68
69
70
71
72
73 protected static final int TERMINAL_TYPE = 24;
74
75
76
77
78 protected static final int TERMINAL_TYPE_SEND = 1;
79
80
81
82
83 protected static final int TERMINAL_TYPE_IS = 0;
84
85
86
87
88 static final byte[] _COMMAND_IS = {
89 (byte) TERMINAL_TYPE, (byte) TERMINAL_TYPE_IS
90 };
91
92
93
94
95 private String terminalType = null;
96
97
98
99
100
101
102 private TelnetOptionHandler optionHandlers[];
103
104
105
106
107
108
109
110 static final byte[] _COMMAND_AYT = {
111 (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT
112 };
113
114
115
116
117 private Object aytMonitor = new Object();
118
119
120
121
122 private boolean aytFlag = true;
123
124
125
126
127
128 private OutputStream spyStream = null;
129
130
131
132
133 private TelnetNotificationHandler __notifhand = null;
134
135
136
137 Telnet()
138 {
139 setDefaultPort(DEFAULT_PORT);
140 _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
141 _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
142 _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
143 optionHandlers =
144 new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
145 }
146
147
148
149
150
151
152
153 Telnet(String termtype)
154 {
155 setDefaultPort(DEFAULT_PORT);
156 _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
157 _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
158 _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
159 terminalType = termtype;
160 optionHandlers =
161 new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
162 }
163
164
165
166
167
168
169
170
171
172 boolean _stateIsWill(int option)
173 {
174 return ((_options[option] & _WILL_MASK) != 0);
175 }
176
177
178
179
180
181
182
183
184 boolean _stateIsWont(int option)
185 {
186 return !_stateIsWill(option);
187 }
188
189
190
191
192
193
194
195
196 boolean _stateIsDo(int option)
197 {
198 return ((_options[option] & _DO_MASK) != 0);
199 }
200
201
202
203
204
205
206
207
208 boolean _stateIsDont(int option)
209 {
210 return !_stateIsDo(option);
211 }
212
213
214
215
216
217
218
219
220 boolean _requestedWill(int option)
221 {
222 return ((_options[option] & _REQUESTED_WILL_MASK) != 0);
223 }
224
225
226
227
228
229
230
231
232 boolean _requestedWont(int option)
233 {
234 return !_requestedWill(option);
235 }
236
237
238
239
240
241
242
243
244 boolean _requestedDo(int option)
245 {
246 return ((_options[option] & _REQUESTED_DO_MASK) != 0);
247 }
248
249
250
251
252
253
254
255
256 boolean _requestedDont(int option)
257 {
258 return !_requestedDo(option);
259 }
260
261
262
263
264
265
266 void _setWill(int option)
267 {
268 _options[option] |= _WILL_MASK;
269
270
271 if (_requestedWill(option))
272 {
273 if (optionHandlers[option] != null)
274 {
275 optionHandlers[option].setWill(true);
276
277 int subneg[] =
278 optionHandlers[option].startSubnegotiationLocal();
279
280 if (subneg != null)
281 {
282 try
283 {
284 _sendSubnegotiation(subneg);
285 }
286 catch (IOException e)
287 {
288 System.err.println(
289 "Exception in option subnegotiation"
290 + e.getMessage());
291 }
292 }
293 }
294 }
295
296 }
297
298
299
300
301
302
303 void _setDo(int option)
304 {
305 _options[option] |= _DO_MASK;
306
307
308 if (_requestedDo(option))
309 {
310 if (optionHandlers[option] != null)
311 {
312 optionHandlers[option].setDo(true);
313
314 int subneg[] =
315 optionHandlers[option].startSubnegotiationRemote();
316
317 if (subneg != null)
318 {
319 try
320 {
321 _sendSubnegotiation(subneg);
322 }
323 catch (IOException e)
324 {
325 System.err.println("Exception in option subnegotiation"
326 + e.getMessage());
327 }
328 }
329 }
330 }
331
332 }
333
334
335
336
337
338
339 void _setWantWill(int option)
340 {
341 _options[option] |= _REQUESTED_WILL_MASK;
342 }
343
344
345
346
347
348
349 void _setWantDo(int option)
350 {
351 _options[option] |= _REQUESTED_DO_MASK;
352 }
353
354
355
356
357
358
359 void _setWont(int option)
360 {
361 _options[option] &= ~_WILL_MASK;
362
363
364 if (optionHandlers[option] != null)
365 {
366 optionHandlers[option].setWill(false);
367 }
368
369 }
370
371
372
373
374
375
376 void _setDont(int option)
377 {
378 _options[option] &= ~_DO_MASK;
379
380
381 if (optionHandlers[option] != null)
382 {
383 optionHandlers[option].setDo(false);
384 }
385
386 }
387
388
389
390
391
392
393 void _setWantWont(int option)
394 {
395 _options[option] &= ~_REQUESTED_WILL_MASK;
396 }
397
398
399
400
401
402
403 void _setWantDont(int option)
404 {
405 _options[option] &= ~_REQUESTED_DO_MASK;
406 }
407
408
409
410
411
412
413
414 void _processDo(int option) throws IOException
415 {
416 if (debugoptions)
417 {
418 System.err.println("RECEIVED DO: "
419 + TelnetOption.getOption(option));
420 }
421
422 if (__notifhand != null)
423 {
424 __notifhand.receivedNegotiation(
425 TelnetNotificationHandler.RECEIVED_DO,
426 option);
427 }
428
429 boolean acceptNewState = false;
430
431
432
433 if (optionHandlers[option] != null)
434 {
435 acceptNewState = optionHandlers[option].getAcceptLocal();
436 }
437 else
438 {
439
440
441 if (option == TERMINAL_TYPE)
442 {
443 if ((terminalType != null) && (terminalType.length() > 0))
444 {
445 acceptNewState = true;
446 }
447 }
448
449
450 }
451
452
453 if (_willResponse[option] > 0)
454 {
455 --_willResponse[option];
456 if (_willResponse[option] > 0 && _stateIsWill(option))
457 {
458 --_willResponse[option];
459 }
460 }
461
462 if (_willResponse[option] == 0)
463 {
464 if (_requestedWont(option))
465 {
466
467 switch (option)
468 {
469
470 default:
471 break;
472
473 }
474
475
476 if (acceptNewState)
477 {
478 _setWantWill(option);
479 _sendWill(option);
480 }
481 else
482 {
483 ++_willResponse[option];
484 _sendWont(option);
485 }
486 }
487 else
488 {
489
490
491 switch (option)
492 {
493
494 default:
495 break;
496
497 }
498
499 }
500 }
501
502 _setWill(option);
503 }
504
505
506
507
508
509
510
511 void _processDont(int option) throws IOException
512 {
513 if (debugoptions)
514 {
515 System.err.println("RECEIVED DONT: "
516 + TelnetOption.getOption(option));
517 }
518 if (__notifhand != null)
519 {
520 __notifhand.receivedNegotiation(
521 TelnetNotificationHandler.RECEIVED_DONT,
522 option);
523 }
524 if (_willResponse[option] > 0)
525 {
526 --_willResponse[option];
527 if (_willResponse[option] > 0 && _stateIsWont(option))
528 {
529 --_willResponse[option];
530 }
531 }
532
533 if (_willResponse[option] == 0 && _requestedWill(option))
534 {
535
536 switch (option)
537 {
538
539 default:
540 break;
541
542 }
543
544
545 if ((_stateIsWill(option)) || (_requestedWill(option)))
546 {
547 _sendWont(option);
548 }
549
550 _setWantWont(option);
551
552 }
553
554 _setWont(option);
555 }
556
557
558
559
560
561
562
563
564 void _processWill(int option) throws IOException
565 {
566 if (debugoptions)
567 {
568 System.err.println("RECEIVED WILL: "
569 + TelnetOption.getOption(option));
570 }
571
572 if (__notifhand != null)
573 {
574 __notifhand.receivedNegotiation(
575 TelnetNotificationHandler.RECEIVED_WILL,
576 option);
577 }
578
579 boolean acceptNewState = false;
580
581
582 if (optionHandlers[option] != null)
583 {
584 acceptNewState = optionHandlers[option].getAcceptRemote();
585 }
586
587
588 if (_doResponse[option] > 0)
589 {
590 --_doResponse[option];
591 if (_doResponse[option] > 0 && _stateIsDo(option))
592 {
593 --_doResponse[option];
594 }
595 }
596
597 if (_doResponse[option] == 0 && _requestedDont(option))
598 {
599
600 switch (option)
601 {
602
603 default:
604 break;
605
606 }
607
608
609 if (acceptNewState)
610 {
611 _setWantDo(option);
612 _sendDo(option);
613 }
614 else
615 {
616 ++_doResponse[option];
617 _sendDont(option);
618 }
619 }
620
621 _setDo(option);
622 }
623
624
625
626
627
628
629
630 void _processWont(int option) throws IOException
631 {
632 if (debugoptions)
633 {
634 System.err.println("RECEIVED WONT: "
635 + TelnetOption.getOption(option));
636 }
637
638 if (__notifhand != null)
639 {
640 __notifhand.receivedNegotiation(
641 TelnetNotificationHandler.RECEIVED_WONT,
642 option);
643 }
644
645 if (_doResponse[option] > 0)
646 {
647 --_doResponse[option];
648 if (_doResponse[option] > 0 && _stateIsDont(option))
649 {
650 --_doResponse[option];
651 }
652 }
653
654 if (_doResponse[option] == 0 && _requestedDo(option))
655 {
656
657 switch (option)
658 {
659
660 default:
661 break;
662
663 }
664
665
666 if ((_stateIsDo(option)) || (_requestedDo(option)))
667 {
668 _sendDont(option);
669 }
670
671 _setWantDont(option);
672
673 }
674
675 _setDont(option);
676 }
677
678
679
680
681
682
683
684
685
686 void _processSuboption(int suboption[], int suboptionLength)
687 throws IOException
688 {
689 if (debug)
690 {
691 System.err.println("PROCESS SUBOPTION.");
692 }
693
694
695 if (suboptionLength > 0)
696 {
697 if (optionHandlers[suboption[0]] != null)
698 {
699 int responseSuboption[] =
700 optionHandlers[suboption[0]].answerSubnegotiation(suboption,
701 suboptionLength);
702 _sendSubnegotiation(responseSuboption);
703 }
704 else
705 {
706 if (suboptionLength > 1)
707 {
708 if (debug)
709 {
710 for (int ii = 0; ii < suboptionLength; ii++)
711 {
712 System.err.println("SUB[" + ii + "]: "
713 + suboption[ii]);
714 }
715 }
716 if ((suboption[0] == TERMINAL_TYPE)
717 && (suboption[1] == TERMINAL_TYPE_SEND))
718 {
719 _sendTerminalType();
720 }
721 }
722 }
723 }
724
725 }
726
727
728
729
730
731
732 final synchronized void _sendTerminalType()
733 throws IOException
734 {
735 if (debug)
736 {
737 System.err.println("SEND TERMINAL-TYPE: " + terminalType);
738 }
739 if (terminalType != null)
740 {
741 _output_.write(_COMMAND_SB);
742 _output_.write(_COMMAND_IS);
743 _output_.write(terminalType.getBytes());
744 _output_.write(_COMMAND_SE);
745 _output_.flush();
746 }
747 }
748
749
750
751
752
753
754
755
756
757
758 final synchronized void _sendSubnegotiation(int subn[])
759 throws IOException
760 {
761 if (debug)
762 {
763 System.err.println("SEND SUBNEGOTIATION: ");
764 if (subn != null)
765 {
766 for (int ii = 0; ii < subn.length; ii++)
767 {
768 System.err.println("subn[" + ii + "]=" + subn[ii]);
769 }
770 }
771 }
772 if (subn != null)
773 {
774 byte byteresp[] = new byte[subn.length];
775 for (int ii = 0; ii < subn.length; ii++)
776 {
777 byteresp[ii] = (byte) subn[ii];
778 }
779
780 _output_.write(_COMMAND_SB);
781 _output_.write(byteresp);
782 _output_.write(_COMMAND_SE);
783
784
785 _output_.flush();
786
787 }
788 }
789
790
791
792
793
794
795 final synchronized void _processAYTResponse()
796 {
797 if (!aytFlag)
798 {
799 synchronized (aytMonitor)
800 {
801 aytFlag = true;
802 try
803 {
804 aytMonitor.notifyAll();
805 }
806 catch (IllegalMonitorStateException e)
807 {
808 System.err.println("Exception notifying:" + e.getMessage());
809 }
810 }
811 }
812 }
813
814
815
816
817
818
819
820 @Override
821 protected void _connectAction_() throws IOException
822 {
823
824 for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
825 {
826 _doResponse[ii] = 0;
827 _willResponse[ii] = 0;
828 _options[ii] = 0;
829 if (optionHandlers[ii] != null)
830 {
831 optionHandlers[ii].setDo(false);
832 optionHandlers[ii].setWill(false);
833 }
834 }
835
836
837 super._connectAction_();
838 _input_ = new BufferedInputStream(_input_);
839 _output_ = new BufferedOutputStream(_output_);
840
841
842 for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
843 {
844 if (optionHandlers[ii] != null)
845 {
846 if (optionHandlers[ii].getInitLocal())
847 {
848 try
849 {
850 _requestWill(optionHandlers[ii].getOptionCode());
851 }
852 catch (IOException e)
853 {
854 System.err.println(
855 "Exception while initializing option: "
856 + e.getMessage());
857 }
858 }
859
860 if (optionHandlers[ii].getInitRemote())
861 {
862 try
863 {
864 _requestDo(optionHandlers[ii].getOptionCode());
865 }
866 catch (IOException e)
867 {
868 System.err.println(
869 "Exception while initializing option: "
870 + e.getMessage());
871 }
872 }
873 }
874 }
875
876 }
877
878
879
880
881
882
883
884 final synchronized void _sendDo(int option)
885 throws IOException
886 {
887 if (debug || debugoptions)
888 {
889 System.err.println("DO: " + TelnetOption.getOption(option));
890 }
891 _output_.write(_COMMAND_DO);
892 _output_.write(option);
893
894
895 _output_.flush();
896
897 }
898
899
900
901
902
903
904
905 final synchronized void _requestDo(int option)
906 throws IOException
907 {
908 if ((_doResponse[option] == 0 && _stateIsDo(option))
909 || _requestedDo(option))
910 {
911 return ;
912 }
913 _setWantDo(option);
914 ++_doResponse[option];
915 _sendDo(option);
916 }
917
918
919
920
921
922
923
924 final synchronized void _sendDont(int option)
925 throws IOException
926 {
927 if (debug || debugoptions)
928 {
929 System.err.println("DONT: " + TelnetOption.getOption(option));
930 }
931 _output_.write(_COMMAND_DONT);
932 _output_.write(option);
933
934
935 _output_.flush();
936
937 }
938
939
940
941
942
943
944
945 final synchronized void _requestDont(int option)
946 throws IOException
947 {
948 if ((_doResponse[option] == 0 && _stateIsDont(option))
949 || _requestedDont(option))
950 {
951 return ;
952 }
953 _setWantDont(option);
954 ++_doResponse[option];
955 _sendDont(option);
956 }
957
958
959
960
961
962
963
964
965 final synchronized void _sendWill(int option)
966 throws IOException
967 {
968 if (debug || debugoptions)
969 {
970 System.err.println("WILL: " + TelnetOption.getOption(option));
971 }
972 _output_.write(_COMMAND_WILL);
973 _output_.write(option);
974
975
976 _output_.flush();
977
978 }
979
980
981
982
983
984
985
986 final synchronized void _requestWill(int option)
987 throws IOException
988 {
989 if ((_willResponse[option] == 0 && _stateIsWill(option))
990 || _requestedWill(option))
991 {
992 return ;
993 }
994 _setWantWill(option);
995 ++_doResponse[option];
996 _sendWill(option);
997 }
998
999
1000
1001
1002
1003
1004
1005 final synchronized void _sendWont(int option)
1006 throws IOException
1007 {
1008 if (debug || debugoptions)
1009 {
1010 System.err.println("WONT: " + TelnetOption.getOption(option));
1011 }
1012 _output_.write(_COMMAND_WONT);
1013 _output_.write(option);
1014
1015
1016 _output_.flush();
1017
1018 }
1019
1020
1021
1022
1023
1024
1025
1026 final synchronized void _requestWont(int option)
1027 throws IOException
1028 {
1029 if ((_willResponse[option] == 0 && _stateIsWont(option))
1030 || _requestedWont(option))
1031 {
1032 return ;
1033 }
1034 _setWantWont(option);
1035 ++_doResponse[option];
1036 _sendWont(option);
1037 }
1038
1039
1040
1041
1042
1043
1044
1045 final synchronized void _sendByte(int b)
1046 throws IOException
1047 {
1048 _output_.write(b);
1049
1050
1051 _spyWrite(b);
1052
1053
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066 final boolean _sendAYT(long timeout)
1067 throws IOException, IllegalArgumentException, InterruptedException
1068 {
1069 boolean retValue = false;
1070 synchronized (aytMonitor)
1071 {
1072 synchronized (this)
1073 {
1074 aytFlag = false;
1075 _output_.write(_COMMAND_AYT);
1076 _output_.flush();
1077 }
1078
1079 try
1080 {
1081 aytMonitor.wait(timeout);
1082 if (aytFlag == false)
1083 {
1084 retValue = false;
1085 aytFlag = true;
1086 }
1087 else
1088 {
1089 retValue = true;
1090 }
1091 }
1092 catch (IllegalMonitorStateException e)
1093 {
1094 System.err.println("Exception processing AYT:"
1095 + e.getMessage());
1096 }
1097 }
1098
1099 return (retValue);
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 void addOptionHandler(TelnetOptionHandler opthand)
1112 throws InvalidTelnetOptionException
1113 {
1114 int optcode = opthand.getOptionCode();
1115 if (TelnetOption.isValidOption(optcode))
1116 {
1117 if (optionHandlers[optcode] == null)
1118 {
1119 optionHandlers[optcode] = opthand;
1120 if (isConnected())
1121 {
1122 if (opthand.getInitLocal())
1123 {
1124 try
1125 {
1126 _requestWill(optcode);
1127 }
1128 catch (IOException e)
1129 {
1130 System.err.println(
1131 "Exception while initializing option: "
1132 + e.getMessage());
1133 }
1134 }
1135
1136 if (opthand.getInitRemote())
1137 {
1138 try
1139 {
1140 _requestDo(optcode);
1141 }
1142 catch (IOException e)
1143 {
1144 System.err.println(
1145 "Exception while initializing option: "
1146 + e.getMessage());
1147 }
1148 }
1149 }
1150 }
1151 else
1152 {
1153 throw (new InvalidTelnetOptionException(
1154 "Already registered option", optcode));
1155 }
1156 }
1157 else
1158 {
1159 throw (new InvalidTelnetOptionException(
1160 "Invalid Option Code", optcode));
1161 }
1162 }
1163
1164
1165
1166
1167
1168
1169
1170 void deleteOptionHandler(int optcode)
1171 throws InvalidTelnetOptionException
1172 {
1173 if (TelnetOption.isValidOption(optcode))
1174 {
1175 if (optionHandlers[optcode] == null)
1176 {
1177 throw (new InvalidTelnetOptionException(
1178 "Unregistered option", optcode));
1179 }
1180 else
1181 {
1182 TelnetOptionHandler opthand = optionHandlers[optcode];
1183 optionHandlers[optcode] = null;
1184
1185 if (opthand.getWill())
1186 {
1187 try
1188 {
1189 _requestWont(optcode);
1190 }
1191 catch (IOException e)
1192 {
1193 System.err.println(
1194 "Exception while turning off option: "
1195 + e.getMessage());
1196 }
1197 }
1198
1199 if (opthand.getDo())
1200 {
1201 try
1202 {
1203 _requestDont(optcode);
1204 }
1205 catch (IOException e)
1206 {
1207 System.err.println(
1208 "Exception while turning off option: "
1209 + e.getMessage());
1210 }
1211 }
1212 }
1213 }
1214 else
1215 {
1216 throw (new InvalidTelnetOptionException(
1217 "Invalid Option Code", optcode));
1218 }
1219 }
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230 void _registerSpyStream(OutputStream spystream)
1231 {
1232 spyStream = spystream;
1233 }
1234
1235
1236
1237
1238
1239 void _stopSpyStream()
1240 {
1241 spyStream = null;
1242 }
1243
1244
1245
1246
1247
1248
1249 void _spyRead(int ch)
1250 {
1251 if (spyStream != null)
1252 {
1253 try
1254 {
1255 if (ch != '\r')
1256 {
1257 spyStream.write(ch);
1258 if (ch == '\n')
1259 {
1260 spyStream.write('\r');
1261 }
1262 spyStream.flush();
1263 }
1264 }
1265 catch (IOException e)
1266 {
1267 spyStream = null;
1268 }
1269 }
1270 }
1271
1272
1273
1274
1275
1276
1277 void _spyWrite(int ch)
1278 {
1279 if (!(_stateIsDo(TelnetOption.ECHO)
1280 && _requestedDo(TelnetOption.ECHO)))
1281 {
1282 if (spyStream != null)
1283 {
1284 try
1285 {
1286 spyStream.write(ch);
1287 spyStream.flush();
1288 }
1289 catch (IOException e)
1290 {
1291 spyStream = null;
1292 }
1293 }
1294 }
1295 }
1296
1297
1298
1299
1300
1301
1302
1303
1304 public void registerNotifHandler(TelnetNotificationHandler notifhand)
1305 {
1306 __notifhand = notifhand;
1307 }
1308
1309
1310
1311
1312
1313 public void unregisterNotifHandler()
1314 {
1315 __notifhand = null;
1316 }
1317 }