#!/usr/python
import socket
import struct
import time
import threading
import logging
 
"""
author:	 Martin Robinson
email:   nosnibor.nitram@gmail.com
project: multicast
libname: plz (please)
license: just email me if you use it, ill be happy
"""
 
def mcastRX(host,port):
	"""
	listen to the udp multicast void 
	and if a lost soul search the light
	"""
	sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
	sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	sock.bind(('', port))
	mreq = struct.pack("4sl", socket.inet_aton(host), socket.INADDR_ANY)
	sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
	#sock.settimeout(expire)
	data,sender = sock.recvfrom(512)
	logging.info(str(sender)+' : '+str(data));
	return data
 
def mcastTX(host,port,message):
	"""
	"""
	sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
	sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
	sock.sendto(message, (host, port))
 
 
class Service(threading.Thread):
	def __init__(self,host,port,grp,fn={}):
		"""
		"""
		super(Service, self).__init__()
		self.port=port
		self.host=host
		self.grp =grp
		if type(fn) is dict:
			self.fn = fn
		else:
			self.fn = {}
		self.start()
		logging.info('Service started')
	
	def run(self):
		"""

		"""
		while True:
			message = mcastRX(self.host,self.port);
			part = message.split(' ',3)
			if (part[0]=='plz'):
				grp = part[1] if len(part)>1 else None
				fnname = part[2] if len(part)>2 else ''
				param = part[3] if len(part)>3 else None
				if grp == self.grp and fnname in self.fn:
					self.fn[fnname](param)
			time.sleep(0.1)
				
def polite(host,port):
	"""
	"""
	def plz(grp,fnname,param):
		message = 'plz '+grp+' '+fnname+' '+param
		mcastTX(host,port,message[:508])
	return plz
 
if __name__ == '__main__':
	channel = '224.1.1.1'
	port = 6000
	
	def now(param):
		print(time.time())
	
	Service(channel,port,'what',{'time':now})
	
	plz = polite(channel, port)
	
	plz('gentlement','scratch','my back')

