#!/usr/bin/env python
# coding=utf-8
import struct
from array import *
import socket
import thread
import time
IP="192.168.56.101"
PORT=12345
basicSpeed=1000

def ipstr_to_int(a):
    octets = a.split('.')
    return int(octets[0]) << 24 |\
           int(octets[1]) << 16 |\
           int(octets[2]) <<  8 |\
           int(octets[3]);

def array_to_ipstr(a):
    return "%d.%d.%d.%d" % (a[0], a[1], a[2], a[3])

class MSG:
    INIT=0x01
    QUERY=0x02
    REPLY=0x03
    CONTROL=0x04
    
    def __init__(self,arr):
        self.arr = arr
        self.links=[]
        if type(arr) == type(1):
            self.msg_type = arr
        elif type(arr) == type(''):
            self.unpack_msg()

        #self.arr=arr
    def set_ip(self,ip):
        self.ip = ip
    def pack_msg(self):
        if self.msg_type==MSG.INIT:
            buf=struct.pack('!B',self.msg_type)
            buf += struct.pack("!I",self.ip)
        elif self.msg_type==MSG.QUERY:
            buf=struct.pack('!B',self.msg_type)
            #added by yhx
            buf += struct.pack('!I',self.ip)

        elif self.msg_type==MSG.REPLY:
            buf=struct.pack('!BI',self.msg_type,len(self.links))
            for link in self.links:
                if link[0]==None:
                    src='00000000000'
                    buf+=src
                    buf+=link[1]
                else: 
                    buf+=link[0]+link[1]
                buf+=struct.pack('!I',link[2])
        elif self.msg_type==MSG.CONTROL:
            buf=struct.pack('!BI',self.msg_type,len(self.links))
            for link in self.links:
                if link[0]==None:
                    src='00000000000'
                    buf+=src
                    buf+=link[1]
                else:
                    buf+=link[0]+link[1]
                buf+=struct.pack('!B',link[2])
        else: 
            print 'error msg type'
        return buf
    def unpack_msg(self):
        (self.msg_type,)=struct.unpack('!B',self.arr[:1])
        print str(self.msg_type)
        if self.msg_type==MSG.INIT or self.msg_type == MSG.QUERY:
            (self.ip,)=struct.unpack('!I',self.arr[1:5])
        elif self.msg_type==MSG.REPLY:
            num=struct.unpack('!I',self.arr[1:5])
            for i in num:
                (arr_reply,)=struct.unpack('!I',self.arr[29:33])
                self.links.append((self.arr[5:17],\
                                  self.arr[17:29],\
                                  arr_reply))
        elif self.msg_type==MSG.CONTROL:
            num=struct.unpack('!I',self.arr[1:5])
            for i in num:
                (control_type,)=struct.unpack('!B',self.arr[29:30])
                self.links.append((self.arr[5:17],\
					  self.arr[17:29],\
					  control_type))
    def add_reply(self,src,dst,arr_reply):
        if src==None:
            src='00000000000'
        if dst==None:
            dst='00000000000'
        self.links.append((src,dst,arr_reply))
    def add_control(self,src,dst,control_type):
        if src==None:
            src='00000000000'
        if dst==None:
            dst='00000000000'
        self.links.append((src,dst,control_type))
        
    def __str__(self):
        s=''
        if self.msg_type==MSG.INIT:
            s='INIT!!! '
        elif self.msg_type==MSG.QUERY:
            s='QUERY!!! '
        elif self.msg_type==MSG.REPLY:
            s='REPLY!!! '
            for link in self.links:
                s+=link[0]+' > '+link[1]+' : '+str(link[2])+' | '
        elif self.msg_type==MSG.CONTROL:
            s='CONTROL!!! '
            for link in self.links:
                s+=link[0]+' > '+link[1]+' : '+str(link[2])+' | '
        else: 
            print 'str error\n'
        return s
#msg is a binary string packed py MSG
def send_packet(msg):
    S= socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    S.sendto(msg.pack_msg(),(IP,PORT))
    S.close()

def recv_packet():
    S=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    S.bind(("192.168.56.102",PORT))
    #S.settimeout(2.5)
    link=[]
    while True:
        #try:
        data=S.recv(1024)
        msg=MSG(data)
        #here is check the data and reply control msg
        #print str(msg)
        print msg
        if len(link)==0:
            link=msg.links
            continue
        else:
            link_new=msg.links
            #from here is checking
            for i in len(link_new):
                link_new[i][2]=link_new[i][2]-link[i][2]
            link=msg.links
            msg_reply=MSG(MSG.CONTROL)
            for j in len(link_new):
                if abs(link_new[i][2])>basicSpeed:
                    msg_reply.add_control(link_new[i][0],link_new[i][1],1)
            if len(msg_reply.links)>0:
                send_packet(msg_reply.pack_msg())
            #except timeout as e:
            #    pass

re=thread.start_new_thread(recv_packet,())


if __name__ == '__main__':
    #msg = MSG(MSG.REPLY)
    #msg.add_reply('012345678912','123456789012',102)
    #msg = MSG(MSG.CONTROL)
    #msg.add_reply('012345678912','123456789012',1)
    #msg = MSG(MSG.QUERY)
    msg = MSG(MSG.INIT)
    msg.set_ip(ipstr_to_int("192.168.0.51"))
    msg.pack_msg()
    send_packet(msg)
    #msg.settimeout(5)
    #msg.setbolcking(0)
    #msg.recv(100)
    #msg_1=MSG(msg.pack_msg())
    #print str(msg_1)
    while True:
        msg_query=MSG(MSG.QUERY)
        msg_query.set_ip(ipstr_to_int('192.168.0.51'))
        #msg_query.pack_msg()
        send_packet(msg_query)
        time.sleep(10)

