Permalink
Browse files

extracted mmp callback

  • Loading branch information...
1 parent 758d8d2 commit c193fcbf09c7db8e0213d3e3508b60b22d862cdf @smirn0v committed May 8, 2012
Showing with 111 additions and 19 deletions.
  1. +68 −17 mrim-bot/mmp_protocol.py
  2. +28 −1 mrim-bot/mmpbase.py
  3. +15 −1 mrim-bot/mrim_bot.py
View
@@ -3,6 +3,31 @@
from twisted.persisted import styles
from twisted.protocols import basic
+class MMPCallbackBase(object):
+ def __init__(self):
+ self.protocol = None
+ def loginPassword(self):
+ """
+ return tuple ("email","password")
+ that should be used during login process
+ """
+ def loggedIn(self):
+ """
+ called on successfull login
+ """
+ def faildedToLogin(self,reason):
+ """
+ called in case of login was failed
+ """
+ def message(self,from_email,message):
+ """
+ called if message received
+ """
+ def authorizationRequest(self,from_email):
+ """
+ called if authorization request was received
+ """
+
class MMPBaseHandler(object):
def __init__(self, protocol):
self.auto_remove_handler = True
@@ -17,7 +42,7 @@ def canHandlePacket(self,packet):
return packet.header.seq == self.seq and isinstance(packet,MMPServerLoginAckPacket)
def handlePacket(self,packet):
- print "[+] Logged in"
+ self.protocol.callback.loggedIn()
class MMPLogin2RejHandler(MMPBaseHandler):
def __init__(self,protocol,seq):
@@ -28,7 +53,7 @@ def canHandlePacket(self,packet):
return packet.header.seq == self.seq and isinstance(packet,MMPServerLoginRejPacket)
def handlePacket(self,packet):
- print "[-] Login rejected: %s"%packet.reason
+ self.protocol.callback.failedToLogin(packet.reason)
class MMPHelloAckHandler(MMPBaseHandler):
def __init__(self, protocol, seq):
@@ -41,7 +66,8 @@ def canHandlePacket(self,packet):
def handlePacket(self,packet):
self.protocol.startHeartbeat(packet.interval)
header = self.protocol.createHeader()
- packet = MMPClientLogin2Packet(header,"johann-the-builder@mail.ru","buildpleasemail")
+ loginPassword = self.protocol.callback.loginPassword()
+ packet = MMPClientLogin2Packet(header,loginPassword[0],loginPassword[1])
self.protocol.addHandler(MMPLogin2RejHandler(self.protocol,header.seq))
self.protocol.addHandler(MMPLogin2AckHandler(self.protocol,header.seq))
self.protocol.sendPacket(packet)
@@ -55,6 +81,13 @@ def canHandlePacket(self,packet):
return isinstance(packet,MMPServerMessageAckPacket)
def handlePacket(self,packet):
+
+ if packet.simple_message():
+ self.protocol.callback.message(packet.from_email,packet.message)
+
+ if packet.flag_set(MESSAGE_FLAG_NORECV):
+ return
+
header = self.protocol.createHeader()
header.seq = packet.header.seq
msgReceivedPacket = MMPClientMessageRecvPacket(header,packet.from_email,packet.msgid)
@@ -70,10 +103,7 @@ def canHandlePacket(self,packet):
packet.flag_set(MESSAGE_FLAG_AUTHORIZE)
def handlePacket(self,packet):
- print "[+] Authorization request received from %s"%packet.from_email
- header = self.protocol.createHeader()
- authorizePacket = MMPClientAuthorizePacket(header,packet.from_email)
- self.protocol.sendPacket(authorizePacket)
+ self.protocol.callback.authrizationRequest(packet.from_email)
class MMPDispatcherMixin(object):
@@ -107,7 +137,10 @@ class MMPProtocol(protocol.Protocol,MMPDispatcherMixin):
MMP protocol implementation
"""
- def __init__(self):
+ def __init__(self,callback):
+ callback.protocol = self
+ self.callback = callback
+ self.heartbeat = None
self.handlers = []
self.supported_server_packets = [MMPServerHelloAckPacket,
MMPServerLoginAckPacket,
@@ -122,13 +155,12 @@ def __init__(self):
self.addHandler(MMPIncomingAuthorizationHandler(self))
def connectionMade(self):
- print "[+] Connected"
packet = MMPClientHelloPacket(self.createHeader())
self.addHandler(MMPHelloAckHandler(self,packet.header.seq))
self.sendPacket(packet)
def connectionLost(self,reason):
- print "[-] Disconnected"
+ self.stopHeartbeat()
def dataReceived(self,data):
self.buffer += data
@@ -146,14 +178,31 @@ def createHeader(self):
def sendPacket(self,packet):
self.transport.write(packet.binary_data())
+ def sendMessage(self,to_email,message):
+ """
+ message expected to be in ascii
+ rtf not supported
+ """
+ header = self.createHeader()
+ packet = MMPClientMessagePacket(header,0,to_email,message)
+ self.sendPacket(packet)
+
+ def authorize(self,email):
+ header = self.createHeader()
+ authorizePacket = MMPClientAuthorizePacket(header,email)
+ self.sendPacket(authorizePacket)
+
def startHeartbeat(self,interval):
- heartbeat = task.LoopingCall(self._sendHeartbeat)
- heartbeat.start(interval, now = False)
+ self.stopHeartbeat()
+ self.heartbeat = task.LoopingCall(self._sendHeartbeat)
+ self.heartbeat.start(interval, now = False)
+
+ def stopHeartbeat(self):
+ if self.heartbeat: self.heartbeat.stop()
def _sendHeartbeat(self):
header = self.createHeader()
packet = MMPClientPingPacket(header)
- print "[+] Sending heartbeat"
self.sendPacket(packet)
def _extractHeader(self):
@@ -163,7 +212,7 @@ def _extractHeader(self):
self.buffer = self.buffer[MMPHeader.size:]
self.header = MMPHeader.from_binary_data(header_data)
self.mode = MMPMode.Body
- print "[+] Header received %s"%self.header
+ #print "[+] Header received %s"%self.header
self._extractBody()
def _extractBody(self):
@@ -173,11 +222,13 @@ def _extractBody(self):
self.buffer = self.buffer[self.header.dlen:]
self.mode = MMPMode.Header
- print "[+] Payload: %s"%payload.encode('hex')
+ #print "[+] Payload: %s"%payload.encode('hex')
self.handlePacket(self.header,payload)
self._extractHeader()
-class MMPClientFactory(protocol.ClientFactory):
+class MMPClientFactory(protocol.ReconnectingClientFactory):
+ def __init__(self,callback):
+ self.callback = callback
def buildProtocol(self, address):
- return MMPProtocol()
+ return MMPProtocol(self.callback)
View
@@ -77,6 +77,7 @@ def unpack_lps(self):
if len(self.binary_data) < string_length:
raise MMPMalformedPacket,"Incorrect string length received"
string = struct.unpack("%ds"%string_length,self.binary_data[:string_length])[0]
+ string = string.decode('cp1251').encode('utf8')
self.binary_data = self.binary_data[string_length:]
return string
@@ -91,7 +92,7 @@ def unpack_uint(self):
def unpack_zstring(self):
''' unpack zero-ended string '''
zero_index = self.binary_data.index('\0')
- result = self.binary_data[:zero_index]
+ result = self.binary_data[:zero_index].decode('cp1251').encode('utf8')
self.binary_data = self.binary_data[zero_index+1:]
return result
@@ -110,6 +111,27 @@ def pack_lps(self,string):
def pack_uint(self,value):
return struct.pack('I',value)
+class MMPClientMessagePacket(PackingMixin):
+ msg = MRIM_CS_MESSAGE
+ def __init__(self,header,flags,to_email,message):
+ """
+ message should be given in ascii
+ rtf messages not supported
+ """
+ self.header = header
+ self.header.msg = self.__class__.msg
+ self.flags = flags
+ self.to_email = to_email
+ self.message = message
+ self.header.dlen = len(self.binary_data()) - MMPHeader.size
+
+ def binary_data(self):
+ data = self.header.binary_data()
+ data += self.pack_uint(self.flags)
+ data += self.pack_lps(self.to_email)
+ data += self.pack_lps(self.message)
+ return data
+
class MMPClientAuthorizePacket(PackingMixin):
msg = MRIM_CS_AUTHORIZE
def __init__(self,header,email):
@@ -201,6 +223,11 @@ def __init__(self, header, binary_data):
self.rtf_message = self.unpack_lps()
def flag_set(self,flag):
return (self.flags | flag) == self.flags
+ def simple_message(self):
+ return not self.flag_set(MESSAGE_FLAG_SYSTEM) and \
+ not self.flag_set(MESSAGE_FLAG_CONTACT) and \
+ not self.flag_set(MESSAGE_FLAG_NOTIFY) and \
+ not self.flag_set(MESSAGE_FLAG_AUTHORIZE)
class MMPServerContactListPacket(PackingMixin):
msg = MRIM_CS_CONTACT_LIST2
View
@@ -3,6 +3,20 @@
import telnetlib
import sys
+class MMPBot(mmp_protocol.MMPCallbackBase):
+ def __init__(self):
+ super(MMPBot,self).__init__()
+
+ def loginPassword(self):
+ return ("johann-the-builder@mail.ru","buildpleasemail")
+
+ def authrizationRequest(self,from_email):
+ self.protocol.authorize(from_email)
+
+ def message(self,from_email,message):
+ print "%s: %s"%(from_email,message)
+
+
def server_to_connect():
telnet = telnetlib.Telnet("mrim.mail.ru",2042)
address = telnet.read_all()
@@ -27,7 +41,7 @@ def main():
print "[+] Host = %s; Port = %d"%(host,int(port))
- reactor.connectTCP(host, port, mmp_protocol.MMPClientFactory())
+ reactor.connectTCP(host, port, mmp_protocol.MMPClientFactory(MMPBot()))
reactor.run()
if __name__ == "__main__":

0 comments on commit c193fcb

Please sign in to comment.