instrumentation: add next-share/
[cs-p2p-next.git] / instrumentation / next-share / BaseLib / Core / NATFirewall / NatTraversal.py
1 from time import strftime
2 from traceback import print_exc
3 import socket
4 import sys
5
6 DEBUG = False
7
8 def coordinateHolePunching(peer1, peer2, holePunchingAddr):
9
10     if DEBUG:
11         print >> sys.stderr, "NatTraversal: coordinateHolePunching at", holePunchingAddr
12
13     # Set up the sockets
14     try :
15         udpsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
16         udpsock.bind(holePunchingAddr)
17         udpsock.settimeout(60)
18
19     except socket.error, (errno, strerror) :
20
21         if udpsock :
22             udpsock.close()
23
24         if DEBUG:
25             print >> sys.stderr, "NatTraversal: Could not open socket: %s" % (strerror)
26
27         return
28
29     if DEBUG:
30         print >> sys.stderr, "NatTraversal: waiting for connection..."
31
32     # Receive messages
33     peeraddr2 = None
34     while True:
35
36         try:
37             data, peeraddr1 = udpsock.recvfrom(1024)
38             if not data:
39                 continue
40             else:
41                 if DEBUG:
42                     print >> sys.stderr, "NatTraversal:", strftime("%Y/%m/%d %H:%M:%S"), "...connected from: ", peeraddr1
43                 if peeraddr2 == None:
44                     peeraddr2 = peeraddr1
45                 elif peeraddr2 != peeraddr1:        
46                     udpsock.sendto(peeraddr1[0] + ":" + str(peeraddr1[1]), peeraddr2)
47                     udpsock.sendto(peeraddr1[0] + ":" + str(peeraddr1[1]), peeraddr2)
48                     udpsock.sendto(peeraddr1[0] + ":" + str(peeraddr1[1]), peeraddr2)
49                     udpsock.sendto(peeraddr2[0] + ":" + str(peeraddr2[1]), peeraddr1)
50                     udpsock.sendto(peeraddr2[0] + ":" + str(peeraddr2[1]), peeraddr1)
51                     udpsock.sendto(peeraddr2[0] + ":" + str(peeraddr2[1]), peeraddr1)
52                     break
53
54         except socket.timeout, error:
55             if DEBUG:
56                 print >> sys.stderr, "NatTraversal: timeout with peers", error
57             udpsock.close()
58             break
59
60     # Close socket
61     udpsock.close()
62
63 def tryConnect(coordinator):
64     
65     # Set up the socket
66     udpsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
67     udpsock.settimeout(5)
68
69     # Send messages
70     udpsock.sendto("ping",coordinator)
71     udpsock.sendto("ping",coordinator)
72     udpsock.sendto("ping",coordinator)
73     if DEBUG:
74         print >> sys.stderr, "NatTraversal: sending ping to ", coordinator
75
76     # Wait for response from the coordinator
77
78     while True:
79         data = None
80         addr = None
81         try:
82             data, addr = udpsock.recvfrom(1024)
83         except socket.timeout, (strerror):
84             if DEBUG:
85                 print >> sys.stderr, "NatTraversal: timeout with coordinator"
86             return "ERR"
87
88         if addr == coordinator:
89             if DEBUG:
90                 print >> sys.stderr, "NatTraversal: received", data, "from coordinator"
91             break
92
93         if DEBUG:
94             print >> sys.stderr, "NatTraversal: received", data, "from", addr
95             
96     #success = False
97     #try:
98     #    host, port = data.split(":")
99     #except:
100     #    print_exc()
101     #    print >> sys.stderr, "NatCheckMsgHandler: error in received data:", data
102     #    return success
103     # peer = (host, int(port))
104     # for i in range(3):
105     #     udpsock.sendto("hello",peer)
106     #     udpsock.sendto("hello",peer)
107     #     udpsock.sendto("hello",peer)
108
109     #     try:
110     #         data, addr = udpsock.recvfrom(1024)
111
112     #     except socket.timeout, (strerror):
113     #         if DEBUG:
114     #             print >> sys.stderr, "NatTraversal: first timeout", strerror
115     #             print >> sys.stderr, "NatTraversal: resend"
116
117     #     else:
118     #         success = True
119     #         break
120
121     try:
122         host, port = data.split(":")
123     except:
124         print_exc()
125         print >> sys.stderr, "NatCheckMsgHandler: error in received data:", data
126         return "ERR"
127
128     peer = (host, int(port))
129     udpsock.sendto("hello",peer)
130     udpsock.sendto("hello",peer)
131     udpsock.sendto("hello",peer)
132
133     # Wait for response
134     data = None
135     addr = None
136
137     while True:
138         try:
139             data, addr = udpsock.recvfrom(1024)
140         except socket.timeout, (strerror):
141             if DEBUG:
142                 print >> sys.stderr, "NatTraversal: first timeout", strerror
143                 print >> sys.stderr, "NatTraversal: resend"
144
145             udpsock.sendto("hello", peer)
146             udpsock.sendto("hello", peer)
147             udpsock.sendto("hello", peer)
148
149             try:
150                 data, addr = udpsock.recvfrom(1024)
151             except socket.timeout, (strerror):
152                 if DEBUG:
153                     print >> sys.stderr, "NatTraversal: second timeout", strerror
154
155                 return "NO"
156
157         # data received, check address
158         if addr == peer: # peer is not symmetric NAT
159             break
160
161         if addr[0] == peer[0]: # peer has a symmetric NAT
162             peer = addr
163             break
164
165         
166     udpsock.sendto("hello",peer)
167     udpsock.sendto("hello",peer)
168     udpsock.sendto("hello",peer)
169
170     # Close socket
171     udpsock.close()
172         
173     if DEBUG:
174         print >> sys.stderr, "NatTraversal: message from", addr, "is", data
175
176     return "YES"
177
178