summaryrefslogtreecommitdiff
path: root/src/terminal/internal/fqterm_telnet.h
blob: 74ea15ec44d5f4a40716cd06457e3332e3b285bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// SPDX-License-Identifier: GPL-2.0-or-later

#ifndef FQTERM_TELNET_H
#define FQTERM_TELNET_H

#include <QAbstractSocket>
#include <QByteArray>
#include "fqterm_socket.h"
#include "connect_info.h"

namespace FQTerm {

#ifndef u_char
#define u_char uchar
#endif

#define NTSTATES	 6	    // # of Telnet Socket-Input FSM States
#define NSSTATES	3		// # of Telnet Option Subnegotiation FSM States
#define NCHRS		256		// # of valid characters

//  declaration
class FQTermTelnet;
// actionFunc is a pointer, point to a FQTermTelnet's func
typedef int(FQTermTelnet:: *ptrActionFunc)(int c);

//fsm struct
struct fsm_trans {
  u_char ft_state; // current state
  short ft_char; // input character
  u_char ft_next; // next state
  ptrActionFunc ft_action; // action to take
};


/*------------------------------------------------------------------------------
 *	FQTermTelnet class definition
 *-------------------------------------------------------------------------------
 */

// Telnet connection, a wrapper of socket.
// It will translate raw NVT data from low level socket to ansi data,
// and then upper level application can read it.
// It also can send ASCII data (0~127).
class FQTermTelnet: public QObject {
  Q_OBJECT;
 public:
  FQTermTelnet(const QString &termtype, int rows, int numColumns, int protocolType, int hostType, const
              char *sshuser = NULL, const char *sshpasswd = NULL);
  ~FQTermTelnet();

  void setProxy(int nProxyType,  //0-no proxy; 1-wingate; 2-sock4; 3-socks5
                bool bAuth,  // if authentation needed
                const QString &strProxyHost, quint16 uProxyPort, const QString &strProxyUsr,
                const QString &strProxyPwd);
  void connectHost(const QString &hostname, quint16 portnumber);

  // Read ANSI data.
  int read(char *data, uint maxlen);

  // Write data raw data
  int write(const char *data, uint len);

  void close(); // User close the connection

  int raw_len();
  int read_raw(char *data, uint maxlen);

  bool readyForInput();

  conn_info_t *connectionInfo() { return socket->connectionInfo(); }

 signals:
  void readyRead(int, int); // There are data to be read out
  void TelnetState(int); // The  state telnet, defined as TSXXXX in fqterm.h
  void requestUserPwd(QString *user, QString *pwd, bool *isOK);
  void warnInsecure(const QString&, bool *isOK);
  void errorMessage(QString);

 public slots:
  void windowSizeChanged(int, int);

 private slots:
  // Retrieve data from socket, translate NVT data to ansi data,
  // then notify data ready.
  void socketReadyRead();

  void connected();
  void showError(QAbstractSocket::SocketError);
  void hostFound();
  void delayCloseFinished();
  void closed();
 protected:
  //init structure fsm
  void init_telnet();
  void fsmbuild();
  void fsminit(u_char fsm[][NCHRS], struct fsm_trans ttab[], int nstates);

  //actions
  int tcdm(int);
  int recopt(int);
  int no_op(int);
  int do_echo(int);
  int do_notsup(int);
  int do_noga(int);
  int do_txbinary(int);
  int will_notsup(int);
  int will_txbinary(int);
  int will_termtype(int);
  int will_naws(int);
  int subopt(int);
  int subtermtype(int);
  int subend(int);
  int soputc(int);
  int ttputc(int);
  int tnabort(int);

  //utility functions
  int xputc_up(char);
  int xputs_up(char*);
  void putc_down(u_char);

signals:
  
  void onSSHAuthOK();

 private:
  // Boolean Flags
  char synching, doecho, sndbinary, rcvbinary;
  char noga;
  char naws;
  char server_sent_do_naws;
  u_char option_cmd; // has value WILL, WONT, DO, or DONT

  char termtype; // non-zero if received "DO TERMTYPE"
  char *term; // terminal name

  /* // TODO: BBS don't need control signals
  // Special keys - Terminal control characters
  // need work...
  static const char t_flushc=FQTERM_CTRL('S'); // Abort Output		i.e:(^S)
  static const char t_intrc=FQTERM_CTRL('C');  // Interrupt		i.e:(^C)
  static const char t_quitc=FQTERM_CTRL('\\'); // Quit			i.e:(^\)
  static const char sg_erase=FQTERM_CTRL('?'); // Erase a character	i.e:(^?)
  static const char sg_kill=FQTERM_CTRL('U');  // Kill a line		i.e:(^U)
  */

  // FSM stuffs
  static struct fsm_trans ttstab[];
  int ttstate;
  u_char ttfsm[NTSTATES][NCHRS];

  static struct fsm_trans substab[];
  int substate;
  u_char subfsm[NSSTATES][NCHRS];

  // socket stuffs
  FQTermSocket *socket;

  //Pointers to internal buffers
  //
  //             |-->from_socket-->process-->to_ansi-->|
  //  socket<--->                                      <---> ansi decode
  //             |<---to_socket<--process<--from_ansi--|
  //
  QByteArray from_socket, to_ansi, from_ansi, to_socket;
  uint rsize; // size of to_ansi buffer
  uint wsize; // size of to_socket buffer

  // for test
  int wx, wy;
  int done_naws;
  bool bConnected;
  int raw_size;
  int hostType_;
  int protocolType_;
};

}  // namespace FQTerm

#endif  // FQTERM_TELNET_H