SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TelnetTransport.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/NativeFeatureIncludes.h"
17 #if _RAKNET_SUPPORT_TelnetTransport==1 && _RAKNET_SUPPORT_TCPInterface==1
18
19 #include "slikenet/TelnetTransport.h"
20 #include "slikenet/TCPInterface.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include "slikenet/LinuxStrings.h"
25 #include "slikenet/linux_adapter.h"
26 #include "slikenet/osx_adapter.h"
27
28 // #define _PRINTF_DEBUG
29
30 #define ECHO_INPUT
31
32 using namespace SLNet;
33
34 STATIC_FACTORY_DEFINITIONS(TelnetTransport,TelnetTransport);
35
36 TelnetTransport::TelnetTransport()
37 {
38 tcpInterface=0;
39 sendSuffix=0;
40 sendPrefix=0;
41 }
42 TelnetTransport::~TelnetTransport()
43 {
44 Stop();
45 if (sendSuffix)
46 rakFree_Ex(sendSuffix, _FILE_AND_LINE_ );
47 if (sendPrefix)
48 rakFree_Ex(sendPrefix, _FILE_AND_LINE_ );
49 }
50 bool TelnetTransport::Start(unsigned short port, bool serverMode)
51 {
52 (void) serverMode;
53 AutoAllocate();
54 RakAssert(serverMode);
55 return tcpInterface->Start(port, 64);
56 }
57 void TelnetTransport::Stop(void)
58 {
59 if (tcpInterface==0) return;
60 tcpInterface->Stop();
61 unsigned i;
62 for (i=0; i < remoteClients.Size(); i++)
63 SLNet::OP_DELETE(remoteClients[i], _FILE_AND_LINE_);
64 remoteClients.Clear(false, _FILE_AND_LINE_);
65 SLNet::OP_DELETE(tcpInterface, _FILE_AND_LINE_);
66 tcpInterface=0;
67 }
68 void TelnetTransport::Send( SystemAddress systemAddress, const char *data,... )
69 {
70 if (tcpInterface==0) return;
71
72 if (data==0 || data[0]==0)
73 return;
74
75 char text[REMOTE_MAX_TEXT_INPUT];
76 size_t prefixLength;
77 if (sendPrefix)
78 {
79 strcpy_s(text, sendPrefix);
80 prefixLength = strlen(sendPrefix);
81 }
82 else
83 {
84 text[0]=0;
85 prefixLength=0;
86 }
87 va_list ap;
88 va_start(ap, data);
89 vsnprintf_s(text+prefixLength, REMOTE_MAX_TEXT_INPUT-prefixLength, REMOTE_MAX_TEXT_INPUT-prefixLength-1, data, ap);
90 va_end(ap);
91
92 if (sendSuffix)
93 {
94 size_t length = strlen(text);
95 size_t availableChars = REMOTE_MAX_TEXT_INPUT-length-1;
96 strncat_s(text, sendSuffix, availableChars);
97 }
98
99 tcpInterface->Send(text, (unsigned int) strlen(text), systemAddress, false);
100 }
101 void TelnetTransport::CloseConnection( SystemAddress systemAddress )
102 {
103 tcpInterface->CloseConnection(systemAddress);
104 }
105 Packet* TelnetTransport::Receive( void )
106 {
107 if (tcpInterface==0) return 0;
108 Packet *p = tcpInterface->Receive();
109 if (p==0)
110 return 0;
111
112 /*
113 if (p->data[0]==255)
114 {
115 unsigned i;
116 for (i=0; i < p->length; i++)
117 {
118 RAKNET_DEBUG_PRINTF("%i ", p->data[i]);
119 }
120 RAKNET_DEBUG_PRINTF("\n");
121 tcpInterface->DeallocatePacket(p);
122 return 0;
123 }
124 */
125
126 // Get this guy's cursor buffer. This is real bullcrap that I have to do this.
127 unsigned i;
128 TelnetClient *remoteClient=0;
129 for (i=0; i < remoteClients.Size(); i++)
130 {
131 if (remoteClients[i]->systemAddress==p->systemAddress)
132 remoteClient=remoteClients[i];
133 }
134 //RakAssert(remoteClient);
135 if (remoteClient==0)
136 {
137 tcpInterface->DeallocatePacket(p);
138 return 0;
139 }
140
141
142 if (p->length==3 && p->data[0]==27 && p->data[1]==91 && p->data[2]==65)
143 {
144 if (remoteClient->lastSentTextInput[0])
145 {
146 // Up arrow, return last string
147 for (i=0; remoteClient->textInput[i]; i++)
148 remoteClient->textInput[i]=8;
149 strcat_s(remoteClient->textInput, remoteClient->lastSentTextInput);
150 tcpInterface->Send((const char *)remoteClient->textInput, (unsigned int) strlen(remoteClient->textInput), p->systemAddress, false);
151 strcpy_s(remoteClient->textInput,remoteClient->lastSentTextInput);
152 remoteClient->cursorPosition=(unsigned int) strlen(remoteClient->textInput);
153 }
154
155 return 0;
156 }
157
158
159 // 127 is delete - ignore that
160 // 9 is tab
161 // 27 is escape
162 if (p->data[0]>=127 || p->data[0]==9 || p->data[0]==27)
163 {
164 tcpInterface->DeallocatePacket(p);
165 return 0;
166 }
167
168 // Hack - I don't know what the hell this is about but cursor keys send 3 characters at a time. I can block these
169 //Up=27,91,65
170 //Down=27,91,66
171 //Right=27,91,67
172 //Left=27,91,68
173 if (p->length==3 && p->data[0]==27 && p->data[1]==91 && p->data[2]>=65 && p->data[2]<=68)
174 {
175 tcpInterface->DeallocatePacket(p);
176 return 0;
177 }
178
179
180
181 // Echo
182 #ifdef ECHO_INPUT
183 tcpInterface->Send((const char *)p->data, p->length, p->systemAddress, false);
184 #endif
185
186 bool gotLine;
187 // Process each character in turn
188 for (i=0; i < p->length; i++)
189 {
190
191 #ifdef ECHO_INPUT
192 if (p->data[i]==8)
193 {
194 char spaceThenBack[2];
195 spaceThenBack[0]=' ';
196 spaceThenBack[1]=8;
197 tcpInterface->Send((const char *)spaceThenBack, 2, p->systemAddress, false);
198 }
199 #endif
200
201 gotLine=ReassembleLine(remoteClient, p->data[i]);
202 if (gotLine && remoteClient->textInput[0])
203 {
204
205 Packet *reassembledLine = (Packet*) rakMalloc_Ex(sizeof(Packet), _FILE_AND_LINE_);
206 reassembledLine->length=(unsigned int) strlen(remoteClient->textInput);
207 memcpy(remoteClient->lastSentTextInput, remoteClient->textInput, reassembledLine->length+1);
208 RakAssert(reassembledLine->length < REMOTE_MAX_TEXT_INPUT);
209 reassembledLine->data= (unsigned char*) rakMalloc_Ex( reassembledLine->length+1, _FILE_AND_LINE_ );
210 memcpy(reassembledLine->data, remoteClient->textInput, reassembledLine->length);
211 #ifdef _PRINTF_DEBUG
212 memset(remoteClient->textInput, 0, REMOTE_MAX_TEXT_INPUT);
213 #endif
214 reassembledLine->data[reassembledLine->length]=0;
215 reassembledLine->systemAddress=p->systemAddress;
216 tcpInterface->DeallocatePacket(p);
217 return reassembledLine;
218 }
219 }
220
221 tcpInterface->DeallocatePacket(p);
222 return 0;
223 }
224 void TelnetTransport::DeallocatePacket( Packet *packet )
225 {
226 if (tcpInterface==0) return;
227 rakFree_Ex(packet->data, _FILE_AND_LINE_ );
228 rakFree_Ex(packet, _FILE_AND_LINE_ );
229 }
230 SystemAddress TelnetTransport::HasNewIncomingConnection(void)
231 {
232 unsigned i;
233 SystemAddress newConnection;
234 newConnection = tcpInterface->HasNewIncomingConnection();
235 // 03/16/06 Can't force the stupid windows telnet to use line mode or local echo so now I have to track all the remote players and their
236 // input buffer
237 if (newConnection != UNASSIGNED_SYSTEM_ADDRESS)
238 {
239 unsigned char command[10];
240 // http://www.pcmicro.com/netfoss/RFC857.html
241 // IAC WON'T ECHO
242 command[0]=255; // IAC
243 //command[1]=253; // WON'T
244 command[1]=251; // WILL
245 command[2]=1; // ECHO
246 tcpInterface->Send((const char*)command, 3, newConnection, false);
247
248 /*
249 // Tell the other side to use line mode
250 // http://www.faqs.org/rfcs/rfc1184.html
251 // IAC DO LINEMODE
252 // command[0]=255; // IAC
253 // command[1]=252; // DO
254 // command[2]=34; // LINEMODE
255 // tcpInterface->Send((const char*)command, 3, newConnection);
256
257 */
258
259 TelnetClient *remoteClient=0;
260 for (i=0; i < remoteClients.Size(); i++)
261 {
262 if (remoteClients[i]->systemAddress==newConnection)
263 {
264 remoteClient=remoteClients[i];
265 remoteClient->cursorPosition=0;
266 }
267 }
268
269 if (remoteClient==0)
270 {
271 remoteClient=new TelnetClient;
272 remoteClient->lastSentTextInput[0]=0;
273 remoteClient->cursorPosition=0;
274 remoteClient->systemAddress=newConnection;
275 #ifdef _PRINTF_DEBUG
276 memset(remoteClient->textInput, 0, REMOTE_MAX_TEXT_INPUT);
277 #endif
278 }
279
280 remoteClients.Insert(remoteClient, _FILE_AND_LINE_);
281 }
282 return newConnection;
283 }
284 SystemAddress TelnetTransport::HasLostConnection(void)
285 {
286 SystemAddress systemAddress;
287 unsigned i;
288 systemAddress=tcpInterface->HasLostConnection();
289 if (systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
290 {
291 for (i=0; i < remoteClients.Size(); i++)
292 {
293 if (remoteClients[i]->systemAddress==systemAddress)
294 {
295 SLNet::OP_DELETE(remoteClients[i], _FILE_AND_LINE_);
296 remoteClients[i]=remoteClients[remoteClients.Size()-1];
297 remoteClients.RemoveFromEnd();
298 }
299 }
300 }
301 return systemAddress;
302 }
303 CommandParserInterface* TelnetTransport::GetCommandParser(void)
304 {
305 return 0;
306 }
307 void TelnetTransport::SetSendSuffix(const char *suffix)
308 {
309 if (sendSuffix)
310 {
311 rakFree_Ex(sendSuffix, _FILE_AND_LINE_ );
312 sendSuffix=0;
313 }
314 if (suffix)
315 {
316 sendSuffix = (char*) rakMalloc_Ex(strlen(suffix)+1, _FILE_AND_LINE_);
317 strcpy_s(sendSuffix, strlen(suffix)+1, suffix);
318 }
319 }
320 void TelnetTransport::SetSendPrefix(const char *prefix)
321 {
322 if (sendPrefix)
323 {
324 rakFree_Ex(sendPrefix, _FILE_AND_LINE_ );
325 sendPrefix=0;
326 }
327 if (prefix)
328 {
329 sendPrefix = (char*) rakMalloc_Ex(strlen(prefix)+1, _FILE_AND_LINE_);
330 strcpy_s(sendPrefix, strlen(prefix)+1, prefix);
331 }
332 }
333 void TelnetTransport::AutoAllocate(void)
334 {
335 if (tcpInterface==0)
336 tcpInterface=new TCPInterface;
337 }
338 bool TelnetTransport::ReassembleLine(TelnetTransport::TelnetClient* remoteClient, unsigned char c)
339 {
340 if (c=='\n')
341 {
342 remoteClient->textInput[remoteClient->cursorPosition]=0;
343 remoteClient->cursorPosition=0;
344 #ifdef _PRINTF_DEBUG
345 RAKNET_DEBUG_PRINTF("[Done] %s\n", remoteClient->textInput);
346 #endif
347 return true;
348 }
349 else if (c==8) // backspace
350 {
351 if (remoteClient->cursorPosition>0)
352 {
353 remoteClient->textInput[--remoteClient->cursorPosition]=0;
354 #ifdef _PRINTF_DEBUG
355 RAKNET_DEBUG_PRINTF("[Back] %s\n", remoteClient->textInput);
356 #endif
357 }
358 }
359 else if (c>=32 && c <127)
360 {
361 if (remoteClient->cursorPosition < REMOTE_MAX_TEXT_INPUT)
362 {
363 remoteClient->textInput[remoteClient->cursorPosition++]=c;
364 #ifdef _PRINTF_DEBUG
365 RAKNET_DEBUG_PRINTF("[Norm] %s\n", remoteClient->textInput);
366 #endif
367 }
368 }
369 return false;
370 }
371
372 #endif // _RAKNET_SUPPORT_*