EMMA Coverage Report (generated Mon Aug 23 17:21:34 CEST 2010)
[all classes][dmg.cells.services.login]

COVERAGE SUMMARY FOR SOURCE FILE [LoginManager.java]

nameclass, %method, %block, %line, %
LoginManager.java100% (5/5)37%  (24/65)28%  (749/2664)28%  (134.9/484)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LoginManager$LoginBrokerHandler100% (1/1)36%  (4/11)11%  (54/509)14%  (13.3/94)
ac_get_children (Args): Object 0%   (0/1)0%   (0/77)0%   (0/11)
ac_lb_set_update_$_1 (Args): String 0%   (0/1)0%   (0/39)0%   (0/9)
access$3100 (LoginManager$LoginBrokerHandler, int, int): void 0%   (0/1)0%   (0/5)0%   (0/1)
getInfo (PrintWriter): void 0%   (0/1)0%   (0/72)0%   (0/9)
loadChanged (int, int): void 0%   (0/1)0%   (0/37)0%   (0/7)
run (): void 0%   (0/1)0%   (0/46)0%   (0/12)
runUpdate (): void 0%   (0/1)0%   (0/96)0%   (0/17)
LoginManager$LoginBrokerHandler (LoginManager): void 100% (1/1)34%  (42/123)44%  (12/27)
isActive (): boolean 100% (1/1)71%  (5/7)71%  (0.7/1)
LoginManager$LoginBrokerHandler (LoginManager, LoginManager$1): void 100% (1/1)100% (4/4)100% (1/1)
access$100 (LoginManager$LoginBrokerHandler): boolean 100% (1/1)100% (3/3)100% (1/1)
     
class LoginManager$ListenThread100% (1/1)50%  (5/10)12%  (91/749)12%  (17.9/153)
access$1800 (LoginManager$ListenThread): ServerSocket 0%   (0/1)0%   (0/3)0%   (0/1)
close (): void 0%   (0/1)0%   (0/1)0%   (0/1)
getInetAddress (): InetAddress [] 0%   (0/1)0%   (0/65)0%   (0/20)
open (): void 0%   (0/1)0%   (0/1)0%   (0/1)
shutdown (): void 0%   (0/1)0%   (0/83)0%   (0/18)
run (): void 100% (1/1)1%   (3/288)2%   (1/51)
LoginManager$ListenThread (LoginManager, int): void 100% (1/1)10%  (4/41)16%  (2/13)
openPort (): void 100% (1/1)29%  (76/259)28%  (13.3/47)
LoginManager$ListenThread (LoginManager, int, LoginManager$1): void 100% (1/1)100% (5/5)100% (1/1)
getListenPort (): int 100% (1/1)100% (3/3)100% (1/1)
     
class LoginManager$KeepAliveThread100% (1/1)43%  (3/7)30%  (37/123)31%  (9.4/30)
access$1700 (LoginManager$KeepAliveThread, long): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$1900 (LoginManager$KeepAliveThread): long 0%   (0/1)0%   (0/3)0%   (0/1)
getKeepAlive (): long 0%   (0/1)0%   (0/3)0%   (0/1)
setKeepAlive (long): void 0%   (0/1)0%   (0/31)0%   (0/6)
run (): void 100% (1/1)25%  (15/60)24%  (4/17)
LoginManager$KeepAliveThread (LoginManager, long): void 100% (1/1)100% (17/17)100% (5/5)
LoginManager$KeepAliveThread (LoginManager, long, LoginManager$1): void 100% (1/1)100% (5/5)100% (1/1)
     
class LoginManager100% (1/1)26%  (9/34)40%  (450/1128)44%  (79.4/180)
ac_set_keepalive_$_1 (Args): String 0%   (0/1)0%   (0/22)0%   (0/3)
ac_set_max_logins_$_1 (Args): String 0%   (0/1)0%   (0/47)0%   (0/10)
access$1100 (LoginManager): Map 0%   (0/1)0%   (0/3)0%   (0/1)
access$1300 (LoginManager): int 0%   (0/1)0%   (0/3)0%   (0/1)
access$1308 (LoginManager): int 0%   (0/1)0%   (0/8)0%   (0/1)
access$1310 (LoginManager): int 0%   (0/1)0%   (0/8)0%   (0/1)
access$1400 (LoginManager): void 0%   (0/1)0%   (0/3)0%   (0/1)
access$2108 (LoginManager): int 0%   (0/1)0%   (0/8)0%   (0/1)
access$2200 (LoginManager): int 0%   (0/1)0%   (0/3)0%   (0/1)
access$2308 (LoginManager): int 0%   (0/1)0%   (0/8)0%   (0/1)
access$2500 (LoginManager): Constructor 0%   (0/1)0%   (0/3)0%   (0/1)
access$2600 (LoginManager): int 0%   (0/1)0%   (0/3)0%   (0/1)
access$2700 (LoginManager): Constructor 0%   (0/1)0%   (0/3)0%   (0/1)
access$2800 (LoginManager): Method 0%   (0/1)0%   (0/3)0%   (0/1)
access$2908 (LoginManager): int 0%   (0/1)0%   (0/8)0%   (0/1)
access$3008 (LoginManager): int 0%   (0/1)0%   (0/8)0%   (0/1)
access$700 (LoginManager): String 0%   (0/1)0%   (0/3)0%   (0/1)
access$800 (LoginManager): CellNucleus 0%   (0/1)0%   (0/3)0%   (0/1)
access$900 (LoginManager): Class 0%   (0/1)0%   (0/3)0%   (0/1)
childrenCounterChanged (): void 0%   (0/1)0%   (0/24)0%   (0/5)
cleanUp (): void 0%   (0/1)0%   (0/13)0%   (0/4)
getCellVersion (): CellVersion 0%   (0/1)0%   (0/19)0%   (0/4)
getInfo (PrintWriter): void 0%   (0/1)0%   (0/174)0%   (0/18)
runKeepAlive (): void 0%   (0/1)0%   (0/56)0%   (0/11)
validateUser (String, String): boolean 0%   (0/1)0%   (0/64)0%   (0/15)
LoginManager (String, String): void 100% (1/1)69%  (398/574)72%  (76.3/106)
toString (): String 100% (1/1)93%  (27/29)93%  (0.9/1)
<static initializer> 100% (1/1)100% (7/7)100% (2/2)
access$1000 (): Logger 100% (1/1)100% (2/2)100% (1/1)
access$1200 (LoginManager): LoginManager$ListenThread 100% (1/1)100% (3/3)100% (1/1)
access$1502 (LoginManager, boolean): boolean 100% (1/1)100% (5/5)100% (1/1)
access$1600 (LoginManager): String 100% (1/1)100% (3/3)100% (1/1)
access$2000 (): Logger 100% (1/1)100% (2/2)100% (1/1)
access$600 (LoginManager): Args 100% (1/1)100% (3/3)100% (1/1)
     
class LoginManager$LocationThread100% (1/1)100% (3/3)75%  (117/155)55%  (14.9/27)
run (): void 100% (1/1)74%  (107/145)53%  (13.9/26)
LoginManager$LocationThread (LoginManager): void 100% (1/1)100% (6/6)100% (1/1)
LoginManager$LocationThread (LoginManager, LoginManager$1): void 100% (1/1)100% (4/4)100% (1/1)

1// $Id: LoginManager.java,v 1.46 2007-10-22 12:30:38 behrmann Exp $
2//
3package  dmg.cells.services.login ;
4 
5import java.lang.reflect.* ;
6import java.net.* ;
7import java.io.* ;
8import java.nio.channels.*;
9import java.util.*;
10 
11import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
13 
14import dmg.cells.nucleus.*;
15import dmg.util.*;
16import dmg.protocols.ssh.* ;
17import dmg.protocols.telnet.* ;
18 
19/**
20 **
21  *
22  *
23  * @author Patrick Fuhrmann
24  * @version 0.1, 15 Feb 1998
25  *
26 */
27public class       LoginManager
28       extends     CellAdapter
29       implements  UserValidatable {
30 
31  private final String       _cellName ;
32  private final CellNucleus  _nucleus ;
33  private final Args         _args ;
34  private final ListenThread _listenThread ;
35  private int          _connectionRequestCounter   = 0 ;
36  private int          _connectionAcceptionCounter = 0 ;
37  private int          _connectionDeniedCounter    = 0 ;
38  private String       _locationManager   = null ;
39  private int          _loginCounter = 0 , _loginFailures = 0 ;
40  private boolean      _sending = false ;
41  private Class        _loginClass        = Object.class ;
42  private Constructor  _loginConstructor  = null ;
43  private Constructor  _authConstructor   = null ;
44  private Method       _loginPrintMethod  = null ;
45  private int          _maxLogin          = -1 ;
46  private final Map<String,Object>      _childHash   = new HashMap<String,Object>() ;
47 
48  /**
49   * actually, _childCount have to be equal to _childHash.size(). But while
50   * cells needs some time to die, _childHash contains cells which are in removing state,
51   * while  _childCount shows active cells only.
52   */
53  private int          _childCount        = 0 ;
54  private String       _authenticator     = null ;
55  private KeepAliveThread _keepAlive      = null  ;
56 
57  private LoginBrokerHandler _loginBrokerHandler = null ;
58 
59  private static Logger _log = LoggerFactory.getLogger(LoginManager.class);
60  private static Logger _logSocketIO = LoggerFactory.getLogger("logger.dev.org.dcache.io.socket");
61 
62  private Class [][] _loginConSignature = {
63    {  java.lang.String.class ,
64       dmg.util.StreamEngine.class } ,
65    {  java.lang.String.class  ,
66       dmg.util.StreamEngine.class ,
67       dmg.util.Args.class           }
68  } ;
69 
70  private Class [] _authConSignature = {
71     dmg.cells.nucleus.CellNucleus.class , dmg.util.Args.class
72  } ;
73 
74 
75  private  Class [] _loginPntSignature = { int.class     } ;
76  private  int      _loginConType      = -1 ;
77 
78  private  String _protocol ;
79  private  String _authClassName ;
80  private  Class  _authClass ;
81  /**
82  *<pre>
83  *   usage   &lt;listenPort&gt; &lt;loginCellClass&gt;
84  *           [-prot=ssh|telnet|raw]
85  *                    default : telnet
86  *           [-auth=&lt;authenticationClass&gt;]
87  *                    default : ssh    : dmg.cells.services.login.SshSAuth_A
88  *                              telnet : dmg.cells.services.login.TelnetSAuth_A
89  *                              raw    : none
90  *
91  *         all residual arguments and all options are sent to
92  *         the &lt;loginCellClass&gt; :
93  *            &lt;init&gt;(String name , StreamEngine engine , Args args )
94  *
95  *         and to the Authentication module (class)
96  *
97  *            &lt;init&gt;(CellNucleus nucleus , Args args )
98  *
99  *         Both get their own copy.
100  *</pre>
101  */
102  public LoginManager( String name , String argString ) throws Exception {
103 
104      super( name , argString , false ) ;
105 
106      _cellName = name ;
107      _nucleus  = getNucleus() ;
108      _args     = getArgs() ;
109      try{
110         Args args = _args ;
111         if( args.argc() < 2 )
112           throw new
113           IllegalArgumentException(
114           "USAGE : ... <listenPort> <loginCellClass>"+
115           " [-prot=ssh|telnet|raw] [-auth=<authCell>]"+
116           " [-maxLogin=<n>|-1]"+
117           " [-keepAlive=<seconds>]"+
118           " [-acceptErrorWait=<msecs>]"+
119           " [args givenToLoginClass]" ) ;
120         //
121         // get the protocol
122         //
123         _protocol = args.getOpt("prot") ;
124         if( _protocol == null )_protocol = "telnet" ;
125 
126         if( ! ( _protocol.equals("ssh")     ||
127                 _protocol.equals("telnet" ) ||
128                 _protocol.equals("raw" )        ) )
129                 throw new
130                 IllegalArgumentException(
131                 "Protocol must be telnet or ssh or raw" ) ;
132 
133         _log.info( "Using Protocol : "+_protocol ) ;
134         //
135         // get the listen port.
136         //
137         int listenPort    = Integer.parseInt( args.argv(0) ) ;
138         args.shift() ;
139         //
140         // which cell to start
141         //
142         if( args.argc() > 0 ){
143            _loginClass = Class.forName( args.argv(0) ) ;
144            _log.info( "Using login class : "+_loginClass.getName() ) ;
145            args.shift() ;
146         }
147         //
148         // get the authentication
149         //
150         _authenticator = args.getOpt("authenticator") ;
151         _authenticator = _authenticator == null ? "pam" : _authenticator ;
152 
153         if( ( _authClassName = args.getOpt("auth") ) == null ){
154            if( _protocol.equals( "ssh" ) ){
155               _authClass = dmg.cells.services.login.SshSAuth_A.class ;
156            }else if( _protocol.equals( "raw" ) ){
157               _authClass = null ;
158            }else if( _protocol.equals( "telnet" ) ){
159               _authClass = dmg.cells.services.login.TelnetSAuth_A.class ;
160            }
161            if( _authClass != null )
162               _log.info( "Using authentication Module : "+_authClass ) ;
163         }else if( _authClassName.equals( "none" ) ){
164//            _authClass = dmg.cells.services.login.NoneSAuth.class ;
165         }else{
166            _log.info( "Using authentication Module : "+_authClassName ) ;
167            _authClass = Class.forName(_authClassName) ;
168         }
169         if( _authClass != null ){
170            _authConstructor = _authClass.getConstructor( _authConSignature ) ;
171            _log.info( "Using authentication Constructor : "+_authConstructor ) ;
172         }else{
173            _authConstructor = null ;
174            _log.info( "No authentication used" ) ;
175         }
176         try{
177            _loginConstructor = _loginClass.getConstructor( _loginConSignature[1] ) ;
178            _loginConType     = 1 ;
179         }catch( NoSuchMethodException nsme ){
180            _loginConstructor = _loginClass.getConstructor( _loginConSignature[0] ) ;
181            _loginConType     = 0 ;
182         }
183         _log.info( "Using constructor : "+_loginConstructor ) ;
184         try{
185 
186            _loginPrintMethod = _loginClass.getMethod(
187                                   "setPrintoutLevel" ,
188                                   _loginPntSignature ) ;
189 
190         }catch( NoSuchMethodException pr ){
191            _log.info( "No setPrintoutLevel(int) found in "+_loginClass.getName() ) ;
192            _loginPrintMethod = null ;
193         }
194         String maxLogin = args.getOpt("maxLogin") ;
195         if( maxLogin != null ){
196            try{
197               _maxLogin = Integer.parseInt(maxLogin);
198            }catch(NumberFormatException ee){/* bad values ignored */}
199         }
200         //
201         //  using the LoginBroker ?
202         //
203         _loginBrokerHandler = new LoginBrokerHandler() ;
204         addCommandListener( _loginBrokerHandler ) ;
205         //
206         // enforce 'maxLogin' if 'loginBroker' is defined
207         //
208         if( ( _loginBrokerHandler.isActive() ) &&
209             ( _maxLogin < 0                  )    ) _maxLogin=100000 ;
210         //
211         if( _maxLogin < 0 ){
212            _log.info("MaxLogin feature disabled") ;
213         }else{
214 
215            _nucleus.addCellEventListener( new LoginEventListener() ) ;
216 
217            _log.info("Maximum Logins set to :"+_maxLogin ) ;
218         }
219         //
220         // keep alive
221         //
222         String keepAliveValue = args.getOpt("keepAlive");
223         long   keepAlive      = 0L ;
224         try{
225            keepAlive = keepAliveValue == null ? 0L :
226                        Long.parseLong(keepAliveValue);
227         }catch(NumberFormatException ee ){
228            _log.warn("KeepAlive value not valid : "+keepAliveValue ) ;
229         }
230         _log.info("Keep Alive set to "+keepAlive+" seconds") ;
231         keepAlive *= 1000L ;
232         _keepAlive = new KeepAliveThread(keepAlive) ;
233         //
234         // get the location manager
235         //
236         _locationManager = args.getOpt("lm") ;
237         //
238 
239         _listenThread  = new ListenThread( listenPort ) ;
240         _log.info( "Listening on port "+_listenThread.getListenPort() ) ;
241 
242 
243         _nucleus.newThread( _listenThread , "listen" ).start() ;
244 
245         _nucleus.newThread( new LocationThread() , "Location" ).start() ;
246 
247         _nucleus.newThread( _keepAlive , "KeepAlive" ).start() ;
248 
249      }catch( Exception e ){
250         _log.warn( "LoginManger >"+getCellName()+"< got exception : "+e, e ) ;
251         start() ;
252         kill() ;
253         throw e ;
254      }
255 
256      start() ;
257 
258  }
259  @Override
260public CellVersion getCellVersion(){
261     try{
262 
263       Method m = _loginClass.getMethod( "getStaticCellVersion" , (Class[])null ) ;
264 
265       return (CellVersion)m.invoke( (Object)null , (Object[])null ) ;
266 
267     }catch(Exception ee ){
268         return super.getCellVersion() ;
269     }
270  }
271  public class LoginBrokerHandler implements Runnable {
272 
273     private String _loginBroker        = null ;
274     private String _protocolFamily     = null ;
275     private String _protocolVersion    = null ;
276     private long   _brokerUpdateTime   = 5*60*1000 ;
277     private double _brokerUpdateOffset = 0.1 ;
278     private LoginBrokerInfo _info      = null ;
279     private double _currentLoad        = 0.0 ;
280     private LoginBrokerHandler(){
281 
282        _loginBroker = _args.getOpt( "loginBroker" ) ;
283        if( _loginBroker == null )return;
284 
285        _protocolFamily    = _args.getOpt("protocolFamily" ) ;
286        if( _protocolFamily == null )_protocolFamily = _protocol ;
287        _protocolVersion = _args.getOpt("protocolVersion") ;
288        if( _protocolVersion == null )_protocolVersion = "0.1" ;
289        String tmp = _args.getOpt("brokerUpdateTime") ;
290        try{
291           _brokerUpdateTime = Long.parseLong(tmp) * 1000 ;
292        }catch(NumberFormatException e ){/* bad values ignored */ }
293        tmp = _args.getOpt("brokerUpdateOffset") ;
294        if(tmp != null) {
295            try{
296               _brokerUpdateOffset = Double.parseDouble(tmp) ;
297            }catch(NumberFormatException e ){/* bad values ignored */ }
298        }
299 
300        _info = new LoginBrokerInfo(
301                     _nucleus.getCellName() ,
302                     _nucleus.getCellDomainName() ,
303                     _protocolFamily ,
304                     _protocolVersion ,
305                     _loginClass.getName() ) ;
306 
307        _info.setUpdateTime( _brokerUpdateTime ) ;
308 
309        _nucleus.newThread( this , "loginBrokerHandler" ).start() ;
310 
311     }
312     public void run(){
313        try{
314          synchronized(this){
315             while( ! Thread.interrupted() ){
316                try{
317                   runUpdate() ;
318                }catch(Exception ie){
319                   _log.warn("Login Broker Thread reports : "+ie);
320                }
321                wait( _brokerUpdateTime ) ;
322             }
323          }
324        }catch( Exception io ){
325          _log.info( "Login Broker Thread terminated due to "+io ) ;
326        }
327     }
328     public String hh_get_children = "[-binary]" ;
329     public Object ac_get_children( Args args ){
330        boolean binary = args.getOpt("binary") != null ;
331        synchronized( _childHash ){
332           if( binary ){
333              String [] list = new String[_childHash.size()] ;
334              list = _childHash.keySet().toArray(list);
335              return new LoginManagerChildrenInfo( getCellName() , getCellDomainName(), list ) ;
336           }else{
337              StringBuilder sb = new StringBuilder() ;
338              for(String child : _childHash.keySet() ){
339                 sb.append(child).append("\n");
340              }
341              return sb.toString();
342           }
343        }
344     }
345     public String hh_lb_set_update = "<updateTime/sec>" ;
346     public String ac_lb_set_update_$_1( Args args ){
347        long update = Long.parseLong( args.argv(0) )*1000 ;
348        if( update < 2000 )
349           throw new
350           IllegalArgumentException("Update time out of range") ;
351 
352        synchronized(this){
353           _brokerUpdateTime = update ;
354           _info.setUpdateTime(update) ;
355           notifyAll() ;
356        }
357        return "" ;
358     }
359     private synchronized void runUpdate(){
360 
361        if( _listenThread == null ) return;
362 
363        InetAddress[] addresses = _listenThread.getInetAddress();
364 
365        if( (addresses == null) || ( addresses.length == 0 ) ) return;
366 
367        String[] hosts = new String[addresses.length];
368 
369        /**
370         *  Add addresses ensuring preferred ordering: external addresses are before any
371         *  internal interface addresses.
372         */
373        int nextExternalIfIndex = 0;
374        int nextInternalIfIndex = addresses.length-1;
375 
376        for( int i = 0; i < addresses.length; i++) {
377                    InetAddress addr = addresses[i];
378 
379                if( !addr.isLinkLocalAddress() && !addr.isLoopbackAddress() &&
380                                !addr.isSiteLocalAddress() && !addr.isMulticastAddress()) {
381                        hosts [nextExternalIfIndex++] = addr.getHostName();
382                } else {
383                        hosts [nextInternalIfIndex--] = addr.getHostName();
384                }
385        }
386 
387        _info.setHosts(hosts);
388        _info.setPort(_listenThread.getListenPort());
389        _info.setLoad(_currentLoad);
390        try{
391           sendMessage(new CellMessage(new CellPath(_loginBroker),_info));
392//           _log.info("Updated : "+_info);
393        }catch(Exception ee){}
394     }
395     public void getInfo( PrintWriter pw ){
396        if( _loginBroker == null ){
397           pw.println( "    Login Broker : DISABLED" ) ;
398           return ;
399        }
400        pw.println( "    LoginBroker      : "+_loginBroker ) ;
401        pw.println( "    Protocol Family  : "+_protocolFamily ) ;
402        pw.println( "    Protocol Version : "+_protocolVersion ) ;
403        pw.println( "    Update Time      : "+(_brokerUpdateTime/1000)+" seconds" ) ;
404        pw.println( "    Update Offset    : "+
405                    ((int)(_brokerUpdateOffset*100.))+" %" ) ;
406 
407     }
408     private boolean isActive(){ return _loginBroker != null ; }
409     private void loadChanged( int children , int maxChildren ){
410       if( _loginBroker == null )return ;
411       synchronized( this ){
412          _currentLoad = (double)children / (double) maxChildren ;
413          if(  Math.abs( _info.getLoad() - _currentLoad ) > _brokerUpdateOffset ){
414            notifyAll() ;
415          }
416       }
417     }
418  }
419  private class LoginEventListener implements CellEventListener {
420     public void cellCreated( CellEvent ce ) { /* forced by interface */  }
421     public void cellDied( CellEvent ce ) {
422        synchronized( _childHash ){
423           String removedCell = ce.getSource().toString() ;
424           if( ! removedCell.startsWith( getCellName() ) )return ;
425 
426               /*
427                *  while in some cases remove may be issued prior cell is inserted into _childHash
428                *  following trick is used:
429                *  if there is no mapping for this cell, we create a 'dead' mapping, which will
430                *  allow following put to identify it as a 'dead' and remove it.
431                *
432                */
433 
434           Object newCell = _childHash.remove( removedCell ) ;
435           if( newCell == null ) {
436                   // it's a dead cell, put it back
437                   _childHash.put(removedCell, new Object() );
438                   _log.warn("LoginEventListener : removing DEAD cell: "+removedCell);
439           }
440           _log.info("LoginEventListener : removing : "+removedCell);
441           _childCount -- ;
442           childrenCounterChanged() ;
443        }
444     }
445     public void cellExported( CellEvent ce ) { /* forced by interface */ }
446     public void routeAdded( CellEvent ce )   { /* forced by interface */ }
447     public void routeDeleted( CellEvent ce ) { /* forced by interface */ }
448  }
449  //
450  // the 'send to location manager thread'
451  //
452  private class LocationThread implements Runnable {
453     public void run(){
454 
455        int listenPort = _listenThread.getListenPort() ;
456 
457        _log.info("Sending 'listeningOn "+getCellName()+" "+listenPort+"'") ;
458        _sending = true ;
459        String dest = _locationManager;
460        if( dest == null )return ;
461        CellPath path = new CellPath( dest ) ;
462        CellMessage msg =
463           new CellMessage(
464                 path ,
465                 "listening on "+getCellName()+" "+listenPort ) ;
466 
467        for( int i = 0 ; ! Thread.interrupted() ; i++ ){
468          _log.info("Sending ("+i+") 'listening on "+getCellName()+" "+listenPort+"'") ;
469 
470          try{
471             if( sendAndWait( msg , 5000 ) != null ){
472                _log.info("Portnumber successfully sent to "+dest ) ;
473                _sending = false ;
474                break ;
475             }
476             _log.warn( "No reply from "+dest ) ;
477          }catch( InterruptedException ie ){
478             _log.warn( "'send portnumber thread' interrupted");
479             break ;
480          }catch(Exception ee ){
481             _log.warn( "Problem sending portnumber "+ee ) ;
482          }
483          try{
484             Thread.sleep(10000) ;
485          }catch(InterruptedException ie ){
486             _log.warn( "'send portnumber thread' (sleep) interrupted");
487             break ;
488 
489          }
490        }
491     }
492  }
493  private class KeepAliveThread implements Runnable {
494     private long   _keepAlive = 0L ;
495     private final Object _lock      = new Object() ;
496     private KeepAliveThread( long keepAlive ){
497        _keepAlive = keepAlive ;
498     }
499     public void run(){
500        synchronized( _lock ){
501          _log.info("KeepAlive Thread started");
502          while( ! Thread.interrupted() ){
503             try{
504                if( _keepAlive < 1 ){
505                   _lock.wait() ;
506                }else{
507                   _lock.wait( _keepAlive ) ;
508                }
509             }catch(InterruptedException ie ){
510                _log.info("KeepAlive thread done (interrupted)");
511                break ;
512             }
513 
514             if( _keepAlive > 0 )
515               try{
516                  runKeepAlive();
517               }catch(Throwable t ){
518                  _log.warn("runKeepAlive reported : "+t);
519               }
520          }
521 
522        }
523 
524     }
525     private void setKeepAlive( long keepAlive ){
526        synchronized( _lock ){
527           _keepAlive = keepAlive ;
528           _log.info("Keep Alive value changed to "+_keepAlive);
529           _lock.notifyAll() ;
530        }
531     }
532     private long getKeepAlive(){
533        return _keepAlive ;
534     }
535  }
536  public String hh_set_keepalive = "<keepAliveValue/seconds>";
537  public String ac_set_keepalive_$_1( Args args ){
538     long keepAlive = Long.parseLong( args.argv(0) ) ;
539     _keepAlive.setKeepAlive( keepAlive * 1000L ) ;
540     return "keepAlive value set to "+keepAlive+" seconds" ;
541  }
542 
543  public void runKeepAlive(){
544     List<Object> list = null ;
545     synchronized( _childHash ){
546        list = new ArrayList<Object>( _childHash.values() ) ;
547     }
548 
549     for( Object o : list ){
550 
551        if( ! ( o instanceof KeepAliveListener ) )continue ;
552        try{
553           ((KeepAliveListener)o).keepAlive() ;
554        }catch(Throwable t ){
555           _log.warn("Problem reported by : "+o+" : "+t);
556        }
557     }
558  }
559  //
560  // the cell implementation
561  //
562  @Override
563public String toString(){
564     return
565        "p="+(_listenThread==null?"???":(""+_listenThread.getListenPort()))+
566        ";c="+_loginClass.getName() ;
567  }
568  @Override
569public void getInfo( PrintWriter pw ){
570    pw.println( "  -- Login Manager $Revision: 1.46 $") ;
571    pw.println( "  Listen Port    : "+_listenThread.getListenPort() ) ;
572    pw.println( "  Login Class    : "+_loginClass ) ;
573    pw.println( "  Protocol       : "+_protocol ) ;
574    pw.println( "  NioChannel     : "+( _listenThread._serverSocket.getChannel() != null ) ) ;
575    pw.println( "  Auth Class     : "+_authClass ) ;
576    pw.println( "  Logins created : "+_loginCounter ) ;
577    pw.println( "  Logins failed  : "+_loginFailures ) ;
578    pw.println( "  Logins denied  : "+_connectionDeniedCounter ) ;
579    pw.println( "  KeepAlive      : "+(_keepAlive.getKeepAlive()/1000L) ) ;
580 
581    if( _maxLogin > -1 )
582    pw.println( "  Logins/max     : "+_childHash.size()+"("+_childCount+")/"+_maxLogin ) ;
583 
584    if( _locationManager != null )
585    pw.println( "  Location Mgr   : "+_locationManager+
586                " ("+(_sending?"Sending":"Informed")+")" ) ;
587 
588    if( _loginBrokerHandler != null ){
589       pw.println( "  LoginBroker Info :" ) ;
590       _loginBrokerHandler.getInfo( pw ) ;
591    }
592    return ;
593  }
594  public String hh_set_max_logins = "<maxNumberOfLogins>|-1" ;
595  public String ac_set_max_logins_$_1( Args args )throws Exception {
596      int n = Integer.parseInt( args.argv(0) ) ;
597      if( ( n > -1 ) && ( _maxLogin < 0 ) )
598         throw new
599         IllegalArgumentException("Can't switch off maxLogin feature" ) ;
600      if( ( n < 0 ) && ( _maxLogin > -1 ) )
601         throw new
602         IllegalArgumentException( "Can't switch on maxLogin feature" ) ;
603 
604      synchronized( _childHash ){
605         _maxLogin = n ;
606         childrenCounterChanged() ;
607      }
608      return "" ;
609  }
610  @Override
611public void cleanUp(){
612     _log.info( "cleanUp requested by nucleus, closing listen socket" ) ;
613     if( _listenThread != null )_listenThread.shutdown() ;
614     _log.info( "Bye Bye" ) ;
615  }
616 
617  private class ListenThread implements Runnable {
618     private int          _listenPort   = 0 ;
619     private ServerSocket _serverSocket = null ;
620     private boolean      _shutdown     = false ;
621     private boolean      _active       = true ;
622     private Thread       _this         = null ;
623     private long         _acceptErrorTimeout = 0L ;
624     private boolean      _isDedicated  = false;
625 
626     private ListenThread( int listenPort) throws Exception {
627        _listenPort   = listenPort ;
628 
629        try{
630           _acceptErrorTimeout = Long.parseLong(_args.getOpt("acceptErrorWait"));
631        }catch(NumberFormatException ee ){ /* bad values ignored */};
632 
633        openPort() ;
634     }
635     private void openPort() throws Exception {
636 
637        String ssf = _args.getOpt("socketfactory") ;
638        String local   = _args.getOpt("listen");
639 
640        if( ssf == null ){
641           SocketAddress socketAddress = null;
642 
643           if ( (local == null ) || local.equals("*") || local.equals("")  ) {
644               socketAddress =  new InetSocketAddress( _listenPort ) ;
645           }else{
646               socketAddress = new InetSocketAddress( InetAddress.getByName(local) , _listenPort ) ;
647               _isDedicated = true;
648           }
649 
650           _serverSocket = ServerSocketChannel.open().socket();
651           _serverSocket.bind( socketAddress );
652           _listenPort   = _serverSocket.getLocalPort() ;
653 
654        }else{
655           StringTokenizer st = new StringTokenizer(ssf,",");
656 
657           /*
658            * socket factory initialization has following format:
659            *   <classname>[<arg1>,...]
660            */
661           if( st.countTokens() < 2 ) {
662               throw new
663               IllegalArgumentException( "Invalid Arguments for 'socketfactory'");
664           }
665 
666           String tunnelFactoryClass = st.nextToken();
667           /*
668            * the rest is passed to factory constructor as String[]
669            */
670           String[] farctoryArgs = new String[ st.countTokens()];
671           for( int i = 0; st.hasMoreTokens() ; i++) {
672               farctoryArgs[i] = st.nextToken();
673           }
674 
675 
676           Class []  constructorArgClassA = { java.lang.String[].class , java.util.Map.class } ;
677           Class []  constructorArgClassB = { java.lang.String[].class } ;
678 
679 
680           Class     ssfClass = Class.forName(tunnelFactoryClass);
681           Object [] args     = null ;
682 
683           Constructor ssfConstructor = null ;
684           try{
685              ssfConstructor = ssfClass.getConstructor(constructorArgClassA) ;
686              args = new Object[2] ;
687              args[0] = farctoryArgs;
688              Map map = new HashMap((Map)getDomainContext()) ;
689              map.put( "UserValidatable" , LoginManager.this ) ;
690              args[1] = map ;
691           }catch( Exception ee ){
692              ssfConstructor = ssfClass.getConstructor(constructorArgClassB) ;
693              args = new Object[1] ;
694              args[0] = farctoryArgs;
695           }
696           Object     obj = ssfConstructor.newInstance(args) ;
697 
698           Method meth = ssfClass.getMethod("createServerSocket", new Class[0]) ;
699           _serverSocket = (ServerSocket)meth.invoke( obj ) ;
700 
701           if ( (local == null ) || local.equals("*") || local.equals("")  ) {
702               _serverSocket.bind(new InetSocketAddress( _listenPort ) );
703           }else{
704               _serverSocket.bind(new InetSocketAddress(InetAddress.getByName(local), _listenPort ) );
705               _isDedicated = true;
706           }
707 
708           _log.info("ListenThread : got serverSocket class : "+_serverSocket.getClass().getName());
709        }
710 
711        if( _logSocketIO.isDebugEnabled() ) {
712            _logSocketIO.debug("Socket BIND local = " + _serverSocket.getInetAddress() + ":" + _serverSocket.getLocalPort() );
713        }
714        _log.info("Nio Socket Channel : "+(_serverSocket.getChannel()!=null));
715     }
716     public int getListenPort(){ return _listenPort ; }
717     public InetAddress[] getInetAddress(){
718         InetAddress[] addresses = null;
719         if( _isDedicated ) {
720             if( _serverSocket != null ) {
721                 addresses = new InetAddress[1];
722                 addresses[0] =  _serverSocket.getInetAddress() ;
723             }
724         }else{
725 
726             /**
727              *  put all local Ip addresses, except loopback
728              */
729 
730             try {
731                 Enumeration<NetworkInterface> ifList = NetworkInterface.getNetworkInterfaces();
732 
733                 Vector<InetAddress> v = new Vector<InetAddress>();
734                 while( ifList.hasMoreElements() ) {
735 
736                     NetworkInterface ne = ifList.nextElement();
737 
738                     Enumeration<InetAddress> ipList = ne.getInetAddresses();
739                     while( ipList.hasMoreElements() ) {
740                        InetAddress ia = ipList.nextElement();
741                        // Currently we do not handle ipv6
742                        if( ! (ia instanceof Inet4Address) ) continue;
743                        if( ! ia.isLoopbackAddress() ) {
744                            v.add( ia ) ;
745                        }
746                     }
747                 }
748                 addresses = v.toArray( new InetAddress[ v.size() ] );
749             }catch(SocketException se_ignored) {}
750         }
751 
752         return addresses;
753     }
754 
755     public void run(){
756         _this = Thread.currentThread() ;
757         while( true ){
758            Socket socket = null ;
759            try{
760               socket = _serverSocket.accept() ;
761               socket.setKeepAlive(true);
762                    if( _logSocketIO.isDebugEnabled() ) {
763                            _logSocketIO.debug("Socket OPEN (ACCEPT) remote = " + socket.getInetAddress() + ":" + socket.getPort() +
764                                                    " local = " +socket.getLocalAddress() + ":" + socket.getLocalPort() );
765                    }
766               _log.info("Nio Channel (accept) : "+(socket.getChannel()!=null));
767 
768 
769               _connectionRequestCounter ++ ;
770               int currentChildHash = 0 ;
771                synchronized( _childHash ){ currentChildHash = _childCount ; }
772               _log.info("New connection : "+currentChildHash);
773               if ((_maxLogin > 0) && (currentChildHash > _maxLogin)) {
774                                                _connectionDeniedCounter++;
775                                                _log.warn("Connection denied " + currentChildHash + " > "
776                                                                + _maxLogin);
777                                                _logSocketIO.warn("number of allowed logins exceeded.");
778                                                new ShutdownEngine(socket);
779                                                continue;
780                                        }
781               _log.info( "Connection request from "+socket.getInetAddress() ) ;
782                synchronized( _childHash ){ _childCount ++; }
783               _nucleus.newThread(
784                   new RunEngineThread(socket) ,
785                   "ClinetThread-" + socket.getInetAddress() + ":" + socket.getPort()    ).start() ;
786 
787            }catch( InterruptedIOException ioe ){
788               _log.warn("Listen thread interrupted") ;
789               try{ _serverSocket.close() ; }catch(IOException ee){}
790               break ;
791            }catch( IOException ioe ){
792                if (_serverSocket.isClosed()) {
793                    break;
794                }
795 
796               _log.warn( "Got an IO Exception ( closing server ) : "+ioe ) ;
797               try{ _serverSocket.close() ; }catch(IOException ee){}
798               if( _acceptErrorTimeout <= 0L )break ;
799               _log.warn( "Waiting "+_acceptErrorTimeout+" msecs");
800               try{
801                  Thread.sleep(_acceptErrorTimeout) ;
802               }catch(InterruptedException ee ){
803                  _log.warn("Recovery halt interrupted");
804                  break ;
805               }
806               _log.warn( "Resuming listener");
807               try{
808 
809                  openPort() ;
810 
811               }catch(Exception ee ){
812                  _log.warn( "openPort reported : "+ee ) ;
813                  _log.warn( "Waiting "+_acceptErrorTimeout+" msecs");
814                  try{
815                     Thread.sleep(_acceptErrorTimeout) ;
816                  }catch(InterruptedException eee ){
817                     _log.warn("Recovery halt interrupted");
818                     break ;
819                  }
820               }
821            }
822 
823         }
824         _log.info( "Listen thread finished");
825     }
826     public class ShutdownEngine implements Runnable {
827         private Socket _socket = null ;
828         public ShutdownEngine( Socket socket ){
829           _socket = socket ;
830           _nucleus.newThread( this , "Shutdown" ).start() ;
831         }
832         public void run(){
833           InputStream inputStream = null ;
834           OutputStream outputStream = null ;
835           try{
836              inputStream  = _socket.getInputStream() ;
837              outputStream = _socket.getOutputStream() ;
838              outputStream.close() ;
839              byte [] buffer = new byte[1024] ;
840              /*
841               * eat the outstanding date from socket and close it
842               */
843              while( inputStream.read(buffer,0,buffer.length) > 0 ) ;
844              inputStream.close() ;
845           }catch(Exception ee ){
846              _log.warn("Shutdown : "+ee.getMessage() ) ;
847           }finally{
848                   try {
849                       if( _logSocketIO.isDebugEnabled() ) {
850                            _logSocketIO.debug("Socket CLOSE (ACCEPT) remote = " + _socket.getInetAddress() + ":" + _socket.getPort() +
851                                                    " local = " +_socket.getLocalAddress() + ":" + _socket.getLocalPort() );
852                    }
853                                _socket.close() ;
854                        } catch (IOException e) {
855                                // ignore
856                        }
857           }
858 
859           _log.info( "Shutdown : done");
860         }
861     }
862     public synchronized void shutdown(){
863 
864        _log.info("Listen thread shutdown requested") ;
865        //
866        // it is still hard to stop an Pending I/O call.
867        //
868        if( _shutdown || ( _serverSocket == null ) )return ;
869        _shutdown = true ;
870 
871        try{
872                 if( _logSocketIO.isDebugEnabled() ) {
873                        _logSocketIO.debug("Socket SHUTDOWN local = " + _serverSocket.getInetAddress() + ":" + _serverSocket.getLocalPort() );
874                }
875            _serverSocket.close() ; }
876        catch(Exception ee){
877            _log.warn( "ServerSocket close : "+ee  ) ;
878        }
879 
880        if (_serverSocket.getChannel() == null) {
881            _log.info("Using faked connect to shutdown listen port");
882            try {
883                new Socket("localhost", _listenPort).close();
884            } catch (Exception e) {
885                _log.warn("ServerSocket faked connect : " + e.getMessage());
886            }
887        }
888 
889        _this.interrupt() ;
890 
891        _log.info("Shutdown sequence done");
892     }
893     public synchronized void open(){
894 
895     }
896     public synchronized void close(){
897 
898     }
899  }
900  private class RunEngineThread implements Runnable {
901     private Socket _socket = null ;
902     private RunEngineThread( Socket socket ){
903        _socket = socket ;
904     }
905     public void run(){
906       Thread t = Thread.currentThread() ;
907       try{
908          _log.info( "acceptThread ("+t+"): creating protocol engine" ) ;
909 
910          Object [] argList = new Object[2] ;
911          Object auth = null ;
912          if( _authConstructor != null ){
913             argList[0]  = _nucleus ;
914             argList[1]  = getArgs().clone() ;
915             auth        = _authConstructor.newInstance( argList ) ;
916          }
917          StreamEngine engine = null ;
918          if( _protocol.equals( "ssh" ) ){
919              engine = new SshStreamEngine( _socket , (SshServerAuthentication)auth ) ;
920          }else if( _protocol.equals( "raw" ) ){
921              engine = new DummyStreamEngine( _socket ) ;
922          }else if( _protocol.equals( "telnet" ) ){
923              engine = new TelnetStreamEngine( _socket , (TelnetServerAuthentication)auth ) ;
924          }
925          String userName = Subjects.getDisplayName(engine.getSubject());
926          _log.info( "acceptThread ("+t+"): connection created for user "+userName ) ;
927          Object [] args ;
928          //
929          //
930          int p = userName.indexOf('@');
931 
932          if( p > -1 )userName = p == 0 ? "unknown" : userName.substring(0,p);
933 
934          if( _loginConType == 0 ){
935             args =  new Object[2] ;
936             args[0] = getCellName()+"-"+userName+"*" ;
937             args[1] = engine ;
938          }else{
939             args =  new Object[3] ;
940             args[0] = getCellName()+"-"+userName+"*" ;
941             args[1] = engine ;
942             args[2] = getArgs().clone() ;
943          }
944 
945          Object cell = _loginConstructor.newInstance( args ) ;
946          if( _loginPrintMethod != null ){
947             try{
948                Object [] a = new Object[1] ;
949                a[0] = Integer.valueOf( _nucleus.getPrintoutLevel() ) ;
950                _loginPrintMethod.invoke( cell , a ) ;
951             }catch( Exception eee ){
952                _log.warn( "Can't setPritoutLevel of " +args[0] ) ;
953             }
954          }
955          if( _maxLogin > -1 ){
956             try{
957                Method m = cell.getClass().getMethod( "getCellName" , new Class[0] ) ;
958                String cellName = (String)m.invoke( cell , new Object[0] ) ;
959                _log.info("Invoked cell name : "+cellName ) ;
960                synchronized( _childHash ){
961 
962                        /*
963                     *  while cell may be already gone do following trick:
964                     *  if put return an old cell, then it's a dead cell and we
965                     *  have to remove it. Dead cell is inserted by cleanup procedure:
966                     *  if a remove for non existing cells issued, then cells is dead, and
967                     *  we put it into _childHash.
968                     */
969 
970                   Object deadCell = _childHash.put(cellName,cell) ;
971                      if(deadCell != null ) {
972                         _childHash.remove(cellName);
973                         _log.warn("Cell died, removing " + cellName) ;
974                      }
975 
976                   childrenCounterChanged() ;
977                }
978             }catch( Exception ee ){
979                 _log.warn("Can't determine child name " + ee, ee) ;
980             }
981          }
982          _loginCounter ++ ;
983 
984       }catch( Exception e ){
985          try{ _socket.close() ; }catch(IOException ee ){/* dead any way....*/}
986          _log.warn( "Exception in secure protocol : "+e, e ) ;
987          _loginFailures ++ ;
988          synchronized( _childHash ){ _childCount -- ; }
989       }
990 
991 
992     }
993  }
994  private void childrenCounterChanged(){
995      int children = _childHash.size() ;
996      _log.info( "New child count : "+children ) ;
997      if( _loginBrokerHandler != null )
998        _loginBrokerHandler.loadChanged( children , _maxLogin ) ;
999  }
1000  public boolean validateUser( String userName , String password ){
1001     String [] request = new String[5] ;
1002 
1003     request[0] = "request" ;
1004     request[1] = userName ;
1005     request[2] = "check-password" ;
1006     request[3] = userName ;
1007     request[4] = password ;
1008 
1009     try{
1010        CellMessage msg = new CellMessage( new CellPath(_authenticator) ,
1011                                           request ) ;
1012 
1013        msg = sendAndWait( msg , 10000 ) ;
1014        if( msg == null )
1015           throw new
1016           Exception("Pam request timed out");
1017 
1018        Object [] r = (Object [])msg.getMessageObject() ;
1019 
1020        return ((Boolean)r[5]).booleanValue() ;
1021 
1022     }catch(Exception ee){
1023        _log.warn(ee.toString(), ee);
1024        return false ;
1025     }
1026 
1027  }
1028}

[all classes][dmg.cells.services.login]
EMMA 2.0.5312 (C) Vladimir Roubtsov