|
| 1 | +#!/usr/bin/env python3 |
| 2 | +""" |
| 3 | +Tag-only protocol examples for py-multiaddr. |
| 4 | +
|
| 5 | +This script demonstrates how to work with tag-only protocols in py-multiaddr. |
| 6 | +Tag-only protocols are protocols that do not accept values - their presence |
| 7 | +alone indicates a specific property or capability (e.g., ``/http``, ``/tls``, |
| 8 | +``/noise``). |
| 9 | +
|
| 10 | +## Overview |
| 11 | +
|
| 12 | +This script shows various examples of tag-only protocol usage: |
| 13 | +
|
| 14 | +1. **Basic Tag-Only Protocol Usage**: Creating and parsing simple tag-only addresses. |
| 15 | +2. **Protocol Validation**: Testing valid and invalid tag-only protocol syntax. |
| 16 | +3. **Error Handling**: Demonstrating clear error messages for invalid value assignments. |
| 17 | +4. **Multiaddr Integration**: Using tag-only protocols in realistic multiaddr stacks. |
| 18 | +5. **Common Tag-Only Protocols**: Examples with various tag-only protocols. |
| 19 | +
|
| 20 | +## Expected Output |
| 21 | +
|
| 22 | +When you run this script, you should see output similar to: |
| 23 | +
|
| 24 | +``` |
| 25 | +Tag-Only Protocol Examples |
| 26 | +================================================== |
| 27 | +=== Basic Tag-Only Protocol Usage === |
| 28 | +Valid tag-only addresses: |
| 29 | + /http |
| 30 | + /https |
| 31 | + /tls |
| 32 | + /noise |
| 33 | + /webrtc |
| 34 | +
|
| 35 | +=== Protocol Validation === |
| 36 | +Testing valid tag-only: /http |
| 37 | + Valid: True |
| 38 | + Protocols: ['http'] |
| 39 | +
|
| 40 | +Testing invalid tag-only (with value): /http/value |
| 41 | + Valid: False |
| 42 | + Error: Protocol 'http' does not take an argument |
| 43 | +
|
| 44 | +Testing invalid tag-only (= syntax): /http=value |
| 45 | + Valid: False |
| 46 | + Error: Protocol 'http' does not take an argument |
| 47 | +
|
| 48 | +=== Multiaddr Integration === |
| 49 | +Complex multiaddr with tag-only protocols: |
| 50 | + Address: /ip4/127.0.0.1/tcp/443/https |
| 51 | + Protocols: ['ip4', 'tcp', 'https'] |
| 52 | + Has 'https' protocol: True |
| 53 | +
|
| 54 | +=== Common Tag-Only Protocols === |
| 55 | +HTTP: /ip4/127.0.0.1/tcp/80/http |
| 56 | +HTTPS: /ip4/127.0.0.1/tcp/443/https |
| 57 | +TLS: /ip4/127.0.0.1/tcp/443/tls |
| 58 | +WebRTC: /ip4/127.0.0.1/udp/9090/webrtc-direct |
| 59 | +Noise: /ip4/127.0.0.1/tcp/12345/noise |
| 60 | +
|
| 61 | +================================================== |
| 62 | +All examples completed! |
| 63 | +``` |
| 64 | +
|
| 65 | +## Key Features Demonstrated |
| 66 | +
|
| 67 | +- **Tag-Only Protocols**: Protocols that don't accept values (http, https, tls, noise, webrtc, etc.) |
| 68 | +- **Validation**: Ensures no value is provided to tag-only protocols |
| 69 | +- **Error Messages**: Clear error messages that don't include invalid values |
| 70 | +- **Multiaddr Integration**: Using tag-only protocols as part of connection stacks |
| 71 | +- **Syntax Validation**: Both ``/tag/value`` and ``/tag=value`` syntaxes are rejected |
| 72 | +
|
| 73 | +## Requirements |
| 74 | +
|
| 75 | +- Python 3.10+ |
| 76 | +- py-multiaddr library |
| 77 | +
|
| 78 | +## Usage |
| 79 | +
|
| 80 | +```bash |
| 81 | +python examples/tag_only/tag_only_examples.py |
| 82 | +``` |
| 83 | +""" |
| 84 | + |
| 85 | +from multiaddr import Multiaddr |
| 86 | +from multiaddr.exceptions import StringParseError |
| 87 | + |
| 88 | +# Common tag-only protocols |
| 89 | +TAG_ONLY_PROTOCOLS = [ |
| 90 | + "http", |
| 91 | + "https", |
| 92 | + "tls", |
| 93 | + "noise", |
| 94 | + "webrtc", |
| 95 | + "webrtc-direct", |
| 96 | + "quic", |
| 97 | + "quic-v1", |
| 98 | + "ws", |
| 99 | + "wss", |
| 100 | + "p2p-circuit", |
| 101 | + "webtransport", |
| 102 | +] |
| 103 | + |
| 104 | + |
| 105 | +def basic_tag_only_usage(): |
| 106 | + """ |
| 107 | + Basic tag-only protocol usage example. |
| 108 | +
|
| 109 | + This function demonstrates: |
| 110 | + - Creating tag-only multiaddrs |
| 111 | + - Extracting protocol information |
| 112 | + - Validating tag-only addresses |
| 113 | + """ |
| 114 | + print("=== Basic Tag-Only Protocol Usage ===") |
| 115 | + print("Valid tag-only addresses:") |
| 116 | + |
| 117 | + for proto_name in TAG_ONLY_PROTOCOLS[:5]: # Show first 5 |
| 118 | + addr_str = f"/{proto_name}" |
| 119 | + try: |
| 120 | + _ = Multiaddr(addr_str) # Validate the address |
| 121 | + print(f" {addr_str}") |
| 122 | + except Exception as e: |
| 123 | + print(f" {addr_str} - Error: {e}") |
| 124 | + |
| 125 | + |
| 126 | +def protocol_validation(): |
| 127 | + """ |
| 128 | + Demonstrate protocol validation for tag-only protocols. |
| 129 | +
|
| 130 | + This function shows: |
| 131 | + - Valid tag-only addresses |
| 132 | + - Invalid tag-only addresses with /tag/value syntax |
| 133 | + - Invalid tag-only addresses with /tag=value syntax |
| 134 | + - Error handling for validation failures |
| 135 | + """ |
| 136 | + print("\n=== Protocol Validation ===") |
| 137 | + |
| 138 | + # Test valid tag-only protocol |
| 139 | + valid_addr = "/http" |
| 140 | + print(f"Testing valid tag-only: {valid_addr}") |
| 141 | + try: |
| 142 | + ma = Multiaddr(valid_addr) |
| 143 | + print(" Valid: True") |
| 144 | + print(f" Protocols: {[p.name for p in ma.protocols()]}") |
| 145 | + except Exception as e: |
| 146 | + print(" Valid: False") |
| 147 | + print(f" Error: {e}") |
| 148 | + |
| 149 | + # Test invalid tag-only with /tag/value syntax |
| 150 | + invalid_addr_slash = "/http/value" |
| 151 | + print(f"\nTesting invalid tag-only (with value): {invalid_addr_slash}") |
| 152 | + try: |
| 153 | + Multiaddr(invalid_addr_slash) |
| 154 | + print(" Valid: True (ERROR: Should have failed)") |
| 155 | + except StringParseError as e: |
| 156 | + print(" Valid: False") |
| 157 | + print(f" Error: {e}") |
| 158 | + # Verify error message doesn't include the invalid value |
| 159 | + error_str = str(e) |
| 160 | + assert "value" not in error_str or "does not take an argument" in error_str |
| 161 | + |
| 162 | + # Test invalid tag-only with /tag=value syntax |
| 163 | + invalid_addr_equals = "/http=value" |
| 164 | + print(f"\nTesting invalid tag-only (= syntax): {invalid_addr_equals}") |
| 165 | + try: |
| 166 | + Multiaddr(invalid_addr_equals) |
| 167 | + print(" Valid: True (ERROR: Should have failed)") |
| 168 | + except StringParseError as e: |
| 169 | + print(" Valid: False") |
| 170 | + print(f" Error: {e}") |
| 171 | + |
| 172 | + |
| 173 | +def multiaddr_integration(): |
| 174 | + """ |
| 175 | + Demonstrate tag-only protocol integration with other protocols. |
| 176 | +
|
| 177 | + This function shows: |
| 178 | + - Using tag-only protocols as part of realistic multiaddr stacks |
| 179 | + - Protocol stack analysis |
| 180 | + - Common use cases |
| 181 | + """ |
| 182 | + print("\n=== Multiaddr Integration ===") |
| 183 | + |
| 184 | + # HTTPS example |
| 185 | + https_addr = "/ip4/127.0.0.1/tcp/443/https" |
| 186 | + print("Complex multiaddr with tag-only protocols:") |
| 187 | + print(f" Address: {https_addr}") |
| 188 | + |
| 189 | + try: |
| 190 | + ma = Multiaddr(https_addr) |
| 191 | + protocols = [p.name for p in ma.protocols()] |
| 192 | + print(f" Protocols: {protocols}") |
| 193 | + |
| 194 | + # Check for 'https' protocol |
| 195 | + has_https = "https" in protocols |
| 196 | + print(f" Has 'https' protocol: {has_https}") |
| 197 | + |
| 198 | + except Exception as e: |
| 199 | + print(f" Error: {e}") |
| 200 | + |
| 201 | + |
| 202 | +def common_tag_only_protocols(): |
| 203 | + """ |
| 204 | + Demonstrate common tag-only protocol use cases. |
| 205 | +
|
| 206 | + This function shows: |
| 207 | + - HTTP and HTTPS usage |
| 208 | + - TLS usage |
| 209 | + - WebRTC usage |
| 210 | + - Noise protocol usage |
| 211 | + """ |
| 212 | + print("\n=== Common Tag-Only Protocols ===") |
| 213 | + |
| 214 | + examples = [ |
| 215 | + ("HTTP", "/ip4/127.0.0.1/tcp/80/http"), |
| 216 | + ("HTTPS", "/ip4/127.0.0.1/tcp/443/https"), |
| 217 | + ("TLS", "/ip4/127.0.0.1/tcp/443/tls"), |
| 218 | + ("WebRTC", "/ip4/127.0.0.1/udp/9090/webrtc-direct"), |
| 219 | + ("Noise", "/ip4/127.0.0.1/tcp/12345/noise"), |
| 220 | + ] |
| 221 | + |
| 222 | + for name, addr_str in examples: |
| 223 | + try: |
| 224 | + _ = Multiaddr(addr_str) # Validate the address |
| 225 | + print(f"{name}: {addr_str}") |
| 226 | + except Exception as e: |
| 227 | + print(f"{name}: {addr_str} - Error: {e}") |
| 228 | + |
| 229 | + |
| 230 | +def chaining_tag_only_protocols(): |
| 231 | + """ |
| 232 | + Demonstrate chaining multiple tag-only protocols. |
| 233 | +
|
| 234 | + This function shows: |
| 235 | + - Multiple tag-only protocols in sequence |
| 236 | + - Valid combinations |
| 237 | + - Protocol stack analysis |
| 238 | + """ |
| 239 | + print("\n=== Chaining Tag-Only Protocols ===") |
| 240 | + |
| 241 | + examples = [ |
| 242 | + "/webrtc/noise", |
| 243 | + "/webrtc-direct/webrtc", |
| 244 | + "/tls/http", |
| 245 | + ] |
| 246 | + |
| 247 | + for addr_str in examples: |
| 248 | + try: |
| 249 | + ma = Multiaddr(addr_str) |
| 250 | + protocols = [p.name for p in ma.protocols()] |
| 251 | + print(f" {addr_str}") |
| 252 | + print(f" Protocols: {protocols}") |
| 253 | + except Exception as e: |
| 254 | + print(f" {addr_str} - Error: {e}") |
| 255 | + |
| 256 | + |
| 257 | +def main(): |
| 258 | + """ |
| 259 | + Run all tag-only protocol examples. |
| 260 | +
|
| 261 | + This function orchestrates all the tag-only protocol examples: |
| 262 | + 1. Basic tag-only usage |
| 263 | + 2. Protocol validation |
| 264 | + 3. Multiaddr integration |
| 265 | + 4. Common tag-only protocols |
| 266 | + 5. Chaining tag-only protocols |
| 267 | +
|
| 268 | + Each example demonstrates different aspects of tag-only protocol |
| 269 | + functionality and shows how to use them with py-multiaddr. |
| 270 | + """ |
| 271 | + print("Tag-Only Protocol Examples") |
| 272 | + print("=" * 50) |
| 273 | + |
| 274 | + try: |
| 275 | + basic_tag_only_usage() |
| 276 | + protocol_validation() |
| 277 | + multiaddr_integration() |
| 278 | + common_tag_only_protocols() |
| 279 | + chaining_tag_only_protocols() |
| 280 | + |
| 281 | + print("\n" + "=" * 50) |
| 282 | + print("All examples completed!") |
| 283 | + print("\nSummary:") |
| 284 | + print("- Tag-only protocols work correctly") |
| 285 | + print("- Validation catches invalid use (with values)") |
| 286 | + print("- Both /tag/value and /tag=value syntaxes are rejected") |
| 287 | + print("- Integration with other protocols works as expected") |
| 288 | + print("- Multiple tag-only protocols can be chained") |
| 289 | + |
| 290 | + except KeyboardInterrupt: |
| 291 | + print("\nExamples interrupted by user") |
| 292 | + except Exception as e: |
| 293 | + print(f"\nUnexpected error: {e}") |
| 294 | + |
| 295 | + |
| 296 | +if __name__ == "__main__": |
| 297 | + main() |
0 commit comments