@@ -72,13 +72,46 @@ async def run(port: int, destination: str, use_varint_format: bool = True) -> No
72
72
client_addr = server_addr .replace ("/ip4/0.0.0.0/" , "/ip4/127.0.0.1/" )
73
73
74
74
format_name = "length-prefixed" if use_varint_format else "raw protobuf"
75
+ format_flag = "--raw-format" if not use_varint_format else ""
75
76
print (
76
77
f"First host listening (using { format_name } format). "
77
78
f"Run this from another console:\n \n "
78
- f"identify-demo "
79
- f"-d { client_addr } \n "
79
+ f"identify-demo { format_flag } -d { client_addr } \n "
80
80
)
81
81
print ("Waiting for incoming identify request..." )
82
+
83
+ # Add a custom handler to show connection events
84
+ async def custom_identify_handler (stream ):
85
+ peer_id = stream .muxed_conn .peer_id
86
+ print (f"\n 🔗 Received identify request from peer: { peer_id } " )
87
+
88
+ # Show remote address in multiaddr format
89
+ try :
90
+ from libp2p .identity .identify .identify import (
91
+ _remote_address_to_multiaddr ,
92
+ )
93
+
94
+ remote_address = stream .get_remote_address ()
95
+ if remote_address :
96
+ observed_multiaddr = _remote_address_to_multiaddr (
97
+ remote_address
98
+ )
99
+ # Add the peer ID to create a complete multiaddr
100
+ complete_multiaddr = f"{ observed_multiaddr } /p2p/{ peer_id } "
101
+ print (f" Remote address: { complete_multiaddr } " )
102
+ else :
103
+ print (f" Remote address: { remote_address } " )
104
+ except Exception :
105
+ print (f" Remote address: { stream .get_remote_address ()} " )
106
+
107
+ # Call the original handler
108
+ await identify_handler (stream )
109
+
110
+ print (f"✅ Successfully processed identify request from { peer_id } " )
111
+
112
+ # Replace the handler with our custom one
113
+ host_a .set_stream_handler (IDENTIFY_PROTOCOL_ID , custom_identify_handler )
114
+
82
115
await trio .sleep_forever ()
83
116
84
117
else :
@@ -93,25 +126,99 @@ async def run(port: int, destination: str, use_varint_format: bool = True) -> No
93
126
info = info_from_p2p_addr (maddr )
94
127
print (f"Second host connecting to peer: { info .peer_id } " )
95
128
96
- await host_b .connect (info )
129
+ try :
130
+ await host_b .connect (info )
131
+ except Exception as e :
132
+ error_msg = str (e )
133
+ if "unable to connect" in error_msg or "SwarmException" in error_msg :
134
+ print (f"\n ❌ Cannot connect to peer: { info .peer_id } " )
135
+ print (f" Address: { destination } " )
136
+ print (f" Error: { error_msg } " )
137
+ print (
138
+ "\n 💡 Make sure the peer is running and the address is correct."
139
+ )
140
+ return
141
+ else :
142
+ # Re-raise other exceptions
143
+ raise
144
+
97
145
stream = await host_b .new_stream (info .peer_id , (IDENTIFY_PROTOCOL_ID ,))
98
146
99
147
try :
100
148
print ("Starting identify protocol..." )
101
149
102
- # Read the complete response (could be either format)
103
- # Read a larger chunk to get all the data before stream closes
104
- response = await stream .read (8192 ) # Read enough data in one go
150
+ # Read the response properly based on the format
151
+ if use_varint_format :
152
+ # For length-prefixed format, read varint length first
153
+ from libp2p .utils .varint import decode_varint_from_bytes
154
+
155
+ # Read varint length prefix
156
+ length_bytes = b""
157
+ while True :
158
+ b = await stream .read (1 )
159
+ if not b :
160
+ raise Exception ("Stream closed while reading varint length" )
161
+ length_bytes += b
162
+ if b [0 ] & 0x80 == 0 :
163
+ break
164
+
165
+ msg_length = decode_varint_from_bytes (length_bytes )
166
+ print (f"Expected message length: { msg_length } bytes" )
167
+
168
+ # Read the protobuf message
169
+ response = await stream .read (msg_length )
170
+ if len (response ) != msg_length :
171
+ raise Exception (
172
+ f"Incomplete message: expected { msg_length } bytes, "
173
+ f"got { len (response )} "
174
+ )
175
+
176
+ # Combine length prefix and message
177
+ full_response = length_bytes + response
178
+ else :
179
+ # For raw format, read all available data
180
+ response = await stream .read (8192 )
181
+ full_response = response
105
182
106
183
await stream .close ()
107
184
108
185
# Parse the response using the robust protocol-level function
109
186
# This handles both old and new formats automatically
110
- identify_msg = parse_identify_response (response )
187
+ identify_msg = parse_identify_response (full_response )
111
188
print_identify_response (identify_msg )
112
189
113
190
except Exception as e :
114
- print (f"Identify protocol error: { e } " )
191
+ error_msg = str (e )
192
+ print (f"Identify protocol error: { error_msg } " )
193
+
194
+ # Check for specific format mismatch errors
195
+ if "Error parsing message" in error_msg or "DecodeError" in error_msg :
196
+ print ("\n " + "=" * 60 )
197
+ print ("FORMAT MISMATCH DETECTED!" )
198
+ print ("=" * 60 )
199
+ if use_varint_format :
200
+ print (
201
+ "You are using length-prefixed format (default) but the "
202
+ "listener"
203
+ )
204
+ print ("is using raw protobuf format." )
205
+ print (
206
+ "\n To fix this, run the dialer with the --raw-format flag:"
207
+ )
208
+ print (f"identify-demo --raw-format -d { destination } " )
209
+ else :
210
+ print ("You are using raw protobuf format but the listener" )
211
+ print ("is using length-prefixed format (default)." )
212
+ print (
213
+ "\n To fix this, run the dialer without the --raw-format "
214
+ "flag:"
215
+ )
216
+ print (f"identify-demo -d { destination } " )
217
+ print ("=" * 60 )
218
+ else :
219
+ import traceback
220
+
221
+ traceback .print_exc ()
115
222
116
223
return
117
224
0 commit comments