mirror of https://github.com/fail2ban/fail2ban
performance fix: minimizes connection overhead, using same socket by multiple commands without close it (ex.: 'start' sends several hundreds commands at once)
parent
38f8e1a82a
commit
81e659b760
|
@ -153,30 +153,36 @@ class Fail2banClient:
|
|||
return self.__processCmd([["ping"]], False)
|
||||
|
||||
def __processCmd(self, cmd, showRet = True):
|
||||
beautifier = Beautifier()
|
||||
streamRet = True
|
||||
for c in cmd:
|
||||
beautifier.setInputCmd(c)
|
||||
try:
|
||||
client = CSocket(self.__conf["socket"])
|
||||
ret = client.send(c)
|
||||
if ret[0] == 0:
|
||||
logSys.debug("OK : " + `ret[1]`)
|
||||
client = None
|
||||
try:
|
||||
beautifier = Beautifier()
|
||||
streamRet = True
|
||||
for c in cmd:
|
||||
beautifier.setInputCmd(c)
|
||||
try:
|
||||
if not client:
|
||||
client = CSocket(self.__conf["socket"])
|
||||
ret = client.send(c)
|
||||
if ret[0] == 0:
|
||||
logSys.debug("OK : " + `ret[1]`)
|
||||
if showRet:
|
||||
print beautifier.beautify(ret[1])
|
||||
else:
|
||||
logSys.error("NOK: " + `ret[1].args`)
|
||||
if showRet:
|
||||
print beautifier.beautifyError(ret[1])
|
||||
streamRet = False
|
||||
except socket.error:
|
||||
if showRet:
|
||||
print beautifier.beautify(ret[1])
|
||||
else:
|
||||
logSys.error("NOK: " + `ret[1].args`)
|
||||
self.__logSocketError()
|
||||
return False
|
||||
except Exception, e:
|
||||
if showRet:
|
||||
print beautifier.beautifyError(ret[1])
|
||||
streamRet = False
|
||||
except socket.error:
|
||||
if showRet:
|
||||
self.__logSocketError()
|
||||
return False
|
||||
except Exception, e:
|
||||
if showRet:
|
||||
logSys.error(e)
|
||||
return False
|
||||
logSys.error(e)
|
||||
return False
|
||||
finally:
|
||||
if client:
|
||||
client.close()
|
||||
return streamRet
|
||||
|
||||
def __logSocketError(self):
|
||||
|
|
|
@ -29,39 +29,45 @@ from pickle import dumps, loads, HIGHEST_PROTOCOL
|
|||
import socket
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
# b"" causes SyntaxError in python <= 2.5, so below implements equivalent
|
||||
EMPTY_BYTES = bytes("", encoding="ascii")
|
||||
else:
|
||||
# python 2.x, string type is equivalent to bytes.
|
||||
EMPTY_BYTES = ""
|
||||
|
||||
|
||||
class CSocket:
|
||||
|
||||
EMPTY_BYTES = ""
|
||||
END_STRING = "<F2B_END_COMMAND>"
|
||||
CLOSE_STRING = "<F2B_CLOSE_COMMAND>"
|
||||
# python 2.x, string type is equivalent to bytes.
|
||||
if sys.version_info >= (3,):
|
||||
END_STRING = bytes("<F2B_END_COMMAND>", encoding='ascii')
|
||||
else:
|
||||
END_STRING = "<F2B_END_COMMAND>"
|
||||
# b"" causes SyntaxError in python <= 2.5, so below implements equivalent
|
||||
EMPTY_BYTES = bytes(EMPTY_BYTES, encoding="ascii")
|
||||
END_STRING = bytes(END_STRING, encoding='ascii')
|
||||
CLOSE_STRING = bytes(CLOSE_STRING, encoding='ascii')
|
||||
|
||||
def __init__(self, sock = "/var/run/fail2ban/fail2ban.sock"):
|
||||
def __init__(self, sock="/var/run/fail2ban/fail2ban.sock"):
|
||||
# Create an INET, STREAMing socket
|
||||
#self.csock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.__csock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
#self.csock.connect(("localhost", 2222))
|
||||
self.__csock.connect(sock)
|
||||
|
||||
def __del__(self):
|
||||
self.close(False)
|
||||
|
||||
def send(self, msg):
|
||||
# Convert every list member to string
|
||||
obj = dumps([str(m) for m in msg], HIGHEST_PROTOCOL)
|
||||
self.__csock.send(obj + CSocket.END_STRING)
|
||||
ret = self.receive(self.__csock)
|
||||
return self.receive(self.__csock)
|
||||
|
||||
def close(self, sendEnd=True):
|
||||
if not self.__csock:
|
||||
return
|
||||
if sendEnd:
|
||||
self.__csock.sendall(CSocket.CLOSE_STRING + CSocket.END_STRING)
|
||||
self.__csock.close()
|
||||
return ret
|
||||
self.__csock = None
|
||||
|
||||
@staticmethod
|
||||
def receive(sock):
|
||||
msg = EMPTY_BYTES
|
||||
msg = CSocket.EMPTY_BYTES
|
||||
while msg.rfind(CSocket.END_STRING) == -1:
|
||||
chunk = sock.recv(6)
|
||||
if chunk == '':
|
||||
|
|
|
@ -38,14 +38,6 @@ from ..helpers import getLogger,formatExceptionInfo
|
|||
# Gets the instance of the logger.
|
||||
logSys = getLogger(__name__)
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
# b"" causes SyntaxError in python <= 2.5, so below implements equivalent
|
||||
EMPTY_BYTES = bytes("", encoding="ascii")
|
||||
else:
|
||||
# python 2.x, string type is equivalent to bytes.
|
||||
EMPTY_BYTES = ""
|
||||
|
||||
|
||||
##
|
||||
# Request handler class.
|
||||
#
|
||||
|
@ -54,10 +46,15 @@ else:
|
|||
|
||||
class RequestHandler(asynchat.async_chat):
|
||||
|
||||
# python 2.x, string type is equivalent to bytes.
|
||||
EMPTY_BYTES = ""
|
||||
END_STRING = "<F2B_END_COMMAND>"
|
||||
CLOSE_STRING = "<F2B_CLOSE_COMMAND>"
|
||||
if sys.version_info >= (3,):
|
||||
END_STRING = bytes("<F2B_END_COMMAND>", encoding="ascii")
|
||||
else:
|
||||
END_STRING = "<F2B_END_COMMAND>"
|
||||
# b"" causes SyntaxError in python <= 2.5, so below implements equivalent
|
||||
EMPTY_BYTES = bytes(EMPTY_BYTES, encoding="ascii")
|
||||
END_STRING = bytes(END_STRING, encoding="ascii")
|
||||
CLOSE_STRING = bytes(CLOSE_STRING, encoding='ascii')
|
||||
|
||||
def __init__(self, conn, transmitter):
|
||||
asynchat.async_chat.__init__(self, conn)
|
||||
|
@ -76,16 +73,22 @@ class RequestHandler(asynchat.async_chat):
|
|||
# This method is called once we have a complete request.
|
||||
|
||||
def found_terminator(self):
|
||||
# Pop whole buffer
|
||||
buf = self.__buffer
|
||||
self.__buffer = []
|
||||
# Joins the buffer items.
|
||||
message = loads(EMPTY_BYTES.join(self.__buffer))
|
||||
message = loads(RequestHandler.EMPTY_BYTES.join(buf))
|
||||
# Close if close received
|
||||
if message == RequestHandler.CLOSE_STRING:
|
||||
# Closes the channel.
|
||||
self.close_when_done()
|
||||
return
|
||||
# Gives the message to the transmitter.
|
||||
message = self.__transmitter.proceed(message)
|
||||
# Serializes the response.
|
||||
message = dumps(message, HIGHEST_PROTOCOL)
|
||||
# Sends the response to the client.
|
||||
self.push(message + RequestHandler.END_STRING)
|
||||
# Closes the channel.
|
||||
self.close_when_done()
|
||||
|
||||
def handle_error(self):
|
||||
e1, e2 = formatExceptionInfo()
|
||||
|
|
Loading…
Reference in New Issue