~ubuntu-branches/ubuntu/trusty/exabgp/trusty

« back to all changes in this revision

Viewing changes to build/lib.linux-x86_64-2.7/exabgp/network/connection.py

  • Committer: Package Import Robot
  • Author(s): Henry-Nicolas Tourneur
  • Date: 2012-03-22 12:00:00 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20120322120000-v4aj8h69mhpmgbjq
Tags: 2.0.7-1

* New upstream release
* Fix bad clean target for build/ directory

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# encoding: utf-8
3
 
"""
4
 
network.py
5
 
 
6
 
Created by Thomas Mangin on 2009-09-06.
7
 
Copyright (c) 2009-2011 Exa Networks. All rights reserved.
8
 
"""
9
 
 
10
 
import os
11
 
import struct
12
 
import time
13
 
import socket
14
 
import select
15
 
 
16
 
from exabgp.utils import hexa,trace
17
 
from exabgp.structure.address import AFI
18
 
from exabgp.message import Failure
19
 
 
20
 
from exabgp.log import Logger,LazyFormat
21
 
logger = Logger()
22
 
 
23
 
class Connection (object):
24
 
        def __init__ (self,peer,local,md5,ttl):
25
 
                self.last_read = 0
26
 
                self.last_write = 0
27
 
                self.peer = peer
28
 
 
29
 
                logger.wire("Opening connection to %s" % self.peer)
30
 
 
31
 
                if peer.afi != local.afi:
32
 
                        raise Failure('The local IP and peer IP must be of the same family (both IPv4 or both IPv6)')
33
 
 
34
 
                try:
35
 
                        if peer.afi == AFI.ipv4:
36
 
                                self.io = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
37
 
                        if peer.afi == AFI.ipv6:
38
 
                                self.io = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_TCP)
39
 
                        try:
40
 
                                self.io.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
41
 
                        except AttributeError:
42
 
                                pass
43
 
                        try:
44
 
                                self.io.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
45
 
                        except AttributeError:
46
 
                                pass
47
 
                        self.io.settimeout(1)
48
 
                        if peer.afi == AFI.ipv4:
49
 
                                self.io.bind((local.ip,0))
50
 
                        if peer.afi == AFI.ipv6:
51
 
                                self.io.bind((local.ip,0,0,0))
52
 
                except socket.error,e:
53
 
                        self.close()
54
 
                        raise Failure('Could not bind to local ip %s - %s' % (local.ip,str(e)))
55
 
 
56
 
                if md5:
57
 
                        try:
58
 
                                TCP_MD5SIG = 14
59
 
                                TCP_MD5SIG_MAXKEYLEN = 80
60
 
                                SS_PADSIZE = 120
61
 
                                
62
 
                                n_addr = socket.inet_aton(peer.ip)
63
 
                                n_port = socket.htons(179)
64
 
                                tcp_md5sig = 'HH4s%dx2xH4x%ds' % (SS_PADSIZE, TCP_MD5SIG_MAXKEYLEN)
65
 
                                md5sig = struct.pack(tcp_md5sig, socket.AF_INET, n_port, n_addr, len(md5), md5)
66
 
                                self.io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, md5sig)
67
 
                        except socket.error,e:
68
 
                                self.close()
69
 
                                raise Failure('This OS does not support TCP_MD5SIG, you can not use MD5 : %s' % str(e))
70
 
 
71
 
                # None (ttl-security unset) or zero (maximum TTL) is the same thing
72
 
                if ttl:
73
 
                        try:
74
 
                                self.io.setsockopt(socket.IPPROTO_IP,socket.IP_TTL, 20)
75
 
                        except socket.error,e:
76
 
                                self.close()
77
 
                                raise Failure('This OS does not support IP_TTL (ttl-security), you can not use MD5 : %s' % str(e))
78
 
 
79
 
                try:
80
 
                        if peer.afi == AFI.ipv4:
81
 
                                self.io.connect((peer.ip,179))
82
 
                        if peer.afi == AFI.ipv6:
83
 
                                self.io.connect((peer.ip,179,0,0))
84
 
                        self.io.setblocking(0)
85
 
                except socket.error, e:
86
 
                        self.close()
87
 
                        raise Failure('Could not connect to peer (if you use MD5, check your passwords): %s' % str(e))
88
 
 
89
 
        def pending (self):
90
 
                r,_,_ = select.select([self.io,],[],[],0)
91
 
                if r: return True
92
 
                return False
93
 
 
94
 
        # File like interface
95
 
 
96
 
        def read (self,number):
97
 
                if number == 0: return ''
98
 
                try:
99
 
                        r = self.io.recv(number)
100
 
                        self.last_read = time.time()
101
 
                        logger.wire(LazyFormat("%15s RECV " % self.peer,hexa,r))
102
 
                        return r
103
 
                except socket.timeout,e:
104
 
                        self.close()
105
 
                        raise Failure('Timeout while reading data from the network:  %s ' % str(e))
106
 
                except socket.error,e:
107
 
                        self.close()
108
 
                        raise Failure('Problem while reading data from the network:  %s ' % str(e))
109
 
 
110
 
        def write (self,data):
111
 
                try:
112
 
                        logger.wire(LazyFormat("%15s SENT " % self.peer,hexa,data))
113
 
                        r = self.io.send(data)
114
 
                        self.last_write = time.time()
115
 
                        return r
116
 
                except socket.error, e:
117
 
                        # Broken pipe, we ignore as we want to make sure if there is data to read before failing
118
 
                        if getattr(e,'errno',None) != 32:
119
 
                                self.close()
120
 
                                logger.wire("%15s %s" % (self.peer,trace()))
121
 
                                raise Failure('Problem while writing data to the network: %s' % str(e))
122
 
 
123
 
        def close (self):
124
 
                try:
125
 
                        logger.wire("Closing connection to %s" % self.peer)
126
 
                        self.io.close()
127
 
                except socket.error:
128
 
                        pass
129