PageRenderTime 67ms CodeModel.GetById 21ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/razpubs/src/org/cybergarage/upnp/ControlPoint.java

http://razpub.googlecode.com/
Java | 929 lines | 610 code | 155 blank | 164 comment | 97 complexity | a247a5d75787a56d9ddb944b47a000e6 MD5 | raw file
  1/******************************************************************
  2*
  3*	CyberUPnP for Java
  4*
  5*	Copyright (C) Satoshi Konno 2002-2004
  6*
  7*	File: ControlPoint.java
  8*
  9*	Revision:
 10*
 11*	11/18/02
 12*		- first revision.
 13*	05/13/03
 14*		- Changed to create socket threads each local interfaces.
 15*		  (HTTP, SSDPNotiry, SSDPSerachResponse)
 16*	05/28/03
 17*		- Changed to send m-serach packets from SSDPSearchResponseSocket.
 18*		  The socket doesn't bind interface address.
 19*		- SSDPSearchResponsSocketList that binds a port and a interface can't
 20*		  send m-serch packets of IPv6 on J2SE v 1.4.1_02 and Redhat 9.
 21*	07/23/03
 22*		- Suzan Foster (suislief)
 23*		- Fixed a bug. HOST field was missing.
 24*	07/29/03
 25*		- Synchronized when a device is added by the ssdp message.
 26*	09/08/03
 27*		- Giordano Sassaroli <sassarol@cefriel.it>
 28*		- Problem : when an event notification message is received and the message
 29*		            contains updates on more than one variable, only the first variable update
 30*		            is notified.
 31*		- Error :  the other xml nodes of the message are ignored
 32*		- Fix : add two methods to the NotifyRequest for extracting the property array
 33*                and modify the httpRequestRecieved method in ControlPoint
 34*	12/12/03
 35*		- Added a static() to initialize UPnP class.
 36*	01/06/04
 37*		- Added the following methods to remove expired devices automatically
 38*		  removeExpiredDevices()
 39*		  setExpiredDeviceMonitoringInterval()/getExpiredDeviceMonitoringInterval()
 40*		  setDeviceDisposer()/getDeviceDisposer()
 41*	04/20/04
 42*		- Added the following methods.
 43*		  start(String target, int mx) and start(String target).
 44*	06/23/04
 45*		- Added setNMPRMode() and isNMPRMode().
 46*	07/08/04
 47*		- Added renewSubscriberService().
 48*		- Changed start() to create renew subscriber thread when the NMPR mode is true.
 49*	08/17/04
 50*		- Fixed removeExpiredDevices() to remove using the device array.
 51*	10/16/04
 52*		- Oliver Newell <newell@media-rush.com>
 53*		- Added this class to allow ControlPoint applications to be notified when 
 54*		  the ControlPoint base class adds/removes a UPnP device
 55*	03/30/05
 56*		- Changed addDevice() to use Parser::parse(URL).
 57*
 58*******************************************************************/
 59
 60package org.cybergarage.upnp;
 61
 62import org.cybergarage.net.*;
 63import org.cybergarage.util.*;
 64import org.cybergarage.xml.*;
 65import org.cybergarage.http.*;
 66
 67import org.cybergarage.upnp.control.*;
 68import org.cybergarage.upnp.ssdp.*;
 69import org.cybergarage.upnp.device.*;
 70import org.cybergarage.upnp.event.*;
 71
 72import com.razie.pub.base.log.Log;
 73
 74import java.net.*;
 75
 76public class ControlPoint implements HTTPRequestListener
 77{
 78	private final static int DEFAULT_EVENTSUB_PORT = 8058;
 79	private final static int DEFAULT_SSDP_PORT = 8008;
 80	private final static int DEFAULT_EXPIRED_DEVICE_MONITORING_INTERVAL = 60;
 81	
 82	private final static String DEFAULT_EVENTSUB_URI = "/evetSub";
 83	
 84	////////////////////////////////////////////////
 85	//	Member
 86	////////////////////////////////////////////////
 87	
 88	private SSDPNotifySocketList ssdpNotifySocketList;
 89	private SSDPSearchResponseSocketList ssdpSearchResponseSocketList;
 90
 91	private SSDPNotifySocketList getSSDPNotifySocketList()
 92	{
 93		return ssdpNotifySocketList;
 94	}
 95	
 96	private SSDPSearchResponseSocketList getSSDPSearchResponseSocketList()
 97	{
 98		return ssdpSearchResponseSocketList;
 99	}
100
101	////////////////////////////////////////////////
102	//	Initialize
103	////////////////////////////////////////////////
104	
105	static 
106	{
107		UPnP.initialize();
108	}
109	
110	////////////////////////////////////////////////
111	//	Constructor
112	////////////////////////////////////////////////
113
114	public ControlPoint(int ssdpPort, int httpPort)
115	{
116		ssdpNotifySocketList = new SSDPNotifySocketList();
117		ssdpSearchResponseSocketList = new SSDPSearchResponseSocketList();
118		
119		setSSDPPort(ssdpPort);
120		setHTTPPort(httpPort);
121		
122		setDeviceDisposer(null);
123		setExpiredDeviceMonitoringInterval(DEFAULT_EXPIRED_DEVICE_MONITORING_INTERVAL);
124
125		setRenewSubscriber(null);
126				
127		setNMPRMode(false);
128		setRenewSubscriber(null);
129	}
130
131	public ControlPoint()
132	{
133		this(DEFAULT_SSDP_PORT, DEFAULT_EVENTSUB_PORT);
134	}
135
136	public void finalize()
137	{
138		stop();
139	}
140
141	////////////////////////////////////////////////
142	// Mutex
143	////////////////////////////////////////////////
144	
145	private Mutex mutex = new Mutex();
146	
147	public void lock()
148	{
149		mutex.lock();
150	}
151	
152	public void unlock()
153	{
154		mutex.unlock();
155	}
156	
157	////////////////////////////////////////////////
158	//	Port (SSDP)
159	////////////////////////////////////////////////
160
161	private int ssdpPort = 0;
162	
163	public int getSSDPPort() {
164		return ssdpPort;
165	}
166
167	public void setSSDPPort(int port) {
168		ssdpPort = port;
169	}
170
171	////////////////////////////////////////////////
172	//	Port (EventSub)
173	////////////////////////////////////////////////
174
175	private int httpPort = 0;
176	
177	public int getHTTPPort() {
178		return httpPort;
179	}
180
181	public void setHTTPPort(int port) {
182		httpPort = port;
183	}
184	
185	////////////////////////////////////////////////
186	//	NMPR
187	////////////////////////////////////////////////
188
189	private boolean nmprMode;
190	
191	public void setNMPRMode(boolean flag)
192	{
193		nmprMode = flag;
194	}
195
196	public boolean isNMPRMode()
197	{
198		return nmprMode;
199	}
200	
201	////////////////////////////////////////////////
202	//	Device List
203	////////////////////////////////////////////////
204
205	private NodeList devNodeList = new NodeList();
206
207	private void addDevice(Node rootNode)
208	{
209		devNodeList.add(rootNode);
210	}
211
212	private synchronized void addDevice(SSDPPacket ssdpPacket)
213	{
214		if (ssdpPacket.isRootDevice() == false)
215			return;
216			
217		String usn = ssdpPacket.getUSN();
218		String udn = USN.getUDN(usn);
219		Device dev = getDevice(udn);
220		if (dev != null) {
221			dev.setSSDPPacket(ssdpPacket);
222			return;
223		}
224		
225		String location = ssdpPacket.getLocation();
226		
227		// vvvvv Razie
228			if (location.contains("http://[")) {
229				// TODO ipv6 support
230				Log.alarmOnce("ERROR_UPNP_IPV6NOTSUPPORTED", 
231						"ERROR_UPNP_IPV6NOTSUPPORTED You have IPV6 UPNP notifications - DON't SUPPRT IPV6 yet... " + location);
232				Log.traceThis("ERROR_UPNP_IPV6NOTSUPPORTED can't reach mutant's descrition at " + location);
233			} else
234		// ^^^^^^ Razie
235	
236		try {	
237			URL locationUrl = new URL(location);
238			Parser parser = UPnP.getXMLParser();
239			Node rootNode = parser.parse(locationUrl);
240			Device rootDev = getDevice(rootNode);
241			if (rootDev == null)
242				return;
243			rootDev.setSSDPPacket(ssdpPacket);
244			addDevice(rootNode);
245
246			// Thanks for Oliver Newell (2004/10/16)
247			// After node is added, invoke the AddDeviceListener to notify high-level 
248			// control point application that a new device has been added. (The 
249			// control point application must implement the DeviceChangeListener interface
250			// to receive the notifications)
251			performAddDeviceListener( rootDev );
252		}
253		catch (MalformedURLException me) {
254			Debug.warning(ssdpPacket.toString());
255			Debug.warning(me);
256		}
257		catch (ParserException pe) {
258			Debug.warning(ssdpPacket.toString());
259			Debug.warning(pe);
260		}
261	}
262
263	private Device getDevice(Node rootNode)
264	{
265		if (rootNode == null)
266				return null;
267		Node devNode = rootNode.getNode(Device.ELEM_NAME);
268		if (devNode == null)
269				return null;
270		return new Device(rootNode, devNode);
271	}
272
273	public DeviceList getDeviceList()
274	{
275		DeviceList devList = new DeviceList();
276		int nRoots = devNodeList.size();
277		for (int n=0; n<nRoots; n++) {
278			Node rootNode = devNodeList.getNode(n);
279			Device dev = getDevice(rootNode);
280			if (dev == null)
281				continue;
282			devList.add(dev);
283		} 
284		return devList;
285	}
286
287	public Device getDevice(String name)
288	{
289		int nRoots = devNodeList.size();
290		for (int n=0; n<nRoots; n++) {
291			Node rootNode = devNodeList.getNode(n);
292			Device dev = getDevice(rootNode);
293			if (dev == null)
294				continue;
295			if (dev.isDevice(name) == true)
296				return dev;
297			Device cdev = dev.getDevice(name);
298			if (cdev != null)
299				return cdev;
300		} 
301		return null;
302	}
303
304	public boolean hasDevice(String name)
305	{
306		return (getDevice(name) != null) ? true : false;
307	}
308
309	private void removeDevice(Node rootNode)
310	{
311		// Thanks for Oliver Newell (2004/10/16)
312		// Invoke device removal listener prior to actual removal so Device node 
313		// remains valid for the duration of the listener (application may want
314		// to access the node)
315		Device dev = getDevice(rootNode);
316		if( dev != null && dev.isRootDevice() )
317			performRemoveDeviceListener( dev );
318	    
319		devNodeList.remove(rootNode);
320	}
321
322	private void removeDevice(Device dev)
323	{
324		if (dev == null)
325			return;
326		removeDevice(dev.getRootNode());
327	}
328	
329	private void removeDevice(String name)
330	{
331		Device dev = getDevice(name);
332		removeDevice(dev);
333	}
334
335	private void removeDevice(SSDPPacket packet)
336	{
337		if (packet.isByeBye() == false)
338			return;
339		String usn = packet.getUSN();
340		String udn = USN.getUDN(usn);
341		removeDevice(udn);
342	}
343	
344	////////////////////////////////////////////////
345	//	Expired Device
346	////////////////////////////////////////////////
347	
348	private Disposer deviceDisposer;
349	private long expiredDeviceMonitoringInterval;
350	
351	public void removeExpiredDevices()
352	{
353		DeviceList devList = getDeviceList();
354		int devCnt = devList.size();
355		Device dev[] = new Device[devCnt];
356		for (int n=0; n<devCnt; n++)
357			dev[n] = devList.getDevice(n);
358		for (int n=0; n<devCnt; n++) {
359			if (dev[n].isExpired() == true) {
360				Debug.message("Expired device = " + dev[n].getFriendlyName());
361				removeDevice(dev[n]);
362			}
363		}		
364	}
365	
366	public void setExpiredDeviceMonitoringInterval(long interval)
367	{
368		expiredDeviceMonitoringInterval = interval;
369	}
370
371	public long getExpiredDeviceMonitoringInterval()
372	{
373		return expiredDeviceMonitoringInterval;
374	}
375	
376	public void setDeviceDisposer(Disposer disposer)
377	{
378		deviceDisposer = disposer;
379	}
380	
381	public Disposer getDeviceDisposer()
382	{
383		return deviceDisposer;
384	}
385	
386	////////////////////////////////////////////////
387	//	Notify
388	////////////////////////////////////////////////
389
390	private ListenerList deviceNotifyListenerList = new ListenerList();
391	 	
392	public void addNotifyListener(NotifyListener listener)
393	{
394		deviceNotifyListenerList.add(listener);
395	}		
396
397	public void removeNotifyListener(NotifyListener listener)
398	{
399		deviceNotifyListenerList.remove(listener);
400	}		
401
402	public void performNotifyListener(SSDPPacket ssdpPacket)
403	{
404		int listenerSize = deviceNotifyListenerList.size();
405		for (int n=0; n<listenerSize; n++) {
406			NotifyListener listener = (NotifyListener)deviceNotifyListenerList.get(n);
407			listener.deviceNotifyReceived(ssdpPacket);
408		}
409	}
410
411	////////////////////////////////////////////////
412	//	SearchResponse
413	////////////////////////////////////////////////
414
415	private ListenerList deviceSearchResponseListenerList = new ListenerList();
416	 	
417	public void addSearchResponseListener(SearchResponseListener listener)
418	{
419		deviceSearchResponseListenerList.add(listener);
420	}		
421
422	public void removeSearchResponseListener(SearchResponseListener listener)
423	{
424		deviceSearchResponseListenerList.remove(listener);
425	}		
426
427	public void performSearchResponseListener(SSDPPacket ssdpPacket)
428	{
429		int listenerSize = deviceSearchResponseListenerList.size();
430		for (int n=0; n<listenerSize; n++) {
431			SearchResponseListener listener = (SearchResponseListener)deviceSearchResponseListenerList.get(n);
432			listener.deviceSearchResponseReceived(ssdpPacket);
433		}
434	}
435
436	/////////////////////////////////////////////////////////////////////
437	// Device status changes (device added or removed) 
438	// Applications that support the DeviceChangeListener interface are 
439	// notified immediately when a device is added to, or removed from,
440	// the control point.
441	/////////////////////////////////////////////////////////////////////
442
443	ListenerList deviceChangeListenerList = new ListenerList();
444	  
445	public void addDeviceChangeListener(DeviceChangeListener listener)
446	{
447		deviceChangeListenerList.add(listener);
448	}		
449
450	public void removeDeviceChangeListener(DeviceChangeListener listener)
451	{
452		deviceChangeListenerList.remove(listener);
453	}		
454
455	public void performAddDeviceListener( Device dev )
456	{
457		int listenerSize = deviceChangeListenerList.size();
458		for (int n=0; n<listenerSize; n++) {
459			DeviceChangeListener listener = (DeviceChangeListener)deviceChangeListenerList.get(n);
460			listener.deviceAdded( dev );
461		}
462	}
463
464	public void performRemoveDeviceListener( Device dev )
465	{
466		int listenerSize = deviceChangeListenerList.size();
467		for (int n=0; n<listenerSize; n++) {
468			DeviceChangeListener listener = (DeviceChangeListener)deviceChangeListenerList.get(n);
469			listener.deviceRemoved( dev );
470		}
471	}
472		
473	////////////////////////////////////////////////
474	//	SSDPPacket
475	////////////////////////////////////////////////
476	
477	public void notifyReceived(SSDPPacket packet)
478	{
479		if (packet.isRootDevice() == true) {
480			if (packet.isAlive() == true)
481				addDevice(packet);
482			if (packet.isByeBye() == true) 
483				removeDevice(packet);
484		}
485		performNotifyListener(packet);
486	}
487
488	public void searchResponseReceived(SSDPPacket packet)
489	{
490		if (packet.isRootDevice() == true)
491			addDevice(packet);
492		performSearchResponseListener(packet);
493	}
494
495	////////////////////////////////////////////////
496	//	M-SEARCH
497	////////////////////////////////////////////////
498
499	private int searchMx = SSDP.DEFAULT_MSEARCH_MX;
500
501	public int getSearchMx()
502	{
503		return searchMx;
504	}
505
506	public void setSearchMx(int mx) 
507	{
508		searchMx = mx;
509	}
510
511	public void search(String target, int mx)
512	{
513		SSDPSearchRequest msReq = new SSDPSearchRequest(target, mx);
514		SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
515		ssdpSearchResponseSocketList.post(msReq);
516	}
517
518	public void search(String target)
519	{
520		search(target, SSDP.DEFAULT_MSEARCH_MX);
521	}
522
523	public void search()
524	{
525		search(ST.ROOT_DEVICE, SSDP.DEFAULT_MSEARCH_MX);
526	}
527
528
529	////////////////////////////////////////////////
530	//	EventSub HTTPServer
531	////////////////////////////////////////////////
532
533	private HTTPServerList httpServerList = new HTTPServerList();
534	
535	private HTTPServerList getHTTPServerList()
536	{
537		return httpServerList;
538	}
539		
540	public void httpRequestRecieved(HTTPRequest httpReq)
541	{
542		if (Debug.isOn() == true)
543			httpReq.print();
544		
545		// Thanks for Giordano Sassaroli <sassarol@cefriel.it> (09/08/03)
546		if (httpReq.isNotifyRequest() == true) {
547			NotifyRequest notifyReq = new NotifyRequest(httpReq);
548			String uuid = notifyReq.getSID();
549			long seq = notifyReq.getSEQ();
550			PropertyList props = notifyReq.getPropertyList();
551			int propCnt = props.size();
552			for (int n = 0; n < propCnt; n++) {
553				Property prop = props.getProperty(n);
554				String varName = prop.getName();
555				String varValue = prop.getValue();
556				performEventListener(uuid, seq, varName, varValue);
557			}
558			httpReq.returnOK();
559			return;
560 		}
561		
562		httpReq.returnBadRequest();
563	}
564
565	////////////////////////////////////////////////
566	//	Event Listener 
567	////////////////////////////////////////////////
568
569	private ListenerList eventListenerList = new ListenerList();
570	 	
571	public void addEventListener(EventListener listener)
572	{
573		eventListenerList.add(listener);
574	}		
575
576	public void removeEventListener(EventListener listener)
577	{
578		eventListenerList.remove(listener);
579	}		
580
581	public void performEventListener(String uuid, long seq, String name, String value)
582	{
583		int listenerSize = eventListenerList.size();
584		for (int n=0; n<listenerSize; n++) {
585			EventListener listener = (EventListener)eventListenerList.get(n);
586			listener.eventNotifyReceived(uuid, seq, name, value);
587		}
588	}
589	
590	////////////////////////////////////////////////
591	//	Subscription 
592	////////////////////////////////////////////////
593
594	private String eventSubURI = DEFAULT_EVENTSUB_URI;
595
596	public String getEventSubURI()
597	{
598		return eventSubURI;
599	}
600
601	public void setEventSubURI(String url)
602	{
603		eventSubURI = url;
604	}
605
606	private String getEventSubCallbackURL(String host)
607	{
608		return HostInterface.getHostURL(host, getHTTPPort(), getEventSubURI());
609	}
610	
611	public boolean subscribe(Service service, long timeout)
612	{
613		if (service.isSubscribed() == true) {
614			String sid = service.getSID();
615			return subscribe(service, sid, timeout);
616		}
617		
618		Device rootDev = service.getRootDevice();
619		if (rootDev == null)
620			return false;
621		String ifAddress = rootDev.getInterfaceAddress();		 
622		SubscriptionRequest subReq = new SubscriptionRequest();
623		subReq.setSubscribeRequest(service, getEventSubCallbackURL(ifAddress), timeout);
624		SubscriptionResponse subRes = subReq.post();
625		if (subRes.isSuccessful() == true) {
626			service.setSID(subRes.getSID());
627			service.setTimeout(subRes.getTimeout());
628			return true;
629			
630		}
631		service.clearSID();
632		return false;
633	}
634
635	public boolean subscribe(Service service)
636	{
637		return subscribe(service, Subscription.INFINITE_VALUE);
638	}
639
640	public boolean subscribe(Service service, String uuid, long timeout)
641	{
642		SubscriptionRequest subReq = new SubscriptionRequest();
643		subReq.setRenewRequest(service, uuid, timeout);
644		if (Debug.isOn() == true)
645			subReq.print();	
646		SubscriptionResponse subRes = subReq.post();
647		if (Debug.isOn() == true)
648			subRes.print();	
649		if (subRes.isSuccessful() == true) {
650			service.setSID(subRes.getSID());
651			service.setTimeout(subRes.getTimeout());
652			return true;
653		}
654		service.clearSID();
655		return false;
656	}
657
658	public boolean subscribe(Service service, String uuid)
659	{
660		return subscribe(service, uuid, Subscription.INFINITE_VALUE);
661	}
662
663	public boolean isSubscribed(Service service)
664	{
665		if (service == null)
666			return false;
667		return service.isSubscribed();
668	}
669	
670	public boolean unsubscribe(Service service)
671	{
672		SubscriptionRequest subReq = new SubscriptionRequest();
673		subReq.setUnsubscribeRequest(service);
674		SubscriptionResponse subRes = subReq.post();
675		if (subRes.isSuccessful() == true) {
676			service.clearSID();
677			return true;
678		}
679		return false;
680	}
681
682	public void unsubscribe(Device device)
683	{
684		ServiceList serviceList = device.getServiceList();
685		int serviceCnt = serviceList.size();
686		for (int n=0; n<serviceCnt; n++) {
687			Service service = serviceList.getService(n);
688			if (service.hasSID() == true)
689				unsubscribe(service);
690		}
691
692		DeviceList childDevList = device.getDeviceList();
693		int childDevCnt = childDevList.size();
694		for (int n=0; n<childDevCnt; n++) {
695			Device cdev = childDevList.getDevice(n);
696			unsubscribe(cdev);
697		}		
698	}
699	
700	public void unsubscribe()
701	{
702		DeviceList devList = getDeviceList();
703		int devCnt = devList.size();
704		for (int n=0; n<devCnt; n++) {
705			Device dev = devList.getDevice(n);
706			unsubscribe(dev);
707		}		
708	}
709
710	////////////////////////////////////////////////
711	//	getSubscriberService	
712	////////////////////////////////////////////////
713
714	public Service getSubscriberService(String uuid)
715	{
716		DeviceList devList = getDeviceList();
717		int devCnt = devList.size();
718		for (int n=0; n<devCnt; n++) {
719			Device dev = devList.getDevice(n);
720			Service service = dev.getSubscriberService(uuid);
721			if (service != null)
722				return service;
723		}		
724		return null;
725	}
726	
727	////////////////////////////////////////////////
728	//	getSubscriberService	
729	////////////////////////////////////////////////
730
731	public void renewSubscriberService(Device dev, long timeout)
732	{
733		ServiceList serviceList = dev.getServiceList();
734		int serviceCnt = serviceList.size();
735		for (int n=0; n<serviceCnt; n++) {
736			Service service = serviceList.getService(n);
737			if (service.isSubscribed() == false)
738				continue;
739			String sid = service.getSID();
740			boolean isRenewed = subscribe(service, sid, timeout);
741			if (isRenewed == false)
742				subscribe(service, timeout);
743		}
744		
745		DeviceList cdevList = dev.getDeviceList();
746		int cdevCnt = cdevList.size();
747		for (int n=0; n<cdevCnt; n++) {
748			Device cdev = cdevList.getDevice(n);
749			renewSubscriberService(cdev, timeout);
750		}
751	}
752	
753	public void renewSubscriberService(long timeout)
754	{
755		DeviceList devList = getDeviceList();
756		int devCnt = devList.size();
757		for (int n=0; n<devCnt; n++) {
758			Device dev = devList.getDevice(n);
759			renewSubscriberService(dev, timeout);
760		}		
761	}
762	
763	public void renewSubscriberService()
764	{
765		renewSubscriberService(Subscription.INFINITE_VALUE);
766	}
767	
768	////////////////////////////////////////////////
769	//	Subscriber
770	////////////////////////////////////////////////
771	
772	private RenewSubscriber renewSubscriber;
773
774	public void setRenewSubscriber(RenewSubscriber sub)
775	{
776		renewSubscriber = sub;
777	}
778	
779	public RenewSubscriber getRenewSubscriber()
780	{
781		return renewSubscriber;	
782	}
783	
784	////////////////////////////////////////////////
785	//	run	
786	////////////////////////////////////////////////
787
788	public boolean start(String target, int mx)
789	{
790		stop();
791		
792		////////////////////////////////////////
793		// HTTP Server
794		////////////////////////////////////////
795		
796		int retryCnt = 0;
797		int bindPort = getHTTPPort();
798		HTTPServerList httpServerList = getHTTPServerList();
799		while (httpServerList.open(bindPort) == false) {
800			retryCnt++;
801			if (UPnP.SERVER_RETRY_COUNT < retryCnt)
802				return false;
803			setHTTPPort(bindPort + 1);
804			bindPort = getHTTPPort();
805		}
806		httpServerList.addRequestListener(this);
807		httpServerList.start();
808		
809		////////////////////////////////////////
810		// Notify Socket
811		////////////////////////////////////////
812		
813		SSDPNotifySocketList ssdpNotifySocketList = getSSDPNotifySocketList();
814		if (ssdpNotifySocketList.open() == false)
815			return false;
816		ssdpNotifySocketList.setControlPoint(this);			
817		ssdpNotifySocketList.start();
818		
819		////////////////////////////////////////
820		// SeachResponse Socket
821		////////////////////////////////////////
822		
823		int ssdpPort = getSSDPPort();
824		retryCnt = 0;
825		SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
826		while (ssdpSearchResponseSocketList.open(ssdpPort) == false) {
827			retryCnt++;
828			if (UPnP.SERVER_RETRY_COUNT < retryCnt)
829				return false;
830			setSSDPPort(ssdpPort + 1);
831			ssdpPort = getSSDPPort();
832		}
833		ssdpSearchResponseSocketList.setControlPoint(this);
834		ssdpSearchResponseSocketList.start();
835
836		////////////////////////////////////////
837		// search root devices
838		////////////////////////////////////////
839		
840		search(target, mx);
841		
842		////////////////////////////////////////
843		// Disposer
844		////////////////////////////////////////
845
846		Disposer disposer = new Disposer(this);
847		setDeviceDisposer(disposer);
848		disposer.start();
849				
850		////////////////////////////////////////
851		// Subscriber
852		////////////////////////////////////////
853		
854		if (isNMPRMode() == true) {
855			RenewSubscriber renewSub = new RenewSubscriber(this);
856			setRenewSubscriber(renewSub);
857			renewSub.start();
858		}
859		
860		return true;
861	}
862	
863	public boolean start(String target)
864	{
865		return start(target, SSDP.DEFAULT_MSEARCH_MX);
866	}
867
868	public boolean start()
869	{
870		return start(ST.ROOT_DEVICE, SSDP.DEFAULT_MSEARCH_MX);
871	}
872	
873	public boolean stop()
874	{ 
875		unsubscribe();
876		
877		SSDPNotifySocketList ssdpNotifySocketList = getSSDPNotifySocketList();
878		ssdpNotifySocketList.stop();
879		ssdpNotifySocketList.close();
880		ssdpNotifySocketList.clear();
881		
882		SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
883		ssdpSearchResponseSocketList.stop();
884		ssdpSearchResponseSocketList.close();
885		ssdpSearchResponseSocketList.clear();
886
887		HTTPServerList httpServerList = getHTTPServerList();
888		httpServerList.stop();
889		httpServerList.close();
890		httpServerList.clear();
891			
892		////////////////////////////////////////
893		// Disposer
894		////////////////////////////////////////
895		
896		Disposer disposer = getDeviceDisposer();
897		if (disposer != null) {
898			disposer.stop();
899			setDeviceDisposer(null);
900		}
901		
902		////////////////////////////////////////
903		// Subscriber
904		////////////////////////////////////////
905		
906		RenewSubscriber renewSub = getRenewSubscriber();
907		if (renewSub != null) {
908			renewSub.stop();
909			setRenewSubscriber(null);
910		}
911		
912		return true;
913	}
914
915	////////////////////////////////////////////////
916	//	print	
917	////////////////////////////////////////////////
918	
919	public void print()
920	{
921		DeviceList devList = getDeviceList();
922		int devCnt = devList.size();
923		Debug.message("Device Num = " + devCnt);
924		for (int n=0; n<devCnt; n++) {
925			Device dev = devList.getDevice(n);
926			Debug.message("[" + n + "] " + dev.getFriendlyName() + ", " + dev.getLeaseTime() + ", " + dev.getElapsedTime());
927		}		
928	}
929}