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

@author: sander
'''

from IPy import IP
from pylisp.packet.ip import IPv4Packet, IPv6Packet, UDPMessage
from pylisp.packet.lisp.control import EncapsulatedControlMessage, \
    MapRequestMessage, ControlMessage, MapRegisterMessage
from pylisp.packet.lisp.control.constants import KEY_ID_HMAC_SHA_256_128
from pylisp.packet.lisp.control.locator_record import LocatorRecord
from pylisp.packet.lisp.control.map_register_record import MapRegisterRecord
import random
import socket
import sys

my_name = socket.getfqdn()
source_port = random.choice(range(30000, 40000))

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

d_addrs = socket.getaddrinfo('127.0.0.1', 4342, 0, 0, socket.SOL_UDP)
# d_addrs = socket.getaddrinfo('mr.lispnet.net', 4342, 0, 0, socket.SOL_UDP)
for d_family, d_socktype, d_proto, d_canonname, d_sockaddr in d_addrs:
    destination = IP(d_sockaddr[0])
    print 'Try %s' % destination

    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(s_sockaddr[0])
        print '- From %s' % source

        # Build packet
        locator = LocatorRecord(priority=1, weight=100, local=True,
                                reachable=True, locator=IP('127.0.0.1'))
        record = MapRegisterRecord(ttl=1440,
                                   action=MapRegisterRecord.ACT_NO_ACTION,
                                   authoritative=True,
                                   map_version=0,
                                   eid_prefix=IP('37.77.62.0/25'),
                                   locator_records=[locator])
        reg = MapRegisterMessage(proxy_map_reply=False,
                                 want_map_notify=False,
                                 nonce=nonce,
                                 key_id=KEY_ID_HMAC_SHA_256_128,
                                 records=[record])
        reg.insert_authentication_data('BlaBlaBla')

        try:
            sock = socket.socket(d_family, d_socktype, d_proto)
            sock.bind(s_sockaddr)
            sock.sendto(bytes(reg), d_sockaddr)
            sock.settimeout(1.0)
            data = sock.recv(4096)
            response = ControlMessage.from_bytes(data)
            print repr(response)
            print response.nonce == nonce
        except socket.error:
            continue

        # Print result
        print
