#!/usr/bin/env python

import asyncore
import socket
from struct import unpack

def od (value):
	def spaced (value):
		even = None
		for v in value:
			if even is False:
				yield ' '
			yield '%02X' % ord(v)
			even = not even
	return ''.join(spaced(value))

class BGPHandler(asyncore.dispatcher_with_send):
	def read_message (self):
		header = self.recv(19)
		print "read header", od(header)
		length = unpack('!H',header[16:18])[0]
		print "waiting for", length, "bytes"
		body = self.recv(length)
		print "read body  ", od(body)
		return header,body

	def handle_read (self):
		# reply with a IBGP response with the same capability (just changing routerID)
		print "reading open"
		header,body = self.read_message()
		routerid = chr((ord(body[8])+1) & 0xFF)
		o = header+body[:8]+routerid+body[9:]
		print "sending open", od(o)
		self.send(o)

class BGPServer(asyncore.dispatcher):
	def __init__(self, host, port):
		asyncore.dispatcher.__init__(self)
		self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
		self.set_reuse_addr()
		self.bind((host, port))
		self.listen(5)

	def handle_accept(self):
		pair = self.accept()
		if pair is not None:
			sock, addr = pair
			print "new BGP connection from", addr
			handler = BGPHandler(sock)

server = BGPServer('localhost', int(os.environ.get('exabgp.tcp.port','179')))
asyncore.loop()
