16 import traceback |
16 import traceback |
17 import types |
17 import types |
18 import zlib |
18 import zlib |
19 |
19 |
20 from eric7.UI.Info import Version |
20 from eric7.UI.Info import Version |
21 # TODO: remove dependency on 'eric7.UI.Info' |
|
22 |
21 |
23 from .EricRequestCategory import EricRequestCategory |
22 from .EricRequestCategory import EricRequestCategory |
24 from .EricServerDebuggerRequestHandler import EricServerDebuggerRequestHandler |
23 from .EricServerDebuggerRequestHandler import EricServerDebuggerRequestHandler |
25 from .EricServerFileSystemRequestHandler import EricServerFileSystemRequestHandler |
24 from .EricServerFileSystemRequestHandler import EricServerFileSystemRequestHandler |
|
25 |
|
26 # TODO: remove dependency on 'eric7.UI.Info' |
26 |
27 |
27 |
28 |
28 class EricServer: |
29 class EricServer: |
29 """ |
30 """ |
30 Class implementing the eric remote server. |
31 Class implementing the eric remote server. |
76 self.__socket = socket.create_server(address, family=socket.AF_INET) |
77 self.__socket = socket.create_server(address, family=socket.AF_INET) |
77 |
78 |
78 def getSelector(self): |
79 def getSelector(self): |
79 """ |
80 """ |
80 Public method to get a reference to the selector object. |
81 Public method to get a reference to the selector object. |
|
82 |
|
83 @return reference to the selector object |
|
84 @rtype selectors.BaseSelector |
81 """ |
85 """ |
82 return self.__selector |
86 return self.__selector |
83 |
87 |
84 ####################################################################### |
88 ####################################################################### |
85 ## Methods for receiving requests and sending the results. |
89 ## Methods for receiving requests and sending the results. |
116 @param jsonCommand dictionary containing the command data or a JSON encoded |
120 @param jsonCommand dictionary containing the command data or a JSON encoded |
117 command string |
121 command string |
118 @type dict or str |
122 @type dict or str |
119 @param sock reference to the socket to send the data to |
123 @param sock reference to the socket to send the data to |
120 @type socket.socket |
124 @type socket.socket |
|
125 @return flag indicating a successful transmission |
|
126 @rtype bool |
121 """ |
127 """ |
122 if isinstance(jsonCommand, dict): |
128 if isinstance(jsonCommand, dict): |
123 jsonCommand = json.dumps(jsonCommand) |
129 jsonCommand = json.dumps(jsonCommand) |
|
130 print("Eric Server Send:", jsonCommand) |
|
131 |
124 data = jsonCommand.encode("utf8", "backslashreplace") |
132 data = jsonCommand.encode("utf8", "backslashreplace") |
125 header = struct.pack(b"!II", len(data), zlib.adler32(data) & 0xFFFFFFFF) |
133 header = struct.pack(b"!II", len(data), zlib.adler32(data) & 0xFFFFFFFF) |
126 sock.sendall(header) |
134 try: |
127 sock.sendall(data) |
135 sock.sendall(header) |
|
136 sock.sendall(data) |
|
137 return True |
|
138 except BrokenPipeError: |
|
139 return False |
128 |
140 |
129 def __receiveBytes(self, length, sock): |
141 def __receiveBytes(self, length, sock): |
130 """ |
142 """ |
131 Private method to receive the given length of bytes. |
143 Private method to receive the given length of bytes. |
132 |
144 |
187 }, |
199 }, |
188 ) |
200 ) |
189 return {} |
201 return {} |
190 |
202 |
191 jsonStr = data.decode("utf8", "backslashreplace") |
203 jsonStr = data.decode("utf8", "backslashreplace") |
|
204 print("Eric Server Receive:", jsonStr) |
192 try: |
205 try: |
193 return json.loads(jsonStr.strip()) |
206 return json.loads(jsonStr.strip()) |
194 except (TypeError, ValueError) as err: |
207 except (TypeError, ValueError) as err: |
195 self.sendJson( |
208 self.sendJson( |
196 category=EricRequestCategory.Error, |
209 category=EricRequestCategory.Error, |
282 def __closeIdeConnection(self): |
295 def __closeIdeConnection(self): |
283 """ |
296 """ |
284 Private method to close the connection to an eric-ide. |
297 Private method to close the connection to an eric-ide. |
285 """ |
298 """ |
286 if self.__connection is not None: |
299 if self.__connection is not None: |
287 print( |
|
288 f"Closing 'eric-ide' connection to {self.__connection.getpeername()}." |
|
289 ) |
|
290 self.__selector.unregister(self.__connection) |
300 self.__selector.unregister(self.__connection) |
291 self.__connection.shutdown(socket.SHUT_RDWR) |
301 try: |
292 self.__connection.close() |
302 print( |
|
303 f"Closing 'eric-ide' connection to" |
|
304 f" {self.__connection.getpeername()}." |
|
305 ) |
|
306 self.__connection.shutdown(socket.SHUT_RDWR) |
|
307 self.__connection.close() |
|
308 except OSError: |
|
309 print("'eric-ide' connection gone.") |
293 self.__connection = None |
310 self.__connection = None |
294 |
311 |
295 self.__debuggerRequestHandler.shutdownClients() |
312 self.__debuggerRequestHandler.shutdownClients() |
296 |
313 |
297 def __serviceIdeConnection(self, key): |
314 def __serviceIdeConnection(self, key): |
306 category, request, params, reqestUuid = self.__receiveJson() |
323 category, request, params, reqestUuid = self.__receiveJson() |
307 if category == EricRequestCategory.Error or request is None: |
324 if category == EricRequestCategory.Error or request is None: |
308 self.__closeIdeConnection() |
325 self.__closeIdeConnection() |
309 return |
326 return |
310 |
327 |
311 if category == EricRequestCategory.Server: |
328 if category == EricRequestCategory.Server and request.lower() == "shutdown": |
312 if request.lower() == "shutdown": |
329 self.__shouldStop = True |
313 self.__shouldStop = True |
330 return |
314 return |
|
315 |
331 |
316 self.__handleRequest(category, request, params, reqestUuid) |
332 self.__handleRequest(category, request, params, reqestUuid) |
317 |
333 |
318 def run(self): |
334 def run(self): |
319 """ |
335 """ |
344 self.__debuggerRequestHandler.initServerSocket() |
360 self.__debuggerRequestHandler.initServerSocket() |
345 |
361 |
346 while True: |
362 while True: |
347 try: |
363 try: |
348 events = self.__selector.select(timeout=None) |
364 events = self.__selector.select(timeout=None) |
349 for key, mask in events: |
365 for key, _mask in events: |
350 if key.data.name == "server": |
366 if key.data.name == "server": |
351 # it is an event for a server socket |
367 # it is an event for a server socket |
352 key.data.acceptHandler(key.fileobj) |
368 key.data.acceptHandler(key.fileobj) |
353 else: |
369 else: |
354 key.data.handler(key) |
370 key.data.handler(key) |
419 """ |
435 """ |
420 Private method to register request handler categories of this class. |
436 Private method to register request handler categories of this class. |
421 """ |
437 """ |
422 self.registerRequestHandler(EricRequestCategory.Echo, self.__handleEchoRequest) |
438 self.registerRequestHandler(EricRequestCategory.Echo, self.__handleEchoRequest) |
423 self.registerRequestHandler( |
439 self.registerRequestHandler( |
424 EricRequestCategory.Server, self.__handleServerRequest |
440 EricRequestCategory.Server, self.__handleServerRequest |
425 ) |
441 ) |
426 self.registerRequestHandler(EricRequestCategory.Error, None) |
442 self.registerRequestHandler(EricRequestCategory.Error, None) |
427 # Register a None handler to indicate we are not expecting a request of the |
443 # Register a None handler to indicate we are not expecting a request of the |
428 # 'Error' category. |
444 # 'Error' category. |
429 |
445 |
441 @type str |
457 @type str |
442 @param params request parameters |
458 @param params request parameters |
443 @type dict |
459 @type dict |
444 @param reqestUuid UUID of the associated request as sent by the eric IDE |
460 @param reqestUuid UUID of the associated request as sent by the eric IDE |
445 @type str |
461 @type str |
446 @exception ValueError raised to indicate an invalid or unsupported request |
|
447 handler catehory |
|
448 """ |
462 """ |
449 try: |
463 try: |
450 handler = self.__requestCategoryHandlerRegistry[category] |
464 handler = self.__requestCategoryHandlerRegistry[category] |
451 handler(request=request, params=params, reqestUuid=reqestUuid) |
465 handler(request=request, params=params, reqestUuid=reqestUuid) |
452 except KeyError: |
466 except KeyError: |
454 category=EricRequestCategory.Error, |
468 category=EricRequestCategory.Error, |
455 reply="UnsupportedServiceCategory", |
469 reply="UnsupportedServiceCategory", |
456 params={"Category": category}, |
470 params={"Category": category}, |
457 ) |
471 ) |
458 |
472 |
459 def __handleEchoRequest(self, request, params, reqestUuid): |
473 def __handleEchoRequest(self, request, params, reqestUuid): # noqa: U100 |
460 """ |
474 """ |
461 Private method to handle an 'Echo' request. |
475 Private method to handle an 'Echo' request. |
462 |
476 |
463 @param request request name |
477 @param request request name |
464 @type str |
478 @type str |
473 reply="Echo", |
487 reply="Echo", |
474 params=params, |
488 params=params, |
475 reqestUuid=reqestUuid, |
489 reqestUuid=reqestUuid, |
476 ) |
490 ) |
477 |
491 |
478 def __handleServerRequest(self, request, params, reqestUuid): |
492 def __handleServerRequest(self, request, params, reqestUuid): # noqa: U100 |
479 """ |
493 """ |
480 Private method to handle a 'Server' request. |
494 Private method to handle a 'Server' request. |
481 |
495 |
482 @param request request name |
496 @param request request name |
483 @type str |
497 @type str |