001/** 002 * 003 * Copyright 2017 Paul Schaub 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.smackx.jingle.transports.jingle_s5b.elements; 018 019import org.jivesoftware.smack.packet.XmlEnvironment; 020import org.jivesoftware.smack.util.InternetAddress; 021import org.jivesoftware.smack.util.Objects; 022import org.jivesoftware.smack.util.StringUtils; 023import org.jivesoftware.smack.util.XmlStringBuilder; 024 025import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream; 026import org.jivesoftware.smackx.jingle.element.JingleContentTransportCandidate; 027 028import org.jxmpp.jid.Jid; 029import org.jxmpp.jid.impl.JidCreate; 030import org.jxmpp.stringprep.XmppStringprepException; 031 032/** 033 * TransportCandidate for Jingle Socks5Bytestream transports. 034 */ 035public final class JingleS5BTransportCandidate extends JingleContentTransportCandidate { 036 037 public static final String NAMESPACE = JingleS5BTransport.NAMESPACE_V1; 038 039 public static final String ATTR_CID = "cid"; 040 public static final String ATTR_HOST = "host"; 041 public static final String ATTR_JID = "jid"; 042 public static final String ATTR_PORT = "port"; 043 public static final String ATTR_PRIORITY = "priority"; 044 public static final String ATTR_TYPE = "type"; 045 046 private final String cid; 047 private final InternetAddress host; 048 private final Jid jid; 049 private final int port; 050 private final int priority; 051 private final Type type; 052 053 public JingleS5BTransportCandidate(String candidateId, String hostString, Jid jid, int port, int priority, Type type) { 054 this(candidateId, InternetAddress.from(hostString), jid, port, priority, type); 055 } 056 057 public JingleS5BTransportCandidate(String candidateId, InternetAddress host, Jid jid, int port, int priority, Type type) { 058 Objects.requireNonNull(candidateId); 059 Objects.requireNonNull(host); 060 Objects.requireNonNull(jid); 061 062 if (priority < 0) { 063 throw new IllegalArgumentException("Priority MUST NOT be less than 0."); 064 } 065 if (port < 0) { 066 throw new IllegalArgumentException("Port MUST NOT be less than 0."); 067 } 068 069 this.cid = candidateId; 070 this.host = host; 071 this.jid = jid; 072 this.port = port; 073 this.priority = priority; 074 this.type = type; 075 } 076 077 public JingleS5BTransportCandidate(Bytestream.StreamHost streamHost, int priority, Type type) { 078 this(StringUtils.randomString(24), streamHost.getAddress(), streamHost.getJID(), streamHost.getPort(), priority, type); 079 } 080 081 public enum Type { 082 assisted (120), 083 direct (126), 084 proxy (10), 085 tunnel (110), 086 ; 087 088 private final int weight; 089 090 public int getWeight() { 091 return weight; 092 } 093 094 Type(int weight) { 095 this.weight = weight; 096 } 097 098 public static Type fromString(String name) { 099 for (Type t : Type.values()) { 100 if (t.toString().equals(name)) { 101 return t; 102 } 103 } 104 throw new IllegalArgumentException("Illegal type: " + name); 105 } 106 } 107 108 public String getCandidateId() { 109 return cid; 110 } 111 112 public InternetAddress getHost() { 113 return host; 114 } 115 116 public Jid getJid() { 117 return jid; 118 } 119 120 public int getPort() { 121 return port; 122 } 123 124 public int getPriority() { 125 return priority; 126 } 127 128 public Type getType() { 129 return type; 130 } 131 132 public Bytestream.StreamHost getStreamHost() { 133 return new Bytestream.StreamHost(jid, host, port); 134 } 135 136 137 @Override 138 public String getNamespace() { 139 return NAMESPACE; 140 } 141 142 @Override 143 public XmlStringBuilder toXML(XmlEnvironment enclosingXmlEnvironment) { 144 XmlStringBuilder xml = new XmlStringBuilder(this, enclosingXmlEnvironment); 145 xml.attribute(ATTR_CID, cid); 146 xml.attribute(ATTR_HOST, host); 147 xml.attribute(ATTR_JID, jid); 148 if (port >= 0) { 149 xml.attribute(ATTR_PORT, port); 150 } 151 xml.attribute(ATTR_PRIORITY, priority); 152 xml.optAttribute(ATTR_TYPE, type); 153 154 xml.closeEmptyElement(); 155 return xml; 156 } 157 158 public static Builder getBuilder() { 159 return new Builder(); 160 } 161 162 public static final class Builder { 163 private String cid; 164 private InternetAddress host; 165 private Jid jid; 166 private int port = -1; 167 private int priority = -1; 168 private Type type; 169 170 private Builder() { 171 } 172 173 public Builder setCandidateId(String cid) { 174 this.cid = cid; 175 return this; 176 } 177 178 public Builder setHost(String host) { 179 InternetAddress inetAddress = InternetAddress.from(host); 180 return setHost(inetAddress); 181 } 182 183 public Builder setHost(InternetAddress host) { 184 this.host = host; 185 return this; 186 } 187 188 public Builder setJid(String jid) throws XmppStringprepException { 189 this.jid = JidCreate.from(jid); 190 return this; 191 } 192 193 public Builder setPort(int port) { 194 if (port < 0) { 195 throw new IllegalArgumentException("Port MUST NOT be less than 0."); 196 } 197 this.port = port; 198 return this; 199 } 200 201 public Builder setPriority(int priority) { 202 if (priority < 0) { 203 throw new IllegalArgumentException("Priority MUST NOT be less than 0."); 204 } 205 this.priority = priority; 206 return this; 207 } 208 209 public Builder setType(Type type) { 210 this.type = type; 211 return this; 212 } 213 214 public JingleS5BTransportCandidate build() { 215 return new JingleS5BTransportCandidate(cid, host, jid, port, priority, type); 216 } 217 } 218 219}