Skip to content

Commit

Permalink
Added timestamps, separated server, and removed mapper
Browse files Browse the repository at this point in the history
* added timestamps to packet (must implement replay engine now)
* separated the server into multiple files to mirror the client
* removed the mapper and replaced it w/ a db class for efficiency
  • Loading branch information
NeatMonster committed Mar 19, 2018
1 parent ec8c94b commit 6729ddd
Show file tree
Hide file tree
Showing 18 changed files with 614 additions and 693 deletions.
32 changes: 28 additions & 4 deletions plugin/idaconnect/core/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def __init__(self, plugin):

self._repo = None
self._branch = None
self._timestamp = 0

def _install(self):
self._idbHooks = IDBHooks(self._plugin)
Expand All @@ -52,7 +53,8 @@ def ready_to_run(self, *_):
# Subscribe to the events stream if needed
if self._plugin.core.repo and self._plugin.core.branch:
self._plugin.network.sendPacket(Subscribe(
self._plugin.core.repo, self._plugin.core.branch))
self._plugin.core.repo, self._plugin.core.branch,
self._plugin.core.timestamp))
self._plugin.core.hookAll()
self._uiHooksCore = UIHooksCore(self._plugin)
self._uiHooksCore.hook()
Expand Down Expand Up @@ -133,6 +135,24 @@ def branch(self, uuid):
"""
self._branch = uuid

@property
def timestamp(self):
"""
Get the current timestamp.
:return: the timestamp
"""
return self._timestamp

@timestamp.setter
def timestamp(self, timestamp):
"""
Set the current timestamp.
:param timestamp: the timestamp
"""
self._timestamp = timestamp

def loadState(self):
"""
Load the state file if it exists.
Expand Down Expand Up @@ -179,7 +199,9 @@ def loadNetnode(self):
return # node doesn't exists
self._repo = node.hashval('hash')
self._branch = node.hashval('uuid')
logger.debug("Loaded netnode: %s, %s" % (self._repo, self._branch))
self._timestamp = int(node.hashval('timestamp'))
logger.debug("Loaded netnode: repo=%s, branch=%s, timestamp=%d"
% (self._repo, self._branch, self._timestamp))

def saveNetnode(self):
"""
Expand All @@ -190,13 +212,15 @@ def saveNetnode(self):
pass # node already exists
node.hashset('hash', self._repo)
node.hashset('uuid', self._branch)
logger.debug("Saved netnode: %s, %s" % (self._repo, self._branch))
node.hashset('timestamp', str(self._timestamp))
logger.debug("Saved netnode: repo=%s, branch=%s, timestamp=%d"
% (self._repo, self._branch, self._timestamp))

def notifyConnected(self):
"""
If the core has loaded a database, subscribe to the events stream.
"""
if self._repo and self._branch:
self._plugin.network.sendPacket(
Subscribe(self._repo, self._branch))
Subscribe(self._repo, self._branch, self._timestamp))
self.hookAll()
8 changes: 5 additions & 3 deletions plugin/idaconnect/interface/actions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import datetime
import logging
import os
import uuid
from functools import partial

import ida_kernwin
import ida_loader
import idaapi
import idautils
import idc
Expand Down Expand Up @@ -374,6 +372,7 @@ def _dialogAccepted(self, dialog):
repo = Repository(hash, file, type, date)
d = self._plugin.network.sendPacket(NewRepository.Query(repo))
d.addCallback(partial(self._onNewRepositoryReply, repo, branch))
d.addErrback(logger.exception)
else:
self._onNewRepositoryReply(repo, branch, None)

Expand All @@ -388,6 +387,7 @@ def _onNewRepositoryReply(self, repo, branch, _):
branch = Branch(uuid_, repo.hash, date, 64 if idc.__EA64__ else 32)
d = self._plugin.network.sendPacket(NewBranch.Query(branch))
d.addCallback(partial(self._onNewBranchReply, repo, branch))
d.addErrback(logger.exception)
else:
self._onNewBranchReply(repo, branch, None)

Expand Down Expand Up @@ -420,6 +420,7 @@ def _onNewBranchReply(self, repo, branch, _):
packet.upback = partial(self._progressCallback, progress)
d = self._plugin.network.sendPacket(packet)
d.addCallback(partial(self._databaseUploaded, repo, branch))
d.addErrback(logger.exception)

def _databaseUploaded(self, repo, branch, _):
# Show a success dialog
Expand All @@ -433,5 +434,6 @@ def _databaseUploaded(self, repo, branch, _):
success.exec_()

# Subscribe to the new events stream
self._plugin.network.sendPacket(Subscribe(repo.hash, branch.uuid))
self._plugin.network.sendPacket(Subscribe(repo.hash, branch.uuid,
self._plugin.core.timestamp))
self._plugin.core.hookAll()
8 changes: 8 additions & 0 deletions plugin/idaconnect/network/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def recvPacket(self, packet):
def callEvent(event):
self._plugin.core.unhookAll()
event()
self._plugin.core.timestamp = \
max(self.plugin.core.timestamp, event.timestamp) + 1
self._plugin.core.hookAll()

d = task.deferLater(reactor, 0.0, callEvent, packet)
Expand All @@ -57,6 +59,12 @@ def callEvent(event):
return False
return True

def sendPacket(self, packet):
if isinstance(packet, Event):
self._plugin.core.timestamp += 1
packet.timestamp = self._plugin.core.timestamp
return super(ClientProtocol, self).sendPacket(packet)


class ClientFactory(Factory, object):
"""
Expand Down
17 changes: 10 additions & 7 deletions plugin/idaconnect/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
logger = startLogging()


class IDAConnect(idaapi.plugin_t):
class Plugin(idaapi.plugin_t):
"""
The IDAConnect plugin.
"""
Expand All @@ -34,8 +34,8 @@ def description():
:return: the description
"""
return "{} v{}".format(IDAConnect.PLUGIN_NAME,
IDAConnect.PLUGIN_VERSION)
return "{} v{}".format(Plugin.PLUGIN_NAME,
Plugin.PLUGIN_VERSION)

@staticmethod
def resource(filename):
Expand Down Expand Up @@ -90,8 +90,9 @@ def init(self):
"""
try:
self._init()
except Exception:
logger.exception("Failed to initialize")
except Exception as e:
logger.error("Failed to initialize")
logger.exception(e)
skip = idaapi.PLUGIN_SKIP
return skip

Expand Down Expand Up @@ -128,8 +129,10 @@ def term(self):
"""
try:
self._term()
except Exception:
logger.exception("Failed to terminate properly")
except Exception as e:
logger.error("Failed to terminate properly")
logger.exception(e)
return

logger.info("Terminated properly")

Expand Down
3 changes: 2 additions & 1 deletion plugin/idaconnect/shared/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,11 @@ class Reply(IReply, Container, Command):
class Subscribe(DefaultCommand):
__command__ = 'subscribe'

def __init__(self, hash, uuid):
def __init__(self, hash, uuid, timestamp):
super(Subscribe, self).__init__()
self.hash = hash
self.uuid = uuid
self.timestamp = timestamp


class Unsubscribe(DefaultCommand):
Expand Down
Loading

0 comments on commit 6729ddd

Please sign in to comment.