This crate provides a simple but high effective framework to manage STUN protocol messages. The implementation is based on:
* RFC8489
. Session Traversal Utilities for NAT (STUN).
* RFC8445
. Interactive Connectivity Establishment (ICE).
* RFC8656
. Traversal Using Relays around NAT (TURN)
* RFC5769
. Test Vectors for Session Traversal Utilities for NAT (STUN).
Example that creates and encodes a STUN Binding request ```rust // Create attributes let username = UserName::new("\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}")?; let nonce = Nonce::new("f//499k954d6OL34oL9FSTvy64sA")?; let realm = Realm::new("example.org")?; let password = "TheMatrIX"; let algorithm = Algorithm::from(AlgorithmId::MD5); let key = HMACKey::newlongterm(&username, &realm, password, algorithm)?; let integrity = MessageIntegrity::new(key);
// Create the message let msg = StunMessageBuilder::new( BINDING, MessageClass::Request, ) .withattribute(username) .withattribute(nonce) .withattribute(realm) .withattribute(integrity) .build();
// Create an encoder to encode the message into a buffer let encoder = MessageEncoderBuilder::default().build(); let mut buffer: [u8; 150] = [0x00; 150]; let size = encoder.encode(&mut buffer, &msg)?; assert_eq!(size, 116); ```
Example that decodes a STUN Binding response and fetches some attributes.
``rust
// This response uses the following parameter:
// Password:
VOkJxbRl1RmTxUk/WvJxBt` (without quotes)
// Software name: "test vector" (without quotes)
// Mapped address: 192.0.2.1 port 32853
let sampleipv4response = [
0x01, 0x01, 0x00, 0x3c, // Response type and message length
0x21, 0x12, 0xa4, 0x42, // Magic cookie
0xb7, 0xe7, 0xa7, 0x01, // }
0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
0xfa, 0x87, 0xdf, 0xae, // }
0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
0x74, 0x65, 0x73, 0x74, // }
0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
0x74, 0x6f, 0x72, 0x20, // }
0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port number
0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY header
0x2b, 0x91, 0xf5, 0x99, // }
0xfd, 0x9e, 0x90, 0xc3, // }
0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
0x2a, 0xf9, 0xba, 0x53, // }
0xf0, 0x6b, 0xe7, 0xd7, // }
0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
0xc0, 0x7d, 0x4c, 0x96, // Reserved for CRC32 fingerprint
];
// Create a STUN decoder context using the password as a short credential // mechanism and force validation of MESSAGE-INTEGRITY and FINGERPRINT let ctx = DecoderContextBuilder::default() .withkey( HMACKey::newshortterm("VOkJxbRl1RmTxUk/WvJxBt")?, ) .withvalidation() .build(); let decoder = MessageDecoderBuilder::default().with_context(ctx).build();
let (msg, size) = decoder.decode(&sampleipv4response)?; asserteq!(size, sampleipv4_response.len());
// Check message method is a BINDING response asserteq!(msg.method(), BINDING); asserteq!(msg.class(), MessageClass::SuccessResponse);
let software = msg.get::
let xoraddr = msg.get::
Patches and feedback are welcome.
If you find this project helpful, you may consider making a donation:
This project is licensed under either of * Apache License, Version 2.0 * MIT license