Skip to content

Commit

Permalink
- Improved memory reading performance, its about twice as fast now
Browse files Browse the repository at this point in the history
- Fixed a bug that allowed the memscan process to remain open after the main program finished
  • Loading branch information
Javieracost committed Mar 24, 2016
1 parent c545886 commit 9cb3db8
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 58 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.*
!/.gitignore
__pycache__
*.pyc
*.pyc
*.lprof
43 changes: 15 additions & 28 deletions agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
from subprocess import call
from os import unlink as delete
from constants import *
#import time

interesting = {'rubber cap', 'terra mantle', 'steel boots', 'terra legs', 'dreaded cleaver', 'mercenary sword',
interesting = {'rubber cap', 'terra mantle', 'steel boots', 'terra legs', 'dreaded cleaver', "butcher's axe", 'mercenary sword',
'glooth amulet', 'giant shimmering pearl', 'terra hood', 'terra boots', 'glooth cape', 'glooth axe',
'glooth club', 'glooth blade', 'glooth bag', 'green gem', 'cheese'
}
Expand All @@ -21,82 +20,72 @@

sockfile = '/tmp/flarelyzer.sock'


def notify(title, msg):
call(['notify-send', '--urgency=low', '--expire-time=' + str(notif_time * 1000), title, msg])


def quit(connection=None):
if connection is not None:
def quit():
global sockfile
try:
print 'stopping memory scanner'
connection.sendall('QUIT')
connection.close()
client.sendall('QUIT')
client.close()
except: pass
notify('Flarelyzer', 'Closed!')
global sockfile
delete(sockfile)
print '--Notification agent closed--'
sys.exit(0)


signal.signal(signal.SIGTERM, lambda x, y: quit)

#@profile

def processLoot(loot):
#print 'before:',loot
loot = map(lambda x: x[1:], loot)
#print 'after:',loot
loot_amounts = dict()
#timeR = time.time()
for i in xrange(len(loot)):
loot_start = loot[i].split()[0]
if loot_start.isdigit():
loot[i] = loot[i][loot[i].find(' ') + 1:]
if loot[i] in pluralMap:
#print '[pluralMap]replaced ' + loot[i] + ' with ' + pluralMap[loot[i]]
loot[i] = pluralMap[loot[i]]
else:
for suffix in plural_suffixes:
if loot[i].endswith(suffix):
#print '[pluralSuffix]replaced ' + loot[i] + ' with ',
loot[i].replace(suffix, plural_suffixes[suffix])
#print loot[i]z
break
else:
for word in plural_words:
if loot[i].startswith(word):
#print '[pluralWords]replaced ' + loot[i] + ' with ',
loot[i].replace(word, plural_words[word])
#print loot[i]
break
loot_amounts[loot[i]] = loot_start
else:
if loot_start in ['a', 'an']:
loot[i] = loot[i][loot[i].find(' ') + 1:]
loot_amounts[loot[i]] = '0'
return loot, loot_amounts
#print 'time spent reading loot: ', time.time() - timeR


print 'Creating temporary socket file...'
agent = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
agent.bind(sockfile)
agent.listen(1)
print 'waiting for client...'
client, addr = agent.accept()
print 'connected!'
try:
while True:
full_msg = client.recv(1024)
client.sendall('ACK')
if full_msg == 'ATTACHED':
notify('Flarelyzer', 'Started successfully!')
client.sendall('ACK')
continue
client.sendall('ACK')
elif full_msg == 'NEXT':
continue
typeInd = full_msg.find('Loot of ') + 8
monsterInd = typeInd
if full_msg[typeInd] == 'a': # not an 'a' if its the loot of a boss
monsterInd = typeInd + 2
monster = full_msg[monsterInd:full_msg.rfind(":")]
monster = full_msg[monsterInd:full_msg.rfind(':')]
loot = full_msg[full_msg.rfind(':') + 1:].split(',')
loot, loot_amounts = processLoot(loot)

Expand All @@ -109,12 +98,10 @@ def processLoot(loot):
lootmsg += v.title() + ', '
else:
lootmsg = lootmsg[:-2]
# print 'notifying: '+lootmsg
notify(monster.title(), lootmsg)
except Exception, e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print 'Notification agent error ' + str(exc_type) + ' - at line: ' + str(exc_tb.tb_lineno)
client.sendall('QUIT')
pass
#exc_type, exc_obj, exc_tb = sys.exc_info()
#print 'Notification agent error ' + str(exc_type) + ' - at line: ' + str(exc_tb.tb_lineno)
finally:
client.close()
quit()
57 changes: 28 additions & 29 deletions memscan.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@
#import time
#TODO: stop opening and closing files with every iteration


cached_loot_messages = set()
notifier = None


def is_timestamp(string):
return string[2] == ':' and string[:2].isdigit() and string[3:5].isdigit() and string[5] == ' '

#@profile
def messages(chunk):
index = 0
while index < len(chunk) - 6: # No point in reading something shorter than '00:00 '
if is_timestamp(chunk[index: index + 6]):
endPos = chunk.find('\0', index + 6)
yield chunk[index:endPos]
index = endPos + 1
else:
index += 1

#@profile
def read_process_memory(pid):
global lootRe
item_drops = []
exp = dict()
damage_dealt = dict()
damage_dealt['You'] = dict()
maps_file = open("/proc/%s/maps" % pid, 'r')
mem_file = open("/proc/%s/mem" % pid, 'r')
try:

for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
if m.group(3) == 'r': # if this is a readable region
Expand All @@ -28,28 +40,21 @@ def read_process_memory(pid):
mem_file.seek(start) # seek to region start
try: chunk = mem_file.read(end - start) # read region contents
except: continue
index = 0
while True:
chunkmatch = re.search('([0-9]{2}:[0-9]{2}[^\0]{10,})\0', chunk[index:])
if chunkmatch is None:
break
log_message = chunkmatch.groups()[0]
for log_message in messages(chunk):
#print log_message
if log_message[5:14] == ' Loot of ':
global cached_loot_messages
if log_message in cached_loot_messages:
index += chunkmatch.end()
continue
#print 'adding lootmsg:', log_message
cached_loot_messages.add(log_message)
item_drops.append(log_message)
elif log_message[5:17] == ' You gained ':
t = log_message[0:5]
try:
e = int(log_message[17:].split(' ')[0])
e = int(log_message[17:log_message.find(' ')])
if t not in exp: exp[t] = e
else: exp[t] += e
except: pass
index += chunkmatch.end()
except KeyboardInterrupt:
return dict()
except Exception, e:
Expand All @@ -68,9 +73,9 @@ def read_process_memory(pid):


def quit():
global notifier
if notifier is not None:
try:
notifier.close()
except: pass
print '--Memory scanner closed--'
sys.exit(0)

Expand Down Expand Up @@ -107,23 +112,17 @@ def main():
if not res:
quit()
for full_msg in res['item_drops']:
#iniW = time.time()
notifier.sendall(full_msg)
response = notifier.recv(8)
#print 'time spent waiting for agent: ', time.time()-iniW
if response == 'QUIT':
print 'stopping memory scan upon request'
quit()
else:
pass
#print 'seconds spent reading memory: ', spent
except socket.error, e:
print 'Error passing msg to agent: ' + str(e)
quit()
notifier.recv(8)
#print 'time spent reading memory: ', spent
notifier.sendall('NEXT')
response = notifier.recv(8)
if response == 'QUIT':
quit()
except Exception, e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print str(e)
print 'error while reading memory: ' + str(exc_type) + ' - at line: ' + str(exc_tb.tb_lineno)
print str(exc_type) + ' - at line: ' + str(exc_tb.tb_lineno)
quit()
print '==Aborting=='
exit(1)
Expand Down

0 comments on commit 9cb3db8

Please sign in to comment.