001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.named.ipc; 020 021import java.io.IOException; 022import java.net.Inet6Address; 023import java.net.InetAddress; 024import java.net.InetSocketAddress; 025import java.net.SocketAddress; 026import java.net.StandardProtocolFamily; 027import java.net.UnixDomainSocketAddress; 028import java.net.UnknownHostException; 029import java.nio.channels.ServerSocketChannel; 030 031/** 032 * Socket factory. 033 * 034 * @since 2.0.1 035 */ 036public enum SocketFamily { 037 inet, 038 unix; 039 040 public ServerSocketChannel openServerSocket() throws IOException { 041 return switch (this) { 042 case inet -> ServerSocketChannel.open().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); 043 case unix -> ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(null, 0); 044 default -> throw new IllegalStateException(); 045 }; 046 } 047 048 public static SocketAddress fromString(String str) { 049 if (str.startsWith("inet:")) { 050 String s = str.substring("inet:".length()); 051 int ic = s.lastIndexOf(':'); 052 String ia = s.substring(0, ic); 053 int is = ia.indexOf('/'); 054 String h = ia.substring(0, is); 055 String a = ia.substring(is + 1); 056 String p = s.substring(ic + 1); 057 InetAddress addr; 058 if ("<unresolved>".equals(a)) { 059 return InetSocketAddress.createUnresolved(h, Integer.parseInt(p)); 060 } else { 061 if (a.indexOf('.') > 0) { 062 String[] as = a.split("\\."); 063 if (as.length != 4) { 064 throw new IllegalArgumentException("Unsupported socket address: '" + str + "'"); 065 } 066 byte[] ab = new byte[4]; 067 for (int i = 0; i < 4; i++) { 068 ab[i] = (byte) Integer.parseInt(as[i]); 069 } 070 try { 071 addr = InetAddress.getByAddress(h.isEmpty() ? null : h, ab); 072 } catch (UnknownHostException e) { 073 throw new IllegalArgumentException("Unsupported address: " + str, e); 074 } 075 } else { 076 throw new IllegalArgumentException("Unsupported address: " + str); 077 } 078 return new InetSocketAddress(addr, Integer.parseInt(p)); 079 } 080 } else if (str.startsWith("unix:")) { 081 return UnixDomainSocketAddress.of(str.substring("unix:".length())); 082 } else { 083 throw new IllegalArgumentException("Unsupported socket address: '" + str + "'"); 084 } 085 } 086 087 public static String toString(SocketAddress address) { 088 switch (familyOf(address)) { 089 case inet: 090 InetSocketAddress isa = (InetSocketAddress) address; 091 String host = isa.getHostString(); 092 InetAddress addr = isa.getAddress(); 093 int port = isa.getPort(); 094 String formatted; 095 if (addr == null) { 096 formatted = host + "/<unresolved>"; 097 } else { 098 formatted = addr.toString(); 099 if (addr instanceof Inet6Address) { 100 int i = formatted.lastIndexOf("/"); 101 formatted = formatted.substring(0, i + 1) + "[" + formatted.substring(i + 1) + "]"; 102 } 103 } 104 return "inet:" + formatted + ":" + port; 105 case unix: 106 // to keep address string unchanged across all OSes 107 return "unix:" + address.toString().replace('\\', '/'); 108 default: 109 throw new IllegalArgumentException("Unsupported socket address: '" + address + "'"); 110 } 111 } 112 113 public static SocketFamily familyOf(SocketAddress address) { 114 if (address instanceof InetSocketAddress) { 115 return SocketFamily.inet; 116 } else if ("java.net.UnixDomainSocketAddress".equals(address.getClass().getName())) { 117 return SocketFamily.unix; 118 } else { 119 throw new IllegalArgumentException("Unsupported socket address '" + address + "'"); 120 } 121 } 122}