#
# Copyright(C) 2008 Litesim Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# litesim-specific IPC handling
# This one is cross-platform (IronPython or the snake itself (CPython))
import sys
if sys.platform=='cli':
import utils
from sockfix import *
from utils import *
from System import *
from socket import *
else:
old_path = sys.path
sys.path.remove('')
from socket import *
sys.path = old_path
import Queue
import thread
import random
import time
def parse_it(it):
# parse it, whatever "it" is
f = {}
cf = 0
i = 0
l = len(it)
while i<l:
if (it[i]=='\\') and (it[i+1]==':'):
i = i + 1
elif (it[i]==':'):
cf = cf+1
else:
if not f.has_key(cf):
f[cf]=''
f[cf]=f[cf] + it[i]
i = i + 1
retval = []
cf = 0
for cf in f.keys():
retval.append(f[cf])
return retval
class ipc_handler:
def handle_ping(self,addr=None,id=0,params=()):
self.call(addr,'PONG',(id,))
def handle_pong(self,addr=None,id=0,params=()): # replace this one
print "Got a ping reply from " + addr[0] + ':' + str(addr[1])
def __init__(self,host='0.0.0.0',listener_port='12036'):
self.server_sock = socket(AF_INET,SOCK_DGRAM)
self.server_sock.bind((host,listener_port))
self.pending_ack = {}
self.packet_handlers = {
'PING' : self.handle_ping,
'PONG' : self.handle_pong,
}
self.worker_threads = []
self.running = False
self.PRNG = random.Random(int(time.time())) # It ain't for security purposes, so use the timer fool
self.pending_packs = Queue.Queue(0)
def call(self,addr,cmd,params,reliable=False):
id = self.PRNG.randint(0,999999999)
pack = str(id) + ':' + cmd
for p in params:
pack = pack + ':' + str(p)
if reliable:
pack = '+' + pack
self.pending_ack[id] = pack
else:
pack = '-' + pack
self.server_sock.sendto(pack,addr)
def process_pack_loop(self):
while self.running:
pack = self.pending_packs.put(self.server_sock.recvfrom(65536))
def dispatch_pack_loop(self):
while self.running:
try:
pack = self.pending_packs.get()
pack_data = pack[0]
pack_addr = pack[1]
parsed_pack = parse_it(pack_data)
if len(parsed_pack)>1:
if (parsed_pack[0] == 'ACK') and self.pending_ack.has_key(parsed_pack[1]):
del self.pending_ack[parsed_pack[1]]
elif parsed_pack[0].startswith('+') or parsed_pack[0].startswith('-'):
if self.packet_handlers.has_key(parsed_pack[1]):
params = parsed_pack[2:len(parsed_pack)-2]
self.packet_handlers[parsed_pack[1]](addr=pack_addr,id=parsed_pack[0].strip('+').strip('-'),params=params)
if pack_data.startswith('+'):
server_sock.sendto('ACK:' + parsed_pack[0].strip('+').strip('-'))
except Exception, e:
print str(e)
def start_server(self,thread_count=1):
self.running = True
for i in range(thread_count):
self.worker_threads.append(thread.start_new_thread(self.process_pack_loop,()))
self.dispatcher = thread.start_new_thread(self.dispatch_pack_loop,())
~