1
1
import base58
2
2
import base64
3
- import binascii
4
3
import os
5
4
6
5
import idna
7
6
from netaddr import IPAddress
8
7
import six
8
+ import struct
9
+ import varint
9
10
10
- from .protocols import code_to_varint
11
11
from .protocols import P_DNS
12
12
from .protocols import P_DNS4
13
13
from .protocols import P_DNS6
@@ -57,7 +57,7 @@ def string_to_bytes(string):
57
57
while sp :
58
58
element = sp .pop (0 )
59
59
proto = protocol_with_name (element )
60
- bs .append (code_to_varint (proto .code ))
60
+ bs .append (varint . encode (proto .code ))
61
61
if proto .size == 0 :
62
62
continue
63
63
if len (sp ) < 1 :
@@ -71,7 +71,6 @@ def string_to_bytes(string):
71
71
72
72
def bytes_to_string (buf ):
73
73
st = ['' ] # start with empty string so we get a leading slash on join()
74
- buf = binascii .unhexlify (buf )
75
74
while buf :
76
75
maddr_component = ""
77
76
code , num_bytes_read = read_varint_code (buf )
@@ -80,7 +79,7 @@ def bytes_to_string(buf):
80
79
maddr_component += proto .name
81
80
size = size_for_addr (proto , buf )
82
81
if size > 0 :
83
- addr = address_bytes_to_string (proto , binascii . hexlify ( buf [:size ]) )
82
+ addr = address_bytes_to_string (proto , buf [:size ])
84
83
if not (proto .path and addr [0 ] == '/' ):
85
84
maddr_component += '/'
86
85
maddr_component += addr
@@ -89,47 +88,27 @@ def bytes_to_string(buf):
89
88
return '/' .join (st )
90
89
91
90
92
- int_to_hex = None
93
- encode_big_endian_16 = None
94
-
95
-
96
91
def address_string_to_bytes (proto , addr_string ):
97
- global int_to_hex
98
- if int_to_hex is None :
99
- from .util import int_to_hex
100
-
101
- global encode_big_endian_16
102
- if encode_big_endian_16 is None :
103
- from .util import encode_big_endian_16
104
-
105
92
if proto .code == P_IP4 : # ipv4
106
93
try :
107
- ip = IPAddress (addr_string )
108
- if ip .version != 4 :
109
- raise ValueError ("failed to parse ip4 addr: %s" % addr_string )
110
- return int_to_hex (int (ip ), 8 )
94
+ return IPAddress (addr_string , version = 4 ).packed
111
95
except Exception :
112
96
raise ValueError ("failed to parse ip4 addr: %s" % addr_string )
113
97
elif proto .code == P_IP6 : # ipv6
114
98
try :
115
- ip = IPAddress (addr_string )
116
- if ip .version != 6 :
117
- raise ValueError ("failed to parse ip6 addr: %s" % addr_string )
118
- return int_to_hex (int (ip ), 32 )
99
+ return IPAddress (addr_string , version = 6 ).packed
119
100
except Exception :
120
101
raise ValueError ("failed to parse ip6 addr: %s" % addr_string )
121
102
# tcp udp dccp sctp
122
103
elif proto .code in [P_TCP , P_UDP , P_DCCP , P_SCTP ]:
123
104
try :
124
- ip = int (addr_string )
105
+ return struct . pack ( '>H' , int (addr_string , 10 ) )
125
106
except ValueError as ex :
126
107
raise ValueError ("failed to parse %s addr: %s"
127
108
% (proto .name , str (ex )))
128
-
129
- if ip >= 65536 :
109
+ except struct .error :
130
110
raise ValueError ("failed to parse %s addr: %s" %
131
111
(proto .name , "greater than 65536" ))
132
- return binascii .hexlify (encode_big_endian_16 (ip ))
133
112
elif proto .code == P_ONION :
134
113
addr = addr_string .split (":" )
135
114
if len (addr ) != 2 :
@@ -143,8 +122,7 @@ def address_string_to_bytes(proto, addr_string):
143
122
"failed to parse %s addr: %s not a Tor onion address."
144
123
% (proto .name , addr_string ))
145
124
try :
146
- onion_host_bytes = binascii .hexlify (
147
- base64 .b32decode (addr [0 ].upper ()))
125
+ onion_host_bytes = base64 .b32decode (addr [0 ].upper ())
148
126
except Exception as ex :
149
127
raise ValueError (
150
128
"failed to decode base32 %s addr: %s %s"
@@ -163,8 +141,7 @@ def address_string_to_bytes(proto, addr_string):
163
141
raise ValueError ("failed to parse %s addr: %s"
164
142
% (proto .name , "port less than 1" ))
165
143
166
- return b'' .join ([onion_host_bytes ,
167
- binascii .hexlify (encode_big_endian_16 (port ))])
144
+ return b'' .join ([onion_host_bytes , struct .pack ('>H' , port )])
168
145
elif proto .code == P_P2P : # ipfs
169
146
# the address is a varint prefixed multihash string representation
170
147
try :
@@ -174,74 +151,69 @@ def address_string_to_bytes(proto, addr_string):
174
151
except Exception as ex :
175
152
raise ValueError ("failed to parse p2p addr: %s %s"
176
153
% (addr_string , str (ex )))
177
- size = code_to_varint (len (mm ))
178
- mm = binascii .hexlify (mm )
179
- if len (mm ) < 10 :
154
+ size = varint .encode (len (mm ))
155
+ if len (mm ) < 5 :
180
156
# TODO - port go-multihash so we can do this correctly
181
157
raise ValueError ("invalid P2P multihash: %s" % mm )
182
158
return b'' .join ([size , mm ])
183
159
elif proto .code == P_UNIX :
184
160
addr_string_bytes = fsencode (addr_string )
185
- size = code_to_varint (len (addr_string_bytes ))
186
- return b'' .join ([size , binascii . hexlify ( addr_string_bytes ) ])
161
+ size = varint . encode (len (addr_string_bytes ))
162
+ return b'' .join ([size , addr_string_bytes ])
187
163
elif proto .code in (P_DNS , P_DNS4 , P_DNS6 ):
188
164
addr_string_bytes = idna .encode (addr_string , uts46 = True )
189
- size = code_to_varint (len (addr_string_bytes ))
190
- return b'' .join ([size , binascii . hexlify ( addr_string_bytes ) ])
165
+ size = varint . encode (len (addr_string_bytes ))
166
+ return b'' .join ([size , addr_string_bytes ])
191
167
else :
192
168
raise ValueError ("failed to parse %s addr: unknown" % proto .name )
193
169
194
170
195
- decode_big_endian_16 = None
171
+ packed_net_bytes_to_int = None
196
172
197
173
198
174
def address_bytes_to_string (proto , buf ):
199
- global decode_big_endian_16
200
- if decode_big_endian_16 is None :
201
- from .util import decode_big_endian_16
175
+ global packed_net_bytes_to_int
176
+ if packed_net_bytes_to_int is None :
177
+ from .util import packed_net_bytes_to_int
178
+
202
179
if proto .code == P_IP4 :
203
- return str (IPAddress (int (buf , 16 ), 4 ). ipv4 ( ))
180
+ return six . text_type (IPAddress (packed_net_bytes_to_int (buf ), 4 ))
204
181
elif proto .code == P_IP6 :
205
- return str (IPAddress (int (buf , 16 ), 6 ). ipv6 ( ))
182
+ return six . text_type (IPAddress (packed_net_bytes_to_int (buf ), 6 ))
206
183
elif proto .code in [P_TCP , P_UDP , P_DCCP , P_SCTP ]:
207
- return str (decode_big_endian_16 (binascii .unhexlify (buf )))
184
+ if len (buf ) != 2 :
185
+ raise ValueError ("Not a uint16" )
186
+ return six .text_type (struct .unpack ('>H' , buf )[0 ])
208
187
elif proto .code == P_ONION :
209
- buf = binascii .unhexlify (buf )
210
188
addr_bytes , port_bytes = (buf [:- 2 ], buf [- 2 :])
211
189
addr = base64 .b32encode (addr_bytes ).decode ('ascii' ).lower ()
212
- port = str ( decode_big_endian_16 ( port_bytes ))
213
- return ':' .join ([addr , port ])
190
+ port = six . text_type ( struct . unpack ( '>H' , port_bytes )[ 0 ] )
191
+ return u ':' .join ([addr , port ])
214
192
elif proto .code == P_P2P :
215
- buf = binascii .unhexlify (buf )
216
193
size , num_bytes_read = read_varint_code (buf )
217
194
buf = buf [num_bytes_read :]
218
195
if len (buf ) != size :
219
196
raise ValueError ("inconsistent lengths" )
220
- return base58 .b58encode (buf ).decode ()
197
+ return base58 .b58encode (buf ).decode ('ascii' )
221
198
elif proto .code == P_UNIX :
222
- buf = binascii .unhexlify (buf )
223
199
size , num_bytes_read = read_varint_code (buf )
224
200
return fsdecode (buf [num_bytes_read :])
225
201
elif proto .code in (P_DNS , P_DNS4 , P_DNS6 ):
226
- buf = binascii .unhexlify (buf )
227
202
size , num_bytes_read = read_varint_code (buf )
228
203
return idna .decode (buf [num_bytes_read :])
229
204
raise ValueError ("unknown protocol" )
230
205
231
206
232
207
def size_for_addr (proto , buf ):
233
- if proto .size > 0 :
208
+ if proto .size >= 0 :
234
209
return proto .size // 8
235
- elif proto .size == 0 :
236
- return 0
237
210
else :
238
211
size , num_bytes_read = read_varint_code (buf )
239
212
return size + num_bytes_read
240
213
241
214
242
215
def bytes_split (buf ):
243
216
ret = []
244
- buf = binascii .unhexlify (buf )
245
217
while buf :
246
218
code , num_bytes_read = read_varint_code (buf )
247
219
proto = protocol_with_code (code )
0 commit comments