5 |
5 |
6 """ |
6 """ |
7 Module implementing the debug server. |
7 Module implementing the debug server. |
8 """ |
8 """ |
9 |
9 |
|
10 import contextlib |
|
11 import importlib |
10 import os |
12 import os |
11 import shlex |
13 import shlex |
12 import contextlib |
14 |
13 |
15 from PyQt6.QtCore import QModelIndex, pyqtSignal, pyqtSlot |
14 from PyQt6.QtCore import pyqtSignal, pyqtSlot, QModelIndex |
16 from PyQt6.QtNetwork import QHostAddress, QHostInfo, QNetworkInterface, QTcpServer |
15 from PyQt6.QtNetwork import QTcpServer, QHostAddress, QHostInfo, QNetworkInterface |
17 |
16 |
18 from eric7 import Preferences |
|
19 from eric7.EricWidgets import EricMessageBox |
17 from eric7.EricWidgets.EricApplication import ericApp |
20 from eric7.EricWidgets.EricApplication import ericApp |
18 from eric7.EricWidgets import EricMessageBox |
21 |
19 |
22 from . import DebugClientCapabilities |
20 from .BreakPointModel import BreakPointModel |
23 from .BreakPointModel import BreakPointModel |
21 from .WatchPointModel import WatchPointModel |
24 from .WatchPointModel import WatchPointModel |
22 from . import DebugClientCapabilities |
|
23 |
|
24 from eric7 import Preferences |
|
25 |
|
26 |
25 |
27 DebuggerInterfaces = { |
26 DebuggerInterfaces = { |
28 "Python": "DebuggerInterfacePython", |
27 "Python": "DebuggerInterfacePython", |
29 "None": "DebuggerInterfaceNone", |
28 "None": "DebuggerInterfaceNone", |
|
29 } |
|
30 |
|
31 NetworkInterfaceMapping = { |
|
32 "all": QHostAddress.SpecialAddress.Any, |
|
33 "allv4": QHostAddress.SpecialAddress.AnyIPv4, |
|
34 "allv6": QHostAddress.SpecialAddress.AnyIPv6, |
|
35 "localv4": QHostAddress.SpecialAddress.LocalHost, |
|
36 "localv6": QHostAddress.SpecialAddress.LocalHostIPv6, |
30 } |
37 } |
31 |
38 |
32 |
39 |
33 class DebugServer(QTcpServer): |
40 class DebugServer(QTcpServer): |
34 """ |
41 """ |
189 # arrays to track already reported issues |
196 # arrays to track already reported issues |
190 self.__reportedBreakpointIssues = [] |
197 self.__reportedBreakpointIssues = [] |
191 self.__reportedWatchpointIssues = [] |
198 self.__reportedWatchpointIssues = [] |
192 |
199 |
193 self.networkInterface = Preferences.getDebugger("NetworkInterface") |
200 self.networkInterface = Preferences.getDebugger("NetworkInterface") |
194 if self.networkInterface == "all": |
201 hostAddress = ( |
195 hostAddress = QHostAddress("0.0.0.0") |
202 QHostAddress(NetworkInterfaceMapping[self.networkInterface]) |
196 # QHostAddress.SpecialAddress.Any) # secok |
203 if self.networkInterface in NetworkInterfaceMapping |
197 elif self.networkInterface == "allv6": |
204 else QHostAddress(self.networkInterface) |
198 hostAddress = QHostAddress("::") |
205 ) |
199 # QHostAddress.SpecialAddress.AnyIPv6) |
|
200 else: |
|
201 hostAddress = QHostAddress(self.networkInterface) |
|
202 ( |
206 ( |
203 self.networkInterfaceName, |
207 self.networkInterfaceName, |
204 self.networkInterfaceIndex, |
208 self.networkInterfaceIndex, |
205 ) = self.__getNetworkInterfaceAndIndex(self.networkInterface) |
209 ) = self.__getNetworkInterfaceAndIndex(self.networkInterface) |
206 |
210 |
207 if not preventPassiveDebugging and Preferences.getDebugger("PassiveDbgEnabled"): |
211 if not preventPassiveDebugging and Preferences.getDebugger("PassiveDbgEnabled"): |
208 sock = Preferences.getDebugger("PassiveDbgPort") # default: 42424 |
212 port = Preferences.getDebugger("PassiveDbgPort") # default: 42424 |
209 self.listen(hostAddress, sock) |
213 self.listen(hostAddress, port) |
210 self.passive = True |
214 self.passive = True |
211 self.passiveClientExited = False |
215 self.passiveClientExited = False |
212 else: |
216 else: |
213 if hostAddress.toString().lower().startswith("fe80"): |
217 if hostAddress.toString().lower().startswith("fe80"): |
214 hostAddress.setScopeId(self.networkInterfaceName) |
218 hostAddress.setScopeId(self.networkInterfaceName) |
215 self.listen(hostAddress) |
219 if Preferences.getDebugger("NetworkPortFixed"): |
|
220 port = Preferences.getDebugger("NetworkPort") |
|
221 res = self.listen(hostAddress, port) |
|
222 if not res and Preferences.getDebugger("NetworkPortIncrement"): |
|
223 maxPort = port + 100 # try a maximum of 100 ports |
|
224 while not res and port < maxPort: |
|
225 port += 1 |
|
226 res = self.listen(hostAddress, port) |
|
227 else: |
|
228 self.listen(hostAddress) |
216 self.passive = False |
229 self.passive = False |
217 |
230 |
218 self.debuggerInterface = None |
231 self.debuggerInterface = None |
219 self.debugging = False |
232 self.debugging = False |
220 self.running = False |
233 self.running = False |
260 @param localhost flag indicating to return the address for localhost |
273 @param localhost flag indicating to return the address for localhost |
261 @type bool |
274 @type bool |
262 @return IP address or hostname |
275 @return IP address or hostname |
263 @rtype str |
276 @rtype str |
264 """ |
277 """ |
265 if self.networkInterface == "all": |
278 if self.networkInterface in ("allv4", "localv4"): |
266 if localhost: |
279 if localhost or self.networkInterface == "localv4": |
267 return "127.0.0.1" |
280 return "127.0.0.1" |
268 else: |
281 else: |
269 return "{0}@@v4".format(QHostInfo.localHostName()) |
282 return "{0}@@v4".format(QHostInfo.localHostName()) |
270 elif self.networkInterface == "allv6": |
283 elif self.networkInterface in ("all", "allv6", "localv6"): |
271 if localhost: |
284 if localhost or self.networkInterface == "localv6": |
272 return "::1" |
285 return "::1" |
273 else: |
286 else: |
274 return "{0}@@v6".format(QHostInfo.localHostName()) |
287 return "{0}@@v6".format(QHostInfo.localHostName()) |
275 else: |
288 else: |
276 return "{0}@@i{1}".format(self.networkInterface, self.networkInterfaceIndex) |
289 return "{0}@@i{1}".format(self.networkInterface, self.networkInterfaceIndex) |
398 def __registerDebuggerInterfaces(self): |
411 def __registerDebuggerInterfaces(self): |
399 """ |
412 """ |
400 Private method to register the available internal debugger interfaces. |
413 Private method to register the available internal debugger interfaces. |
401 """ |
414 """ |
402 for name, interface in DebuggerInterfaces.items(): |
415 for name, interface in DebuggerInterfaces.items(): |
403 modName = "eric7.Debugger.{0}".format(interface) |
416 mod = importlib.import_module(".{0}".format(interface), __package__) |
404 mod = __import__(modName) |
|
405 components = modName.split(".") |
|
406 for comp in components[1:]: |
|
407 mod = getattr(mod, comp) |
|
408 |
|
409 self.registerDebuggerInterface(name, mod.getRegistryData) |
417 self.registerDebuggerInterface(name, mod.getRegistryData) |
410 |
418 |
411 def getSupportedLanguages(self, shellOnly=False): |
419 def getSupportedLanguages(self, shellOnly=False): |
412 """ |
420 """ |
413 Public slot to return the supported programming languages. |
421 Public slot to return the supported programming languages. |