KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > netbios > server > NetBIOSNameServer


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.netbios.server;
18
19 import java.io.IOException JavaDoc;
20 import java.net.DatagramPacket JavaDoc;
21 import java.net.DatagramSocket JavaDoc;
22 import java.net.InetAddress JavaDoc;
23 import java.net.SocketException JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.Hashtable JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 import org.alfresco.filesys.netbios.NetBIOSName;
29 import org.alfresco.filesys.netbios.NetBIOSPacket;
30 import org.alfresco.filesys.netbios.NetworkSettings;
31 import org.alfresco.filesys.netbios.RFCNetBIOSProtocol;
32 import org.alfresco.filesys.server.NetworkServer;
33 import org.alfresco.filesys.server.ServerListener;
34 import org.alfresco.filesys.server.config.ServerConfiguration;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37
38 /**
39  * NetBIOS name server class.
40  */

41 public class NetBIOSNameServer extends NetworkServer implements Runnable JavaDoc
42 {
43     private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.netbios");
44
45     // Server version
46

47     private static final String JavaDoc ServerVersion = "3.5.0";
48
49     // Various NetBIOS packet sizes
50

51     public static final int AddNameSize = 256;
52     public static final int DeleteNameSize = 256;
53     public static final int RefreshNameSize = 256;
54
55     // Add name thread broadcast interval and retry count
56

57     private static final int AddNameInterval = 2000; // ms between transmits
58
private static final int AddNameRetries = 5; // number of broadcasts
59

60     private static final int AddNameWINSInterval = 250; // ms between requests when using WINS
61

62     // Delete name interval and retry count
63

64     private static final int DeleteNameInterval = 200; // ms between transmits
65
private static final int DeleteNameRetries = 1; // number of broadcasts
66

67     // Refresh name retry count
68

69     public static final int RefreshNameRetries = 2; // number of broadcasts
70

71     // NetBIOS flags
72

73     public static final int GroupName = 0x8000;
74
75     // Default time to live value for names registered by this server, in seconds
76

77     public static final int DefaultTTL = 10800; // 3 hours
78

79     // Name refresh thread wakeup interval
80

81     public static final long NameRefreshWakeupInterval = 180000L; // 3 minutes
82

83     // Name transaction id
84

85     private static int m_tranId;
86
87     // NetBIOS name service datagram socket
88

89     private DatagramSocket JavaDoc m_socket;
90
91     // Shutdown flag
92

93     private boolean m_shutdown;
94
95     // Local address to bind the name server to
96

97     private InetAddress JavaDoc m_bindAddress;
98
99     // Broadcast address, if not using WINS
100

101     private InetAddress JavaDoc m_bcastAddr;
102
103     // Port/socket to bind to
104

105     private int m_port = RFCNetBIOSProtocol.NAME_PORT;
106
107     // WINS server addresses
108

109     private InetAddress JavaDoc m_winsPrimary;
110     private InetAddress JavaDoc m_winsSecondary;
111
112     // Local add name listener list
113

114     private Vector JavaDoc<AddNameListener> m_addListeners;
115
116     // Local name query listener list
117

118     private Vector JavaDoc<QueryNameListener> m_queryListeners;
119
120     // Remote name add listener list
121

122     private Vector JavaDoc<RemoteNameListener> m_remoteListeners;
123
124     // Local NetBIOS name table
125

126     private Vector JavaDoc<NetBIOSName> m_localNames;
127
128     // Remote NetBIOS name table
129

130     private Hashtable JavaDoc<NetBIOSName, byte[]> m_remoteNames;
131
132     // List of active add name requests
133

134     private Vector JavaDoc<NetBIOSRequest> m_reqList;
135
136     // NetBIOS request handler and name refresh threads
137

138     private NetBIOSRequestHandler m_reqHandler;
139     private NetBIOSNameRefresh m_refreshThread;
140
141     // Server thread
142

143     private Thread JavaDoc m_srvThread;
144
145     // NetBIOS request handler thread inner class
146

147     class NetBIOSRequestHandler extends Thread JavaDoc
148     {
149
150         // Shutdown request flag
151

152         private boolean m_hshutdown = false;
153
154         /**
155          * Default constructor
156          */

157         public NetBIOSRequestHandler()
158         {
159             setDaemon(true);
160             setName("NetBIOSRequest");
161         }
162
163         /**
164          * Shutdown the request handler thread
165          */

166         public final void shutdownRequest()
167         {
168             m_hshutdown = true;
169
170             synchronized (m_reqList)
171             {
172                 m_reqList.notify();
173             }
174         }
175
176         /**
177          * Main thread code
178          */

179         public void run()
180         {
181
182             // Loop until shutdown requested
183

184             while (m_hshutdown == false)
185             {
186
187                 try
188                 {
189
190                     // Wait for something to do
191

192                     NetBIOSRequest req = null;
193
194                     synchronized (m_reqList)
195                     {
196
197                         // Check if there are any requests in the queue
198

199                         if (m_reqList.size() == 0)
200                         {
201
202                             // Debug
203

204                             if (logger.isDebugEnabled() && hasDebug())
205                                 logger.debug("NetBIOS handler waiting for request ...");
206
207                             // Wait for some work ...
208

209                             m_reqList.wait();
210                         }
211
212                         // Remove a request from the queue
213

214                         if (m_reqList.size() > 0)
215                             req = m_reqList.get(0);
216                         else if (m_hshutdown == true)
217                             break;
218                     }
219
220                     // Get the request retry count, for WINS only send one request
221

222                     int reqRetry = req.getRetryCount();
223                     if (hasPrimaryWINSServer())
224                         reqRetry = 1;
225
226                     // Process the request
227

228                     boolean txsts = true;
229                     int retry = 0;
230
231                     while (req.hasErrorStatus() == false && retry++ < reqRetry)
232                     {
233
234                         // Debug
235

236                         if (logger.isDebugEnabled())
237                             logger.debug("NetBIOS handler, processing " + req);
238
239                         // Process the request
240

241                         switch (req.isType())
242                         {
243
244                         // Add name request
245

246                         case NetBIOSRequest.AddName:
247
248                             // Check if a WINS server is configured
249

250                             if (hasPrimaryWINSServer())
251                                 txsts = sendAddName(req, getPrimaryWINSServer(), false);
252                             else
253                                 txsts = sendAddName(req, getBroadcastAddress(), true);
254                             break;
255
256                         // Delete name request
257

258                         case NetBIOSRequest.DeleteName:
259
260                             // Check if a WINS server is configured
261

262                             if (hasPrimaryWINSServer())
263                                 txsts = sendDeleteName(req, getPrimaryWINSServer(), false);
264                             else
265                                 txsts = sendDeleteName(req, getBroadcastAddress(), true);
266                             break;
267
268                         // Refresh name request
269

270                         case NetBIOSRequest.RefreshName:
271
272                             // Check if a WINS server is configured
273

274                             if (hasPrimaryWINSServer())
275                                 txsts = sendRefreshName(req, getPrimaryWINSServer(), false);
276                             else
277                                 txsts = sendRefreshName(req, getBroadcastAddress(), true);
278                             break;
279                         }
280
281                         // Check if the request was successful
282

283                         if (txsts == true && req.getRetryInterval() > 0)
284                         {
285
286                             // Sleep for a while
287

288                             sleep(req.getRetryInterval());
289                         }
290                     }
291
292                     // Check if the request was successful
293

294                     if (req.hasErrorStatus() == false)
295                     {
296
297                         // Debug
298

299                         if (logger.isDebugEnabled())
300                             logger.debug("NetBIOS handler successful, " + req);
301
302                         // Update the name record
303

304                         NetBIOSName nbName = req.getNetBIOSName();
305
306                         switch (req.isType())
307                         {
308
309                         // Add name request
310

311                         case NetBIOSRequest.AddName:
312
313                             // Add the name to the list of local names
314

315                             if (m_localNames.contains(nbName) == false)
316                                 m_localNames.addElement(nbName);
317
318                             // Update the expiry time for the name
319

320                             nbName.setExpiryTime(System.currentTimeMillis() + (nbName.getTimeToLive() * 1000L));
321
322                             // Inform listeners that the request was successful
323

324                             fireAddNameEvent(nbName, NetBIOSNameEvent.ADD_SUCCESS);
325                             break;
326
327                         // Delete name request
328

329                         case NetBIOSRequest.DeleteName:
330
331                             // Remove the name from the list of local names
332

333                             m_localNames.remove(req.getNetBIOSName());
334                             break;
335
336                         // Refresh name registration request
337

338                         case NetBIOSRequest.RefreshName:
339
340                             // Update the expiry time for the name
341

342                             nbName.setExpiryTime(System.currentTimeMillis() + (nbName.getTimeToLive() * 1000L));
343                             break;
344                         }
345                     }
346                     else
347                     {
348
349                         // Error occurred
350

351                         switch (req.isType())
352                         {
353
354                         // Add name request
355

356                         case NetBIOSRequest.AddName:
357
358                             // Remove the name from the local name list
359

360                             m_localNames.remove(req.getNetBIOSName());
361                             break;
362                         }
363                     }
364
365                     // Remove the request from the queue
366

367                     synchronized (m_reqList)
368                     {
369                         m_reqList.remove(0);
370                     }
371                 }
372                 catch (InterruptedException JavaDoc ex)
373                 {
374                 }
375
376                 // Check if the request handler has been shutdown
377

378                 if (m_hshutdown == true)
379                     break;
380             }
381         }
382
383         /**
384          * Send an add name request
385          *
386          * @param req NetBIOSRequest
387          * @param dest InetAddress
388          * @param bcast boolean
389          * @return boolean
390          */

391         private final boolean sendAddName(NetBIOSRequest req, InetAddress JavaDoc dest, boolean bcast)
392         {
393
394             try
395             {
396
397                 // Allocate a buffer for the add name NetBIOS packet
398

399                 byte[] buf = new byte[AddNameSize];
400                 NetBIOSPacket addPkt = new NetBIOSPacket(buf);
401
402                 // Build an add name packet for each IP address
403

404                 for (int i = 0; i < req.getNetBIOSName().numberOfAddresses(); i++)
405                 {
406
407                     // Build an add name request for the current IP address
408

409                     int len = addPkt.buildAddNameRequest(req.getNetBIOSName(), i, req.getTransactionId());
410                     if (bcast == false)
411                         addPkt.setFlags(0);
412
413                     // Allocate the datagram packet, using the add name buffer
414

415                     DatagramPacket JavaDoc pkt = new DatagramPacket JavaDoc(buf, len, dest, getPort());
416
417                     // Send the add name request
418

419                     if (m_socket != null)
420                         m_socket.send(pkt);
421
422                     // Debug
423

424                     if (logger.isDebugEnabled())
425                         logger.debug(" Add name " + (bcast ? "broadcast" : "WINS") + ", " + req);
426                 }
427             }
428             catch (IOException JavaDoc ex)
429             {
430                 fireAddNameEvent(req.getNetBIOSName(), NetBIOSNameEvent.ADD_IOERROR);
431                 req.setErrorStatus(true);
432                 return false;
433             }
434
435             // Add name broadcast successful
436

437             return true;
438         }
439
440         /**
441          * Send a refresh name request
442          *
443          * @param req NetBIOSRequest
444          * @param dest InetAddress
445          * @param bcast boolean
446          * @return boolean
447          */

448         private final boolean sendRefreshName(NetBIOSRequest req, InetAddress JavaDoc dest, boolean bcast)
449         {
450
451             try
452             {
453
454                 // Allocate a buffer for the refresh name NetBIOS packet
455

456                 byte[] buf = new byte[RefreshNameSize];
457                 NetBIOSPacket refreshPkt = new NetBIOSPacket(buf);
458
459                 // Build a refresh name packet for each IP address
460

461                 for (int i = 0; i < req.getNetBIOSName().numberOfAddresses(); i++)
462                 {
463
464                     // Build a refresh name request for the current IP address
465

466                     int len = refreshPkt.buildRefreshNameRequest(req.getNetBIOSName(), i, req.getTransactionId());
467                     if (bcast == false)
468                         refreshPkt.setFlags(0);
469
470                     // Allocate the datagram packet, using the refresh name buffer
471

472                     DatagramPacket JavaDoc pkt = new DatagramPacket JavaDoc(buf, len, dest, getPort());
473
474                     // Send the refresh name request
475

476                     if (m_socket != null)
477                         m_socket.send(pkt);
478
479                     // Debug
480

481                     if (logger.isDebugEnabled())
482                         logger.debug(" Refresh name " + (bcast ? "broadcast" : "WINS") + ", " + req);
483                 }
484             }
485             catch (IOException JavaDoc ex)
486             {
487                 req.setErrorStatus(true);
488                 return false;
489             }
490
491             // Add name broadcast successful
492

493             return true;
494         }
495
496         /**
497          * Send a delete name request via a network broadcast
498          *
499          * @param req NetBIOSRequest
500          * @param dest InetAddress
501          * @param bcast boolean
502          * @return boolean
503          */

504         private final boolean sendDeleteName(NetBIOSRequest req, InetAddress JavaDoc dest, boolean bcast)
505         {
506
507             try
508             {
509
510                 // Allocate a buffer for the delete name NetBIOS packet
511

512                 byte[] buf = new byte[DeleteNameSize];
513                 NetBIOSPacket delPkt = new NetBIOSPacket(buf);
514
515                 // Build a delete name packet for each IP address
516

517                 for (int i = 0; i < req.getNetBIOSName().numberOfAddresses(); i++)
518                 {
519
520                     // Build an add name request for the current IP address
521

522                     int len = delPkt.buildDeleteNameRequest(req.getNetBIOSName(), i, req.getTransactionId());
523                     if (bcast == false)
524                         delPkt.setFlags(0);
525
526                     // Allocate the datagram packet, using the add name buffer
527

528                     DatagramPacket JavaDoc pkt = new DatagramPacket JavaDoc(buf, len, dest, getPort());
529
530                     // Send the add name request
531

532                     if (m_socket != null)
533                         m_socket.send(pkt);
534
535                     // Debug
536

537                     if (logger.isDebugEnabled())
538                         logger.debug(" Delete name " + (bcast ? "broadcast" : "WINS") + ", " + req);
539                 }
540             }
541             catch (IOException JavaDoc ex)
542             {
543                 req.setErrorStatus(true);
544                 return false;
545             }
546
547             // Delete name broadcast successful
548

549             return true;
550         }
551     };
552
553     // NetBIOS name refresh thread inner class
554

555     class NetBIOSNameRefresh extends Thread JavaDoc
556     {
557
558         // Shutdown request flag
559

560         private boolean m_hshutdown = false;
561
562         /**
563          * Default constructor
564          */

565         public NetBIOSNameRefresh()
566         {
567             setDaemon(true);
568             setName("NetBIOSRefresh");
569         }
570
571         /**
572          * Shutdown the name refresh thread
573          */

574         public final void shutdownRequest()
575         {
576             m_hshutdown = true;
577
578             // Wakeup the thread
579

580             this.interrupt();
581         }
582
583         /**
584          * Main thread code
585          */

586         public void run()
587         {
588
589             // Loop for ever
590

591             while (m_hshutdown == false)
592             {
593
594                 try
595                 {
596
597                     // Sleep for a while
598

599                     sleep(NameRefreshWakeupInterval);
600
601                     // Check if there is a shutdown pending
602

603                     if (m_hshutdown == true)
604                         break;
605
606                     // Debug
607

608                     if (logger.isDebugEnabled())
609                         logger.debug("NetBIOS name refresh wakeup ...");
610
611                     // Check if there are any registered names that will expire in the next interval
612

613                     synchronized (m_localNames)
614                     {
615
616                         // Get the current time plus the wakeup interval
617

618                         long expireTime = System.currentTimeMillis() + NameRefreshWakeupInterval;
619
620                         // Loop through the local name list
621

622                         for (int i = 0; i < m_localNames.size(); i++)
623                         {
624
625                             // Get a name from the list
626

627                             NetBIOSName nbName = m_localNames.get(i);
628
629                             // Check if the name has expired, or will expire before the next wakeup
630
// event
631

632                             if (nbName.getExpiryTime() < expireTime)
633                             {
634
635                                 // Debug
636

637                                 if (logger.isDebugEnabled())
638                                     logger.debug("Queuing name refresh for " + nbName);
639
640                                 // Queue a refresh request for the NetBIOS name
641

642                                 NetBIOSRequest nbReq = new NetBIOSRequest(NetBIOSRequest.RefreshName, nbName,
643                                         getNextTransactionId());
644                                 nbReq.setRetryCount(RefreshNameRetries);
645
646                                 // Queue the request
647

648                                 synchronized (m_reqList)
649                                 {
650
651                                     // Add the request to the list
652

653                                     m_reqList.addElement(nbReq);
654
655                                     // Wakeup the processing thread
656

657                                     m_reqList.notify();
658                                 }
659                             }
660                         }
661                     }
662                 }
663                 catch (Exception JavaDoc ex)
664                 {
665
666                     // Debug
667

668                     if ( m_hshutdown == false)
669                         logger.error("NetBIOS Name refresh thread exception", ex);
670                 }
671             }
672         }
673     };
674
675     /**
676      * Default constructor
677      *
678      * @param serviceRegistry repository connection
679      * @param config ServerConfiguration
680      * @exception SocketException If a network setup error occurs
681      */

682     public NetBIOSNameServer(ServerConfiguration config) throws SocketException JavaDoc
683     {
684         super("NetBIOS", config);
685
686         // Perform common constructor code
687
commonConstructor();
688     }
689
690     /**
691      * Common constructor code
692      *
693      * @exception SocketException If a network setup error occurs
694      */

695     private final void commonConstructor() throws SocketException JavaDoc
696     {
697
698         // Set the server version
699

700         setVersion(ServerVersion);
701
702         // Allocate the local and remote name tables
703

704         m_localNames = new Vector JavaDoc<NetBIOSName>();
705         m_remoteNames = new Hashtable JavaDoc<NetBIOSName, byte[]>();
706
707         // Check if NetBIOS name server debug output is enabled
708

709         if (getConfiguration().hasNetBIOSDebug())
710             setDebug(true);
711
712         // Set the local address to bind the server to, and server port
713

714         setBindAddress(getConfiguration().getNetBIOSBindAddress());
715         setServerPort(RFCNetBIOSProtocol.NAME_PORT);
716
717         // Copy the WINS server addresses, if set
718

719         setPrimaryWINSServer(getConfiguration().getPrimaryWINSServer());
720         setSecondaryWINSServer(getConfiguration().getSecondaryWINSServer());
721
722         // Check if WINS is not enabled, use broadcasts instead
723

724         if (hasPrimaryWINSServer() == false)
725         {
726
727             try
728             {
729                 m_bcastAddr = InetAddress.getByName(getConfiguration().getBroadcastMask());
730             }
731             catch (Exception JavaDoc ex)
732             {
733             }
734         }
735     }
736
737     /**
738      * Return the local address the server binds to, or null if all local addresses are used.
739      *
740      * @return java.net.InetAddress
741      */

742     public final InetAddress JavaDoc getBindAddress()
743     {
744         return m_bindAddress;
745     }
746
747     /**
748      * Return the next available transaction id for outgoing NetBIOS packets.
749      *
750      * @return int
751      */

752     protected final synchronized int getNextTransactionId()
753     {
754         return m_tranId++;
755     }
756
757     /**
758      * Return the port/socket that the server is bound to.
759      *
760      * @return int
761      */

762     public final int getPort()
763     {
764         return m_port;
765     }
766
767     /**
768      * Determine if the server binds to a particulat local address, or all addresses
769      *
770      * @return boolean
771      */

772     public final boolean hasBindAddress()
773     {
774         return m_bindAddress != null ? true : false;
775     }
776
777     /**
778      * Return the remote name table
779      *
780      * @return Hashtable<NetBIOSName, byte[]>
781      */

782     public final Hashtable JavaDoc<NetBIOSName, byte[]> getNameTable()
783     {
784         return m_remoteNames;
785     }
786
787     /**
788      * Return the broadcast address, if WINS is disabled
789      *
790      * @return InetAddress
791      */

792     public final InetAddress JavaDoc getBroadcastAddress()
793     {
794         return m_bcastAddr;
795     }
796
797     /**
798      * Determine if the primary WINS server address has been set
799      *
800      * @return boolean
801      */

802     public final boolean hasPrimaryWINSServer()
803     {
804         return m_winsPrimary != null ? true : false;
805     }
806
807     /**
808      * Return the primary WINS server address
809      *
810      * @return InetAddress
811      */

812     public final InetAddress JavaDoc getPrimaryWINSServer()
813     {
814         return m_winsPrimary;
815     }
816
817     /**
818      * Determine if the secondary WINS server address has been set
819      *
820      * @return boolean
821      */

822     public final boolean hasSecondaryWINSServer()
823     {
824         return m_winsSecondary != null ? true : false;
825     }
826
827     /**
828      * Return the secondary WINS server address
829      *
830      * @return InetAddress
831      */

832     public final InetAddress JavaDoc getSecondaryWINSServer()
833     {
834         return m_winsSecondary;
835     }
836
837     /**
838      * Add a NetBIOS name.
839      *
840      * @param name NetBIOS name to be added
841      * @exception java.io.IOException I/O error occurred.
842      */

843     public final synchronized void AddName(NetBIOSName name) throws IOException JavaDoc
844     {
845
846         // Check if the NetBIOS name socket has been initialized
847

848         if (m_socket == null)
849             throw new IOException JavaDoc("NetBIOS name socket not initialized");
850
851         // Create an add name request and add to the request list
852

853         NetBIOSRequest nbReq = new NetBIOSRequest(NetBIOSRequest.AddName, name, getNextTransactionId());
854
855         // Set the retry interval
856

857         if (hasPrimaryWINSServer())
858             nbReq.setRetryInterval(AddNameWINSInterval);
859         else
860             nbReq.setRetryInterval(AddNameInterval);
861
862         // Add the name to the local name list
863

864         m_localNames.addElement(name);
865
866         // Queue the request
867

868         synchronized (m_reqList)
869         {
870
871             // Add the request to the list
872

873             m_reqList.addElement(nbReq);
874
875             // Wakeup the processing thread
876

877             m_reqList.notify();
878         }
879     }
880
881     /**
882      * Delete a NetBIOS name.
883      *
884      * @param name NetBIOS name to be deleted
885      * @exception java.io.IOException I/O error occurred.
886      */

887     public final synchronized void DeleteName(NetBIOSName name) throws IOException JavaDoc
888     {
889
890         // Check if the NetBIOS name socket has been initialized
891

892         if (m_socket == null)
893             throw new IOException JavaDoc("NetBIOS name socket not initialized");
894
895         // Create a delete name request and add to the request list
896

897         NetBIOSRequest nbReq = new NetBIOSRequest(NetBIOSRequest.DeleteName, name, getNextTransactionId(),
898                 DeleteNameRetries);
899         nbReq.setRetryInterval(DeleteNameInterval);
900
901         synchronized (m_reqList)
902         {
903
904             // Add the request to the list
905

906             m_reqList.addElement(nbReq);
907
908             // Wakeup the processing thread
909

910             m_reqList.notify();
911         }
912     }
913
914     /**
915      * Add a local add name listener to the NetBIOS name server.
916      *
917      * @param l AddNameListener
918      */

919     public final synchronized void addAddNameListener(AddNameListener l)
920     {
921
922         // Check if the add name listener list is allocated
923

924         if (m_addListeners == null)
925             m_addListeners = new Vector JavaDoc<AddNameListener>();
926         m_addListeners.addElement(l);
927     }
928
929     /**
930      * Add a query name listener to the NetBIOS name server.
931      *
932      * @param l QueryNameListener
933      */

934     public final synchronized void addQueryListener(QueryNameListener l)
935     {
936
937         // Check if the query name listener list is allocated
938

939         if (m_queryListeners == null)
940             m_queryListeners = new Vector JavaDoc<QueryNameListener>();
941         m_queryListeners.addElement(l);
942     }
943
944     /**
945      * Add a remote name listener to the NetBIOS name server.
946      *
947      * @param l RemoteNameListener
948      */

949     public final synchronized void addRemoteListener(RemoteNameListener l)
950     {
951
952         // Check if the remote name listener list is allocated
953

954         if (m_remoteListeners == null)
955             m_remoteListeners = new Vector JavaDoc<RemoteNameListener>();
956         m_remoteListeners.addElement(l);
957     }
958
959     /**
960      * Trigger an add name event to all registered listeners.
961      *
962      * @param name NetBIOSName
963      * @param sts int
964      */

965     protected final synchronized void fireAddNameEvent(NetBIOSName name, int sts)
966     {
967
968         // Check if there are any listeners
969

970         if (m_addListeners == null || m_addListeners.size() == 0)
971             return;
972
973         // Create a NetBIOS name event
974

975         NetBIOSNameEvent evt = new NetBIOSNameEvent(name, sts);
976
977         // Inform all registered listeners
978

979         for (int i = 0; i < m_addListeners.size(); i++)
980         {
981             AddNameListener addListener = m_addListeners.get(i);
982             addListener.netbiosNameAdded(evt);
983         }
984     }
985
986     /**
987      * Trigger an query name event to all registered listeners.
988      *
989      * @param name NetBIOSName
990      * @param sts int
991      */

992     protected final synchronized void fireQueryNameEvent(NetBIOSName name, InetAddress JavaDoc addr)
993     {
994
995         // Check if there are any listeners
996

997         if (m_queryListeners == null || m_queryListeners.size() == 0)
998             return;
999
1000        // Create a NetBIOS name event
1001

1002        NetBIOSNameEvent evt = new NetBIOSNameEvent(name, NetBIOSNameEvent.QUERY_NAME);
1003
1004        // Inform all registered listeners
1005

1006        for (int i = 0; i < m_queryListeners.size(); i++)
1007        {
1008            QueryNameListener queryListener = m_queryListeners.get(i);
1009            queryListener.netbiosNameQuery(evt, addr);
1010        }
1011    }
1012
1013    /**
1014     * Trigger a name register event to all registered listeners.
1015     *
1016     * @param name NetBIOSName
1017     * @param sts int
1018     */

1019    protected final synchronized void fireNameRegisterEvent(NetBIOSName name, InetAddress JavaDoc addr)
1020    {
1021
1022        // Check if there are any listeners
1023

1024        if (m_remoteListeners == null || m_remoteListeners.size() == 0)
1025            return;
1026
1027        // Create a NetBIOS name event
1028

1029        NetBIOSNameEvent evt = new NetBIOSNameEvent(name, NetBIOSNameEvent.REGISTER_NAME);
1030
1031        // Inform all registered listeners
1032

1033        for (int i = 0; i < m_remoteListeners.size(); i++)
1034        {
1035            RemoteNameListener nameListener = m_remoteListeners.get(i);
1036            nameListener.netbiosAddRemoteName(evt, addr);
1037        }
1038    }
1039
1040    /**
1041     * Trigger a name release event to all registered listeners.
1042     *
1043     * @param name NetBIOSName
1044     * @param sts int
1045     */

1046    protected final synchronized void fireNameReleaseEvent(NetBIOSName name, InetAddress JavaDoc addr)
1047    {
1048
1049        // Check if there are any listeners
1050

1051        if (m_remoteListeners == null || m_remoteListeners.size() == 0)
1052            return;
1053
1054        // Create a NetBIOS name event
1055

1056        NetBIOSNameEvent evt = new NetBIOSNameEvent(name, NetBIOSNameEvent.REGISTER_NAME);
1057
1058        // Inform all registered listeners
1059

1060        for (int i = 0; i < m_remoteListeners.size(); i++)
1061        {
1062            RemoteNameListener nameListener = m_remoteListeners.get(i);
1063            nameListener.netbiosReleaseRemoteName(evt, addr);
1064        }
1065    }
1066
1067    /**
1068     * Open the server socket
1069     *
1070     * @exception SocketException
1071     */

1072    private void openSocket() throws java.net.SocketException JavaDoc
1073    {
1074
1075        // Check if the server should bind to a particular local address, or all addresses
1076

1077        if (hasBindAddress())
1078            m_socket = new DatagramSocket JavaDoc(getPort(), m_bindAddress);
1079        else
1080            m_socket = new DatagramSocket JavaDoc(getPort());
1081    }
1082
1083    /**
1084     * Process a NetBIOS name query.
1085     *
1086     * @param pkt NetBIOSPacket
1087     * @param fromAddr InetAddress
1088     * @param fromPort int
1089     */

1090    protected final void processNameQuery(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1091    {
1092
1093        // Check that the name query packet is valid
1094

1095        if (pkt.getQuestionCount() != 1)
1096            return;
1097
1098        // Get the name that is being queried
1099

1100        String JavaDoc searchName = pkt.getQuestionName();
1101        char nameType = searchName.charAt(15);
1102
1103        int len = 0;
1104        while (len <= 14 && searchName.charAt(len) != ' ')
1105            len++;
1106        searchName = searchName.substring(0, len);
1107
1108        // Debug
1109

1110        if (logger.isDebugEnabled())
1111            logger.debug("%% Query name=" + searchName + ", type=" + NetBIOSName.TypeAsString(nameType) + ", len="
1112                    + len);
1113
1114        // Search for the name in the local name table
1115

1116        Enumeration JavaDoc<NetBIOSName> enm = m_localNames.elements();
1117        NetBIOSName nbName = null;
1118        boolean foundName = false;
1119
1120        while (enm.hasMoreElements() && foundName == false)
1121        {
1122
1123            // Get the current NetBIOS name item from the local name table
1124

1125            nbName = enm.nextElement();
1126
1127            // Debug
1128

1129            if (logger.isDebugEnabled())
1130                logger.debug("NetBIOS Name - " + nbName.getName() + ", len=" + nbName.getName().length() + ",type="
1131                        + NetBIOSName.TypeAsString(nbName.getType()));
1132
1133            // Check if the name matches the query name
1134

1135            if (nbName.getType() == nameType && nbName.getName().compareTo(searchName) == 0)
1136                foundName = true;
1137        }
1138
1139        // Check if we found a matching name
1140

1141        if (foundName == true)
1142        {
1143
1144            // Debug
1145

1146            if (logger.isDebugEnabled())
1147                logger.debug("%% Found name " + searchName + " in local name table : " + nbName.toString());
1148
1149            // Build the name query response
1150

1151            int pktLen = pkt.buildNameQueryResponse(nbName);
1152
1153            // Debug
1154

1155            if (logger.isDebugEnabled())
1156            {
1157                logger.debug("%% NetBIOS Reply to " + fromAddr.getHostAddress() + " :-");
1158                pkt.DumpPacket(false);
1159            }
1160
1161            // Send the reply packet
1162

1163            try
1164            {
1165
1166                // Send the name query reply
1167

1168                sendPacket(pkt, pktLen, fromAddr, fromPort);
1169            }
1170            catch (java.io.IOException JavaDoc ex)
1171            {
1172                logger.error("Name query response error", ex);
1173            }
1174
1175            // Inform listeners of the name query
1176

1177            fireQueryNameEvent(nbName, fromAddr);
1178        }
1179        else
1180        {
1181
1182            // Debug
1183

1184            if (logger.isDebugEnabled())
1185                logger.debug("%% Failed to find match for name " + searchName);
1186        }
1187    }
1188
1189    /**
1190     * Process a NetBIOS name register request.
1191     *
1192     * @param pkt NetBIOSPacket
1193     * @param fromAddr InetAddress
1194     * @param fromPort int
1195     */

1196    protected final void processNameRegister(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1197    {
1198
1199        // Check that the name register packet is valid
1200

1201        if (pkt.getQuestionCount() != 1)
1202            return;
1203
1204        // Get the name that is being registered
1205

1206        String JavaDoc regName = pkt.getQuestionName();
1207        char nameType = regName.charAt(15);
1208
1209        int len = 0;
1210        while (len <= 14 && regName.charAt(len) != ' ')
1211            len++;
1212        regName = regName.substring(0, len);
1213
1214        // Debug
1215

1216        if (logger.isDebugEnabled())
1217            logger.debug("%% Register name=" + regName + ", type=" + NetBIOSName.TypeAsString(nameType) + ", len="
1218                    + len);
1219
1220        // Create a NetBIOS name for the host
1221

1222        byte[] hostIP = fromAddr.getAddress();
1223        NetBIOSName nbName = new NetBIOSName(regName, nameType, false, hostIP);
1224
1225        // Add the name to the remote host name table
1226

1227        m_remoteNames.put(nbName, hostIP);
1228
1229        // Inform listeners that a new remote name has been added
1230

1231        fireNameRegisterEvent(nbName, fromAddr);
1232
1233        // Debug
1234

1235        if (logger.isDebugEnabled())
1236            logger.debug("%% Added remote name " + nbName.toString() + " to remote names table");
1237    }
1238
1239    /**
1240     * Process a NetBIOS name release.
1241     *
1242     * @param pkt NetBIOSPacket
1243     * @param fromAddr InetAddress
1244     * @param fromPort int
1245     */

1246    protected final void processNameRelease(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1247    {
1248
1249        // Check that the name release packet is valid
1250

1251        if (pkt.getQuestionCount() != 1)
1252            return;
1253
1254        // Get the name that is being released
1255

1256        String JavaDoc regName = pkt.getQuestionName();
1257        char nameType = regName.charAt(15);
1258
1259        int len = 0;
1260        while (len <= 14 && regName.charAt(len) != ' ')
1261            len++;
1262        regName = regName.substring(0, len);
1263
1264        // Debug
1265

1266        if (logger.isDebugEnabled())
1267            logger
1268                    .debug("%% Release name=" + regName + ", type=" + NetBIOSName.TypeAsString(nameType) + ", len="
1269                            + len);
1270
1271        // Create a NetBIOS name for the host
1272

1273        byte[] hostIP = fromAddr.getAddress();
1274        NetBIOSName nbName = new NetBIOSName(regName, nameType, false, hostIP);
1275
1276        // Remove the name from the remote host name table
1277

1278        m_remoteNames.remove(nbName);
1279
1280        // Inform listeners that a remote name has been released
1281

1282        fireNameReleaseEvent(nbName, fromAddr);
1283
1284        // Debug
1285

1286        if (logger.isDebugEnabled())
1287            logger.debug("%% Released remote name " + nbName.toString() + " from remote names table");
1288    }
1289
1290    /**
1291     * Process a NetBIOS query response.
1292     *
1293     * @param pkt NetBIOSPacket
1294     * @param fromAddr InetAddress
1295     * @param fromPort int
1296     */

1297    protected final void processQueryResponse(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1298    {
1299    }
1300
1301    /**
1302     * Process a NetBIOS name register response.
1303     *
1304     * @param pkt NetBIOSPacket
1305     * @param fromAddr InetAddress
1306     * @param fromPort int
1307     */

1308    protected final void processRegisterResponse(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1309    {
1310
1311        // Check if there are any reply name details
1312

1313        if (pkt.getAnswerCount() == 0)
1314            return;
1315
1316        // Get the details from the response packet
1317

1318        int tranId = pkt.getTransactionId();
1319
1320        // Find the matching request
1321

1322        NetBIOSRequest req = findRequest(tranId);
1323        if (req == null)
1324            return;
1325
1326        // Get the error code from the response
1327

1328        int errCode = pkt.getResultCode();
1329
1330        if (errCode != 0)
1331        {
1332
1333            // Mark the request error
1334

1335            req.setErrorStatus(true);
1336
1337            // Get the name details
1338

1339            String JavaDoc regName = pkt.getAnswerName();
1340            char nameType = regName.charAt(15);
1341
1342            int len = 0;
1343            while (len <= 14 && regName.charAt(len) != ' ')
1344                len++;
1345            regName = regName.substring(0, len);
1346
1347            // Create a NetBIOS name for the host
1348

1349            byte[] hostIP = fromAddr.getAddress();
1350            NetBIOSName nbName = new NetBIOSName(regName, nameType, false, hostIP);
1351
1352            // Debug
1353

1354            if (logger.isDebugEnabled())
1355                logger.debug("%% Negative Name Registration name=" + nbName);
1356
1357            // Inform listeners of the add name failure
1358

1359            fireAddNameEvent(req.getNetBIOSName(), NetBIOSNameEvent.ADD_FAILED);
1360        }
1361        else
1362        {
1363
1364            // Debug
1365

1366            if (logger.isDebugEnabled())
1367                logger.debug("%% Name Registration Successful name=" + req.getNetBIOSName().getName());
1368
1369            // Inform listeners that the add name was successful
1370

1371            fireAddNameEvent(req.getNetBIOSName(), NetBIOSNameEvent.ADD_SUCCESS);
1372        }
1373    }
1374
1375    /**
1376     * Process a NetBIOS name release response.
1377     *
1378     * @param pkt NetBIOSPacket
1379     * @param fromAddr InetAddress
1380     * @param fromPort int
1381     */

1382    protected final void processReleaseResponse(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1383    {
1384    }
1385
1386    /**
1387     * Process a NetBIOS WACK.
1388     *
1389     * @param pkt NetBIOSPacket
1390     * @param fromAddr InetAddress
1391     * @param fromPort int
1392     */

1393    protected final void processWack(NetBIOSPacket pkt, InetAddress JavaDoc fromAddr, int fromPort)
1394    {
1395    }
1396
1397    /**
1398     * Remove a local add name listener from the NetBIOS name server.
1399     *
1400     * @param l AddNameListener
1401     */

1402    public final synchronized void removeAddNameListener(AddNameListener l)
1403    {
1404
1405        // Check if the listener list is valid
1406

1407        if (m_addListeners == null)
1408            return;
1409        m_addListeners.removeElement(l);
1410    }
1411
1412    /**
1413     * Remove a query name listner from the NetBIOS name server.
1414     *
1415     * @param l QueryNameListener
1416     */

1417    public final synchronized void removeQueryNameListener(QueryNameListener l)
1418    {
1419
1420        // Check if the listener list is valid
1421

1422        if (m_queryListeners == null)
1423            return;
1424        m_queryListeners.removeElement(l);
1425    }
1426
1427    /**
1428     * Remove a remote name listener from the NetBIOS name server.
1429     *
1430     * @param l RemoteNameListener
1431     */

1432    public final synchronized void removeRemoteListener(RemoteNameListener l)
1433    {
1434
1435        // Check if the listener list is valid
1436

1437        if (m_remoteListeners == null)
1438            return;
1439        m_remoteListeners.removeElement(l);
1440    }
1441
1442    /**
1443     * Run the NetBIOS name server.
1444     */

1445    public void run()
1446    {
1447
1448        // Initialize the NetBIOS name socket
1449

1450        NetBIOSPacket nbPkt = null;
1451        DatagramPacket JavaDoc pkt = null;
1452        byte[] buf = null;
1453
1454        try
1455        {
1456
1457            // Get a list of the local IP addresses
1458

1459            Vector JavaDoc<byte[]> ipList = new Vector JavaDoc<byte[]>();
1460
1461            if (hasBindAddress())
1462            {
1463
1464                // Use the specified bind address
1465

1466                ipList.add(getBindAddress().getAddress());
1467            }
1468            else
1469            {
1470
1471                // Get a list of all the local addresses
1472

1473                InetAddress JavaDoc[] addrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
1474
1475                for (int i = 0; i < addrs.length; i++)
1476                {
1477
1478                    // Check for a valid address, filter out '127.0.0.1' and '0.0.0.0' addresses
1479

1480                    if (addrs[i].getHostAddress().equals("127.0.0.1") == false
1481                            && addrs[i].getHostAddress().equals("0.0.0.0") == false)
1482                        ipList.add(addrs[i].getAddress());
1483                }
1484                
1485                // Check if any addresses were added to the list
1486

1487                if ( ipList.size() == 0)
1488                {
1489                    // Log the available IP addresses
1490

1491                    logger.error("Failed to get IP address(es) for NetBIOS name");
1492                    for ( int i = 0; i < addrs.length; i++)
1493                        logger.error( " Address: " + addrs[i]);
1494                    logger.error("Check hosts file and/or DNS setup");
1495                    logger.error("NetBIOS name server is shutting down");
1496                    
1497                    return;
1498                }
1499            }
1500
1501            // Initialize the NetBIOS name socket
1502

1503            if (m_socket == null)
1504                openSocket();
1505
1506            // Allocate the NetBIOS request queue, and add the server name/alias name requests
1507

1508            m_reqList = new Vector JavaDoc<NetBIOSRequest>();
1509
1510            // Add the server name requests to the queue
1511

1512            AddName(new NetBIOSName(getConfiguration().getServerName(), NetBIOSName.FileServer, false, ipList,
1513                    DefaultTTL));
1514            AddName(new NetBIOSName(getConfiguration().getServerName(), NetBIOSName.WorkStation, false, ipList,
1515                    DefaultTTL));
1516
1517            if (getConfiguration().getDomainName() != null)
1518                AddName(new NetBIOSName(getConfiguration().getDomainName(), NetBIOSName.Domain, true, ipList,
1519                        DefaultTTL));
1520
1521            // Create the request handler thread
1522

1523            m_reqHandler = new NetBIOSRequestHandler();
1524            m_reqHandler.start();
1525
1526            // Create the name refresh thread
1527

1528            m_refreshThread = new NetBIOSNameRefresh();
1529            m_refreshThread.start();
1530
1531            // Allocate a receive buffer, NetBIOS packet and datagram packet
1532

1533            buf = new byte[1024];
1534            nbPkt = new NetBIOSPacket(buf);
1535            pkt = new DatagramPacket JavaDoc(buf, buf.length);
1536        }
1537        catch (Exception JavaDoc ex)
1538        {
1539
1540            // Debug
1541

1542            logger.error("NetBIOSNameServer setup error:", ex);
1543
1544            // Save the exception and inform listeners of the error
1545

1546            setException(ex);
1547            fireServerEvent(ServerListener.ServerError);
1548        }
1549
1550        // If there are any pending requests in the queue then wakeup the request handler thread
1551

1552        if (m_reqList != null && m_reqList.size() > 0)
1553        {
1554            synchronized (m_reqList)
1555            {
1556                m_reqList.notify();
1557            }
1558        }
1559
1560        // Indicate that the server is active
1561

1562        setActive(true);
1563        fireServerEvent(ServerListener.ServerActive);
1564
1565        // Loop
1566

1567        if (hasException() == false)
1568        {
1569
1570            // Clear the shutdown request flag
1571

1572            m_shutdown = false;
1573
1574            while (m_shutdown == false)
1575            {
1576
1577                try
1578                {
1579
1580                    // Wait for an incoming packet ....
1581

1582                    m_socket.receive(pkt);
1583
1584                    // Check for a zero length datagram
1585

1586                    if (pkt.getLength() == 0)
1587                        continue;
1588
1589                    // Get the incoming NetBIOS packet opcode
1590

1591                    InetAddress JavaDoc fromAddr = pkt.getAddress();
1592                    int fromPort = pkt.getPort();
1593
1594                    switch (nbPkt.getOpcode())
1595                    {
1596
1597                    // Name query
1598

1599                    case NetBIOSPacket.NAME_QUERY:
1600                        processNameQuery(nbPkt, fromAddr, fromPort);
1601                        break;
1602
1603                    // Name register
1604

1605                    case NetBIOSPacket.NAME_REGISTER:
1606                        processNameRegister(nbPkt, fromAddr, fromPort);
1607                        break;
1608
1609                    // Name release
1610

1611                    case NetBIOSPacket.NAME_RELEASE:
1612                        processNameRelease(nbPkt, fromAddr, fromPort);
1613                        break;
1614
1615                    // Name register response
1616

1617                    case NetBIOSPacket.RESP_REGISTER:
1618                        processRegisterResponse(nbPkt, fromAddr, fromPort);
1619                        break;
1620
1621                    // Name query response
1622

1623                    case NetBIOSPacket.RESP_QUERY:
1624                        processQueryResponse(nbPkt, fromAddr, fromPort);
1625                        break;
1626
1627                    // Name release response
1628

1629                    case NetBIOSPacket.RESP_RELEASE:
1630                        processReleaseResponse(nbPkt, fromAddr, fromPort);
1631                        break;
1632
1633                    // WACK
1634

1635                    case NetBIOSPacket.WACK:
1636                        processWack(nbPkt, fromAddr, fromPort);
1637                        break;
1638
1639                        // Refresh
1640

1641                    case NetBIOSPacket.REFRESH:
1642                        processNameRegister(nbPkt, fromAddr, fromPort);
1643                        break;
1644                      
1645                    // Multi-homed name registration
1646

1647                    case NetBIOSPacket.NAME_REGISTER_MULTI:
1648                        processNameRegister(nbPkt, fromAddr, fromPort);
1649                        break;
1650                      
1651                    // Unknown opcode
1652

1653                    default:
1654                        logger.error("Unknown OpCode 0x" + Integer.toHexString(nbPkt.getOpcode()));
1655                        break;
1656                    }
1657                }
1658                catch (Exception JavaDoc ex)
1659                {
1660
1661                    // Debug
1662

1663                    if ( m_shutdown == false)
1664                        logger.error("NetBIOSNameServer error", ex);
1665
1666                    // Store the error and inform listeners of the server error. If the server is
1667
// shutting down we expect a
1668
// socket error as the socket is closed by the shutdown thread and the pending
1669
// read request generates an
1670
// exception.
1671

1672                    if (m_shutdown == false)
1673                    {
1674                        setException(ex);
1675                        fireServerEvent(ServerListener.ServerError);
1676                    }
1677                }
1678            }
1679        }
1680
1681        // Indicate that the server is closed
1682

1683        setActive(false);
1684        fireServerEvent(ServerListener.ServerShutdown);
1685    }
1686
1687    /**
1688     * Send a packet via the NetBIOS naming datagram socket.
1689     *
1690     * @param pkt NetBIOSPacket
1691     * @param len int
1692     * @exception java.io.IOException The exception description.
1693     */

1694    protected final void sendPacket(NetBIOSPacket nbpkt, int len) throws java.io.IOException JavaDoc
1695    {
1696
1697        // Allocate the datagram packet, using the add name buffer
1698

1699        DatagramPacket JavaDoc pkt = new DatagramPacket JavaDoc(nbpkt.getBuffer(), len, NetworkSettings.getBroadcastAddress(),
1700                getPort());
1701
1702        // Send the datagram packet
1703

1704        m_socket.send(pkt);
1705    }
1706
1707    /**
1708     * Send a packet via the NetBIOS naming datagram socket.
1709     *
1710     * @param pkt NetBIOSPacket
1711     * @param len int
1712     * @param replyAddr InetAddress
1713     * @param replyPort int
1714     * @exception java.io.IOException The exception description.
1715     */

1716    protected final void sendPacket(NetBIOSPacket nbpkt, int len, InetAddress JavaDoc replyAddr, int replyPort)
1717            throws java.io.IOException JavaDoc
1718    {
1719
1720        // Allocate the datagram packet, using the add name buffer
1721

1722        DatagramPacket JavaDoc pkt = new DatagramPacket JavaDoc(nbpkt.getBuffer(), len, replyAddr, replyPort);
1723
1724        // Send the datagram packet
1725

1726        m_socket.send(pkt);
1727    }
1728
1729    /**
1730     * Set the local address that the server should bind to
1731     *
1732     * @param addr java.net.InetAddress
1733     */

1734    public final void setBindAddress(InetAddress JavaDoc addr)
1735    {
1736        m_bindAddress = addr;
1737    }
1738
1739    /**
1740     * Set the server port
1741     *
1742     * @param port int
1743     */

1744    public final void setServerPort(int port)
1745    {
1746        m_port = port;
1747    }
1748
1749    /**
1750     * Set the primary WINS server address
1751     *
1752     * @param addr InetAddress
1753     */

1754    public final void setPrimaryWINSServer(InetAddress JavaDoc addr)
1755    {
1756        m_winsPrimary = addr;
1757    }
1758
1759    /**
1760     * Set the secondary WINS server address
1761     *
1762     * @param addr InetAddress
1763     */

1764    public final void setSecondaryWINSServer(InetAddress JavaDoc addr)
1765    {
1766        m_winsSecondary = addr;
1767    }
1768
1769    /**
1770     * Find the NetBIOS request with the specified transation id
1771     *
1772     * @param id int
1773     * @return NetBIOSRequest
1774     */

1775    private final NetBIOSRequest findRequest(int id)
1776    {
1777
1778        // Check if the request list is valid
1779

1780        if (m_reqList == null)
1781            return null;
1782
1783        // Need to lock access to the request list
1784

1785        NetBIOSRequest req = null;
1786
1787        synchronized (m_reqList)
1788        {
1789
1790            // Search for the required request
1791

1792            int idx = 0;
1793
1794            while (req == null && idx < m_reqList.size())
1795            {
1796
1797                // Get the current request and check if it is the required request
1798

1799                NetBIOSRequest curReq = (NetBIOSRequest) m_reqList.elementAt(idx++);
1800                if (curReq.getTransactionId() == id)
1801                    req = curReq;
1802            }
1803        }
1804
1805        // Return the request, or null if not found
1806

1807        return req;
1808    }
1809
1810    /**
1811     * Shutdown the NetBIOS name server
1812     *
1813     * @param immediate boolean
1814     */

1815    public void shutdownServer(boolean immediate)
1816    {
1817
1818        // Close the name refresh thread
1819

1820        try
1821        {
1822
1823            if (m_refreshThread != null)
1824            {
1825                m_refreshThread.shutdownRequest();
1826            }
1827        }
1828        catch (Exception JavaDoc ex)
1829        {
1830
1831            // Debug
1832

1833            logger.error("Shutdown NetBIOS server error", ex);
1834        }
1835
1836        // If the shutdown is not immediate then release all of the names registered by this server
1837

1838        if (isActive() && immediate == false)
1839        {
1840
1841            // Release all local names
1842

1843            for (int i = 0; i < m_localNames.size(); i++)
1844            {
1845
1846                // Get the current name details
1847

1848                NetBIOSName nbName = (NetBIOSName) m_localNames.elementAt(i);
1849
1850                // Queue a delete name request
1851

1852                try
1853                {
1854                    DeleteName(nbName);
1855                }
1856                catch (IOException JavaDoc ex)
1857                {
1858                    logger.error("Shutdown NetBIOS server error", ex);
1859                }
1860            }
1861
1862            // Wait for the request handler thread to process the delete name requests
1863

1864            while (m_reqList.size() > 0)
1865            {
1866                try
1867                {
1868                    Thread.sleep(100);
1869                }
1870                catch (InterruptedException JavaDoc ex)
1871                {
1872                }
1873            }
1874        }
1875
1876        // Close the request handler thread
1877

1878        try
1879        {
1880
1881            // Close the request handler thread
1882

1883            if (m_reqHandler != null)
1884            {
1885                m_reqHandler.shutdownRequest();
1886                m_reqHandler.join(1000);
1887                m_reqHandler = null;
1888            }
1889        }
1890        catch (Exception JavaDoc ex)
1891        {
1892
1893            // Debug
1894

1895            logger.error("Shutdown NetBIOS request handler error", ex);
1896        }
1897
1898        // Indicate that the server is closing
1899

1900        m_shutdown = true;
1901
1902        try
1903        {
1904
1905            // Close the server socket so that any pending receive is cancelled
1906

1907            if (m_socket != null)
1908            {
1909
1910                try
1911                {
1912                    m_socket.close();
1913                }
1914                catch (Exception JavaDoc ex)
1915                {
1916                }
1917                m_socket = null;
1918            }
1919        }
1920        catch (Exception JavaDoc ex)
1921        {
1922            logger.error("Shutdown NetBIOS server error", ex);
1923        }
1924
1925        // Fire a shutdown notification event
1926

1927        fireServerEvent(ServerListener.ServerShutdown);
1928    }
1929
1930    /**
1931     * Start the NetBIOS name server is a seperate thread
1932     */

1933    public void startServer()
1934    {
1935
1936        // Create a seperate thread to run the NetBIOS name server
1937

1938        m_srvThread = new Thread JavaDoc(this);
1939        m_srvThread.setName("NetBIOS Name Server");
1940        m_srvThread.setDaemon(true);
1941
1942        m_srvThread.start();
1943
1944        // Fire a server startup event
1945

1946        fireServerEvent(ServerListener.ServerStartup);
1947    }
1948}
Popular Tags