Commit d611a2da authored by jehan's avatar jehan
Browse files

prepare stun client

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@94 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
parent b08b2fbd
No related merge requests found
Showing 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;
}
}
/*
* 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 ;
}
}
}
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment