📄 upnpsswanconnectionimpl.java
字号:
/*
* Created on 15-Jun-2004
* Created by Paul Gardner
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package com.aelitis.net.upnp.impl.services;
import java.util.*;
import org.gudy.azureus2.core3.util.*;
import com.aelitis.net.upnp.*;
import com.aelitis.net.upnp.impl.UPnPImpl;
import com.aelitis.net.upnp.impl.device.UPnPRootDeviceImpl;
import com.aelitis.net.upnp.services.UPnPWANConnection;
import com.aelitis.net.upnp.services.UPnPWANConnectionListener;
import com.aelitis.net.upnp.services.UPnPWANConnectionPortMapping;
/**
* @author parg
*
*/
public class
UPnPSSWANConnectionImpl
implements UPnPWANConnection
{
private static AEMonitor class_mon = new AEMonitor( "UPnPSSWANConnection" );
private static List services = new ArrayList();
static{
SimpleTimer.addPeriodicEvent(
"UPnPSSWAN:checker",
10*60*1000,
new TimerEventPerformer() {
public void perform( TimerEvent ev ) {
try{
List to_check = new ArrayList();
try{
class_mon.enter();
Iterator it = services.iterator();
while( it.hasNext()){
UPnPSSWANConnectionImpl s = (UPnPSSWANConnectionImpl)it.next();
if ( s.getGenericService().getDevice().getRootDevice().isDestroyed()){
it.remove();
}else{
to_check.add( s );
}
}
}finally{
class_mon.exit();
}
for (int i=0;i<to_check.size();i++){
try{
((UPnPSSWANConnectionImpl)to_check.get(i)).checkMappings();
}catch( Throwable e ){
//Debug.printStackTrace(e);
}
}
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
);
}
private UPnPServiceImpl service;
private List mappings = new ArrayList();
private List listeners = new ArrayList();
private boolean recheck_mappings = true;
// start off true to avoid logging first of repetitive failures
private boolean last_mapping_check_failed = true;
protected
UPnPSSWANConnectionImpl(
UPnPServiceImpl _service )
{
service = _service;
try{
class_mon.enter();
services.add( this );
}finally{
class_mon.exit();
}
}
public int
getCapabilities()
{
String device_name = service.getDevice().getRootDevice().getDevice().getFriendlyName();
int capabilities = CAP_ALL;
if ( device_name.equals( "WRT54G" )){
capabilities = CAP_ALL & ~CAP_UDP_TCP_SAME_PORT;
}
return( capabilities );
}
public UPnPService
getGenericService()
{
return( service );
}
public String[]
getStatusInfo()
throws UPnPException
{
UPnPAction act = service.getAction( "GetStatusInfo" );
if ( act == null ){
log( "Action 'GetStatusInfo' not supported, binding not established" );
throw( new UPnPException( "GetStatusInfo not supported" ));
}else{
UPnPActionInvocation inv = act.getInvocation();
UPnPActionArgument[] args = inv.invoke();
String connection_status = null;
String connection_error = null;
String uptime = null;
for (int i=0;i<args.length;i++){
UPnPActionArgument arg = args[i];
String name = arg.getName();
if ( name.equalsIgnoreCase("NewConnectionStatus")){
connection_status = arg.getValue();
}else if ( name.equalsIgnoreCase("NewLastConnectionError")){
connection_error = arg.getValue();
}else if ( name.equalsIgnoreCase("NewUptime")){
uptime = arg.getValue();
}
}
return( new String[]{ connection_status, connection_error, uptime });
}
}
public void
periodicallyRecheckMappings(
boolean on )
{
recheck_mappings = on;
}
protected void
checkMappings()
throws UPnPException
{
if ( !recheck_mappings ){
return;
}
List mappings_copy;
try{
class_mon.enter();
mappings_copy = new ArrayList( mappings );
}finally{
class_mon.exit();
}
UPnPWANConnectionPortMapping[] current = getPortMappings();
Iterator it = mappings_copy.iterator();
while( it.hasNext()){
portMapping mapping = (portMapping)it.next();
for (int j=0;j<current.length;j++){
UPnPWANConnectionPortMapping c = current[j];
if ( c.getExternalPort() == mapping.getExternalPort() &&
c.isTCP() == mapping.isTCP()){
it.remove();
break;
}
}
}
boolean log = false;
if ( mappings_copy.size() > 0 ){
if ( !last_mapping_check_failed ){
last_mapping_check_failed = true;
log = true;
}
}else{
last_mapping_check_failed = false;
}
it = mappings_copy.iterator();
while( it.hasNext()){
portMapping mapping = (portMapping)it.next();
try{
// some routers appear to continually fail to report the mappings - avoid
// reporting this
if ( log ){
log( "Re-establishing mapping " + mapping.getString());
}
addPortMapping( mapping.isTCP(), mapping.getExternalPort(), mapping.getDescription());
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
public void
addPortMapping(
boolean tcp, // false -> UDP
int port,
String description )
throws UPnPException
{
UPnPAction act = service.getAction( "AddPortMapping" );
if ( act == null ){
log( "Action 'AddPortMapping' not supported, binding not established" );
}else{
UPnPActionInvocation add_inv = act.getInvocation();
add_inv.addArgument( "NewRemoteHost", "" ); // "" = wildcard for hosts, 0 = wildcard for ports
add_inv.addArgument( "NewExternalPort", "" + port );
add_inv.addArgument( "NewProtocol", tcp?"TCP":"UDP" );
add_inv.addArgument( "NewInternalPort", "" + port );
add_inv.addArgument( "NewInternalClient", service.getDevice().getRootDevice().getLocalAddress().getHostAddress());
add_inv.addArgument( "NewEnabled", "1" );
add_inv.addArgument( "NewPortMappingDescription", description );
add_inv.addArgument( "NewLeaseDuration", "0" ); // 0 -> infinite (?)
boolean ok = false;
try{
add_inv.invoke();
ok = true;
}catch( UPnPException original_error ){
// some routers won't add properly if the mapping's already there
try{
UPnPActionInvocation rem_inv = act.getInvocation();
rem_inv.addArgument( "NewRemoteHost", "" ); // "" = wildcard for hosts, 0 = wildcard for ports
rem_inv.addArgument( "NewProtocol", tcp?"TCP":"UDP" );
rem_inv.addArgument( "NewExternalPort", "" + port );
rem_inv.invoke();
}catch( Throwable e ){
throw( original_error );
}
add_inv.invoke();
ok = true;
}finally{
((UPnPRootDeviceImpl)service.getDevice().getRootDevice()).portMappingResult(ok);
for (int i=0;i<listeners.size();i++){
UPnPWANConnectionListener listener = (UPnPWANConnectionListener)listeners.get(i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -