mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-02-07 14:18:25 +00:00
prepare stun client
git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@94 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
b08b2fbd1c
commit
d611a2dacc
3 changed files with 213 additions and 4 deletions
|
|
@ -39,7 +39,7 @@ public class AddressInfo {
|
|||
AddressInfo(InetSocketAddress aPrivateAddress) {
|
||||
mPrivateAddress = aPrivateAddress;
|
||||
}
|
||||
public Mode getType() {
|
||||
public Mode getMode() {
|
||||
return mMode;
|
||||
}
|
||||
public void setMode(Mode aMode) {
|
||||
|
|
@ -49,6 +49,9 @@ public class AddressInfo {
|
|||
return mPrivateAddress;
|
||||
}
|
||||
public InetSocketAddress getPublicAddress() {
|
||||
return mPrivateAddress;
|
||||
return mPublicAddress;
|
||||
}
|
||||
public void setPublicAddress(InetSocketAddress aPublicAddress) {
|
||||
mPublicAddress = aPublicAddress;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
110
p2pproxy/src/org/linphone/p2pproxy/core/stun/DiscoveryInfo.java
Normal file
110
p2pproxy/src/org/linphone/p2pproxy/core/stun/DiscoveryInfo.java
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* This file is part of JSTUN.
|
||||
*
|
||||
* Copyright (c) 2005 Thomas King <king@t-king.de> - All rights
|
||||
* reserved.
|
||||
*
|
||||
* This software is licensed under either the GNU Public License (GPL),
|
||||
* or the Apache 2.0 license. Copies of both license agreements are
|
||||
* included in this distribution.
|
||||
*/
|
||||
|
||||
package org.linphone.p2pproxy.core.stun;
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class DiscoveryInfo {
|
||||
private boolean error = false;
|
||||
private int errorResponseCode = 0;
|
||||
private String errorReason;
|
||||
private boolean blockedUDP = false;
|
||||
private boolean fullCone = false;
|
||||
private boolean symmetric = false;
|
||||
private InetSocketAddress mTestSocketAddress;
|
||||
private InetSocketAddress mPublicSocketAddress;
|
||||
|
||||
public DiscoveryInfo(InetSocketAddress aTestSocketAddress) {
|
||||
mTestSocketAddress = aTestSocketAddress;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(int responseCode, String reason) {
|
||||
this.error = true;
|
||||
this.errorResponseCode = responseCode;
|
||||
this.errorReason = reason;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isBlockedUDP() {
|
||||
if (error) return false;
|
||||
return blockedUDP;
|
||||
}
|
||||
|
||||
public void setBlockedUDP() {
|
||||
this.blockedUDP = true;
|
||||
}
|
||||
|
||||
public boolean isFullCone() {
|
||||
if (error) return false;
|
||||
return fullCone;
|
||||
}
|
||||
|
||||
public void setFullCone() {
|
||||
this.fullCone = true;
|
||||
}
|
||||
|
||||
public boolean isSymmetric() {
|
||||
if (error) return false;
|
||||
return symmetric;
|
||||
}
|
||||
|
||||
public void setSymmetric() {
|
||||
this.symmetric = true;
|
||||
}
|
||||
|
||||
public InetSocketAddress getLocalSocketAddress() {
|
||||
return mTestSocketAddress;
|
||||
}
|
||||
|
||||
public InetSocketAddress getPublicSocketAddress() {
|
||||
return mPublicSocketAddress;
|
||||
}
|
||||
public void setPublicSocketAddress(InetSocketAddress address) {
|
||||
mPublicSocketAddress = address;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("Network interface: ");
|
||||
try {
|
||||
sb.append(NetworkInterface.getByInetAddress(mTestSocketAddress.getAddress()).getName());
|
||||
} catch (SocketException se) {
|
||||
sb.append("unknown");
|
||||
}
|
||||
sb.append("\n");
|
||||
sb.append("Local Socket address: ");
|
||||
sb.append(mTestSocketAddress);
|
||||
sb.append("\n");
|
||||
if (error) {
|
||||
sb.append(errorReason + " - Responsecode: " + errorResponseCode);
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append("Result: ");
|
||||
if (blockedUDP) sb.append("Firewall blocks UDP.\n");
|
||||
if (fullCone) sb.append("Full Cone NAT handles connections.\n");
|
||||
if (symmetric) sb.append("Symmetric Cone NAT handles connections.\n");
|
||||
sb.append("Public IP address: ");
|
||||
if (mPublicSocketAddress != null) {
|
||||
sb.append(mPublicSocketAddress.toString());
|
||||
} else {
|
||||
sb.append("unknown");
|
||||
}
|
||||
sb.append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,19 +20,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
package org.linphone.p2pproxy.core.stun;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.linphone.p2pproxy.api.P2pProxyException;
|
||||
import org.linphone.p2pproxy.core.JxtaNetworkManager;
|
||||
import org.linphone.p2pproxy.core.P2pProxyAdvertisementNotFoundException;
|
||||
import org.linphone.p2pproxy.core.sipproxy.NetworkResourceAdvertisement;
|
||||
import org.linphone.p2pproxy.test.StunServerTester;
|
||||
|
||||
import de.javawi.jstun.attribute.ChangeRequest;
|
||||
import de.javawi.jstun.attribute.ChangedAddress;
|
||||
import de.javawi.jstun.attribute.ErrorCode;
|
||||
import de.javawi.jstun.attribute.MappedAddress;
|
||||
import de.javawi.jstun.attribute.MessageAttribute;
|
||||
import de.javawi.jstun.attribute.MessageAttributeParsingException;
|
||||
import de.javawi.jstun.header.MessageHeader;
|
||||
import de.javawi.jstun.header.MessageHeaderParsingException;
|
||||
import de.javawi.jstun.util.UtilityException;
|
||||
|
||||
public class StunClient {
|
||||
private List<InetSocketAddress> mStunServerList;
|
||||
private static Logger mLog = Logger.getLogger(StunClient.class);
|
||||
private List<InetSocketAddress> mStunServerList;
|
||||
JxtaNetworkManager mJxtaNetworkManager;
|
||||
private DiscoveryInfo mDiscoveryInfo;
|
||||
private int SO_TIME_OUT = 300;
|
||||
|
||||
StunClient(List<InetSocketAddress> aStunServerList) {
|
||||
mStunServerList = aStunServerList;
|
||||
|
|
@ -56,5 +76,81 @@ public class StunClient {
|
|||
return lSocketAddressList;
|
||||
}
|
||||
|
||||
|
||||
public AddressInfo computeAddressInfo(DatagramSocket lLocalSocket) throws P2pProxyException {
|
||||
//1 bind request
|
||||
try {
|
||||
//1 bind request
|
||||
bindRequest(lLocalSocket,lLocalSocket, mStunServerList.get(0));
|
||||
//open new socket
|
||||
} catch (Exception e) {
|
||||
throw new P2pProxyException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void bindRequest(DatagramSocket aLocalSocket, DatagramSocket aResponseSocket,InetSocketAddress aStunAddress) throws UtilityException, SocketException, UnknownHostException, IOException, MessageAttributeParsingException, MessageHeaderParsingException, P2pProxyException {
|
||||
int timeSinceFirstTransmission = 0;
|
||||
int lSoTimeOut = SO_TIME_OUT;
|
||||
while (true) {
|
||||
try {
|
||||
aLocalSocket.setReuseAddress(true);
|
||||
aLocalSocket.connect(aStunAddress);
|
||||
aLocalSocket.setSoTimeout(lSoTimeOut);
|
||||
|
||||
MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
|
||||
sendMH.generateTransactionID();
|
||||
|
||||
ChangeRequest changeRequest = new ChangeRequest();
|
||||
sendMH.addMessageAttribute(changeRequest);
|
||||
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
aLocalSocket.send(send);
|
||||
|
||||
MessageHeader receiveMH = new MessageHeader();
|
||||
while (!(receiveMH.equalTransactionID(sendMH))) {
|
||||
DatagramPacket receive = new DatagramPacket(new byte[200], 200);
|
||||
aResponseSocket.receive(receive);
|
||||
receiveMH = MessageHeader.parseHeader(receive.getData());
|
||||
receiveMH.parseAttributes(receive.getData());
|
||||
}
|
||||
|
||||
MappedAddress lMappedAddress = (MappedAddress) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);
|
||||
ErrorCode ec = (ErrorCode) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.ErrorCode);
|
||||
if (ec != null) {
|
||||
mDiscoveryInfo.setError(ec.getResponseCode(), ec.getReason());
|
||||
throw new P2pProxyException("Message header contains an Errorcode message attribute. ["+ec+"]");
|
||||
}
|
||||
if ((lMappedAddress == null)) {
|
||||
throw new P2pProxyException("Response does not contain a Mapped Address message attribute.");
|
||||
|
||||
} else {
|
||||
if (aLocalSocket.getLocalSocketAddress().equals(aResponseSocket.getLocalSocketAddress())) {
|
||||
mDiscoveryInfo.setPublicSocketAddress(new InetSocketAddress(lMappedAddress.getAddress().getInetAddress(),lMappedAddress.getPort()));
|
||||
} else {
|
||||
mDiscoveryInfo.setFullCone();
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
} catch (SocketTimeoutException ste) {
|
||||
if (timeSinceFirstTransmission < 7900) {
|
||||
if (mLog.isInfoEnabled()) mLog.info("Socket timeout while receiving the response.");
|
||||
timeSinceFirstTransmission += lSoTimeOut;
|
||||
int timeoutAddValue = (timeSinceFirstTransmission * 2);
|
||||
if (timeoutAddValue > 1600) timeoutAddValue = 1600;
|
||||
lSoTimeOut = timeoutAddValue;
|
||||
} else {
|
||||
// node is not capable of udp communication
|
||||
if (mLog.isInfoEnabled()) mLog.info("Socket timeout while receiving the response. Maximum retry limit exceed. Give up.");
|
||||
if (aLocalSocket.getLocalSocketAddress().equals(aResponseSocket.getLocalSocketAddress())) {
|
||||
mDiscoveryInfo.setBlockedUDP();
|
||||
} else {
|
||||
mDiscoveryInfo.setSymmetric();
|
||||
}
|
||||
if (mLog.isInfoEnabled()) mLog.info("Node is not capable of UDP communication.");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue