View Javadoc
1   /*
2    * Copyright 2015 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.unix;
17  
18  import java.net.Inet6Address;
19  import java.net.InetAddress;
20  import java.net.InetSocketAddress;
21  import java.net.UnknownHostException;
22  
23  /**
24   * <strong>Internal usage only!</strong>
25   */
26  public final class NativeInetAddress {
27      private static final byte[] IPV4_MAPPED_IPV6_PREFIX = {
28              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff };
29      final byte[] address;
30      final int scopeId;
31  
32      public static NativeInetAddress newInstance(InetAddress addr) {
33          byte[] bytes = addr.getAddress();
34          if (addr instanceof Inet6Address) {
35              return new NativeInetAddress(bytes, ((Inet6Address) addr).getScopeId());
36          } else {
37              // convert to ipv4 mapped ipv6 address;
38              return new NativeInetAddress(ipv4MappedIpv6Address(bytes));
39          }
40      }
41  
42      public NativeInetAddress(byte[] address, int scopeId) {
43          this.address = address;
44          this.scopeId = scopeId;
45      }
46  
47      public NativeInetAddress(byte[] address) {
48          this(address, 0);
49      }
50  
51      public byte[] address() {
52          return address;
53      }
54  
55      public int scopeId() {
56          return scopeId;
57      }
58  
59      public static byte[] ipv4MappedIpv6Address(byte[] ipv4) {
60          byte[] address = new byte[16];
61          copyIpv4MappedIpv6Address(ipv4, address);
62          return address;
63      }
64  
65      public static void copyIpv4MappedIpv6Address(byte[] ipv4, byte[] ipv6) {
66          System.arraycopy(IPV4_MAPPED_IPV6_PREFIX, 0, ipv6, 0, IPV4_MAPPED_IPV6_PREFIX.length);
67          System.arraycopy(ipv4, 0, ipv6, 12, ipv4.length);
68      }
69  
70      public static InetSocketAddress address(byte[] addr, int offset, int len) {
71          // The last 4 bytes are always the port
72          final int port = decodeInt(addr, offset + len - 4);
73          final InetAddress address;
74  
75          try {
76              switch (len) {
77                  // 8 bytes:
78                  // - 4  == ipaddress
79                  // - 4  == port
80                  case 8:
81                      byte[] ipv4 = new byte[4];
82                      System.arraycopy(addr, offset, ipv4, 0, 4);
83                      address = InetAddress.getByAddress(ipv4);
84                      break;
85  
86                  // 24 bytes:
87                  // - 16  == ipaddress
88                  // - 4   == scopeId
89                  // - 4   == port
90                  case 24:
91                      byte[] ipv6 = new byte[16];
92                      System.arraycopy(addr, offset, ipv6, 0, 16);
93                      int scopeId = decodeInt(addr, offset + len  - 8);
94                      address = Inet6Address.getByAddress(null, ipv6, scopeId);
95                      break;
96                  default:
97                      throw new Error();
98              }
99              return new InetSocketAddress(address, port);
100         } catch (UnknownHostException e) {
101             throw new Error("Should never happen", e);
102         }
103     }
104 
105     static int decodeInt(byte[] addr, int index) {
106         return  (addr[index]     & 0xff) << 24 |
107                 (addr[index + 1] & 0xff) << 16 |
108                 (addr[index + 2] & 0xff) <<  8 |
109                 addr[index + 3] & 0xff;
110     }
111 }