Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.55 KB | None | 0 0
  1. import socket
  2. import sys
  3. from threading import Thread
  4.  
  5. SERVER_CONFIRMATION = ''
  6. SERVER_MOVE = '102 MOVE\a\b'.encode('utf-8')
  7. SERVER_TURN_LEFT = '103 TURN LEFT\a\b'.encode('utf-8')
  8. SERVER_TURN_RIGHT = '104 TURN RIGHT\a\b'.encode('utf-8')
  9. SERVER_PICK_UP= '105 GET MESSAGE\a\b'.encode('utf-8')
  10. SERVER_LOGOUT= '106 LOGOUT\a\b'.encode('utf-8')
  11. SERVER_OK= '200 OK\a\b'.encode('utf-8')
  12. SERVER_LOGIN_FAILED= '300 LOGIN FAILED\a\b'.encode('utf-8')
  13. SERVER_SYNTAX_ERROR= '301 SYNTAX ERROR\a\b'.encode('utf-8')
  14. SERVER_LOGIC_ERROR= '302 LOGIC ERROR\a\b'.encode('utf-8')
  15.  
  16. CLIENT_RECHARGING = 'RECHARGING\a\b'
  17. CLIENT_FULL_POWER = 'FULL POWER\a\b'
  18.  
  19. CLIENT_USERNAME_LEN = 10
  20. CLIENT_CONFIRMATION_LEN = 5
  21. CLIENT_OK_LEN = 10
  22. CLIENT_RECHARGING_LEN = 10
  23. CLIENT_FULL_POWER_LEN = 10
  24. CLIENT_MESSAGE_LEN = 98
  25.  
  26. KLIENT_KEY = 45328
  27. SERVER_KEY = 54621
  28.  
  29. UNINICIALIZED = -1
  30. UP = 0
  31. RIGHT = 1
  32. DOWN = 2
  33. LEFT = 3
  34.  
  35.  
  36. #Robot a definovani vsech jeho moznych pohybu
  37. class Robot:
  38. def __init__(self):
  39. self.visitedBoxCorner = False
  40. self.direction = UNINICIALIZED
  41. self.previousCoordinates = None
  42. self.previouslyPickedUpTreasure = False
  43. self.goUp = True
  44. self.moveRight = True
  45. self.moveRightX = -2
  46.  
  47. def RightDirection(self,x,y,goalX,goalY):
  48. if goalY > y:
  49. return UP
  50. if goalY < y:
  51. return DOWN
  52. if goalX > x:
  53. return RIGHT
  54. if goalX < x:
  55. return LEFT
  56.  
  57. def TurnLeftOrRight(self,goalDirection):#
  58. if self.direction == goalDirection:
  59. return SERVER_TURN_RIGHT
  60. if self.direction - goalDirection == 1 or self.direction == UP and goalDirection == LEFT:
  61. self.direction = (self.direction - 1) % 4
  62. return SERVER_TURN_LEFT
  63. else:
  64. self.direction = (self.direction + 1) % 4
  65. return SERVER_TURN_RIGHT
  66.  
  67. def VisitCorner(self,x,y):
  68. correctDirection = self.RightDirection(x,y,-2,-2)
  69. self.previousCoordinates = (x, y)
  70. if correctDirection == self.direction:
  71. return SERVER_MOVE
  72. else:
  73. return self.TurnLeftOrRight(correctDirection)
  74.  
  75. def SetAnotherGoalCoordinatesInBox(self,x,y):
  76. if y != 2 and self.goUp:
  77. return x,2
  78. if y == 2 and self.goUp and x == self.moveRightX:
  79. return x+1,y
  80. if y == 2 and self.goUp and x > self.moveRightX:
  81. self.moveRightX = x
  82. self.goUp = False
  83. return x, -2
  84. if y != -2 and not self.goUp:
  85. return x, -2
  86. if y == -2 and not self.goUp and x == self.moveRightX:
  87. return x+1,y
  88. if y == -2 and not self.goUp and x > self.moveRightX:
  89. self.moveRightX = x
  90. self.goUp = True
  91. return x, 2
  92.  
  93. def LookForTreasure(self,x,y):
  94. if not self.previouslyPickedUpTreasure:
  95. self.previouslyPickedUpTreasure = True
  96. self.previousCoordinates = (x, y)
  97. return SERVER_PICK_UP
  98. else:
  99. goalX,goalY = self.SetAnotherGoalCoordinatesInBox(x,y)
  100. correctDirection = self.RightDirection(x, y, goalX, goalY)
  101. if correctDirection == self.direction:
  102. self.previouslyPickedUpTreasure = False
  103. self.previousCoordinates = (x, y)
  104. return SERVER_MOVE
  105. else:
  106. self.previousCoordinates = (x, y)
  107. return self.TurnLeftOrRight(correctDirection)
  108.  
  109.  
  110. def Move(self,x,y):
  111. if x == 999999 and y == 999999:
  112. return SERVER_MOVE
  113. if self.previousCoordinates == None:
  114. self.previousCoordinates = (x,y)
  115. return SERVER_MOVE
  116. if self.direction == UNINICIALIZED and self.previousCoordinates == (x,y):
  117. self.previousCoordinates = (x,y)
  118. return SERVER_MOVE
  119.  
  120. if self.direction == UNINICIALIZED:
  121. if x > self.previousCoordinates[0]:
  122. self.direction = RIGHT
  123. elif x < self.previousCoordinates[0]:
  124. self.direction = LEFT
  125. elif y < self.previousCoordinates[1]:
  126. self.direction = DOWN
  127. elif y > self.previousCoordinates[1]:
  128. self.direction = UP
  129.  
  130. if not self.visitedBoxCorner and (x,y) == (-2,-2):
  131. self.visitedBoxCorner = True
  132.  
  133. if self.visitedBoxCorner:
  134. return self.LookForTreasure(x,y)
  135. return self.VisitCorner(x,y)
  136.  
  137.  
  138. def ExtractData(DataWithAdditionalStuff,connection,stage,treasureMessage):
  139. DataWithAdditionalStuff = DataWithAdditionalStuff.decode('utf-8')
  140. data = ''
  141. if DataWithAdditionalStuff == '':
  142. return data,0
  143. counter = 0
  144. while DataWithAdditionalStuff[len(DataWithAdditionalStuff) - 2] != '\a' or DataWithAdditionalStuff[len(DataWithAdditionalStuff) - 1] != '\b':
  145. if '\a\b' not in DataWithAdditionalStuff and not CheckOnlyLength(DataWithAdditionalStuff,stage,treasureMessage):
  146. return DataWithAdditionalStuff, 0
  147. if '\0' in DataWithAdditionalStuff:
  148. break
  149. connection.settimeout(1)
  150. tmp = connection.recv(1000)
  151. tmp = tmp.decode('utf-8')
  152. DataWithAdditionalStuff += tmp
  153. if DataWithAdditionalStuff[len(DataWithAdditionalStuff) - 2] != '\a' or DataWithAdditionalStuff[len(DataWithAdditionalStuff) - 1] != '\b':
  154. return ['2','ERROR'], 2
  155.  
  156. while True:
  157. if DataWithAdditionalStuff[counter] == '\a' and DataWithAdditionalStuff[counter+1] == '\b':
  158. if counter == len(DataWithAdditionalStuff) - 2:
  159. return data,0
  160. else:#multiple messages
  161. data = [data]
  162. anotherData = ''
  163. counter += 2
  164. while True:
  165. if DataWithAdditionalStuff[counter] == '\a' and DataWithAdditionalStuff[counter + 1] == '\b':
  166. if counter == len(DataWithAdditionalStuff) - 2:
  167. data.append(anotherData)
  168. return data,len(data)
  169. else:
  170. data.append(anotherData)
  171. counter += 2
  172. anotherData = ''
  173. else:
  174. anotherData += DataWithAdditionalStuff[counter]
  175. counter += 1
  176. else:
  177. data += DataWithAdditionalStuff[counter]
  178. counter += 1
  179.  
  180. def EncapsulateMessage(data):
  181. data = str(data)
  182. data += '\a\b'
  183. data = data.encode('utf-8')
  184. return data
  185.  
  186. def ConfirmationFromServer(name):
  187. mySum = 0
  188. for myChar in name:
  189. mySum+=ord(myChar)
  190.  
  191. mySum *= 1000
  192. myHash = mySum%65536
  193. mySum += SERVER_KEY
  194. mySum %= 65536
  195. mySum = EncapsulateMessage(mySum)
  196. return mySum, myHash
  197.  
  198. def CompareHashes(number,hash):
  199. number += 65536 - KLIENT_KEY
  200. number %= 65536
  201. if number == hash:
  202. return True
  203. return False
  204.  
  205. def ExtractCoordinates(data):
  206. x = 0
  207. y = 0
  208. tmp = data.split(' ')
  209. x = int(tmp[1])
  210. y = int(tmp[2])
  211. return x,y
  212.  
  213.  
  214. def CheckOnlyLength(data,stage,treasureMessage):
  215. myLen = len(data)
  216. if myLen and data[myLen-1] == '\a':
  217. myLen -= 1
  218. if 'RECHARGING' in data or 'FULL POWER' in data:
  219. return myLen <= CLIENT_RECHARGING_LEN
  220. if stage == 1:
  221. return myLen <= CLIENT_CONFIRMATION_LEN
  222. else:
  223. if data == '':
  224. return True
  225. if stage == 0:
  226. return myLen <= CLIENT_USERNAME_LEN
  227. if stage == 2 and not treasureMessage:
  228. return myLen <= CLIENT_OK_LEN
  229. return myLen <= CLIENT_MESSAGE_LEN
  230.  
  231. def CheckLengthAndSyntax(data,stage,treasureMessage):
  232. if 'RECHARGING' in data or 'FULL POWER' in data:
  233. return len(data) <= CLIENT_RECHARGING_LEN
  234. if stage == 1:
  235. if len(data) <= CLIENT_CONFIRMATION_LEN:
  236. return not (' ' in data)
  237. return len(data) <= CLIENT_CONFIRMATION_LEN
  238. else:
  239. if data == '':
  240. return True
  241. if stage == 0:
  242. return len(data) <= CLIENT_USERNAME_LEN
  243. if stage == 2 and not treasureMessage:
  244. if len(data) <= CLIENT_OK_LEN:
  245. try:
  246. if not (data[0] == 'O' and data[1] == 'K' and data[2] == ' '):
  247. return False
  248. tmp = data.split(' ')
  249. tmp[1] = int(tmp[1])
  250. tmp[2] = int(tmp[2])
  251. a = tmp[0] + ' ' + str(tmp[1]) + ' ' + str(tmp[2])
  252. if a != data:
  253. return False
  254. except Exception as ex:
  255. return False
  256. return len(data) <= CLIENT_OK_LEN
  257. return len(data) <= CLIENT_MESSAGE_LEN
  258.  
  259. class TCP_Server:
  260. def __init__(self):
  261. self.listOfThreads = []
  262.  
  263. def Communicate(self,mySocket):
  264. while True:
  265.  
  266. # Wait for a connection
  267. print('waiting for a connection')
  268. connection, client_address = mySocket.accept()
  269. connection.settimeout(1)
  270. t1 = Thread(target = self.CommunicateSingleThread, args = (mySocket,connection,client_address))
  271. t1.start()
  272. self.listOfThreads.append(t1)
  273.  
  274.  
  275. def CommunicateSingleThread(self,mySocket,connection,client_address):
  276. myHash = 0
  277. stage = 0
  278. recharge = False
  279. multipleMessages = False
  280. robot = Robot()
  281. data = ''
  282. counter = 0
  283. cnt = 0
  284. try:
  285. print('connection from', client_address)
  286.  
  287. # Receive the data
  288. while True:
  289. if not multipleMessages:
  290. data = connection.recv(1000)
  291. print('Received {!r}'.format(data))
  292. temporaryData, cnt = ExtractData(data, connection, stage,
  293. robot.previouslyPickedUpTreasure)
  294. if cnt:
  295. multipleMessages = True
  296. data = temporaryData[counter]
  297. counter += 1
  298. cnt -= 1
  299. if not cnt:
  300. counter = 0
  301. multipleMessages = False
  302. else:
  303. data = temporaryData
  304.  
  305. if data == SERVER_SYNTAX_ERROR or not CheckLengthAndSyntax(data, stage,
  306. robot.previouslyPickedUpTreasure):
  307. connection.sendall(SERVER_SYNTAX_ERROR)
  308. break
  309.  
  310. if data == 'RECHARGING':
  311. connection.settimeout(5)
  312. recharge = True
  313. continue
  314. if data == 'FULL POWER':
  315. recharge = False
  316. connection.settimeout(1)
  317. continue
  318.  
  319. if recharge:
  320. connection.sendall(SERVER_LOGIC_ERROR)
  321. break
  322.  
  323. if stage == 0:
  324. SERVER_CONFIRMATION, myHash = ConfirmationFromServer(data)
  325. connection.sendall(SERVER_CONFIRMATION)
  326. stage += 1
  327. elif stage == 1:
  328. if CompareHashes(int(data), myHash):
  329. connection.sendall(SERVER_OK)
  330. connection.sendall(robot.Move(999999, 999999))
  331. stage += 1
  332. else:
  333. connection.sendall(SERVER_LOGIN_FAILED)
  334. break
  335. elif stage == 2:
  336. if data != '' and data[0] == 'O' and data[1] == 'K' and data[2] == ' ':
  337. x, y = ExtractCoordinates(data)
  338. connection.sendall(robot.Move(x, y))
  339. else:
  340. if data == '':
  341. connection.sendall(
  342. robot.Move(robot.previousCoordinates[0], robot.previousCoordinates[1]))
  343. else:
  344. connection.sendall(SERVER_LOGOUT)
  345. break
  346. except socket.timeout:
  347. print('Caught timeout')
  348. finally:
  349. # Clean up the connection
  350. connection.close()
  351.  
  352.  
  353. server = TCP_Server()
  354. #create socket
  355. socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  356. server_address = ('local_host', 10000)
  357. socket.bind(server_address)
  358.  
  359. socket.listen(1)
  360.  
  361. server.Communicate(socket)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement