// Copyright 2016, Cong Ding. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: Cong Ding package stun import ( "net" ) // Padding the length of the byte slice to multiple of 4. func padding(bytes []byte) []byte { length := uint16(len(bytes)) return append(bytes, make([]byte, align(length)-length)...) } // Align the uint16 number to the smallest multiple of 4, which is larger than // or equal to the uint16 number. func align(n uint16) uint16 { return (n + 3) & 0xfffc } // isLocalAddress check if localRemote is a local address. func isLocalAddress(local, localRemote string) bool { // Resolve the IP returned by the STUN server first. localRemoteAddr, err := net.ResolveUDPAddr("udp", localRemote) if err != nil { return false } // Try comparing with the local address on the socket first, but only if // it's actually specified. addr, err := net.ResolveUDPAddr("udp", local) if err == nil && addr.IP != nil && !addr.IP.IsUnspecified() { return addr.IP.Equal(localRemoteAddr.IP) } // Fallback to checking IPs of all interfaces addrs, err := net.InterfaceAddrs() if err != nil { return false } for _, addr := range addrs { ip, _, err := net.ParseCIDR(addr.String()) if err != nil { continue } if ip.Equal(localRemoteAddr.IP) { return true } } return false }