001/** 002 * 003 * Copyright 2020-2021 Aditya Borikar, Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.websocket.rce; 018 019import java.net.InetAddress; 020import java.net.URI; 021import java.net.URISyntaxException; 022import java.net.UnknownHostException; 023import java.util.Arrays; 024import java.util.Collection; 025import java.util.List; 026import java.util.logging.Level; 027import java.util.logging.Logger; 028 029import org.jivesoftware.smack.datatypes.UInt16; 030import org.jivesoftware.smack.util.rce.RemoteConnectionEndpoint; 031 032public abstract class WebSocketRemoteConnectionEndpoint implements RemoteConnectionEndpoint { 033 034 public static final String INSECURE_WEB_SOCKET_SCHEME = "ws"; 035 public static final String SECURE_WEB_SOCKET_SCHEME = INSECURE_WEB_SOCKET_SCHEME + "s"; 036 037 private static final Logger LOGGER = Logger.getAnonymousLogger(); 038 039 private final URI uri; 040 private final UInt16 port; 041 042 protected WebSocketRemoteConnectionEndpoint(URI uri) { 043 this.uri = uri; 044 int portInt = uri.getPort(); 045 if (portInt >= 0) { 046 port = UInt16.from(portInt); 047 } else { 048 port = null; 049 } 050 } 051 052 public final URI getUri() { 053 return uri; 054 } 055 056 @Override 057 public final String getHost() { 058 return uri.getHost(); 059 } 060 061 @Override 062 public UInt16 getPort() { 063 return port; 064 } 065 066 public abstract boolean isSecureEndpoint(); 067 068 private List<? extends InetAddress> inetAddresses; 069 070 private void resolveInetAddressesIfRequired() { 071 if (inetAddresses != null) { 072 return; 073 } 074 075 String host = getHost(); 076 InetAddress[] addresses; 077 try { 078 addresses = InetAddress.getAllByName(host); 079 } catch (UnknownHostException e) { 080 LOGGER.log(Level.WARNING, "Could not resolve IP addresses of " + host, e); 081 return; 082 } 083 inetAddresses = Arrays.asList(addresses); 084 } 085 086 @Override 087 public Collection<? extends InetAddress> getInetAddresses() { 088 resolveInetAddressesIfRequired(); 089 return inetAddresses; 090 } 091 092 @Override 093 public String getDescription() { 094 return null; 095 } 096 097 @Override 098 public String toString() { 099 return uri.toString(); 100 } 101 102 public static WebSocketRemoteConnectionEndpoint from(CharSequence uriCharSequence) throws URISyntaxException { 103 String uriString = uriCharSequence.toString(); 104 URI uri = URI.create(uriString); 105 return from(uri); 106 } 107 108 public static WebSocketRemoteConnectionEndpoint from(URI uri) { 109 String scheme = uri.getScheme(); 110 switch (scheme) { 111 case INSECURE_WEB_SOCKET_SCHEME: 112 return new InsecureWebSocketRemoteConnectionEndpoint(uri); 113 case SECURE_WEB_SOCKET_SCHEME: 114 return new SecureWebSocketRemoteConnectionEndpoint(uri); 115 default: 116 throw new IllegalArgumentException("Only allowed protocols are " + INSECURE_WEB_SOCKET_SCHEME + " and " + SECURE_WEB_SOCKET_SCHEME); 117 } 118 } 119}