#!/usr/bin/env python
'''
Created on 11 jan. 2013

@author: sander
'''

from ipaddress import IPv6Address, ip_address, IPv4Address
from pylisp.packet.ip import IPv4Packet, IPv6Packet, UDPMessage
from pylisp.packet.lisp.control import EncapsulatedControlMessage, MapRequestMessage, ControlMessage
import random
import socket
import sys

my_name = socket.getfqdn()
query = ip_address(unicode(sys.argv[1]))
if isinstance(query, IPv4Address):
    query_source = IPv4Address(u'37.77.56.75')
    query_source = IPv4Address(u'0.0.0.0')
else:
    query_source = IPv6Address(u'2a00:8640:1:0:224:36ff:feef:1d89')
    query_source = IPv6Address(u'::')

source_port = 14342

# Build the map request
nonce = ''.join([chr(random.choice(xrange(256))) for i in range(8)])

d_addrs = socket.getaddrinfo('37.77.56.75', 4342, 0, 0, socket.SOL_UDP)
for d_family, d_socktype, d_proto, d_canonname, d_sockaddr in d_addrs:
    destination = ip_address(unicode(d_sockaddr[0]))

    s_addrs = socket.getaddrinfo(my_name, source_port, d_family, d_socktype, d_proto)
    for s_family, s_socktype, s_proto, s_canonname, s_sockaddr in s_addrs:
        source = ip_address(unicode(s_sockaddr[0]))
        print 'From %s to %s' % (source, destination)

        # Build packet
        req = MapRequestMessage(nonce=nonce,
                                source_eid=query_source,
                                itr_rlocs=[source],
                                eid_prefixes=[query])
        udp = UDPMessage(source_port=source_port,
                         destination_port=4342,
                         payload=req)
        udp.checksum = udp.calculate_checksum(source=query_source,
                                              destination=query)
        if isinstance(query, IPv4Address):
            ecm_content = IPv4Packet(ttl=64,
                                     protocol=udp.header_type,
                                     source=query_source,
                                     destination=query,
                                     payload=udp)
        else:
            ecm_content = IPv6Packet(next_header=udp.header_type,
                                     hop_limit=64,
                                     source=query_source,
                                     destination=query,
                                     payload=udp)

        ecm = EncapsulatedControlMessage(ddt_originated=True,
                                         payload=ecm_content)

        try:
            print 'Sending request:\n%r\n' % ecm
            sock = socket.socket(d_family, d_socktype, d_proto)
            sock.bind(s_sockaddr)
            sock.sendto(bytes(ecm), d_sockaddr)
            data = sock.recv(4096)
            response = ControlMessage.from_bytes(data)
            print 'Received reply:\n%r\n' % response
        except socket.error:
            continue
