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