130 if data is None: |
131 if data is None: |
131 # socket was closed by debug client |
132 # socket was closed by debug client |
132 self.__clientSocketDisconnected(sock) |
133 self.__clientSocketDisconnected(sock) |
133 elif data: |
134 elif data: |
134 method = data["method"] |
135 method = data["method"] |
|
136 |
|
137 # 1. process debug client messages before relaying |
135 if method == "DebuggerId" and sock in self.__pendingConnections: |
138 if method == "DebuggerId" and sock in self.__pendingConnections: |
136 debuggerId = data['params']['debuggerId'] |
139 debuggerId = data['params']['debuggerId'] |
137 self.__connections[debuggerId] = sock |
140 self.__connections[debuggerId] = sock |
138 self.__pendingConnections.remove(sock) |
141 self.__pendingConnections.remove(sock) |
139 if self.__mainClientId is None: |
142 if self.__mainClientId is None: |
141 |
144 |
142 elif method == "ResponseBanner": |
145 elif method == "ResponseBanner": |
143 # add an indicator for the eric-ide server |
146 # add an indicator for the eric-ide server |
144 data["params"]["platform"] += " (eric-ide Server)" |
147 data["params"]["platform"] += " (eric-ide Server)" |
145 |
148 |
146 # pass on the data to the eric-ide |
149 # 2. pass on the data to the eric-ide |
147 jsonStr = json.dumps(data) |
150 jsonStr = json.dumps(data) |
148 print("Client Response:", jsonStr) |
151 print("Client Response:", jsonStr) |
149 self.__server.sendJson( |
152 self.__server.sendJson( |
150 category=EricRequestCategory.Debugger, |
153 category=EricRequestCategory.Debugger, |
151 reply="DebugClientResponse", |
154 reply="DebugClientResponse", |
152 params={"response": jsonStr}, |
155 params={"response": jsonStr}, |
153 ) |
156 ) |
|
157 |
|
158 # 3. process debug client messages after relaying |
|
159 if method == "ResponseExit": |
|
160 for sock in list(self.__connections.values()): |
|
161 if not self.__server.isSocketClosed(sock): |
|
162 self.__clientSocketDisconnected(sock) |
154 |
163 |
155 def __clientSocketDisconnected(self, sock): |
164 def __clientSocketDisconnected(self, sock): |
156 """ |
165 """ |
157 Private slot handling a socket disconnecting. |
166 Private method handling a socket disconnecting. |
158 |
167 |
159 @param sock reference to the disconnected socket |
168 @param sock reference to the disconnected socket |
160 @type QTcpSocket |
169 @type socket.socket |
161 """ |
170 """ |
162 self.__server.getSelector().unregister(sock) |
171 self.__server.getSelector().unregister(sock) |
163 |
172 |
164 for debuggerId in list(self.__connections): |
173 for debuggerId in list(self.__connections): |
165 if self.__connections[debuggerId] is sock: |
174 if self.__connections[debuggerId] is sock: |
176 break |
185 break |
177 else: |
186 else: |
178 if sock in self.__pendingConnections: |
187 if sock in self.__pendingConnections: |
179 self.__pendingConnections.remove(sock) |
188 self.__pendingConnections.remove(sock) |
180 |
189 |
181 sock.shutdown(socket.SHUT_RDWR) |
|
182 sock.close() |
190 sock.close() |
183 |
191 |
184 if not self.__connections: |
192 if not self.__connections: |
185 # no active connections anymore |
193 # no active connections anymore |
186 self.__server.sendJson( |
194 self.__server.sendJson( |
187 category=EricRequestCategory.Debugger, |
195 category=EricRequestCategory.Debugger, |
188 reply="LastDebugClientExited", |
196 reply="LastDebugClientExited", |
189 params={}, |
197 params={}, |
190 ) |
198 ) |
|
199 |
|
200 def __mainClientExited(self): |
|
201 """ |
|
202 Private method to handle exiting of the main debug client. |
|
203 """ |
|
204 self.__server.sendJson( |
|
205 category=EricRequestCategory.Debugger, |
|
206 reply="MainClientExited", |
|
207 params={"debugger_id": self.__mainClientId if self.__mainClientId else ""}, |
|
208 ) |
191 |
209 |
192 def __serviceDbgClientStdoutStderr(self, key): |
210 def __serviceDbgClientStdoutStderr(self, key): |
193 """ |
211 """ |
194 Private method to service the debug client stdout and stderr channels. |
212 Private method to service the debug client stdout and stderr channels. |
195 |
213 |
236 params={}, |
254 params={}, |
237 ) |
255 ) |
238 |
256 |
239 def __shutdownSocket(self, debuggerId, sock): |
257 def __shutdownSocket(self, debuggerId, sock): |
240 """ |
258 """ |
241 Private slot to shut down a socket. |
259 Private method to shut down a socket. |
242 |
260 |
243 @param debuggerId ID of the debugger the socket belongs to |
261 @param debuggerId ID of the debugger the socket belongs to |
244 @type str |
262 @type str |
245 @param sock reference to the socket |
263 @param sock reference to the socket |
246 @type socket.socket |
264 @type socket.socket |
307 self.__client = subprocess.Popen( |
325 self.__client = subprocess.Popen( |
308 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE |
326 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE |
309 ) |
327 ) |
310 # TODO: register stdin & stderr with selector |
328 # TODO: register stdin & stderr with selector |
311 |
329 |
312 def __stopClient(self, params): |
330 def __stopClient(self, params): # noqa: U100 |
313 """ |
331 """ |
314 Private method to stop the current debug client process. |
332 Private method to stop the current debug client process. |
315 |
333 |
316 @param params dictionary containing the request data |
334 @param params dictionary containing the request data |
317 @type dict |
335 @type dict |
331 """ |
349 """ |
332 debuggerId = params["debugger_id"] |
350 debuggerId = params["debugger_id"] |
333 jsonStr = params["command"] |
351 jsonStr = params["command"] |
334 print(debuggerId, "->", jsonStr) |
352 print(debuggerId, "->", jsonStr) |
335 |
353 |
336 if not debuggerId and self.__mainClientId: |
354 if not debuggerId and self.__mainClientId and "RequestBanner" in jsonStr: |
|
355 # modify the target for the 'RequestBanner' request |
337 debuggerId = self.__mainClientId |
356 debuggerId = self.__mainClientId |
338 |
357 |
339 try: |
358 if debuggerId == "<<all>>": |
340 sock = self.__connections[debuggerId] |
359 # broadcast to all connected debug clients |
341 except KeyError: |
360 for sock in self.__connections.values(): |
342 print(f"Command for unknown debugger ID '{debuggerId}' received.") |
361 self.__server.sendJsonCommand(jsonStr, sock) |
343 # tell the eric-ide again, that this debugger ID is gone |
362 else: |
344 self.__server.sendJson( |
363 try: |
345 category=EricRequestCategory.Debugger, |
364 sock = self.__connections[debuggerId] |
346 reply="DebugClientDisconnected", |
365 self.__server.sendJsonCommand(jsonStr, sock) |
347 params={"debugger_id": debuggerId}, |
366 except KeyError: |
348 ) |
367 print(f"Command for unknown debugger ID '{debuggerId}' received.") |
349 sock = ( |
|
350 self.__connections[self.__mainClientId] if self.__mainClientId else None |
|
351 ) |
|
352 if sock: |
|
353 self.__server.sendJsonCommand(jsonStr, sock) |
|