2017-07-21 23:05:46 +02:00
/ * *
*
* Copyright 2017 Paul Schaub
*
* Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
package org.jivesoftware.smackx.jingle.transport.jingle_s5b ;
2017-07-19 23:15:17 +02:00
2017-07-21 17:58:57 +02:00
import java.io.IOException ;
2017-08-07 11:36:40 +02:00
import java.net.ServerSocket ;
2017-07-21 17:58:57 +02:00
import java.net.Socket ;
import java.util.concurrent.TimeoutException ;
2017-08-01 17:12:27 +02:00
import java.util.logging.Level ;
import java.util.logging.Logger ;
2017-07-21 17:58:57 +02:00
import org.jivesoftware.smack.SmackException ;
import org.jivesoftware.smack.XMPPException ;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Client ;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5ClientForInitiator ;
2017-07-19 23:15:17 +02:00
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream ;
2017-08-04 23:05:59 +02:00
import org.jivesoftware.smackx.jingle.component.JingleContent ;
import org.jivesoftware.smackx.jingle.component.JingleSession ;
import org.jivesoftware.smackx.jingle.component.JingleTransportCandidate ;
2017-07-27 23:31:04 +02:00
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportCandidateElement ;
2017-07-19 23:15:17 +02:00
/ * *
2017-07-21 23:05:46 +02:00
* Jingle SOCKS5Bytestream transport candidate .
2017-07-19 23:15:17 +02:00
* /
2017-07-21 23:51:06 +02:00
public class JingleS5BTransportCandidate extends JingleTransportCandidate < JingleS5BTransportCandidateElement > {
2017-08-01 17:12:27 +02:00
private static final Logger LOGGER = Logger . getLogger ( JingleS5BTransportCandidate . class . getName ( ) ) ;
2017-07-19 23:15:17 +02:00
private final String candidateId ;
private final Bytestream . StreamHost streamHost ;
private final JingleS5BTransportCandidateElement . Type type ;
2017-07-21 17:58:57 +02:00
private Socket socket ;
2017-08-03 23:01:55 +02:00
public JingleS5BTransportCandidate ( JingleS5BTransportCandidateElement element ) {
this ( element . getCandidateId ( ) , new Bytestream . StreamHost ( element . getJid ( ) , element . getHost ( ) , element . getPort ( ) ) , element . getPriority ( ) , element . getType ( ) ) ;
}
2017-07-19 23:15:17 +02:00
public JingleS5BTransportCandidate ( String candidateId ,
Bytestream . StreamHost streamHost ,
int priority ,
JingleS5BTransportCandidateElement . Type type ) {
this . candidateId = candidateId ;
this . streamHost = streamHost ;
this . type = type ;
2017-07-21 17:58:57 +02:00
setPriority ( priority ) ;
}
2017-08-02 20:52:52 +02:00
public JingleS5BTransportCandidate ( JingleS5BTransportCandidate other ) {
this ( other . candidateId ,
other . getStreamHost ( ) ,
other . getPriority ( ) ,
other . type ) ;
}
2017-07-21 17:58:57 +02:00
public static JingleS5BTransportCandidate fromElement ( JingleS5BTransportCandidateElement element ) {
return new JingleS5BTransportCandidate ( element . getCandidateId ( ) , element . getStreamHost ( ) , element . getPriority ( ) , element . getType ( ) ) ;
2017-07-19 23:15:17 +02:00
}
public String getCandidateId ( ) {
return candidateId ;
}
public Bytestream . StreamHost getStreamHost ( ) {
return streamHost ;
}
public JingleS5BTransportCandidateElement . Type getType ( ) {
return type ;
}
2017-07-27 17:35:16 +02:00
@Override
2017-07-21 17:58:57 +02:00
public JingleS5BTransportCandidateElement getElement ( ) {
return new JingleS5BTransportCandidateElement (
getCandidateId ( ) , getStreamHost ( ) . getAddress ( ) ,
getStreamHost ( ) . getJID ( ) , getStreamHost ( ) . getPort ( ) ,
getPriority ( ) , getType ( ) ) ;
}
2017-08-01 17:12:27 +02:00
public JingleS5BTransportCandidate connect ( int timeout , boolean peersProposal ) throws InterruptedException , TimeoutException , SmackException , XMPPException , IOException {
2017-08-02 20:52:52 +02:00
JingleS5BTransport transport = ( JingleS5BTransport ) getParent ( ) ;
2017-07-21 17:58:57 +02:00
2017-08-07 11:36:40 +02:00
switch ( getType ( ) ) {
case proxy :
Socks5Client client ;
if ( peersProposal ) {
LOGGER . log ( Level . INFO , " Connect to foreign candidate " + getCandidateId ( ) + " using " + transport . getTheirDstAddr ( ) ) ;
LOGGER . log ( Level . INFO , getStreamHost ( ) . getAddress ( ) + " : " + getStreamHost ( ) . getPort ( ) + " " + getStreamHost ( ) . getJID ( ) . toString ( ) + " " + getType ( ) ) ;
client = new Socks5Client ( getStreamHost ( ) , transport . getTheirDstAddr ( ) ) ;
} else {
LOGGER . log ( Level . INFO , " Connect to our candidate " + getCandidateId ( ) + " using " + transport . getOurDstAddr ( ) ) ;
LOGGER . log ( Level . INFO , getStreamHost ( ) . getAddress ( ) + " : " + getStreamHost ( ) . getPort ( ) + " " + getStreamHost ( ) . getJID ( ) . toString ( ) + " " + getType ( ) ) ;
JingleContent content = transport . getParent ( ) ;
JingleSession session = content . getParent ( ) ;
client = new Socks5ClientForInitiator ( getStreamHost ( ) , transport . getOurDstAddr ( ) , session . getJingleManager ( ) . getConnection ( ) , transport . getSid ( ) , session . getPeer ( ) ) ;
}
this . socket = client . getSocket ( timeout ) ;
break ;
case direct :
if ( peersProposal ) {
2017-08-07 14:35:00 +02:00
LOGGER . log ( Level . INFO , " Connect to foreign direct candidate " + getCandidateId ( ) + " Address: " + getStreamHost ( ) . getAddress ( ) + " : " + getStreamHost ( ) . getPort ( ) ) ;
2017-08-07 11:36:40 +02:00
this . socket = new Socket ( getStreamHost ( ) . getAddress ( ) , getStreamHost ( ) . getPort ( ) ) ;
} else {
2017-08-07 14:35:00 +02:00
LOGGER . log ( Level . INFO , " Connect to our direct candidate " + getCandidateId ( ) + " at port " + getStreamHost ( ) . getPort ( ) ) ;
2017-08-07 11:36:40 +02:00
this . socket = new ServerSocket ( getStreamHost ( ) . getPort ( ) ) . accept ( ) ;
}
break ;
default :
LOGGER . log ( Level . INFO , " Unsupported candidate type: " + getType ( ) ) ;
break ;
2017-07-21 17:58:57 +02:00
}
2017-07-21 18:29:27 +02:00
return this ;
}
public Socket getSocket ( ) {
2017-07-21 17:58:57 +02:00
return socket ;
2017-07-19 23:15:17 +02:00
}
2017-08-05 14:30:00 +02:00
@Override
public boolean equals ( Object other ) {
if ( this = = other ) {
return true ;
}
if ( ! ( other instanceof JingleS5BTransportCandidate ) ) {
return false ;
}
JingleS5BTransportCandidate o = ( JingleS5BTransportCandidate ) other ;
return o . getCandidateId ( ) . equals ( this . getCandidateId ( ) ) & &
o . getType ( ) = = this . getType ( ) & &
o . getStreamHost ( ) . equals ( this . getStreamHost ( ) ) ;
}
@Override
public int hashCode ( ) {
return getCandidateId ( ) . hashCode ( ) + 3 * getType ( ) . hashCode ( ) + 5 * getStreamHost ( ) . hashCode ( ) ;
}
2017-07-19 23:15:17 +02:00
}