-
Notifications
You must be signed in to change notification settings - Fork 0
/
PythonServer.h
212 lines (161 loc) · 5.09 KB
/
PythonServer.h
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#ifndef PythonServer_h_DEFINED
#define PythonServer_h_DEFINED
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/socket.h>
#include <errno.h>
#include <string>
#include <deque>
#include "PyRideCommon.h"
#include "PyModuleStub.h"
// define python config
#define PYTHONSERVER_BUFFER_SIZE 2048
#define PS_SEND_BUFFER_SIZE PYTHONSERVER_BUFFER_SIZE*2
#define PS_RECEIVE_BUFFER_SIZE PYTHONSERVER_BUFFER_SIZE
#define PYTHON_SERVER_PORT 27005
#ifdef ROS_BUILD
#define DEFAULT_PYTHON_SCRIPT_PATH "scripts"
#elif IOS_BUILD
#define DEFAULT_PYTHON_SCRIPT_PATH "scripts"
#else
#define DEFAULT_PYTHON_SCRIPT_PATH "/home/nao/naoqi/lib/python"
#endif
// define telnet protocol
#define TELNET_ECHO 1
#define TELNET_LINEMODE 34
#define TELNET_SE 240
#define TELNET_SB 250
#define TELNET_WILL 251
#define TELNET_WONT 252
#define TELNET_DO 253
#define TELNET_DONT 254
#define TELNET_IAC 255
#define ERASE_EOL "\033[K"
#define KEY_CTRL_A 1
#define KEY_CTRL_C 3
#define KEY_CTRL_D 4
#define KEY_CTRL_E 5
#define KEY_CTRL_G 7
#define KEY_BACKSPACE 8
#define KEY_HTAB 9
#define KEY_DEL 127
#define KEY_ENTER 13
#define KEY_ESC 27
#define TERMINAL_SIZE 80
#define MAX_HISTORY_COMMAND 20
#define PYRIDE_MAIN_SCRIPT_NAME "py_main"
namespace pyride {
class PythonSession;
class PythonServer : public PyOutputWriter
{
public:
~PythonServer();
void init( bool enableTelnetConsole, PyModuleExtension * pyModule, const char * scriptDir = NULL, const char * pythonHome = NULL );
void fini();
void continuousProcessing();
void restartPythonServer();
void write( const char * msg );
void broadcastMessage( const char * mesg );
bool isActive() { return isActive_; }
PyObject * mainScript() { return pMainScript_; }
bool RunMyString( const char * command );
std::string & welcomeStr() { return welcomeStr_; }
void activeSession( PythonSession * session ) { activeSession_ = session; }
static PythonServer * instance();
private:
typedef struct sClientItem {
SOCKET_T fd;
struct sockaddr_in addr;
struct sClientItem * pNext;
PythonSession * pSession;
} ClientItem;
char customScriptBase[256];
char customPythonHome[256];
pthread_t runThread_;
pthread_mutex_t t_mutex_;
pthread_mutexattr_t t_mta;
static PythonServer * s_pPythonServer;
bool isActive_;
bool hasInterpreter_;
PyInterpreterState * intpState_;
PyObject * prevStderr_;
PyObject * prevStdout_;
PyObject * pSysModule_;
PyObject * pMainModule_;
PyObject * pMainScript_;
PyObject * pPyMod_;
struct sockaddr_in sAddr_;
struct sockaddr_in bcAddr_;
SOCKET_T udpSocket_;
SOCKET_T tcpSocket_;
unsigned char * dgramBuffer_;
unsigned char * clientDataBuffer_;
ClientItem * clientList_;
int maxFD_;
fd_set masterFDSet_;
bool runningTelnetConsole_;
bool keepRunning_;
PythonSession * activeSession_;
PyModuleExtension * pyModuleExtension_;
std::string welcomeStr_;
PythonServer();
bool initUDPListener();
bool initTelnetConsole();
void finiTelnetConsole();
bool initPyInterpreter();
void runMainScript();
void finiPyInterpreter();
void initModuleExtension();
void finiModuleExtension();
PyInterpreterState * getInterpreterState() const { return intpState_; }
void initIPAddresses();
bool getObjectDir( const std::string & searchStr, std::vector<std::string> & mlist );
void processIncomingData( fd_set * readyFDSet );
void processUDPInput( const unsigned char * recBuffer, int recBytes, struct sockaddr_in & cAddr );
bool messageValidation( const unsigned char * receivedMesg, const int receivedBytes, char & cID,
char & command, char & subcommand );
ClientItem * addFdToClientList( const SOCKET_T & fd, struct sockaddr_in & cAddr );
void disconnectClient( ClientItem * client, bool sendNotification = false );
void broadcastServerMessage( const char * mesg );
friend class PythonSession;
};
class PythonSession
{
public:
PythonSession( PythonServer * server, SOCKET_T fd );
~PythonSession();
void processInput( PythonServer::ClientItem * client, unsigned char * recvData, int bytesReceived );
void sayGoodBye();
void write( const char * str );
void writePrompt();
private:
PythonServer * server_;
SOCKET_T fd_;
bool telnetSubnegotiation_;
std::string promptStr_;
std::deque<unsigned char> readBuffer_;
std::deque<std::string> historyBuffer_;
std::string currentLine_;
int historyPos_;
unsigned int charPos_;
std::string multiline_;
void connectReady();
bool handleTelnetCommand();
bool handleVTCommand();
void handleLine( PythonServer::ClientItem * client );
void handleDel();
void handleChar();
void handleTab();
void handleUp();
void handleDown();
void handleLeft();
void handleRight();
void handleHome();
void handleEnd();
void tabCompletion( const std::string & fullStr, const std::string & curStr,
bool fullprint = false );
};
} //namespace pyride
#endif // PythonServer_h_DEFINED