mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-21 13:08:08 +00:00
add native test ++
git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@84 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
c4338648b7
commit
09ca76f825
12 changed files with 300 additions and 323 deletions
|
|
@ -121,6 +121,7 @@
|
|||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
|
||||
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
|
|
@ -506,6 +507,7 @@
|
|||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
|
||||
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ all: p2pproxy-launcher
|
|||
p2pproxy-launcher: $(OBJS) $(USER_OBJS)
|
||||
@echo 'Building target: $@'
|
||||
@echo 'Invoking: GCC C Linker'
|
||||
gcc -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64 -L/usr/lib/jvm/java-6-openjdk/jre/lib/i386 -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server -L/usr/lib/jvm/java-6-openjdk/jre/lib/i386/server -o"p2pproxy-launcher" $(OBJS) $(USER_OBJS) $(LIBS)
|
||||
gcc -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64 -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server -o"p2pproxy-launcher" $(OBJS) $(USER_OBJS) $(LIBS)
|
||||
@echo 'Finished building target: $@'
|
||||
@echo ' '
|
||||
|
||||
|
|
|
|||
|
|
@ -32,15 +32,27 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
char string_buffer[256];
|
||||
if (p2pproxy_resourcelocation_get_sip_proxyregistrar_uri(string_buffer,256) != P2PPROXY_NO_ERROR) {
|
||||
if (p2pproxy_resourcemgt_lookup_sip_proxy(string_buffer,256,"p2p.linphone.org") != P2PPROXY_NO_ERROR) {
|
||||
printf("cannot get proxy\n");
|
||||
} else {
|
||||
printf("registrar is [%s]\n",string_buffer);
|
||||
}
|
||||
|
||||
if (p2pproxy_resourcemgt_revoke_sip_proxy(string_buffer) != P2PPROXY_NO_ERROR) {
|
||||
printf("cannot fulsh proxy [%s]\n",string_buffer);
|
||||
}
|
||||
|
||||
if (p2pproxy_resourcemgt_lookup_sip_proxy(string_buffer,256,"toto.linphone.org") != P2PPROXY_RESOURCEMGT_SERVER_NOT_FOUND) {
|
||||
printf("unexpected proxy [%s]\n",string_buffer);
|
||||
} else {
|
||||
printf("unknown domaine\n");
|
||||
}
|
||||
|
||||
if (p2pproxy_accountmgt_deleteAccount("sip:titi@p2p.linphone.org") != P2PPROXY_NO_ERROR) {
|
||||
printf("cannot delete account \n");
|
||||
}
|
||||
|
||||
|
||||
p2pproxy_application_stop();
|
||||
pthread_join(th,NULL);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
#include "p2pproxy.h"
|
||||
|
||||
#ifndef P2PPROXY_JMX_PORT
|
||||
|
|
@ -138,25 +139,43 @@ int p2pproxy_accountmgt_deleteAccount(const char* user_name) {
|
|||
return lResult;
|
||||
}
|
||||
|
||||
int p2pproxy_resourcelocation_get_sip_proxyregistrar_uri(char* aStringArray, size_t aSize) {
|
||||
jmethodID getSipProxyRegistrarUriMethod;
|
||||
int p2pproxy_resourcemgt_lookup_sip_proxy(char* proxy_uri,size_t size, char* domaine) {
|
||||
jmethodID lLookupSipProxyUriMethod;
|
||||
jstring lJStringResult;
|
||||
const jbyte* lString;
|
||||
jboolean lIsCopy;
|
||||
GET_JNI_ENV
|
||||
jstring applicationArg;
|
||||
|
||||
getSipProxyRegistrarUriMethod = (*lJniEnv)->GetStaticMethodID(lJniEnv, lMainClass, "getSipProxyRegistrarUri", "()Ljava/lang/String;");
|
||||
lJStringResult = (*lJniEnv)->CallStaticObjectMethod(lJniEnv, lMainClass, getSipProxyRegistrarUriMethod);
|
||||
GET_JNI_ENV
|
||||
|
||||
|
||||
applicationArg = (*lJniEnv)->NewStringUTF(lJniEnv, domaine);
|
||||
lLookupSipProxyUriMethod = (*lJniEnv)->GetStaticMethodID(lJniEnv, lMainClass, "lookupSipProxyUri", "(Ljava/lang/String;)Ljava/lang/String;");
|
||||
lJStringResult = (*lJniEnv)->CallStaticObjectMethod(lJniEnv, lMainClass, lLookupSipProxyUriMethod, applicationArg);
|
||||
if (lJStringResult == 0) {
|
||||
return P2PPROXY_ERROR_RESOURCELOCATOR_SERVER_NOT_FOUND;
|
||||
return P2PPROXY_RESOURCEMGT_SERVER_NOT_FOUND;
|
||||
}
|
||||
lString = (*lJniEnv)->GetStringUTFChars(lJniEnv, lJStringResult, &lIsCopy);
|
||||
memcpy(aStringArray,lString,aSize);
|
||||
memcpy(proxy_uri,lString,size);
|
||||
(*lJniEnv)->ReleaseStringUTFChars(lJniEnv, lJStringResult, lString);
|
||||
(*p2pproxy_application_jvm)->DetachCurrentThread(p2pproxy_application_jvm);
|
||||
return P2PPROXY_NO_ERROR;
|
||||
}
|
||||
|
||||
int p2pproxy_resourcemgt_revoke_sip_proxy(char* proxy_uri) {
|
||||
jmethodID revokeProxyMethod;
|
||||
jstring lJStringResult;
|
||||
const jbyte* lString;
|
||||
jboolean lIsCopy;
|
||||
GET_JNI_ENV
|
||||
|
||||
revokeProxyMethod = (*lJniEnv)->GetStaticMethodID(lJniEnv, lMainClass, "revokeSipProxy", "(Ljava/lang/String;)V");
|
||||
(*lJniEnv)->CallStaticVoidMethod(lJniEnv, lMainClass, revokeProxyMethod);
|
||||
if (lJStringResult == 0) {
|
||||
return P2PPROXY_ERROR;
|
||||
}
|
||||
return P2PPROXY_NO_ERROR;
|
||||
}
|
||||
int p2pproxy_application_get_state() {
|
||||
jmethodID stateMethod;
|
||||
GET_JNI_ENV
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define P2PPROXY_ACCOUNTMGT_USER_EXIST 1
|
||||
#define P2PPROXY_ACCOUNTMGT_USER_NOT_EXIST 0
|
||||
|
||||
#define P2PPROXY_RESOURCEMGT_SERVER_NOT_FOUND 3
|
||||
/* state code*/
|
||||
#define P2PPROXY_CONNECTED 2
|
||||
#define P2PPROXY_NOT_CONNECTED 1
|
||||
|
|
@ -41,7 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define P2PPROXY_ERROR_APPLICATION_ALREADY_STARTED -3
|
||||
#define P2PPROXY_ERROR_ACCOUNTMGT_USER_ALREADY_EXIST -4
|
||||
#define P2PPROXY_ERROR_ACCOUNTMGT_BAD_SIP_URI -5
|
||||
#define P2PPROXY_ERROR_RESOURCELOCATOR_SERVER_NOT_FOUND -6
|
||||
#define P2PPROXY_ERROR_RESOURCEMGT_SERVER_NOT_FOUND -6
|
||||
|
||||
#ifndef SWIG
|
||||
/**
|
||||
|
|
@ -97,16 +97,24 @@ int p2pproxy_accountmgt_isValidAccount(const char* user_name);
|
|||
*/
|
||||
int p2pproxy_accountmgt_deleteAccount(const char* user_name);
|
||||
|
||||
/***************************/
|
||||
/***resource location******/
|
||||
/***************************/
|
||||
/****************************/
|
||||
/***resource management******/
|
||||
/****************************/
|
||||
/**
|
||||
* access a proxy registrar sip addreess
|
||||
* @param buffer allocated by the user
|
||||
* @param size buffer size
|
||||
* access a proxy registrar sip addreess for a given domaine name
|
||||
* @param [out] proxy_uri buffer allocated by the user
|
||||
* @param [in] size buffer size
|
||||
* @param [in] domaine name
|
||||
* @return status code P2PPROXY_NO_ERROR, P2PPROXY_ERROR_RESOURCELOCATOR_SERVER_NOT_FOUND
|
||||
*/
|
||||
int p2pproxy_resourcelocation_get_sip_proxyregistrar_uri(char* string_buffer,size_t size) ;
|
||||
int p2pproxy_resourcemgt_lookup_sip_proxy(char* proxy_uri,size_t size, char* domaine) ;
|
||||
/*
|
||||
* notify the library at a given proxy is no longuer reachable
|
||||
* @param [in] proxy sip uri
|
||||
* @return status code P2PPROXY_NO_ERROR
|
||||
*/
|
||||
int p2pproxy_resourcemgt_revoke_sip_proxy(char* proxy_uri);
|
||||
|
||||
|
||||
#endif /*SWIG*/
|
||||
|
||||
|
|
|
|||
|
|
@ -19,12 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone.p2pproxy.api;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
|
||||
public interface P2pProxySipProxyRegistrarManagement {
|
||||
/**
|
||||
*
|
||||
* @return the SIP uri of an available sip proxy registrar
|
||||
* @return the SIP uri of an available sip proxy registrar for a given domaine
|
||||
*/
|
||||
public String getSipProxyRegistrarUri() throws P2pProxyException ;
|
||||
public String lookupSipProxyUri(String aDomaine) throws P2pProxyException ;
|
||||
|
||||
public void revokeSipProxy(String aProxy) throws P2pProxyException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,8 @@ public class JxtaNetworkManager {
|
|||
} else {
|
||||
lNetworkConfigurator.load();
|
||||
}
|
||||
|
||||
//mode is alway taken from start line
|
||||
lNetworkConfigurator.setMode(lMode);
|
||||
// set sedding host
|
||||
if (aProperties.getProperty(SEEDING_RDV) != null) {
|
||||
StringTokenizer lSeedingRdvList = new StringTokenizer(aProperties.getProperty(SEEDING_RDV),"|" );
|
||||
|
|
|
|||
|
|
@ -386,11 +386,10 @@ private static void isReady() throws P2pProxyNotReadyException {
|
|||
try {
|
||||
if ((mJxtaNetworkManager!=null && mJxtaNetworkManager.isConnectedToRendezVous(0) == true)
|
||||
||
|
||||
(mJxtaNetworkManager!=null && mJxtaNetworkManager.getPeerGroup().getRendezVousService().isRendezVous()))
|
||||
{
|
||||
(mJxtaNetworkManager!=null && mJxtaNetworkManager.getPeerGroup().getRendezVousService().isRendezVous())) {
|
||||
//nop connected
|
||||
} else {
|
||||
throw new P2pProxyNotReadyException("not connected to any rdv");
|
||||
throw new P2pProxyNotReadyException("not connected to any rdv: status ["+mJxtaNetworkManager.getPeerGroup().getRendezVousService().getRendezVousStatus()+"]");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new P2pProxyNotReadyException(e);
|
||||
|
|
@ -431,10 +430,10 @@ public static int isValidAccount(String aUserName){
|
|||
return P2pProxylauncherConstants.P2PPROXY_ERROR;
|
||||
}
|
||||
}
|
||||
public static String getSipProxyRegistrarUri() {
|
||||
public static String lookupSipProxyUri(String aDomaine) {
|
||||
try {
|
||||
isReady();
|
||||
return mP2pProxySipProxyRegistrarManagement.getSipProxyRegistrarUri();
|
||||
return mP2pProxySipProxyRegistrarManagement.lookupSipProxyUri(aDomaine);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -444,9 +443,20 @@ public static int getState() {
|
|||
isReady();
|
||||
return P2pProxylauncherConstants.P2PPROXY_CONNECTED;
|
||||
} catch (P2pProxyException e) {
|
||||
mLog.error("cannot get state",e);
|
||||
return P2pProxylauncherConstants.P2PPROXY_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
public static int revokeSipProxy(String aProxy) {
|
||||
try {
|
||||
isReady();
|
||||
mLog.error("not implemented");
|
||||
return P2pProxylauncherConstants.P2PPROXY_ERROR;
|
||||
} catch (P2pProxyException e) {
|
||||
return P2pProxylauncherConstants.P2PPROXY_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
mExit = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,38 @@
|
|||
package org.linphone.p2pproxy.core;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.linphone.p2pproxy.api.P2pProxyException;
|
||||
import org.linphone.p2pproxy.api.P2pProxySipProxyRegistrarManagement;
|
||||
import org.linphone.p2pproxy.core.sipproxy.SipProxyRegistrarAdvertisement;
|
||||
|
||||
public class P2pProxySipProxyRegistrarManagementImpl implements P2pProxySipProxyRegistrarManagement {
|
||||
protected final JxtaNetworkManager mJxtaNetworkManager;
|
||||
P2pProxySipProxyRegistrarManagementImpl(JxtaNetworkManager aJxtaNetworkManager) {
|
||||
mJxtaNetworkManager = aJxtaNetworkManager;
|
||||
}
|
||||
public String getSipProxyRegistrarUri() throws P2pProxyException {
|
||||
try {
|
||||
SipProxyRegistrarAdvertisement lSipProxyRegistrarAdvertisement = (SipProxyRegistrarAdvertisement) (mJxtaNetworkManager.getAdvertisement(null, SipProxyRegistrarAdvertisement.NAME, true));
|
||||
return lSipProxyRegistrarAdvertisement.getAddress();
|
||||
}catch (Exception e) {
|
||||
throw new P2pProxyException(e);
|
||||
}
|
||||
protected final JxtaNetworkManager mJxtaNetworkManager;
|
||||
private final String DOMAINE="p2p.linphone.org";
|
||||
private final static Logger mLog = Logger.getLogger(P2pProxySipProxyRegistrarManagementImpl.class);
|
||||
P2pProxySipProxyRegistrarManagementImpl(JxtaNetworkManager aJxtaNetworkManager) {
|
||||
mJxtaNetworkManager = aJxtaNetworkManager;
|
||||
}
|
||||
public String lookupSipProxyUri(String aDomaine) throws P2pProxyException {
|
||||
try {
|
||||
if (!DOMAINE.equals(aDomaine)) {
|
||||
//unknown domaine
|
||||
return null;
|
||||
}
|
||||
SipProxyRegistrarAdvertisement lSipProxyRegistrarAdvertisement = (SipProxyRegistrarAdvertisement) (mJxtaNetworkManager.getAdvertisement(null, SipProxyRegistrarAdvertisement.NAME, true));
|
||||
return lSipProxyRegistrarAdvertisement.getAddress();
|
||||
}catch (Exception e) {
|
||||
throw new P2pProxyException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public void revokeSipProxy(String aProxy) throws P2pProxyException {
|
||||
try {
|
||||
SipProxyRegistrarAdvertisement lSipProxyRegistrarAdvertisement = (SipProxyRegistrarAdvertisement) (mJxtaNetworkManager.getAdvertisement(null, SipProxyRegistrarAdvertisement.ADDRESS_TAG, true));
|
||||
mJxtaNetworkManager.getPeerGroup().getDiscoveryService().flushAdvertisement(lSipProxyRegistrarAdvertisement);
|
||||
mLog.info(aProxy +"revoked");
|
||||
} catch (Exception e) {
|
||||
throw new P2pProxyException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
184
p2pproxy/src/org/linphone/p2pproxy/core/stun/StunServer.java
Normal file
184
p2pproxy/src/org/linphone/p2pproxy/core/stun/StunServer.java
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
|
||||
import de.javawi.jstun.attribute.ChangeRequest;
|
||||
import de.javawi.jstun.attribute.ChangedAddress;
|
||||
import de.javawi.jstun.attribute.MappedAddress;
|
||||
import de.javawi.jstun.attribute.MessageAttributeException;
|
||||
import de.javawi.jstun.attribute.MessageAttributeParsingException;
|
||||
import de.javawi.jstun.attribute.ResponseAddress;
|
||||
import de.javawi.jstun.attribute.SourceAddress;
|
||||
import de.javawi.jstun.attribute.UnknownAttribute;
|
||||
import de.javawi.jstun.attribute.UnknownMessageAttributeException;
|
||||
import de.javawi.jstun.attribute.MessageAttributeInterface.MessageAttributeType;
|
||||
import de.javawi.jstun.header.MessageHeader;
|
||||
import de.javawi.jstun.header.MessageHeaderParsingException;
|
||||
import de.javawi.jstun.header.MessageHeaderInterface.MessageHeaderType;
|
||||
import de.javawi.jstun.util.Address;
|
||||
import de.javawi.jstun.util.UtilityException;
|
||||
|
||||
/*
|
||||
* This class implements a STUN server as described in RFC 3489.
|
||||
* The server requires a machine that is dual-homed to be functional.
|
||||
*/
|
||||
public class StunServer {
|
||||
private static Logger logger = Logger.getLogger("org.linphone.p2pproxy.core.stun.StunServer");
|
||||
Vector<DatagramSocket> sockets;
|
||||
|
||||
public StunServer(int primaryPort, InetAddress primary, int secondaryPort) throws SocketException {
|
||||
sockets = new Vector<DatagramSocket>();
|
||||
sockets.add(new DatagramSocket(primaryPort, primary));
|
||||
sockets.add(new DatagramSocket(secondaryPort, primary));
|
||||
}
|
||||
|
||||
public void start() throws SocketException {
|
||||
for (DatagramSocket socket : sockets) {
|
||||
socket.setReceiveBufferSize(2000);
|
||||
StunServerReceiverThread ssrt = new StunServerReceiverThread(socket);
|
||||
ssrt.start();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Inner class to handle incoming packets and react accordingly.
|
||||
* I decided not to start a thread for every received Binding Request, because the time
|
||||
* required to receive a Binding Request, parse it, generate a Binding Response and send
|
||||
* it varies only between 2 and 4 milliseconds. This amount of time is small enough so
|
||||
* that no extra thread is needed for incoming Binding Request.
|
||||
*/
|
||||
class StunServerReceiverThread extends Thread {
|
||||
private DatagramSocket receiverSocket;
|
||||
private DatagramSocket changedPort;
|
||||
|
||||
StunServerReceiverThread(DatagramSocket datagramSocket) {
|
||||
this.receiverSocket = datagramSocket;
|
||||
for (DatagramSocket socket : sockets) {
|
||||
if ((socket.getLocalPort() != receiverSocket.getLocalPort()) &&
|
||||
(socket.getLocalAddress().equals(receiverSocket.getLocalAddress())))
|
||||
changedPort = socket;
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
DatagramPacket receive = new DatagramPacket(new byte[200], 200);
|
||||
receiverSocket.receive(receive);
|
||||
logger.finest(receiverSocket.getLocalAddress().getHostAddress() + ":" + receiverSocket.getLocalPort() + " datagram received from " + receive.getAddress().getHostAddress() + ":" + receive.getPort());
|
||||
MessageHeader receiveMH = MessageHeader.parseHeader(receive.getData());
|
||||
try {
|
||||
receiveMH.parseAttributes(receive.getData());
|
||||
if (receiveMH.getType() == MessageHeaderType.BindingRequest) {
|
||||
logger.config(receiverSocket.getLocalAddress().getHostAddress() + ":" + receiverSocket.getLocalPort() + " Binding Request received from " + receive.getAddress().getHostAddress() + ":" + receive.getPort());
|
||||
ChangeRequest cr = (ChangeRequest) receiveMH.getMessageAttribute(MessageAttributeType.ChangeRequest);
|
||||
if (cr == null) throw new MessageAttributeException("Message attribute change request is not set.");
|
||||
ResponseAddress ra = (ResponseAddress) receiveMH.getMessageAttribute(MessageAttributeType.ResponseAddress);
|
||||
|
||||
MessageHeader sendMH = new MessageHeader(MessageHeaderType.BindingResponse);
|
||||
sendMH.setTransactionID(receiveMH.getTransactionID());
|
||||
|
||||
// Mapped address attribute
|
||||
MappedAddress ma = new MappedAddress();
|
||||
ma.setAddress(new Address(receive.getAddress().getAddress()));
|
||||
ma.setPort(receive.getPort());
|
||||
sendMH.addMessageAttribute(ma);
|
||||
if (cr.isChangePort()) {
|
||||
logger.finer("Change port received in Change Request attribute");
|
||||
// Source address attribute
|
||||
SourceAddress sa = new SourceAddress();
|
||||
sa.setAddress(new Address(changedPort.getLocalAddress().getAddress()));
|
||||
sa.setPort(changedPort.getLocalPort());
|
||||
sendMH.addMessageAttribute(sa);
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
if (ra != null) {
|
||||
send.setPort(ra.getPort());
|
||||
send.setAddress(ra.getAddress().getInetAddress());
|
||||
} else {
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
}
|
||||
changedPort.send(send);
|
||||
logger.config(changedPort.getLocalAddress().getHostAddress() + ":" + changedPort.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
} else if ((!cr.isChangePort()) && (!cr.isChangeIP())) {
|
||||
logger.finer("Nothing received in Change Request attribute");
|
||||
// Source address attribute
|
||||
SourceAddress sa = new SourceAddress();
|
||||
sa.setAddress(new Address(receiverSocket.getLocalAddress().getAddress()));
|
||||
sa.setPort(receiverSocket.getLocalPort());
|
||||
sendMH.addMessageAttribute(sa);
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
if (ra != null) {
|
||||
send.setPort(ra.getPort());
|
||||
send.setAddress(ra.getAddress().getInetAddress());
|
||||
} else {
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
}
|
||||
receiverSocket.send(send);
|
||||
logger.config(receiverSocket.getLocalAddress().getHostAddress() + ":" + receiverSocket.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
} else {
|
||||
logger.warning("cannot handle cr ["+cr+"]");
|
||||
}
|
||||
}
|
||||
} catch (UnknownMessageAttributeException umae) {
|
||||
umae.printStackTrace();
|
||||
// Generate Binding error response
|
||||
MessageHeader sendMH = new MessageHeader(MessageHeaderType.BindingErrorResponse);
|
||||
sendMH.setTransactionID(receiveMH.getTransactionID());
|
||||
|
||||
// Unknown attributes
|
||||
UnknownAttribute ua = new UnknownAttribute();
|
||||
ua.addAttribute(umae.getType());
|
||||
sendMH.addMessageAttribute(ua);
|
||||
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
receiverSocket.send(send);
|
||||
logger.config(" send Binding Error Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (MessageAttributeParsingException mape) {
|
||||
mape.printStackTrace();
|
||||
} catch (MessageAttributeException mae) {
|
||||
mae.printStackTrace();
|
||||
} catch (MessageHeaderParsingException mhpe) {
|
||||
mhpe.printStackTrace();
|
||||
} catch (UtilityException ue) {
|
||||
ue.printStackTrace();
|
||||
} catch (ArrayIndexOutOfBoundsException aioobe) {
|
||||
aioobe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
* 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.turnserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.log4j.BasicConfigurator;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
import de.javawi.jstun.attribute.ChangeRequest;
|
||||
import de.javawi.jstun.attribute.ChangedAddress;
|
||||
import de.javawi.jstun.attribute.MappedAddress;
|
||||
import de.javawi.jstun.attribute.MessageAttributeException;
|
||||
import de.javawi.jstun.attribute.MessageAttributeParsingException;
|
||||
import de.javawi.jstun.attribute.ResponseAddress;
|
||||
import de.javawi.jstun.attribute.SourceAddress;
|
||||
import de.javawi.jstun.attribute.UnknownAttribute;
|
||||
import de.javawi.jstun.attribute.UnknownMessageAttributeException;
|
||||
import de.javawi.jstun.attribute.MessageAttributeInterface.MessageAttributeType;
|
||||
import de.javawi.jstun.header.MessageHeader;
|
||||
import de.javawi.jstun.header.MessageHeaderParsingException;
|
||||
import de.javawi.jstun.header.MessageHeaderInterface.MessageHeaderType;
|
||||
import de.javawi.jstun.util.Address;
|
||||
import de.javawi.jstun.util.UtilityException;
|
||||
|
||||
/*
|
||||
* This class implements a STUN server as described in RFC 3489.
|
||||
* The server requires a machine that is dual-homed to be functional.
|
||||
* This implementation uses a single ip/port. This lead to limited functionnality.
|
||||
*/
|
||||
public class TurnServer {
|
||||
private static Logger logger = Logger.getLogger(TurnServer.class);
|
||||
Vector<DatagramSocket> sockets;
|
||||
|
||||
public TurnServer(int primaryPort, InetAddress primary) throws SocketException {
|
||||
sockets = new Vector<DatagramSocket>();
|
||||
sockets.add(new DatagramSocket(primaryPort, primary));
|
||||
}
|
||||
|
||||
public TurnServer(int primaryPort, InetAddress primary, int secondaryPort, InetAddress secondary) throws SocketException {
|
||||
sockets = new Vector<DatagramSocket>();
|
||||
sockets.add(new DatagramSocket(primaryPort, primary));
|
||||
//sockets.add(new DatagramSocket(secondaryPort, primary));
|
||||
//sockets.add(new DatagramSocket(primaryPort, secondary));
|
||||
//sockets.add(new DatagramSocket(secondaryPort, secondary));
|
||||
}
|
||||
|
||||
public void start() throws SocketException {
|
||||
for (DatagramSocket socket : sockets) {
|
||||
socket.setReceiveBufferSize(2000);
|
||||
StunServerReceiverThread ssrt = new StunServerReceiverThread(socket);
|
||||
ssrt.start();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Inner class to handle incoming packets and react accordingly.
|
||||
* I decided not to start a thread for every received Binding Request, because the time
|
||||
* required to receive a Binding Request, parse it, generate a Binding Response and send
|
||||
* it varies only between 2 and 4 milliseconds. This amount of time is small enough so
|
||||
* that no extra thread is needed for incoming Binding Request.
|
||||
*/
|
||||
class StunServerReceiverThread extends Thread {
|
||||
private DatagramSocket receiverSocket;
|
||||
private DatagramSocket changedPort;
|
||||
private DatagramSocket changedIP;
|
||||
private DatagramSocket changedPortIP;
|
||||
|
||||
StunServerReceiverThread(DatagramSocket datagramSocket) {
|
||||
this.receiverSocket = datagramSocket;
|
||||
for (DatagramSocket socket : sockets) {
|
||||
if ((socket.getLocalPort() != receiverSocket.getLocalPort()) &&
|
||||
(socket.getLocalAddress().equals(receiverSocket.getLocalAddress())))
|
||||
changedPort = socket;
|
||||
if ((socket.getLocalPort() == receiverSocket.getLocalPort()) &&
|
||||
(!socket.getLocalAddress().equals(receiverSocket.getLocalAddress())))
|
||||
changedIP = socket;
|
||||
if ((socket.getLocalPort() != receiverSocket.getLocalPort()) &&
|
||||
(!socket.getLocalAddress().equals(receiverSocket.getLocalAddress())))
|
||||
changedPortIP = socket;
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
DatagramPacket receive = new DatagramPacket(new byte[200], 200);
|
||||
receiverSocket.receive(receive);
|
||||
logger.debug(receiverSocket.getLocalAddress().getHostAddress() + ":" + receiverSocket.getLocalPort() + " datagram received from " + receive.getAddress().getHostAddress() + ":" + receive.getPort());
|
||||
MessageHeader receiveMH = MessageHeader.parseHeader(receive.getData());
|
||||
try {
|
||||
receiveMH.parseAttributes(receive.getData());
|
||||
logger.info(receiverSocket.getLocalAddress().getHostAddress() + ":" + receiverSocket.getLocalPort() + " Request received from " + receive.getAddress().getHostAddress() + ":" + receive.getPort());
|
||||
|
||||
if (receiveMH.getType() == MessageHeaderType.BindingRequest) {
|
||||
logger.info("Binding Request received ");
|
||||
ChangeRequest cr = (ChangeRequest) receiveMH.getMessageAttribute(MessageAttributeType.ChangeRequest);
|
||||
if (cr == null) throw new MessageAttributeException("Message attribute change request is not set.");
|
||||
ResponseAddress ra = (ResponseAddress) receiveMH.getMessageAttribute(MessageAttributeType.ResponseAddress);
|
||||
|
||||
MessageHeader sendMH = new MessageHeader(MessageHeaderType.BindingResponse);
|
||||
sendMH.setTransactionID(receiveMH.getTransactionID());
|
||||
|
||||
// Mapped address attribute
|
||||
MappedAddress ma = new MappedAddress();
|
||||
ma.setAddress(new Address(receive.getAddress().getAddress()));
|
||||
ma.setPort(receive.getPort());
|
||||
sendMH.addMessageAttribute(ma);
|
||||
// Changed address attribute
|
||||
//ChangedAddress ca = new ChangedAddress();
|
||||
//ca.setAddress(new Address(changedPortIP.getLocalAddress().getAddress()));
|
||||
//ca.setPort(changedPortIP.getLocalPort());
|
||||
//sendMH.addMessageAttribute(ca);
|
||||
if (cr.isChangePort() && (!cr.isChangeIP())) {
|
||||
logger.info("Change port received in Change Request attribute");
|
||||
// Source address attribute
|
||||
SourceAddress sa = new SourceAddress();
|
||||
sa.setAddress(new Address(changedPort.getLocalAddress().getAddress()));
|
||||
sa.setPort(changedPort.getLocalPort());
|
||||
sendMH.addMessageAttribute(sa);
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
if (ra != null) {
|
||||
send.setPort(ra.getPort());
|
||||
send.setAddress(ra.getAddress().getInetAddress());
|
||||
} else {
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
}
|
||||
changedPort.send(send);
|
||||
logger.info(changedPort.getLocalAddress().getHostAddress() + ":" + changedPort.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
} else if ((!cr.isChangePort()) && cr.isChangeIP()) {
|
||||
logger.info("Change ip received in Change Request attribute");
|
||||
// Source address attribute
|
||||
SourceAddress sa = new SourceAddress();
|
||||
sa.setAddress(new Address(changedIP.getLocalAddress().getAddress()));
|
||||
sa.setPort(changedIP.getLocalPort());
|
||||
sendMH.addMessageAttribute(sa);
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
if (ra != null) {
|
||||
send.setPort(ra.getPort());
|
||||
send.setAddress(ra.getAddress().getInetAddress());
|
||||
} else {
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
}
|
||||
changedIP.send(send);
|
||||
logger.info(changedIP.getLocalAddress().getHostAddress() + ":" + changedIP.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
} else if ((!cr.isChangePort()) && (!cr.isChangeIP())) {
|
||||
logger.info("Nothing received in Change Request attribute");
|
||||
// Source address attribute
|
||||
SourceAddress sa = new SourceAddress();
|
||||
sa.setAddress(new Address(receiverSocket.getLocalAddress().getAddress()));
|
||||
sa.setPort(receiverSocket.getLocalPort());
|
||||
sendMH.addMessageAttribute(sa);
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
if (ra != null) {
|
||||
send.setPort(ra.getPort());
|
||||
send.setAddress(ra.getAddress().getInetAddress());
|
||||
} else {
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
}
|
||||
receiverSocket.send(send);
|
||||
logger.info(receiverSocket.getLocalAddress().getHostAddress() + ":" + receiverSocket.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
} else if (cr.isChangePort() && cr.isChangeIP()) {
|
||||
logger.info("Change port and ip received in Change Request attribute");
|
||||
// Source address attribute
|
||||
SourceAddress sa = new SourceAddress();
|
||||
sa.setAddress(new Address(changedPortIP.getLocalAddress().getAddress()));
|
||||
sa.setPort(changedPortIP.getLocalPort());
|
||||
sendMH.addMessageAttribute(sa);
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
if (ra != null) {
|
||||
send.setPort(ra.getPort());
|
||||
send.setAddress(ra.getAddress().getInetAddress());
|
||||
} else {
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
}
|
||||
changedPortIP.send(send);
|
||||
logger.info(changedPortIP.getLocalAddress().getHostAddress() + ":" + changedPortIP.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
}
|
||||
} else if (receiveMH.getType() == MessageHeaderType.AllocateRequest) {
|
||||
logger.info("Allocate Request received ");
|
||||
MessageHeader sendMH = new MessageHeader(MessageHeaderType.AllocateResponse);
|
||||
sendMH.setTransactionID(receiveMH.getTransactionID());
|
||||
|
||||
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
receiverSocket.send(send);
|
||||
logger.info( "Send Allocate Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
}
|
||||
} catch (UnknownMessageAttributeException umae) {
|
||||
umae.printStackTrace();
|
||||
// Generate Binding error response
|
||||
MessageHeader sendMH = new MessageHeader(MessageHeaderType.BindingErrorResponse);
|
||||
sendMH.setTransactionID(receiveMH.getTransactionID());
|
||||
|
||||
// Unknown attributes
|
||||
UnknownAttribute ua = new UnknownAttribute();
|
||||
ua.addAttribute(umae.getType());
|
||||
sendMH.addMessageAttribute(ua);
|
||||
|
||||
byte[] data = sendMH.getBytes();
|
||||
DatagramPacket send = new DatagramPacket(data, data.length);
|
||||
send.setPort(receive.getPort());
|
||||
send.setAddress(receive.getAddress());
|
||||
receiverSocket.send(send);
|
||||
logger.info(changedPortIP.getLocalAddress().getHostAddress() + ":" + changedPortIP.getLocalPort() + " send Binding Error Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (MessageAttributeParsingException mape) {
|
||||
mape.printStackTrace();
|
||||
} catch (MessageAttributeException mae) {
|
||||
mae.printStackTrace();
|
||||
} catch (MessageHeaderParsingException mhpe) {
|
||||
mhpe.printStackTrace();
|
||||
} catch (UtilityException ue) {
|
||||
ue.printStackTrace();
|
||||
} catch (ArrayIndexOutOfBoundsException aioobe) {
|
||||
aioobe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To invoke the STUN server two IP addresses and two ports are required.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
if (args.length != 4) {
|
||||
System.out.println("usage: java de.javawi.jstun.test.demo.StunServer PORT1 IP1 PORT2 IP2");
|
||||
System.out.println();
|
||||
System.out.println(" PORT1 - the first port that should be used by the server");
|
||||
System.out.println(" IP1 - the first ip address that should be used by the server");
|
||||
System.out.println(" PORT2 - the second port that should be used by the server");
|
||||
System.out.println(" IP2 - the second ip address that should be used by the server");
|
||||
System.exit(0);
|
||||
}
|
||||
BasicConfigurator.configure();
|
||||
TurnServer ss = new TurnServer(Integer.parseInt(args[0]),
|
||||
InetAddress.getByName(args[1]),
|
||||
Integer.parseInt(args[2]),
|
||||
InetAddress.getByName(args[3]));
|
||||
ss.start();
|
||||
} catch (SocketException se) {
|
||||
se.printStackTrace();
|
||||
} catch (UnknownHostException uhe) {
|
||||
uhe.printStackTrace();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,8 @@ import junit.framework.TestCase;
|
|||
|
||||
import org.apache.log4j.BasicConfigurator;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.linphone.p2pproxy.core.turnserver.TurnServer;
|
||||
import org.linphone.p2pproxy.core.stun.StunServer;
|
||||
|
||||
|
||||
|
||||
import de.javawi.jstun.attribute.ChangeRequest;
|
||||
|
|
@ -40,8 +41,8 @@ import de.javawi.jstun.header.MessageHeaderParsingException;
|
|||
import de.javawi.jstun.test.DiscoveryInfo;
|
||||
import de.javawi.jstun.util.UtilityException;
|
||||
|
||||
public class TurnServerTester extends TestCase {
|
||||
private static Logger logger = Logger.getLogger(TurnServerTester.class);
|
||||
public class StunServerTester extends TestCase {
|
||||
private static Logger logger = Logger.getLogger(StunServerTester.class);
|
||||
InetAddress iaddress ;
|
||||
String stunServer = "localhost";
|
||||
int port = 16000;
|
||||
|
|
@ -51,14 +52,14 @@ public class TurnServerTester extends TestCase {
|
|||
boolean nodeNatted = true;
|
||||
DatagramSocket socketTest1 = null;
|
||||
DiscoveryInfo di = null;
|
||||
static TurnServer mSturServer = null;
|
||||
static StunServer mSturServer = null;
|
||||
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
if (mSturServer == null) {
|
||||
BasicConfigurator.configure();
|
||||
if (mSturServer == null) mSturServer = new TurnServer(port,InetAddress.getByName("localhost"));
|
||||
if (mSturServer == null) mSturServer = new StunServer(port,InetAddress.getByName("localhost"),port+1);
|
||||
mSturServer.start();
|
||||
iaddress = InetAddress.getLocalHost();
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue