qserialsocket.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /****************************************************************************
  2. **
  3. ** This file is part of the Qt Extended Opensource Package.
  4. **
  5. ** Copyright (C) 2009 Trolltech ASA.
  6. **
  7. ** Contact: Qt Extended Information (info@qtextended.org)
  8. **
  9. ** This file may be used under the terms of the GNU General Public License
  10. ** version 2.0 as published by the Free Software Foundation and appearing
  11. ** in the file LICENSE.GPL included in the packaging of this file.
  12. **
  13. ** Please review the following information to ensure GNU General Public
  14. ** Licensing requirements will be met:
  15. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html.
  16. **
  17. **
  18. ****************************************************************************/
  19. #include "qserialsocket.h"
  20. #include <QTcpSocket>
  21. #include <QTcpServer>
  22. #include <QTimer>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <unistd.h>
  26. enum TelnetOption
  27. {
  28. TO_BINARY = 0,
  29. TO_ECHO = 1,
  30. TO_RCP = 2,
  31. TO_SGA = 3,
  32. TO_NAMS = 4,
  33. TO_STATUS = 5,
  34. TO_TM = 6,
  35. TO_RCTE = 7,
  36. TO_NAOL = 8,
  37. TO_NAOP = 9,
  38. TO_NAOCRD = 10,
  39. TO_NAOHTS = 11,
  40. TO_NAOHTD = 12,
  41. TO_NAOFFD = 13,
  42. TO_NAOVTS = 14,
  43. TO_NAOVTD = 15,
  44. TO_NAOLFD = 16,
  45. TO_XASCII = 17,
  46. TO_LOGOUT = 18,
  47. TO_BM = 19,
  48. TO_DET = 20,
  49. TO_SUPDUP = 21,
  50. TO_SUPDUPOUTPUT = 22,
  51. TO_SNDLOC = 23,
  52. TO_TTYPE = 24,
  53. TO_EOR = 25,
  54. TO_TUID = 26,
  55. TO_OUTMRK = 27,
  56. TO_TTYLOC = 28,
  57. TO_3270REGIME = 29,
  58. TO_X3PAD = 30,
  59. TO_NAWS = 31,
  60. TO_TSPEED = 32,
  61. TO_LFLOW = 33,
  62. TO_LINEMODE = 34,
  63. TO_XDISPLOC = 35,
  64. TO_OLD_ENVIRON = 36,
  65. TO_AUTHENTICATION = 37,
  66. TO_ENCRYPT = 38,
  67. TO_NEW_ENVIRON = 39,
  68. TO_MODEM_SIGNALS = 78, // Private extension for modem signals.
  69. TO_EXOPL = 255
  70. };
  71. /*!
  72. \class QSerialSocket
  73. \inpublicgroup QtBaseModule
  74. \brief The QSerialSocket class provides a serial port abstraction via a TCP socket.
  75. \ingroup io
  76. This serial port abstraction implements the telnet protocol (RFC 854),
  77. to make it easy to debug AT command handlers using a telnet client.
  78. The QSerialSocket class is also used by data calls initiated by QPhoneCall
  79. to pass the raw modem data and handshaking signals to client applications.
  80. \sa QSerialSocketServer, QSerialIODevice, QPhoneCall
  81. */
  82. #include <QDebug>
  83. class QSerialSocketPrivate
  84. {
  85. public:
  86. QSerialSocketPrivate( QTcpSocket *sock )
  87. {
  88. socket = sock;
  89. valid = true;
  90. dtr = true;
  91. dsr = true;
  92. cts = true;
  93. rts = true;
  94. incomingCarrier = false;
  95. outgoingCarrier = false;
  96. canUseSignals = false;
  97. bufPosn = 0;
  98. bufLen = 0;
  99. optionsLen = 0;
  100. optionsMode = 0;
  101. }
  102. ~QSerialSocketPrivate()
  103. {
  104. //delete later -> crashes otherwise due to pending signals
  105. socket->deleteLater();
  106. }
  107. QTcpSocket *socket;
  108. bool valid;
  109. bool dtr, dsr, cts, rts;
  110. bool incomingCarrier;
  111. bool outgoingCarrier;
  112. bool canUseSignals;
  113. char buffer[1024];
  114. // unsigned char buffer[256];
  115. int bufPosn;
  116. int bufLen;
  117. char options[1024];
  118. int optionsLen;
  119. int optionsMode;
  120. };
  121. QSerialSocket::QSerialSocket( QTcpSocket *socket )
  122. : QSerialIODevice()
  123. {
  124. d = new QSerialSocketPrivate( socket );
  125. socket->setParent( 0 ); //take ownership from QTcpServer. It might delete the socket in front of us
  126. init();
  127. }
  128. /*!
  129. Construct a serial-over-sockets session object and attach
  130. it to \a parent. The session will connect to \a port on \a host.
  131. */
  132. QSerialSocket::QSerialSocket
  133. ( const QString& host, quint16 port, QObject *parent )
  134. : QSerialIODevice( parent )
  135. {
  136. d = new QSerialSocketPrivate( new QTcpSocket() );
  137. init();
  138. d->socket->connectToHost( host, port );
  139. if ( ! d->socket->waitForConnected() )
  140. QTimer::singleShot( 0, this, SIGNAL(closed()) );
  141. }
  142. /*!
  143. Destroy this socket-based serial port abstraction.
  144. */
  145. QSerialSocket::~QSerialSocket()
  146. {
  147. delete d;
  148. }
  149. /*!
  150. Opens this serial I/O device in \a mode. This just sets the
  151. device to open. The actual connect is done during the constructor.
  152. Returns true if the device can be opened; false otherwise.
  153. */
  154. bool QSerialSocket::open( OpenMode mode )
  155. {
  156. if ( isOpen() )
  157. return true;
  158. setOpenMode( mode | Unbuffered );
  159. return true;
  160. }
  161. /*!
  162. Closes this serial I/O device. The socket will remain connected
  163. until this object is destroyed.
  164. */
  165. void QSerialSocket::close()
  166. {
  167. setOpenMode( NotOpen );
  168. }
  169. /*!
  170. \reimp
  171. */
  172. bool QSerialSocket::waitForReadyRead(int msecs)
  173. {
  174. if ( d->bufPosn < d->bufLen )
  175. return true;
  176. return d->socket->waitForReadyRead( msecs );
  177. }
  178. /*!
  179. \reimp
  180. */
  181. qint64 QSerialSocket::bytesAvailable() const
  182. {
  183. return d->bufLen - d->bufPosn;
  184. }
  185. /*!
  186. \reimp
  187. */
  188. bool QSerialSocket::dtr() const
  189. {
  190. return d->dtr;
  191. }
  192. /*!
  193. \reimp
  194. */
  195. void QSerialSocket::setDtr( bool value )
  196. {
  197. if ( d->dtr != value ) {
  198. d->dtr = value;
  199. sendModemSignal( value ? 'D' : 'd' );
  200. }
  201. }
  202. /*!
  203. \reimp
  204. */
  205. bool QSerialSocket::dsr() const
  206. {
  207. return d->dsr;
  208. }
  209. /*!
  210. \reimp
  211. */
  212. bool QSerialSocket::carrier() const
  213. {
  214. return d->incomingCarrier;
  215. }
  216. /*!
  217. \reimp
  218. */
  219. bool QSerialSocket::setCarrier( bool value )
  220. {
  221. if ( d->outgoingCarrier != value ) {
  222. d->outgoingCarrier = value;
  223. sendModemSignal( value ? 'C' : 'c' );
  224. }
  225. return true;
  226. }
  227. /*!
  228. \reimp
  229. */
  230. bool QSerialSocket::rts() const
  231. {
  232. return d->rts;
  233. }
  234. /*!
  235. \reimp
  236. */
  237. void QSerialSocket::setRts( bool value )
  238. {
  239. if ( d->rts != value ) {
  240. d->rts = value;
  241. sendModemSignal( value ? 'R' : 'r' );
  242. }
  243. }
  244. /*!
  245. \reimp
  246. */
  247. bool QSerialSocket::cts() const
  248. {
  249. return d->cts;
  250. }
  251. /*!
  252. \reimp
  253. */
  254. void QSerialSocket::discard()
  255. {
  256. // Nothing to do here.
  257. }
  258. /*!
  259. \reimp
  260. */
  261. bool QSerialSocket::isValid() const
  262. {
  263. return d->valid;
  264. }
  265. /*!
  266. \fn void QSerialSocket::closed()
  267. Signal that is emitted when the socket is closed by
  268. the other end of the connection.
  269. */
  270. /*!
  271. \reimp
  272. */
  273. qint64 QSerialSocket::readData( char *data, qint64 maxlen )
  274. {
  275. maxlen = 178;
  276. if ( d->valid ) {
  277. int retlen;
  278. if ( maxlen > ( d->bufLen - d->bufPosn ) ) {
  279. retlen = d->bufLen - d->bufPosn;
  280. } else {
  281. retlen = (int)maxlen;
  282. }
  283. memcpy( data, d->buffer + d->bufPosn, retlen );
  284. d->bufPosn += retlen;
  285. return retlen;
  286. } else {
  287. return 0;
  288. }
  289. }
  290. /*!
  291. \reimp
  292. */
  293. qint64 QSerialSocket::writeData( const char *data, qint64 len )
  294. {
  295. if ( d->valid ) {
  296. const char *s = (const char *)::memchr( data, (char)0xFF, (int)len );
  297. if ( !s )
  298. return d->socket->write( data, len );
  299. qint64 written = 0;
  300. qint64 towrite, temp;
  301. do {
  302. if ( s != data ) {
  303. // Write all data up to the next 0xFF.
  304. towrite = (qint64)( s - data );
  305. temp = d->socket->write( data, towrite );
  306. if ( temp < towrite ) {
  307. if ( temp > 0 )
  308. written += temp;
  309. break;
  310. }
  311. ++written;
  312. data = s;
  313. len -= temp;
  314. } else {
  315. // Escape 0xFF for other side's telnet decoding.
  316. temp = d->socket->write( "\377\377", 2 );
  317. if ( temp != 2 )
  318. break;
  319. ++written;
  320. ++data;
  321. --len;
  322. s = (const char *)::memchr( data, (char)0xFF, (int)len );
  323. if ( !s )
  324. s = data + (int)len;
  325. }
  326. } while ( len > 0 );
  327. return written;
  328. } else {
  329. return len;
  330. }
  331. }
  332. void QSerialSocket::socketReadyRead()
  333. {
  334. // Read data into our internal buffer.
  335. if ( d->bufPosn > 0 && d->bufPosn < d->bufLen ) {
  336. memmove( d->buffer, d->buffer + d->bufPosn, d->bufLen - d->bufPosn );
  337. d->bufLen -= d->bufPosn;
  338. d->bufPosn = 0;
  339. } else if ( d->bufPosn > 0 && d->bufPosn == d->bufLen ) {
  340. d->bufPosn = 0;
  341. d->bufLen = 0;
  342. }
  343. if ( d->bufLen >= (int)sizeof( d->buffer ) ) {
  344. // Buffer is full! Notify the higher layers to read it and then exit.
  345. internalReadyRead();
  346. return;
  347. }
  348. int size = d->socket->read
  349. ( d->buffer + d->bufLen, sizeof( d->buffer ) - d->bufLen );
  350. if ( size <= 0 )
  351. return;
  352. d->bufLen += size;
  353. // Search for telnet options within the data stream and extract them.
  354. int index = d->bufPosn;
  355. int newIndex = index;
  356. while ( index < d->bufLen ) {
  357. char ch = d->buffer[index++];
  358. if ( d->optionsMode == 0 ) {
  359. if ( ch == (char)255 ) {
  360. // Start of a telnet option.
  361. d->options[(d->optionsLen)++] = ch;
  362. d->optionsMode = 1;
  363. } else {
  364. // Ordinary character.
  365. d->buffer[newIndex++] = ch;
  366. }
  367. } else if ( d->optionsMode == 1 ) {
  368. if ( ch == (char)255 ) {
  369. // Escaped 0xFF character.
  370. d->buffer[newIndex++] = ch;
  371. d->optionsMode = 0;
  372. } else if ( ch == (char)251 || ch == (char)252 ||
  373. ch == (char)253 || ch == (char)254 ) {
  374. // WILL, WONT, DO, DONT option.
  375. d->options[(d->optionsLen)++] = ch;
  376. d->optionsMode = 2;
  377. } else if ( ch == (char)250 ) {
  378. // SB option.
  379. d->options[(d->optionsLen)++] = ch;
  380. d->optionsMode = 3;
  381. } else {
  382. // Don't know, so ignore it.
  383. d->optionsMode = 0;
  384. }
  385. } else if ( d->optionsMode == 2 ) {
  386. // WILL, WONT, DO, DONT option code. Remove the 0xFF and type
  387. // and then dispatch the command.
  388. d->optionsLen -= 2;
  389. char type = d->options[d->optionsLen + 1];
  390. if ( type == (char)251 )
  391. receiveWill( ch & 0xFF );
  392. else if ( type == (char)252 )
  393. receiveWont( ch & 0xFF );
  394. else if ( type == (char)253 )
  395. receiveDo( ch & 0xFF );
  396. else
  397. receiveDont( ch & 0xFF );
  398. d->optionsMode = 0;
  399. } else if ( d->optionsMode == 3 ) {
  400. // Contents of an SB option.
  401. if ( ch == (char)255 ) {
  402. d->optionsMode = 4;
  403. } else if ( d->optionsLen < (int)sizeof( d->options ) ) {
  404. d->options[(d->optionsLen)++] = ch;
  405. }
  406. } else if ( d->optionsMode == 4 ) {
  407. // Encountered 0xFF within an SB block.
  408. if ( ch == (char)240 ) {
  409. // This is the SE at the end of the block.
  410. receiveSubOption( d->options[2] & 0xFF, d->options + 3,
  411. d->optionsLen - 3 );
  412. d->optionsMode = 0;
  413. d->optionsLen = 0;
  414. } else {
  415. // Normal escaped character within an SB block.
  416. d->options[(d->optionsLen)++] = ch;
  417. d->optionsMode = 3;
  418. }
  419. }
  420. }
  421. d->bufLen = newIndex;
  422. // Notify higher layers about the new data.
  423. internalReadyRead();
  424. }
  425. void QSerialSocket::socketClosed()
  426. {
  427. d->valid = false;
  428. emit closed();
  429. }
  430. void QSerialSocket::init()
  431. {
  432. // Connect up the interesting signals.
  433. connect( d->socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()) );
  434. connect( d->socket, SIGNAL(disconnected()), this, SLOT(socketClosed()) );
  435. connect( d->socket, SIGNAL(error(QAbstractSocket::SocketError)),
  436. this, SLOT(socketClosed()) );
  437. }
  438. void QSerialSocket::sendModemSignal( int ch )
  439. {
  440. if ( d->valid && d->canUseSignals ) {
  441. char sig[1];
  442. sig[0] = (char)ch;
  443. sendSubOption( TO_MODEM_SIGNALS, sig, 1 );
  444. }
  445. }
  446. void QSerialSocket::sendCommand( const char *buf, int len )
  447. {
  448. if ( d->valid )
  449. d->socket->write( buf, len );
  450. }
  451. // Send a telnet "DO" command.
  452. void QSerialSocket::sendDo( int option )
  453. {
  454. char cmd[3];
  455. cmd[0] = (char)255; // IAC
  456. cmd[1] = (char)253; // DO
  457. cmd[2] = (char)option;
  458. sendCommand( cmd, 3 );
  459. }
  460. void QSerialSocket::sendDont( int option )
  461. {
  462. char cmd[3];
  463. cmd[0] = (char)255; // IAC
  464. cmd[1] = (char)254; // DO
  465. cmd[2] = (char)option;
  466. sendCommand( cmd, 3 );
  467. }
  468. void QSerialSocket::sendWill( int option )
  469. {
  470. char cmd[3];
  471. cmd[0] = (char)255; // IAC
  472. cmd[1] = (char)251; // WILL
  473. cmd[2] = (char)option;
  474. sendCommand( cmd, 3 );
  475. }
  476. void QSerialSocket::sendWont( int option )
  477. {
  478. char cmd[3];
  479. cmd[0] = (char)255; // IAC
  480. cmd[1] = (char)252; // WONT
  481. cmd[2] = (char)option;
  482. sendCommand( cmd, 3 );
  483. }
  484. void QSerialSocket::sendSubOption( int option, const char *buf, int len )
  485. {
  486. char *block = new char [ len + 5 ];
  487. block[0] = (char)255; // IAC
  488. block[1] = (char)250; // SB
  489. block[2] = (char)option;
  490. memcpy( block + 3, buf, len );
  491. block[len + 3] = (char)255; // IAC
  492. block[len + 4] = (char)240; // SE
  493. sendCommand( block, len + 5 );
  494. delete block;
  495. }
  496. void QSerialSocket::initTelnet()
  497. {
  498. // Send enough options to pretend to be a telnetd implementation
  499. // to a regular Unix-like telnet client.
  500. sendDo( TO_ECHO );
  501. sendDo( TO_LINEMODE );
  502. sendDo( TO_NAWS );
  503. sendWill( TO_STATUS );
  504. sendDo( TO_LFLOW );
  505. sendWill( TO_ECHO );
  506. // Negotiate our extension for modem signals when we are talking
  507. // to another instance of QSerialSocket on the other end.
  508. sendWill( TO_MODEM_SIGNALS );
  509. }
  510. void QSerialSocket::receiveModemSignal( int ch )
  511. {
  512. switch ( ch ) {
  513. case 'D':
  514. {
  515. d->dsr = true;
  516. emit dsrChanged( d->dsr );
  517. }
  518. break;
  519. case 'd':
  520. {
  521. d->dsr = false;
  522. emit dsrChanged( d->dsr );
  523. }
  524. break;
  525. case 'C':
  526. {
  527. d->incomingCarrier = true;
  528. emit carrierChanged( d->incomingCarrier );
  529. }
  530. break;
  531. case 'c':
  532. {
  533. d->incomingCarrier = false;
  534. emit carrierChanged( d->incomingCarrier );
  535. }
  536. break;
  537. case 'R':
  538. {
  539. d->cts = true;
  540. emit ctsChanged( d->cts );
  541. }
  542. break;
  543. case 'r':
  544. {
  545. d->cts = false;
  546. emit ctsChanged( d->cts );
  547. }
  548. break;
  549. }
  550. }
  551. void QSerialSocket::receiveDo( int option )
  552. {
  553. switch ( (TelnetOption)option ) {
  554. case TO_MODEM_SIGNALS:
  555. {
  556. // We are talking to something capable of modem signals.
  557. if ( !d->canUseSignals ) {
  558. sendWill( option );
  559. d->canUseSignals = true;
  560. }
  561. }
  562. break;
  563. default: break;
  564. }
  565. }
  566. void QSerialSocket::receiveDont( int option )
  567. {
  568. // Nothing to do here yet.
  569. Q_UNUSED(option);
  570. }
  571. void QSerialSocket::receiveWill( int option )
  572. {
  573. switch ( (TelnetOption)option ) {
  574. case TO_MODEM_SIGNALS:
  575. {
  576. // We are talking to something that will send us modem signals,
  577. // so we can now send them in reply.
  578. d->canUseSignals = true;
  579. }
  580. break;
  581. default: break;
  582. }
  583. }
  584. void QSerialSocket::receiveWont( int option )
  585. {
  586. // Nothing to do here yet.
  587. Q_UNUSED(option);
  588. }
  589. void QSerialSocket::receiveSubOption( int option, const char *buf, int len )
  590. {
  591. if ( option != TO_MODEM_SIGNALS || len < 1 )
  592. return;
  593. receiveModemSignal( buf[0] );
  594. }
  595. /*!
  596. \class QSerialSocketServer
  597. \inpublicgroup QtBaseModule
  598. \brief The QSerialSocketServer class provides a server to handle incoming serial-over-sockets connections.
  599. \ingroup io
  600. \ingroup ipc
  601. As each connection arrives, the incoming() signal is emitted with a QSerialSocket
  602. instance as its argument.
  603. \sa QSerialSocket
  604. */
  605. /*!
  606. Construct a new serial-over-sockets server, bound to \a port,
  607. and attach it to \a parent. If \a localHostOnly is true
  608. (the default), then the socket will only be accessible from
  609. applications on the same host.
  610. */
  611. QSerialSocketServer::QSerialSocketServer
  612. ( quint16 port, bool localHostOnly, QObject *parent )
  613. : QObject( parent )
  614. {
  615. server = new QTcpServer( this );
  616. connect( server, SIGNAL(newConnection()), this, SLOT(newConnection()) );
  617. if ( localHostOnly )
  618. server->listen( QHostAddress::LocalHost, port );
  619. else
  620. server->listen( QHostAddress::Any, port );
  621. }
  622. /*!
  623. Destroy this serial-over-sockets server.
  624. */
  625. QSerialSocketServer::~QSerialSocketServer()
  626. {
  627. }
  628. /*!
  629. Returns true if this server was able to listen on the specified
  630. port number when it was constructed; otherwise returns false.
  631. */
  632. bool QSerialSocketServer::isListening() const
  633. {
  634. return server->isListening();
  635. }
  636. /*!
  637. Returns the port number that this serial-over-sockets server is bound to.
  638. */
  639. quint16 QSerialSocketServer::port() const
  640. {
  641. return server->serverPort();
  642. }
  643. /*!
  644. \fn void QSerialSocketServer::incoming( QSerialSocket *socket )
  645. Signal that is emitted when an incoming connection is detected.
  646. The session is represented by \a socket.
  647. */
  648. void QSerialSocketServer::newConnection()
  649. {
  650. while ( server->hasPendingConnections() ) {
  651. QSerialSocket *socket
  652. = new QSerialSocket( server->nextPendingConnection() );
  653. socket->open( QIODevice::ReadWrite );
  654. socket->initTelnet();
  655. emit incoming( socket );
  656. }
  657. }