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