/aztarna/helpers.py

https://github.com/aliasrobotics/aztarna · Python · 91 lines · 65 code · 5 blank · 21 comment · 5 complexity · 47dd865289a05a5182723a1fb9d9fec7 MD5 · raw file

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import asyncio
  4. from platform import system as system_name # Returns the system/OS name
  5. from subprocess import call as system_call # Execute a shell command
  6. class HelpersLINQ:
  7. """
  8. A helper class for emulating .NET useful methods.
  9. """
  10. @staticmethod
  11. def distinct(sequence):
  12. seen = set()
  13. for s in sequence:
  14. if not s in seen:
  15. seen.add(s)
  16. yield s
  17. class HelpersNetWorking:
  18. """
  19. A helper class that checks networking related data
  20. """
  21. @staticmethod
  22. def ping(host):
  23. """
  24. A method that replicates the command line ping utility.
  25. :param host: Host to ping to
  26. :return: A boolean type that means if the ping reaches the destination or not
  27. """
  28. ret = None
  29. # Ping command count option as function of OS
  30. param = '-n' if system_name().lower() == 'windows' else '-c'
  31. # Building the command. Ex: "ping -c 1 google.com"
  32. command = ['ping', param, '1', host]
  33. with open("/dev/null", "w+") as f:
  34. ret = system_call(command, stdout=f) == 0
  35. return ret
  36. class PortScanner:
  37. """
  38. A base class that provides methods to check correct por scans.
  39. """
  40. @staticmethod
  41. async def check_port(ip, port):
  42. """
  43. Checks if a certain port is open
  44. :param ip: The host's IP address
  45. :param port: The host's port
  46. :return: The scanned port if open, else None
  47. """
  48. conn = asyncio.open_connection(ip, port)
  49. try:
  50. reader, writer = await asyncio.wait_for(conn, timeout=3)
  51. writer.close()
  52. return port
  53. except:
  54. return None
  55. @staticmethod
  56. async def check_port_sem(sem, ip, port):
  57. """
  58. Calls to :method:check_port with a Semaphore to avoid too many open connections.
  59. :param sem:
  60. :param ip:
  61. :param port:
  62. :return:
  63. """
  64. async with sem:
  65. return await PortScanner.check_port(ip, port)
  66. @staticmethod
  67. async def scan_host(address, start_port, end_port, max_conns=400):
  68. """
  69. :param address: IPv4 address to scan
  70. :param start_port: First port value to scan
  71. :param end_port: Last port value to scan
  72. :param max_conns: Maximum simultaneous number of connections
  73. :return:
  74. """
  75. sem = asyncio.Semaphore(max_conns)
  76. ports = range(start_port, end_port)
  77. tasks = [asyncio.ensure_future(PortScanner.check_port_sem(sem, address, port)) for port in ports]
  78. responses = await asyncio.gather(*tasks)
  79. open_ports = list(filter(lambda x: x is not None, responses))
  80. return open_ports