wstest.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/python
  2. '''
  3. WebSocket server-side load test program. Sends and receives traffic
  4. that has a random payload (length and content) that is checksummed and
  5. given a sequence number. Any errors are reported and counted.
  6. '''
  7. import sys, os, socket, ssl, time, traceback
  8. import random, time
  9. from select import select
  10. sys.path.insert(0,os.path.dirname(__file__) + "/../utils/")
  11. from websocket import WebSocketServer
  12. class WebSocketTest(WebSocketServer):
  13. buffer_size = 65536
  14. max_packet_size = 10000
  15. recv_cnt = 0
  16. send_cnt = 0
  17. def __init__(self, *args, **kwargs):
  18. self.errors = 0
  19. self.delay = kwargs.pop('delay')
  20. print "Prepopulating random array"
  21. self.rand_array = []
  22. for i in range(0, self.max_packet_size):
  23. self.rand_array.append(random.randint(0, 9))
  24. WebSocketServer.__init__(self, *args, **kwargs)
  25. def new_client(self, client):
  26. self.send_cnt = 0
  27. self.recv_cnt = 0
  28. try:
  29. self.responder(client)
  30. except:
  31. print "accumulated errors:", self.errors
  32. self.errors = 0
  33. raise
  34. def responder(self, client):
  35. cqueue = []
  36. cpartial = ""
  37. socks = [client]
  38. last_send = time.time() * 1000
  39. while True:
  40. ins, outs, excepts = select(socks, socks, socks, 1)
  41. if excepts: raise Exception("Socket exception")
  42. if client in ins:
  43. buf = client.recv(self.buffer_size)
  44. if len(buf) == 0:
  45. raise self.EClose("Client closed")
  46. #print "Client recv: %s (%d)" % (repr(buf[1:-1]), len(buf))
  47. if buf[-1] == '\xff':
  48. if cpartial:
  49. err = self.check(cpartial + buf)
  50. cpartial = ""
  51. else:
  52. err = self.check(buf)
  53. if err:
  54. self.traffic("}")
  55. self.errors = self.errors + 1
  56. print err
  57. else:
  58. self.traffic(">")
  59. else:
  60. self.traffic(".>")
  61. cpartial = cpartial + buf
  62. now = time.time() * 1000
  63. if client in outs and now > (last_send + self.delay):
  64. last_send = now
  65. #print "Client send: %s" % repr(cqueue[0])
  66. client.send(self.generate())
  67. self.traffic("<")
  68. def generate(self):
  69. length = random.randint(10, self.max_packet_size)
  70. numlist = self.rand_array[self.max_packet_size-length:]
  71. # Error in length
  72. #numlist.append(5)
  73. chksum = sum(numlist)
  74. # Error in checksum
  75. #numlist[0] = 5
  76. nums = "".join( [str(n) for n in numlist] )
  77. data = "^%d:%d:%d:%s$" % (self.send_cnt, length, chksum, nums)
  78. self.send_cnt += 1
  79. return WebSocketServer.encode(data)
  80. def check(self, buf):
  81. try:
  82. data_list = WebSocketServer.decode(buf)
  83. except:
  84. print "\n<BOF>" + repr(buf) + "<EOF>"
  85. return "Failed to decode"
  86. err = ""
  87. for data in data_list:
  88. if data.count('$') > 1:
  89. raise Exception("Multiple parts within single packet")
  90. if len(data) == 0:
  91. self.traffic("_")
  92. continue
  93. if data[0] != "^":
  94. err += "buf did not start with '^'\n"
  95. continue
  96. try:
  97. cnt, length, chksum, nums = data[1:-1].split(':')
  98. cnt = int(cnt)
  99. length = int(length)
  100. chksum = int(chksum)
  101. except:
  102. print "\n<BOF>" + repr(data) + "<EOF>"
  103. err += "Invalid data format\n"
  104. continue
  105. if self.recv_cnt != cnt:
  106. err += "Expected count %d but got %d\n" % (self.recv_cnt, cnt)
  107. self.recv_cnt = cnt + 1
  108. continue
  109. self.recv_cnt += 1
  110. if len(nums) != length:
  111. err += "Expected length %d but got %d\n" % (length, len(nums))
  112. continue
  113. inv = nums.translate(None, "0123456789")
  114. if inv:
  115. err += "Invalid characters found: %s\n" % inv
  116. continue
  117. real_chksum = 0
  118. for num in nums:
  119. real_chksum += int(num)
  120. if real_chksum != chksum:
  121. err += "Expected checksum %d but real chksum is %d\n" % (chksum, real_chksum)
  122. return err
  123. if __name__ == '__main__':
  124. try:
  125. if len(sys.argv) < 2: raise
  126. listen_port = int(sys.argv[1])
  127. if len(sys.argv) == 3:
  128. delay = int(sys.argv[2])
  129. else:
  130. delay = 10
  131. except:
  132. print "Usage: %s <listen_port> [delay_ms]" % sys.argv[0]
  133. sys.exit(1)
  134. server = WebSocketTest(
  135. listen_port=listen_port,
  136. verbose=True,
  137. cert='self.pem',
  138. web='.',
  139. delay=delay)
  140. server.start_server()