Browse Source

Ensures that the response (report-id) is send back to the peer completely.

One cannot be sure that socket#send(...) sends back all the data in a buffer
back to the connected peer, and thus either have to test whether the number
of transmitted bytes equals the size of the buffer or ... use a convenience
method - like socket#sendall(...) - for that.

In the response, the server now also appends an CRLF after the report-id to
indicate the end of the report-id, as this usually is easy to process as a
(data-)delimiter by the receiver. In case an error occurs while receiving
the report, only CRLF gets send back to the peer and the server continues
listening for new connections after closing the connection.

Lastly, a socket operation always should be surrounded by a try-except- or
try-finally-block, as an exception might be thrown an kill the process. When-
ever a try-finally-block is appropriate (like here), the socket should be
closed in the finally-block.
Stefan Laudemann 9 years ago
parent
commit
f2374db31f
1 changed files with 23 additions and 9 deletions
  1. 23 9
      server.py

+ 23 - 9
server.py

@@ -24,17 +24,31 @@ def server(port, bindTo):
 		report_id = myrandom(10)
 		filename = '/opt/debugserver/reports/' + datetime.date.today().strftime('%Y-%m-%d_') + report_id + '.gz'
 
-		f = open(filename, 'w')
-		while 1:
-			data = conn.recv(BUFFER_SIZE)
-			if not data: break
-			f.write(data) # python will convert \n to os.linesep
-		f.flush()
-		f.close() 
+		with open(filename, 'w') as f:
+			try:
+				while 1:
+					data = conn.recv(BUFFER_SIZE)
+					if not data: break
+					f.write(data) # python will convert \n to os.linesep
+			except:
+				# delete the incompletely received report
+				f.close()
+				os.remove(filename)
+				# try to send a zero-length response back to the peer to indicate a problem
+				try:
+					conn.sendall("\r\n")
+				finally:
+					conn.close()
+				continue
+			f.flush()
+			# f will be closed automatically by leaving the 'with'-scope
 
 		# send reply to reportee
-		conn.send(report_id)
-		conn.close()
+		response = "%s\r\n" % report_id
+		try:
+			conn.sendall(response)
+		finally:
+			conn.close()
 
 		command = 'echo "'+'new report \\\"{0}\\\" from [{2}]:{3} stored as \\\"{1}\\\""'.format(report_id, filename, addr[0], addr[1])
 		command = command + ' | /usr/local/bin/ff_log_to_bot'