]> sjero.net Git - linphone/blob - p2pproxy/dependencies-src/jxse-src-2.5/api/src/net/jxta/platform/NetworkManager.java
remove mediastreamer2 and add it as a submodule instead.
[linphone] / p2pproxy / dependencies-src / jxse-src-2.5 / api / src / net / jxta / platform / NetworkManager.java
1 /*
2  * Copyright (c) 2006-2007 Sun Microsystems, Inc.  All rights reserved.
3  *  
4  *  The Sun Project JXTA(TM) Software License
5  *  
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions are met:
8  *  
9  *  1. Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *  
12  *  2. Redistributions in binary form must reproduce the above copyright notice, 
13  *     this list of conditions and the following disclaimer in the documentation 
14  *     and/or other materials provided with the distribution.
15  *  
16  *  3. The end-user documentation included with the redistribution, if any, must 
17  *     include the following acknowledgment: "This product includes software 
18  *     developed by Sun Microsystems, Inc. for JXTA(TM) technology." 
19  *     Alternately, this acknowledgment may appear in the software itself, if 
20  *     and wherever such third-party acknowledgments normally appear.
21  *  
22  *  4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must 
23  *     not be used to endorse or promote products derived from this software 
24  *     without prior written permission. For written permission, please contact 
25  *     Project JXTA at http://www.jxta.org.
26  *  
27  *  5. Products derived from this software may not be called "JXTA", nor may 
28  *     "JXTA" appear in their name, without prior written permission of Sun.
29  *  
30  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
32  *  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN 
33  *  MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
34  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
35  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
36  *  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
37  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
38  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
39  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *  
41  *  JXTA is a registered trademark of Sun Microsystems, Inc. in the United 
42  *  States and other countries.
43  *  
44  *  Please see the license information page at :
45  *  <http://www.jxta.org/project/www/license.html> for instructions on use of 
46  *  the license in source files.
47  *  
48  *  ====================================================================
49  *  
50  *  This software consists of voluntary contributions made by many individuals 
51  *  on behalf of Project JXTA. For more information on Project JXTA, please see 
52  *  http://www.jxta.org.
53  *  
54  *  This license is based on the BSD license adopted by the Apache Foundation. 
55  */
56
57 package net.jxta.platform;
58
59
60 import javax.security.cert.CertificateException;
61 import java.io.File;
62 import java.io.IOException;
63 import java.net.URI;
64 import java.util.logging.Level;
65 import java.util.logging.Logger;
66
67 import net.jxta.credential.AuthenticationCredential;
68 import net.jxta.credential.Credential;
69 import net.jxta.exception.PeerGroupException;
70 import net.jxta.exception.ProtocolNotSupportedException;
71 import net.jxta.id.IDFactory;
72 import net.jxta.logging.Logging;
73 import net.jxta.membership.InteractiveAuthenticator;
74 import net.jxta.membership.MembershipService;
75 import net.jxta.peer.PeerID;
76 import net.jxta.peergroup.NetPeerGroupFactory;
77 import net.jxta.peergroup.PeerGroup;
78 import net.jxta.peergroup.PeerGroupID;
79 import net.jxta.rendezvous.RendezVousService;
80 import net.jxta.rendezvous.RendezvousEvent;
81 import net.jxta.rendezvous.RendezvousListener;
82
83 import net.jxta.impl.membership.pse.StringAuthenticator;
84
85
86 /**
87  * NetworkManager provides a simplified JXTA platform configuration abstraction, and provides a JXTA platform life-cycle
88  * management. The node configuration is created during construction of this object and can be obtained for fine tuning
89  * or alteration.  Note that all alterations must be done prior to calling #startNetwork(), otherwise the default
90  * configuration is used.  Configuration persistence is on by default and maybe overridden by call to #setEnableConfigPersistence
91  * <p/>
92  * NetworkManager defines six abstractions of a node configurations as follows :
93  * ADHOC : A node which typically deployed in an ad-hoc network
94  * EDGE : In addition to supporting ADHOC function, an Edge node can attach to a infrastructure (a Rendezvous, Relay, or both)
95  * RENDEZVOUS: provides network bootstrapping services, such as discovery, pipe resolution, etc.
96  * RELAY: provides message relaying services, enabling cross firewall traversal
97  * PROXY: provide JXME JXTA for J2ME proxying services
98  * SUPER: provide the functionality of a Rendezvous, Relay, Proxy node.
99  */
100 public class NetworkManager implements RendezvousListener {
101
102     /**
103      * Logger
104      */
105     private final static transient Logger LOG = Logger.getLogger(NetworkManager.class.getName());
106
107     protected final transient URI publicSeedingRdvURI = URI.create("http://rdv.jxtahosts.net/cgi-bin/rendezvous.cgi?3");
108     protected final transient URI publicSeedingRelayURI = URI.create("http://rdv.jxtahosts.net/cgi-bin/relays.cgi?3");
109
110     /**
111      * Define node standard node operating modes
112      */
113     public enum ConfigMode {
114
115         /**
116          * A AD-HOC node
117          */
118         ADHOC,
119         /**
120          * A Edge node
121          */
122         EDGE,
123         /**
124          * A Rendezvous node
125          */
126         RENDEZVOUS,
127         /**
128          * A Relay node
129          */
130         RELAY,
131         /**
132          * Rendezvous and a Relay
133          */
134         RENDEZVOUS_RELAY,
135         /**
136          * JXME Proxy node
137          */
138         PROXY,
139         /**
140          * A Rendezvous, Relay, and JXME Proxy node
141          */
142         SUPER
143     }
144
145     private final Object networkConnectLock = new String("rendezvous connection lock");
146     private PeerGroup netPeerGroup = null;
147     private volatile boolean started = false;
148     private volatile boolean connected = false;
149     private volatile boolean stopped = false;
150     private RendezVousService rendezvous;
151     private String instanceName = "NA";
152     private ShutdownHook shutdownHook;
153     private ConfigMode mode;
154     private URI instanceHome;
155     private PeerGroupID infrastructureID = PeerGroupID.defaultNetPeerGroupID;
156     private PeerID peerID = IDFactory.newPeerID(PeerGroupID.defaultNetPeerGroupID);
157     private NetworkConfigurator config;
158     private boolean configPersistent = true;
159     private boolean useDefaultSeeds;
160
161     /**
162      * Creates NetworkManger instance with default instance home set to "$CWD"/.jxta"
163      * At this point, alternate Infrastructure PeerGroupID maybe specified, as well as a PeerID. if neither are
164      * specified, the default NetPeerGroupID will be used, and a new PeerID will be generated. Also note the default
165      * seeding URIs are the to development. Alternate values must be specified, if desired, prior to a call to {@link #startNetwork}
166      *
167      * @param mode         Operating mode  the node operating {@link ConfigMode}
168      * @param instanceName Node name
169      * @throws IOException if an io error occurs
170      */
171     public NetworkManager(ConfigMode mode, String instanceName) throws IOException {
172         this(mode, instanceName, new File(".jxta/").toURI());
173     }
174
175     /**
176      * Creates NetworkManger instance.
177      * At this point, alternate Infrastructure PeerGroupID maybe specified, as well as a PeerID. if neither are
178      * specified, the default NetPeerGroupID will be used, and a new PeerID will be generated. Also note the default
179      * seeding URIs are the to development. Alternate values must be specified, if desired, prior to a call to {@link #startNetwork}
180      *
181      * @param mode         Operating mode  the node operating {@link ConfigMode}
182      * @param instanceName Node name
183      * @param instanceHome instance home is a uri to the instance persistent store (aka Cache Manager store home)
184      * @throws IOException if an io error occurs
185      */
186     public NetworkManager(ConfigMode mode, String instanceName, URI instanceHome) throws IOException {
187         this.instanceName = instanceName;
188         this.mode = mode;
189         this.instanceHome = instanceHome;
190     }
191
192     /**
193      * Returns the {@link NetworkConfigurator} for additional tuning
194      *
195      * @return the {@link NetworkConfigurator} for additional tuning
196      * @throws java.io.IOException if an io error occurs
197      */
198     public synchronized NetworkConfigurator getConfigurator() throws IOException {
199         if (config == null) {
200             configure(mode);
201         }
202         return config;
203     }
204
205     /**
206      * Getter for property 'infrastructureID'.
207      *
208      * @return Value for property 'infrastructureID'.
209      */
210     public PeerGroupID getInfrastructureID() {
211         return infrastructureID;
212     }
213
214     /**
215      * Setter for property 'infrastructureID'.
216      *
217      * @param infrastructureID Value to set for property 'infrastructureID'.
218      */
219     public void setInfrastructureID(PeerGroupID infrastructureID) {
220         this.infrastructureID = infrastructureID;
221         if (config != null) {
222             config.setInfrastructureID(infrastructureID);
223         }
224     }
225
226     /**
227      * Getter for property 'instanceName'.
228      *
229      * @return Value for property 'instanceName'.
230      */
231     public String getInstanceName() {
232         return instanceName;
233     }
234
235     /**
236      * Setter for property 'instanceName'.
237      *
238      * @param instanceName Value to set for property 'instanceName'.
239      */
240     public void setInstanceName(String instanceName) {
241         this.instanceName = instanceName;
242     }
243
244     /**
245      * Getter for property 'instanceHome'.
246      *
247      * @return Value for property 'instanceHome'.
248      */
249     public URI getInstanceHome() {
250         return instanceHome;
251     }
252
253     /**
254      * Setter for property 'instanceHome'.
255      *
256      * @param instanceHome Value to set for property 'instanceHome'.
257      */
258     public void setInstanceHome(URI instanceHome) {
259         this.instanceHome = instanceHome;
260     }
261
262     /**
263      * Getter for property node operating 'mode'.
264      *
265      * @return Value for property 'mode'.
266      */
267     public ConfigMode getMode() {
268         return mode;
269     }
270
271     /**
272      * Setter for property 'mode'.
273      *
274      * @param mode Value to set for property 'mode'.
275      * @throws IOException if an io error occurs
276      */
277     public void setMode(ConfigMode mode) throws IOException {
278         this.mode = mode;
279         configure(mode);
280     }
281
282     /**
283      * Getter for property 'peerID'.
284      *
285      * @return Value for property 'peerID'.
286      */
287     public PeerID getPeerID() {
288         return peerID;
289     }
290
291     /**
292      * Setter for property 'peerID'.
293      *
294      * @param peerID Value to set for property 'peerID'.
295      */
296     public void setPeerID(PeerID peerID) {
297         this.peerID = peerID;
298     }
299
300     /**
301      * Getter for property 'configPersistent'.
302      *
303      * @return Value for property 'configPersistent'.
304      */
305     public boolean isConfigPersistent() {
306         return configPersistent;
307     }
308
309     /**
310      * Setter for property 'configPersistent'. if disabled a PlatformConfig is not persisted. It assumed that
311      * the PeerID is will be set, or a new PeerID will always be generated.
312      *
313      * @param persisted Value to set for property 'configPersistent'.
314      */
315     public void setConfigPersistent(boolean persisted) {
316         this.configPersistent = persisted;
317     }
318
319     private void configure(ConfigMode mode) throws IOException {
320         switch (mode) {
321             case ADHOC:
322                 config = NetworkConfigurator.newAdHocConfiguration(instanceHome);
323                 break;
324
325             case EDGE:
326                 config = NetworkConfigurator.newEdgeConfiguration(instanceHome);
327                 break;
328
329             case RENDEZVOUS:
330                 config = NetworkConfigurator.newRdvConfiguration(instanceHome);
331                 break;
332
333             case RELAY:
334                 config = NetworkConfigurator.newRelayConfiguration(instanceHome);
335                 break;
336
337             case RENDEZVOUS_RELAY:
338                 config = NetworkConfigurator.newRdvRelayConfiguration(instanceHome);
339                 break;
340
341             case PROXY:
342                 config = NetworkConfigurator.newProxyConfiguration(instanceHome);
343                 break;
344
345             case SUPER:
346                 config = NetworkConfigurator.newRdvRelayProxyConfiguration(instanceHome);
347                 break;
348
349             default:
350                 config = NetworkConfigurator.newAdHocConfiguration(instanceHome);
351         }
352         if (!config.exists()) {
353             if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
354                 LOG.log(Level.INFO, "Created new configuration. mode = " + mode.toString());
355             }
356
357             config.setDescription("Created by NetworkManager");
358             config.setPeerID(peerID);
359             config.setInfrastructureID(infrastructureID);
360             config.setName(instanceName);
361             if (useDefaultSeeds) {
362                 config.addRdvSeedingURI(publicSeedingRdvURI);
363                 config.addRelaySeedingURI(publicSeedingRelayURI);
364             }
365         } else {
366             if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
367                 LOG.log(Level.INFO, "Loading existing configuration. mode = " + mode.toString());
368             }
369
370             File pc = new File(config.getHome(), "PlatformConfig");
371
372             try {
373                 config.load(pc.toURI());
374             } catch (CertificateException pseFailed) {
375                 IOException failure = new IOException("Failure reading membership service certificates.");
376
377                 failure.initCause(pseFailed);
378                 throw failure;
379             }
380
381             // XXX 20070524 bondolo Aren't we completely ignoring the mode? What if it changed?
382             // 20070614 hamada Good question, this feature is postponed due to the difficulty of comparing a stored/requested modes. 
383         }
384     }
385
386     /**
387      * Creates and starts the JXTA infrastructure peer group (aka NetPeerGroup) based on the specified mode
388      * template. This class also registers a listener for rendezvous events.
389      *
390      * @return The Net Peer Group
391      * @throws net.jxta.exception.PeerGroupException
392      *                             if the group fails to initialize
393      * @throws java.io.IOException if an io error occurs
394      */
395     public synchronized PeerGroup startNetwork() throws PeerGroupException, IOException {
396
397         if (started) {
398             return netPeerGroup;
399         }
400
401         if (config == null) {
402             configure(mode);
403         }
404
405         if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
406             LOG.log(Level.INFO, "Starting JXTA Network! MODE = " + mode.toString() + ",  HOME = " + instanceHome);
407         }
408
409         // create, and Start the default jxta NetPeerGroup
410         NetPeerGroupFactory factory = new NetPeerGroupFactory(config.getPlatformConfig(), instanceHome);
411
412         netPeerGroup = factory.getInterface();
413
414         if (configPersistent) {
415             config.save();
416         }
417
418         rendezvous = netPeerGroup.getRendezVousService();
419         rendezvous.addListener(this);
420         started = true;
421
422         if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
423             LOG.log(Level.INFO, "Started JXTA Network!");
424         }
425
426         return netPeerGroup;
427     }
428
429     /**
430      * Establishes group credential.  This is a required step when planning to
431      * to utilize TLS messengers or secure pipes
432      *
433      * @param group              peer group to establish credentials in
434      * @param keystore_password  The passphrase for the keystore. This is a
435      *                           char[] rather than a String so that it can be blanked after use.
436      * @param principal_password The passphrase for the identity. This is a
437      *                           char[] rather than a String so that it can be blanked after use.
438      * @throws net.jxta.exception.PeerGroupException
439      *          if group credentials were rejected
440      * @throws net.jxta.exception.ProtocolNotSupportedException
441      *          if authenticator rejected the credential
442      */
443     public static void login(PeerGroup group, char[] keystore_password, char[] principal_password) throws PeerGroupException, ProtocolNotSupportedException {
444         StringAuthenticator auth;
445         MembershipService membership = group.getMembershipService();
446         Credential cred = membership.getDefaultCredential();
447
448         if (cred == null) {
449             AuthenticationCredential authCred = new AuthenticationCredential(group, "StringAuthentication", null);
450
451             auth = (StringAuthenticator) membership.apply(authCred);
452             if (auth != null) {
453                 auth.setAuth1_KeyStorePassword(keystore_password);
454                 auth.setAuth2Identity(group.getPeerID());
455                 auth.setAuth3_IdentityPassword(principal_password);
456                 if (auth.isReadyForJoin()) {
457                     membership.join(auth);
458                 }
459             }
460         }
461
462         cred = membership.getDefaultCredential();
463         if (null == cred) {
464             AuthenticationCredential authCred = new AuthenticationCredential(group, "InteractiveAuthentication", null);
465             InteractiveAuthenticator iAuth = (InteractiveAuthenticator) membership.apply(authCred);
466
467             if (iAuth.interact() && iAuth.isReadyForJoin()) {
468                 membership.join(iAuth);
469             }
470         }
471     }
472
473     /**
474      * Stops and unreferences the NetPeerGroup
475      */
476     public synchronized void stopNetwork() {
477         if (stopped || !started) {
478             return;
479         }
480
481         if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
482             LOG.log(Level.INFO, "Stopping JXTA Network!");
483         }
484
485         stopped = true;
486         synchronized(networkConnectLock) {
487             connected = false;
488             networkConnectLock.notifyAll();
489         }
490         
491         rendezvous.removeListener(this);
492         netPeerGroup.stopApp();
493         netPeerGroup.unref();
494         netPeerGroup = null;
495         // permit restart.
496         started = false;
497
498         if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
499             LOG.log(Level.INFO, "Stopped JXTA Network!");
500         }
501     }
502
503     /**
504      * Gets the netPeerGroup object
505      *
506      * @return The netPeerGroup value
507      */
508     public PeerGroup getNetPeerGroup() {
509         return netPeerGroup;
510     }
511
512     /**
513      * Blocks only, if not connected to a rendezvous, or until a connection to rendezvous node occurs.
514      *
515      * @param timeout timeout in milliseconds, a zero timeout of waits forever
516      * @return true if connected to a rendezvous, false otherwise
517      */
518     public boolean waitForRendezvousConnection(long timeout) {
519         if (0 == timeout) {
520             timeout = Long.MAX_VALUE;
521         }
522
523         long timeoutAt = System.currentTimeMillis() + timeout;
524
525         if (timeoutAt <= 0) {
526             // handle overflow.
527             timeoutAt = Long.MAX_VALUE;
528         }
529
530         while (started && !stopped && !rendezvous.isConnectedToRendezVous() && !rendezvous.isRendezVous()) {
531             try {
532                 long waitFor = timeoutAt - System.currentTimeMillis();
533
534                 if (waitFor > 0) {
535                     synchronized (networkConnectLock) {
536                         networkConnectLock.wait(timeout);
537                     }
538                 } else {
539                     // all done with waiting.
540                     break;
541                 }
542             } catch (InterruptedException e) {
543                 Thread.interrupted();
544                 break;
545             }
546         }
547         
548         return rendezvous.isConnectedToRendezVous() || rendezvous.isRendezVous();
549     }
550
551     /**
552      * rendezvousEvent the rendezvous event
553      *
554      * @param event rendezvousEvent
555      */
556     public void rendezvousEvent(RendezvousEvent event) {
557         if (event.getType() == RendezvousEvent.RDVCONNECT || event.getType() == RendezvousEvent.RDVRECONNECT
558                 || event.getType() == RendezvousEvent.BECAMERDV) {
559             synchronized (networkConnectLock) {
560                 connected = true;
561                 networkConnectLock.notifyAll();
562             }
563         }
564     }
565
566     /**
567      * if true uses the public rendezvous seeding service
568      *
569      * @param useDefaultSeeds if true uses the default development seeding service
570      */
571     public void setUseDefaultSeeds(boolean useDefaultSeeds) {
572         this.useDefaultSeeds = useDefaultSeeds;
573     }
574
575     /**
576      * Returns true if useDefaultSeeds is set to true
577      *
578      * @return true if useDefaultSeeds is set to true
579      */
580     public boolean getUseDefaultSeeds() {
581         return useDefaultSeeds;
582     }
583
584     /**
585      * Registers a Runtime shutdown hook to cleanly shutdown the JXTA platform
586      */
587     public synchronized void registerShutdownHook() {
588         if (shutdownHook != null) {
589             return;
590         }
591         shutdownHook = new NetworkManager.ShutdownHook();
592         Runtime.getRuntime().addShutdownHook(shutdownHook);
593     }
594
595     /**
596      * Unregisters a Runtime shutdown hook to cleanly shutdown the JXTA platform
597      */
598     public synchronized void unregisterShutdownHook() {
599
600         if (shutdownHook == null) {
601             return;
602         }
603         Runtime.getRuntime().removeShutdownHook(shutdownHook);
604         shutdownHook = null;
605     }
606
607     private class ShutdownHook extends Thread {
608
609         /**
610          * {@inheritDoc}
611          */
612         @Override
613         public void run() {
614             stopNetwork();
615         }
616     }
617 }