server.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/python
  2. from __future__ import print_function
  3. import datetime
  4. import socket
  5. import random, string
  6. import daemon, getopt, sys
  7. import daemon.pidlockfile
  8. import traceback
  9. import os
  10. BUFFER_SIZE = 4096
  11. def myrandom(length):
  12. return ''.join(random.choice(string.lowercase) for i in range(length))
  13. def serve(port, bindTo, path_report_store=None):
  14. assert path_report_store != None
  15. s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
  16. s.bind((bindTo, port))
  17. s.listen(1)
  18. print('DebugReport server listening on [{0}]:{1}'.format(bindTo, port))
  19. try:
  20. from cStringIO import StringIO # Python 2
  21. except ImportError:
  22. from io import StringIO # Python 3
  23. report_buffer = StringIO()
  24. while 1:
  25. conn, addr = s.accept()
  26. conn.settimeout(30.0)
  27. report_id = None
  28. try:
  29. while 1:
  30. data = conn.recv(BUFFER_SIZE)
  31. if not data: break
  32. report_buffer.write(data) # python will convert \n to os.linesep
  33. report_id = myrandom(10)
  34. except:
  35. # try to send a zero-length response back to the peer to indicate a problem
  36. try:
  37. conn.sendall("\r\n")
  38. finally:
  39. report_buffer.truncate(0)
  40. conn.close()
  41. continue
  42. # don't want to receive any more data from the client
  43. conn.shutdown(socket.SHUT_RD)
  44. filename = os.path.join(
  45. path_report_store,
  46. "%s_%s.log" % (datetime.date.today().strftime('%Y-%m-%d_'), report_id)
  47. )
  48. with open(filename, 'w') as f:
  49. try:
  50. f.write(report_buffer.getvalue())
  51. f.flush()
  52. except:
  53. try:
  54. conn.sendall("\r\n")
  55. finally:
  56. report_buffer.truncate(0)
  57. conn.close()
  58. continue
  59. # f will be closed automatically by leaving the 'with'-scope
  60. report_buffer.truncate(0)
  61. # send reply to reportee
  62. response = "%s\r\n" % report_id
  63. try:
  64. conn.sendall(response)
  65. finally:
  66. conn.close()
  67. command = 'echo "'+'new report \\\"{0}\\\" from [{2}]:{3} stored as \\\"{1}\\\""'.format(report_id, filename, addr[0], addr[1])
  68. command = command + ' | /usr/local/bin/ff_log_to_bot'
  69. os.system(command)
  70. print('new report "{0}" from [{2}]:{3} stored as "{1}"'.format(report_id, filename, addr[0], addr[1]))
  71. pass
  72. if __name__ == '__main__':
  73. try:
  74. opts, args = getopt.getopt(sys.argv[1:], "dp:b:s:", ["daemonize", "port=", "bind-to=", "report-store="])
  75. except:
  76. print ('Unrecognized option')
  77. sys.exit(2)
  78. daemonize = False
  79. port = 1337
  80. bindTo = None
  81. path_report_store = os.path.join(os.path.dirname(sys.argv[0]), "reports")
  82. for opt, arg in opts:
  83. if opt in ("-d", "--daemonize"):
  84. daemonize = True
  85. elif opt in ("-p", "--port"):
  86. port = int(arg)
  87. elif opt in ("-b", "--bind-to"):
  88. try:
  89. socket.inet_pton(socket.AF_INET6, arg)
  90. bindTo = str(arg)
  91. except:
  92. traceback.print_exc()
  93. sys.exit(1)
  94. elif opt in ("-s", "--report-store"):
  95. path_report_store = arg
  96. else:
  97. assert False
  98. if bindTo == None:
  99. print("Listening IP address is unset. Using default ::")
  100. bindTo = "::"
  101. if not os.path.exists(path_report_store):
  102. os.makedirs(path_report_store)
  103. if daemonize == True:
  104. daemonContext = daemon.DaemonContext(pidfile = daemon.pidlockfile.PIDLockFile("/var/run/ffpb-debugserver.pid"))
  105. with daemonContext:
  106. serve(port, bindTo, path_report_store=path_report_store)
  107. else:
  108. serve(port, bindTo, path_report_store=path_report_store)