| 1 | package dmg.cells.services ; |
| 2 | |
| 3 | import java.net.* ; |
| 4 | import java.io.* ; |
| 5 | import java.util.* ; |
| 6 | |
| 7 | import dmg.cells.nucleus.* ; |
| 8 | import dmg.util.*; |
| 9 | |
| 10 | import org.slf4j.Logger; |
| 11 | import org.slf4j.LoggerFactory; |
| 12 | |
| 13 | public class LocationManager extends CellAdapter { |
| 14 | |
| 15 | private final static Logger _log = |
| 16 | LoggerFactory.getLogger(LocationManager.class); |
| 17 | |
| 18 | /** |
| 19 | */ |
| 20 | private DatagramSocket _socket = null ; |
| 21 | private Server _server = null ; |
| 22 | private Client _client = null ; |
| 23 | private Args _args = null ; |
| 24 | private CellNucleus _nucleus = null ; |
| 25 | // Server Options : -strict[=yes|on|off|no] |
| 26 | // -perm=<helpFilename> |
| 27 | // -setupmode=write|rdonly|auto |
| 28 | // -setup=<setupFile> |
| 29 | // |
| 30 | // Client Options : -noboot |
| 31 | // |
| 32 | public class Server implements Runnable { |
| 33 | private class NodeInfo { |
| 34 | private String _domainName = null ; |
| 35 | private HashSet _list = new HashSet() ; |
| 36 | private String _default = null ; |
| 37 | private boolean _listen = false ; |
| 38 | private String _address = null ; |
| 39 | private boolean _defined = true ; |
| 40 | private int _port = 0 ; |
| 41 | private String _sec = null ; |
| 42 | |
| 43 | private NodeInfo( String domainName ){ |
| 44 | _domainName = domainName ; |
| 45 | } |
| 46 | private NodeInfo( String domainName , boolean defined ){ |
| 47 | _domainName = domainName ; |
| 48 | _defined = defined ; |
| 49 | } |
| 50 | private boolean isDefined(){ return _defined ; } |
| 51 | private String getDomainName(){ return _domainName ; } |
| 52 | private synchronized void setDefault( String defaultNode ){ |
| 53 | _default = defaultNode ; |
| 54 | } |
| 55 | private int getConnectionCount(){ return _list.size() ; } |
| 56 | private synchronized void add( String nodeName ){ |
| 57 | _list.add(nodeName); |
| 58 | } |
| 59 | private synchronized void remove( String nodeName ){ |
| 60 | _list.remove( nodeName ) ; |
| 61 | return; |
| 62 | } |
| 63 | private void setListenPort( int port ){ _port = port ; } |
| 64 | private void setSecurity( String sec ){ _sec = sec ; } |
| 65 | private void setListen( boolean listen ){ _listen = listen ; } |
| 66 | private void setAddress( String address ){ _listen=true; _address = address ; } |
| 67 | |
| 68 | private String getAddress(){ return _address ; } |
| 69 | private String getDefault(){ return _default ; } |
| 70 | private Iterator connections(){ return _list.iterator() ; } |
| 71 | private boolean mustListen(){ return _listen ; } |
| 72 | private String getSecurity(){ return _sec ; } |
| 73 | |
| 74 | public String toWhatToDoReply( boolean strict ){ |
| 75 | |
| 76 | StringBuffer sb = new StringBuffer() ; |
| 77 | sb.append(_domainName).append(" ") ; |
| 78 | if( _listen ){ |
| 79 | |
| 80 | sb.append( "\"l:" ); |
| 81 | if( _port > 0 )sb.append(_port) ; |
| 82 | sb.append(":"); |
| 83 | if( _sec != null )sb.append(_sec) ; |
| 84 | sb.append(":"); |
| 85 | sb.append('"'); |
| 86 | if( ( ! strict ) && ( _address != null ) )sb.append(" (").append(_address).append(")") ; |
| 87 | |
| 88 | }else{ |
| 89 | sb.append("nl"); |
| 90 | } |
| 91 | if( _default != null )sb.append( " d:" ).append( _default ) ; |
| 92 | Iterator i = connections() ; |
| 93 | while( i.hasNext() )sb.append(" c:").append(i.next().toString()) ; |
| 94 | return sb.toString() ; |
| 95 | } |
| 96 | public String toString(){ |
| 97 | return toWhatToDoReply(false); |
| 98 | } |
| 99 | |
| 100 | } |
| 101 | private final Map<String, NodeInfo> _nodeDb = new HashMap<String, NodeInfo>() ; |
| 102 | private int _port = 0 ; |
| 103 | private DatagramSocket _socket = null ; |
| 104 | private Thread _worker = null ; |
| 105 | private boolean _strict = true ; |
| 106 | private int _requestsReceived = 0 ; |
| 107 | private int _repliesSent = 0 ; |
| 108 | private int _totalExceptions = 0 ; |
| 109 | /** |
| 110 | * Server |
| 111 | * -strict=yes|no # 'yes' allows any client to register |
| 112 | * -setup=<setupFile> # full path of setupfile |
| 113 | * -setupmode=rdonly|rw|auto # write back the setup [def=rw] |
| 114 | * -perm=<filename> # store registry information |
| 115 | */ |
| 116 | private final static int SETUP_NONE = -2 ; |
| 117 | private final static int SETUP_ERROR = -1 ; |
| 118 | private final static int SETUP_AUTO = 0 ; |
| 119 | private final static int SETUP_WRITE = 1 ; |
| 120 | private final static int SETUP_RDONLY = 2 ; |
| 121 | private int _setupMode = SETUP_NONE ; |
| 122 | private String _setupFileName = null ; |
| 123 | private File _setupFile = null ; |
| 124 | private File _permFile = null ; |
| 125 | |
| 126 | private Server( int port , Args args ) throws Exception { |
| 127 | _port = port ; |
| 128 | addCommandListener(this); |
| 129 | |
| 130 | String strict = args.getOpt("strict") ; |
| 131 | if( strict == null ){ |
| 132 | _strict = true ; |
| 133 | }else{ |
| 134 | if( strict.equals("off") || strict.equals("no") ) |
| 135 | _strict = false ; |
| 136 | } |
| 137 | |
| 138 | prepareSetup( args.getOpt("setup") , args.getOpt("setupmode") ) ; |
| 139 | if( ( _setupMode == SETUP_WRITE ) || ( _setupMode == SETUP_RDONLY ) ) |
| 140 | execSetupFile( _setupFile ) ; |
| 141 | |
| 142 | preparePersistentMap( args.getOpt( "perm" ) ) ; |
| 143 | |
| 144 | try{ loadPersistentMap() ; }catch(Exception dd ){} |
| 145 | _socket = new DatagramSocket( _port ) ; |
| 146 | _worker = _nucleus.newThread(this,"Server") ; |
| 147 | _worker.start() ; |
| 148 | } |
| 149 | private void preparePersistentMap( String permFileName ) throws Exception { |
| 150 | if( ( permFileName == null ) || ( permFileName.length() < 1 ) )return ; |
| 151 | |
| 152 | File permFile = new File( permFileName ) ; |
| 153 | |
| 154 | if( permFile.exists() ){ |
| 155 | if( ! permFile.canWrite() ) |
| 156 | throw new |
| 157 | IllegalArgumentException( "Can't write to : "+permFileName ) ; |
| 158 | _permFile = permFile ; |
| 159 | // loadPersistentMap() ; |
| 160 | }else{ |
| 161 | if( ! permFile.createNewFile() ) |
| 162 | throw new |
| 163 | IllegalArgumentException( "Can't create : "+permFileName ) ; |
| 164 | _permFile = permFile ; |
| 165 | } |
| 166 | _log.info("Persistent map file set to : "+_permFile); |
| 167 | return; |
| 168 | } |
| 169 | private synchronized void loadPersistentMap() throws Exception { |
| 170 | if( _permFile == null )return ; |
| 171 | ObjectInputStream in = new ObjectInputStream( |
| 172 | new FileInputStream( _permFile ) ) ; |
| 173 | Map<String, String> hm = null ; |
| 174 | _log.info("Loading persistent map file"); |
| 175 | try{ |
| 176 | hm = (HashMap)in.readObject() ; |
| 177 | |
| 178 | _log.info("Persistent map : "+hm); |
| 179 | |
| 180 | for(Map.Entry<String, String> node_and_address: hm.entrySet()) { |
| 181 | |
| 182 | String node = node_and_address.getKey(); |
| 183 | String address = node_and_address.getValue(); |
| 184 | |
| 185 | NodeInfo info = getInfo( node , true ) ; |
| 186 | if( info == null )continue ; |
| 187 | info.setAddress( node ) ; |
| 188 | _log.info( "Updated : <"+node+"> -> "+address ) ; |
| 189 | } |
| 190 | |
| 191 | }catch(Exception ee){ |
| 192 | _log.warn("Problem reading persistent map "+ee.getMessage() ); |
| 193 | _permFile.delete() ; |
| 194 | }finally{ |
| 195 | try{ in.close() ; }catch(IOException ee){} |
| 196 | } |
| 197 | |
| 198 | } |
| 199 | private synchronized void savePersistentMap() throws Exception { |
| 200 | if( _permFile == null )return ; |
| 201 | |
| 202 | Map<String, String> hm = new HashMap<String, String>() ; |
| 203 | |
| 204 | for( NodeInfo info: _nodeDb.values() ){ |
| 205 | String address = info.getAddress() ; |
| 206 | if( ( address != null ) && info.mustListen() ) |
| 207 | hm.put( info.getDomainName() , info.getAddress() ) ; |
| 208 | } |
| 209 | ObjectOutputStream out = null; |
| 210 | |
| 211 | try{ |
| 212 | out = new ObjectOutputStream( new FileOutputStream( _permFile ) ) ; |
| 213 | out.writeObject( hm ) ; |
| 214 | }catch(Exception e){ |
| 215 | _log.warn("Problem writing persistent map "+e.getMessage() ); |
| 216 | _permFile.delete() ; |
| 217 | }finally{ |
| 218 | if(out != null) try{ out.close() ; }catch(Exception ee){} |
| 219 | } |
| 220 | return ; |
| 221 | } |
| 222 | private void prepareSetup( String setupFile , String setupMode ) throws Exception { |
| 223 | |
| 224 | if( ( _setupFileName = setupFile ) == null ){ |
| 225 | _setupMode = SETUP_NONE ; |
| 226 | return ; |
| 227 | } |
| 228 | String tmp = setupMode ; |
| 229 | |
| 230 | _setupMode = tmp == null ? SETUP_AUTO : |
| 231 | tmp.equals("rw") ? SETUP_WRITE : |
| 232 | tmp.equals("rdonly") ? SETUP_RDONLY : |
| 233 | tmp.equals("auto") ? SETUP_AUTO : |
| 234 | SETUP_ERROR ; |
| 235 | |
| 236 | if( _setupMode == SETUP_ERROR ) |
| 237 | throw new |
| 238 | IllegalArgumentException( |
| 239 | "Setup error, don't understand : "+_setupMode); |
| 240 | |
| 241 | _setupFile = new File( _setupFileName ) ; |
| 242 | |
| 243 | boolean fileExists = false , canWrite = false ; |
| 244 | try{ |
| 245 | fileExists = _setupFile.exists() ; |
| 246 | canWrite = _setupFile.canWrite() ; |
| 247 | }catch(Exception ee ){ |
| 248 | _log.warn("Can't check setup file <"+_setupFileName+"> : "+ee.getMessage(), ee) ; |
| 249 | throw ee ; |
| 250 | } |
| 251 | if( fileExists && ! _setupFile.isFile() ) |
| 252 | throw new |
| 253 | IllegalArgumentException("Not a file : "+_setupFileName ) ; |
| 254 | |
| 255 | if( _setupMode == SETUP_AUTO ){ |
| 256 | if( fileExists ){ |
| 257 | _setupMode = canWrite ? SETUP_WRITE : SETUP_RDONLY ; |
| 258 | return ; |
| 259 | } |
| 260 | if( ! _setupFile.createNewFile() ) |
| 261 | throw new |
| 262 | IllegalArgumentException( |
| 263 | "File doesn't exist and can't be created : "+_setupFileName ) ; |
| 264 | _setupMode = SETUP_WRITE ; |
| 265 | }else if( _setupMode == SETUP_WRITE ){ |
| 266 | // |
| 267 | // readwrite case |
| 268 | // |
| 269 | if( fileExists ){ |
| 270 | |
| 271 | if( canWrite )return ; |
| 272 | throw new |
| 273 | IllegalArgumentException( |
| 274 | "File not writeable : "+_setupFileName ) ; |
| 275 | } |
| 276 | if( ! _setupFile.createNewFile() ) |
| 277 | throw new |
| 278 | IllegalArgumentException( |
| 279 | "File doesn't exist and can't be created : "+_setupFileName ) ; |
| 280 | |
| 281 | }else if( _setupMode == SETUP_RDONLY ){ |
| 282 | if( ! fileExists ) |
| 283 | throw new |
| 284 | IllegalArgumentException( |
| 285 | "Setupfile not found : "+_setupFileName) ; |
| 286 | |
| 287 | if( ! _setupFile.canRead() ) |
| 288 | throw new |
| 289 | IllegalArgumentException( |
| 290 | "Setupfile not readable : "+_setupFileName) ; |
| 291 | }else if( _setupMode == SETUP_NONE ){ |
| 292 | _setupFileName = null ; |
| 293 | } |
| 294 | return ; |
| 295 | } |
| 296 | private void execSetupFile( File setupFile )throws Exception { |
| 297 | BufferedReader br = new BufferedReader( new FileReader( setupFile ) ) ; |
| 298 | String line = null ; |
| 299 | try{ |
| 300 | while( ( line = br.readLine() ) != null ){ |
| 301 | if( line.length() < 1 )continue ; |
| 302 | if( line.charAt(0) == '#' )continue ; |
| 303 | _log.info("Exec : "+line) ; |
| 304 | command( new Args(line) ) ; |
| 305 | } |
| 306 | }catch( EOFException eof ){ |
| 307 | }catch( Exception ef ){ |
| 308 | _log.warn("Ups : "+ef ) ; |
| 309 | }finally{ |
| 310 | try{ br.close() ; }catch(Exception ce ){} |
| 311 | } |
| 312 | return ; |
| 313 | } |
| 314 | public void getInfo( PrintWriter pw ){ |
| 315 | pw.println( " Version : $Id: LocationManager.java,v 1.15 2007-10-22 12:30:38 behrmann Exp $") ; |
| 316 | pw.println( " # of nodes : "+_nodeDb.size() ) ; |
| 317 | pw.println( "RequestsReceived : "+_requestsReceived ) ; |
| 318 | pw.println( " RepliesSent : "+_repliesSent) ; |
| 319 | pw.println( " Exceptions : "+_totalExceptions) ; |
| 320 | } |
| 321 | public String toString(){ |
| 322 | return "Server:Nodes="+_nodeDb.size()+";Reqs="+_requestsReceived; |
| 323 | } |
| 324 | public void run(){ |
| 325 | DatagramPacket packet = null ; |
| 326 | while (!Thread.currentThread().isInterrupted()){ |
| 327 | try{ |
| 328 | packet = new DatagramPacket(new byte[1024],1024) ; |
| 329 | _socket.receive(packet); |
| 330 | }catch(Exception ie){ |
| 331 | _log.warn("Exception in Server receive loop (exiting)", ie); |
| 332 | break ; |
| 333 | } |
| 334 | try{ |
| 335 | process( packet ) ; |
| 336 | _socket.send(packet); |
| 337 | }catch(Exception se ){ |
| 338 | _log.warn("Exception in send ", se); |
| 339 | } |
| 340 | } |
| 341 | _socket.close(); |
| 342 | } |
| 343 | public void process( DatagramPacket packet )throws Exception{ |
| 344 | byte [] data = packet.getData() ; |
| 345 | int datalen = packet.getLength() ; |
| 346 | InetAddress address = packet.getAddress() ; |
| 347 | if( datalen <= 0 ){ |
| 348 | _log.warn( "Empty Packet arrived from "+packet.getAddress() ) ; |
| 349 | return ; |
| 350 | } |
| 351 | String message = new String( data , 0 , datalen ) ; |
| 352 | _log.info( "server query : ["+address+"] "+"("+message.length()+") "+message) ; |
| 353 | |
| 354 | message = (String)command( new Args( message ) ) ; |
| 355 | |
| 356 | _log.info( "server reply : "+message ) ; |
| 357 | data = message.getBytes() ; |
| 358 | packet.setData(data) ; |
| 359 | packet.setLength(data.length); |
| 360 | return ; |
| 361 | } |
| 362 | private void createSetup( PrintWriter pw ){ |
| 363 | pw.println( "#") ; |
| 364 | pw.println( "# This setup was created by the LocationManager at "+( new Date().toString())); |
| 365 | pw.println( "#" ) ; |
| 366 | Iterator i = _nodeDb.values().iterator() ; |
| 367 | while( i.hasNext() ){ |
| 368 | NodeInfo info = (NodeInfo)i.next() ; |
| 369 | pw.println( "define "+info.getDomainName() ) ; |
| 370 | if( info.mustListen() )pw.println( "listen "+info.getDomainName() ) ; |
| 371 | String def = info.getDefault() ; |
| 372 | if( def != null )pw.println( "defaultroute "+info.getDomainName()+" "+def ) ; |
| 373 | Iterator j = info.connections() ; |
| 374 | while( j.hasNext() ) |
| 375 | pw.println( "connect "+info.getDomainName()+" "+j.next().toString() ) ; |
| 376 | |
| 377 | } |
| 378 | } |
| 379 | /** |
| 380 | * command interface |
| 381 | */ |
| 382 | private final String [] __mode2string = |
| 383 | { "none" , "error" , "auto" , "rw" , "rdonly" } ; |
| 384 | private String setupToString( int mode ){ |
| 385 | if( ( mode < -2 ) || ( mode > 2 ) )return "?("+mode+")" ; |
| 386 | return __mode2string[mode+2] ; |
| 387 | } |
| 388 | public String hh_ls_perm = " # list permanent file" ; |
| 389 | public String ac_ls_perm( Args args ) throws Exception { |
| 390 | if( _permFile == null ) |
| 391 | throw new |
| 392 | IllegalArgumentException("Permamanet file not defined" ) ; |
| 393 | |
| 394 | ObjectInputStream in = new ObjectInputStream( |
| 395 | new FileInputStream( _permFile ) ) ; |
| 396 | Map<String, String> hm = null ; |
| 397 | try{ |
| 398 | hm = (HashMap)in.readObject() ; |
| 399 | }finally{ |
| 400 | if( in != null) try{ in.close() ; }catch(Exception ee){} |
| 401 | } |
| 402 | |
| 403 | StringBuilder sb = new StringBuilder() ; |
| 404 | for(Map.Entry<String, String> node_and_address: hm.entrySet()) { |
| 405 | |
| 406 | String node = node_and_address.getKey() ; |
| 407 | String address = node_and_address.getValue() ; |
| 408 | |
| 409 | sb.append(node).append(" -> ").append(address).append("\n"); |
| 410 | } |
| 411 | return sb.toString() ; |
| 412 | |
| 413 | } |
| 414 | public String hh_setup_define = "<filename> [-mode=rw|rdonly|auto]" ; |
| 415 | public String ac_setup_define_$_1( Args args )throws Exception { |
| 416 | String filename = args.argv(0); |
| 417 | prepareSetup( filename , args.getOpt( "mode" ) ) ; |
| 418 | return "setupfile (mode="+setupToString(_setupMode)+") : "+filename ; |
| 419 | } |
| 420 | public String hh_setup_read = "" ; |
| 421 | public String ac_setup_read( Args args )throws Exception { |
| 422 | if( _setupFileName == null ) |
| 423 | throw new |
| 424 | IllegalArgumentException( "Setupfile not defined" ) ; |
| 425 | |
| 426 | try{ |
| 427 | execSetupFile( _setupFile ) ; |
| 428 | }catch(Exception ee){ |
| 429 | throw new |
| 430 | Exception( "Problem in setupFile : "+ee.getMessage()); |
| 431 | } |
| 432 | return "" ; |
| 433 | |
| 434 | } |
| 435 | public String hh_setup_write = "" ; |
| 436 | public String ac_setup_write( Args args )throws Exception { |
| 437 | if( _setupMode != SETUP_WRITE ) |
| 438 | throw new |
| 439 | IllegalArgumentException("Setupfile not in write mode" ) ; |
| 440 | |
| 441 | File tmpFile = new File( _setupFile.getParent() , "$-"+_setupFile.getName() ) ; |
| 442 | PrintWriter pw = new PrintWriter( new FileWriter( tmpFile ) ) ; |
| 443 | try{ |
| 444 | createSetup( pw ) ; |
| 445 | }catch(Exception ee ){ |
| 446 | throw ee ; |
| 447 | }finally{ |
| 448 | try{ pw.close() ; }catch(Exception eee){} |
| 449 | } |
| 450 | if( ! tmpFile.renameTo( _setupFile ) ) |
| 451 | throw new |
| 452 | IOException("Failed to replace setupFile" ) ; |
| 453 | |
| 454 | return "" ; |
| 455 | |
| 456 | } |
| 457 | private synchronized NodeInfo getInfo( String nodeName , boolean create ){ |
| 458 | NodeInfo info = (NodeInfo)_nodeDb.get(nodeName) ; |
| 459 | if( ( info != null ) || ! create )return info ; |
| 460 | _nodeDb.put( nodeName , info = new NodeInfo( nodeName ) ) ; |
| 461 | return info ; |
| 462 | } |
| 463 | public String hh_define = "<domainName>" ; |
| 464 | public String ac_define_$_1( Args args ){ |
| 465 | getInfo( args.argv(0) , true ) ; |
| 466 | return "" ; |
| 467 | } |
| 468 | public String hh_undefine = "<domainName>" ; |
| 469 | public String ac_undefine_$_1( Args args ){ |
| 470 | String nodeName = args.argv(0) ; |
| 471 | _nodeDb.remove( nodeName ) ; |
| 472 | Iterator i = _nodeDb.values().iterator() ; |
| 473 | while( i.hasNext() ) ((NodeInfo)i.next()).remove( nodeName ) ; |
| 474 | return "" ; |
| 475 | } |
| 476 | public String hh_nodefaultroute = "<sourceDomainName>" ; |
| 477 | public String ac_nodefaultroute_$_1( Args args ){ |
| 478 | NodeInfo info = getInfo( args.argv(0) , false ) ; |
| 479 | if( info == null )return ""; |
| 480 | info.setDefault( null ) ; |
| 481 | return "" ; |
| 482 | } |
| 483 | public String hh_defaultroute = "<sourceDomainName> <destinationDomainName>" ; |
| 484 | public String ac_defaultroute_$_2( Args args ){ |
| 485 | getInfo( args.argv(1) , true ) ; |
| 486 | getInfo( args.argv(0) , true ).setDefault( args.argv(1) ) ; |
| 487 | return "" ; |
| 488 | } |
| 489 | public String hh_connect = "<sourceDomainName> <destinationDomainName>" ; |
| 490 | public String ac_connect_$_2( Args args ){ |
| 491 | NodeInfo dest = getInfo( args.argv(1) , true ) ; |
| 492 | dest.setListen(true); |
| 493 | getInfo( args.argv(0) , true ).add( args.argv(1) ) ; |
| 494 | return "" ; |
| 495 | } |
| 496 | public String hh_disconnect = "<sourceDomainName> <destinationDomainName>" ; |
| 497 | public String ac_disconnect_$_2( Args args ){ |
| 498 | NodeInfo info = getInfo( args.argv(0) , false ) ; |
| 499 | if( info == null )return ""; |
| 500 | info.remove( args.argv(1) ) ; |
| 501 | return "" ; |
| 502 | |
| 503 | } |
| 504 | public String hh_listen = "<listenDomainName> [...] [-port=<portNumber>] [-security=<security>]" ; |
| 505 | public String ac_listen_$_1_99( Args args ){ |
| 506 | int port = 0 ; |
| 507 | String portString = args.getOpt("port") ; |
| 508 | if( portString != null )port = Integer.parseInt(portString); |
| 509 | String secString = args.getOpt("security"); |
| 510 | |
| 511 | for( int i = 0 ; i < args.argc() ; i++ ){ |
| 512 | NodeInfo info = getInfo( args.argv(i) , true ) ; |
| 513 | info.setListen(true) ; |
| 514 | if( port > 0 )info.setListenPort( port ) ; |
| 515 | if( ( secString != null ) && |
| 516 | ( secString.length() > 0 ) && |
| 517 | ! secString.equalsIgnoreCase("none") )info.setSecurity( secString ) ; |
| 518 | } |
| 519 | return "" ; |
| 520 | } |
| 521 | public String hh_unlisten = "<listenDomainName> [...]" ; |
| 522 | public String ac_unlisten_$_1_99( Args args ){ |
| 523 | for( int i = 0 ; i < args.argc() ; i++ ){ |
| 524 | NodeInfo info = getInfo( args.argv(i) , false ) ; |
| 525 | if( info == null )continue ; |
| 526 | info.setListen(false) ; |
| 527 | } |
| 528 | return "" ; |
| 529 | } |
| 530 | public String hh_ls_setup = "" ; |
| 531 | public String ac_ls_setup( Args args ){ |
| 532 | StringWriter sw = new StringWriter() ; |
| 533 | PrintWriter pw = new PrintWriter( sw ) ; |
| 534 | createSetup( pw ) ; |
| 535 | pw.flush() ; |
| 536 | sw.flush() ; |
| 537 | return sw.getBuffer().toString() ; |
| 538 | } |
| 539 | public String hh_ls_node = "[<domainName>]" ; |
| 540 | public String ac_ls_node_$_0_1( Args args ){ |
| 541 | if( args.argc() == 0 ){ |
| 542 | Iterator i = _nodeDb.values().iterator() ; |
| 543 | StringBuffer sb = new StringBuffer() ; |
| 544 | while( i.hasNext() )sb.append( i.next().toString() ).append("\n") ; |
| 545 | return sb.toString() ; |
| 546 | }else{ |
| 547 | NodeInfo info = getInfo(args.argv(0),false); |
| 548 | if( info == null ) |
| 549 | throw new |
| 550 | IllegalArgumentException( "Node not found : "+args.argv(0)); |
| 551 | return info.toString() ; |
| 552 | } |
| 553 | } |
| 554 | public String hh_set_address = "<domainname> <address>" ; |
| 555 | public String ac_set_address_$_2( Args args ){ |
| 556 | NodeInfo info = getInfo(args.argv(0),false) ; |
| 557 | if( info == null ) |
| 558 | throw new |
| 559 | IllegalArgumentException( "Domain not defined : "+args.argv(0)); |
| 560 | |
| 561 | if( ! info.mustListen() ) |
| 562 | throw new |
| 563 | IllegalArgumentException( "Domain won't listen : "+args.argv(0)); |
| 564 | |
| 565 | info.setAddress( args.argv(1) ) ; |
| 566 | try { savePersistentMap() ; }catch(Exception eee){} |
| 567 | return info.toString() ; |
| 568 | } |
| 569 | public String hh_unset_address = "<domainname>" ; |
| 570 | public String ac_unset_address_$_1( Args args ){ |
| 571 | NodeInfo info = getInfo(args.argv(0),false) ; |
| 572 | if( info == null ) |
| 573 | throw new |
| 574 | IllegalArgumentException( "Domain not defined : "+args.argv(0)); |
| 575 | |
| 576 | info.setAddress( null ) ; |
| 577 | try { savePersistentMap() ; }catch(Exception eee){} |
| 578 | return info.toString() ; |
| 579 | } |
| 580 | public String hh_clear_server = "" ; |
| 581 | public String ac_clear_server( Args args ){ |
| 582 | _nodeDb.clear() ; |
| 583 | return "" ; |
| 584 | } |
| 585 | public String hh_whatToDo = "<domainName>" ; |
| 586 | public String ac_whatToDo_$_1( Args args ){ |
| 587 | NodeInfo info = getInfo( args.argv(0) , false ) ; |
| 588 | if( info == null ){ |
| 589 | if( _strict || ( ( info = getInfo( "*" , false ) ) == null ) ) |
| 590 | throw new |
| 591 | IllegalArgumentException( "Domain not defined : "+args.argv(0) ); |
| 592 | |
| 593 | } |
| 594 | String tmp = null ; |
| 595 | String serial = ( tmp = args.getOpt("serial") ) != null ? |
| 596 | ( "-serial="+tmp ) : "" ; |
| 597 | return "do "+serial+" "+info.toWhatToDoReply(true) ; |
| 598 | } |
| 599 | public String hh_whereIs = "<domainName>" ; |
| 600 | public String ac_whereIs_$_1( Args args ){ |
| 601 | NodeInfo info = getInfo( args.argv(0) , false ) ; |
| 602 | if( info == null ) |
| 603 | throw new |
| 604 | IllegalArgumentException( "Domain not defined : "+args.argv(0) ); |
| 605 | String tmp = null ; |
| 606 | String serial = ( tmp = args.getOpt("serial") ) != null ? |
| 607 | ( "-serial="+tmp ) : "" ; |
| 608 | |
| 609 | StringBuffer sb = new StringBuffer() ; |
| 610 | sb.append("location ").append(serial).append(" ").append(info.getDomainName()) ; |
| 611 | String out = info.getAddress() ; |
| 612 | sb.append(" ").append( out == null ? "none" : out ) ; |
| 613 | out = info.getSecurity() ; |
| 614 | if( out != null )sb.append(" -security=\"").append(out).append("\""); ; |
| 615 | |
| 616 | return sb.toString() ; |
| 617 | } |
| 618 | public String hh_listeningOn = "<domainName> <address>" ; |
| 619 | public String ac_listeningOn_$_2( Args args ){ |
| 620 | String nodeName = args.argv(0); |
| 621 | NodeInfo info = getInfo( nodeName , false ) ; |
| 622 | if( info == null ){ |
| 623 | if( _strict ) |
| 624 | throw new |
| 625 | IllegalArgumentException( "Domain not defined : "+nodeName ); |
| 626 | |
| 627 | _nodeDb.put( nodeName , info = new NodeInfo( nodeName , false ) ) ; |
| 628 | } |
| 629 | info.setAddress( args.argv(1).equals("none") ? null : args.argv(1) ) ; |
| 630 | try { savePersistentMap() ; }catch(Exception eee){} |
| 631 | String tmp = null ; |
| 632 | String serial = ( tmp = args.getOpt("serial") ) != null ? |
| 633 | ( "-serial="+tmp ) : "" ; |
| 634 | return "listenOn "+serial+ |
| 635 | " "+info.getDomainName()+ |
| 636 | " "+( info.getAddress() == null ? "none" : info.getAddress() ) ; |
| 637 | } |
| 638 | |
| 639 | /** |
| 640 | * Shutdown the server. Notice that the method will not wait |
| 641 | * for the worker thread to shut down. |
| 642 | */ |
| 643 | public void shutdown() |
| 644 | { |
| 645 | _worker.interrupt(); |
| 646 | _socket.close(); |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | private class LocationManagerHandler implements Runnable { |
| 651 | |
| 652 | private DatagramSocket _socket = null ; |
| 653 | private Map<Integer, StringBuffer> _map = new HashMap<Integer, StringBuffer>() ; |
| 654 | private int _serial = 0 ; |
| 655 | private InetAddress _address = null ; |
| 656 | private int _port = 0 ; |
| 657 | private Thread _thread = null ; |
| 658 | |
| 659 | private int _requestsSent = 0 ; |
| 660 | private int _repliesReceived = 0 ; |
| 661 | |
| 662 | private LocationManagerHandler( InetAddress address , int port ) throws Exception { |
| 663 | _port = port ; |
| 664 | _socket = new DatagramSocket( ) ; |
| 665 | _address = address ; |
| 666 | _thread = _nucleus.newThread( this , "LocationManagerHandler" ) ; |
| 667 | } |
| 668 | public void start(){ |
| 669 | _thread.start() ; |
| 670 | } |
| 671 | public int getRequestsSent(){ return _requestsSent ; } |
| 672 | public int getRepliesReceived(){ return _repliesReceived ; } |
| 673 | |
| 674 | public void run() |
| 675 | { |
| 676 | DatagramPacket packet = null; |
| 677 | while (!Thread.currentThread().isInterrupted()) { |
| 678 | try { |
| 679 | packet = new DatagramPacket(new byte[1024], 1024); |
| 680 | |
| 681 | _socket.receive(packet); |
| 682 | |
| 683 | byte [] data = packet.getData(); |
| 684 | int packLen = packet.getLength(); |
| 685 | |
| 686 | if ((data == null) || (packLen == 0)) { |
| 687 | _log.warn("Zero packet received"); |
| 688 | continue; |
| 689 | } |
| 690 | |
| 691 | Args a = new Args(new String(data, 0, packLen)); |
| 692 | String tmp = a.getOpt("serial"); |
| 693 | if (tmp == null) { |
| 694 | _log.warn("Packet didn't provide a serial number"); |
| 695 | continue; |
| 696 | } |
| 697 | |
| 698 | Integer s = Integer.valueOf(tmp); |
| 699 | StringBuffer b = _map.get(s); |
| 700 | if (b == null) { |
| 701 | _log.warn("Not waiting for " + s); |
| 702 | continue; |
| 703 | } |
| 704 | |
| 705 | _log.info("Reasonable reply arrived (" + s + ") : " + b); |
| 706 | |
| 707 | synchronized (b) { |
| 708 | b.append(a.toString()); |
| 709 | b.notifyAll(); |
| 710 | } |
| 711 | } catch (InterruptedIOException e) { |
| 712 | Thread.currentThread().interrupt(); |
| 713 | } catch (SocketException e) { |
| 714 | if (!Thread.currentThread().isInterrupted()) { |
| 715 | _log.warn("Receiver socket problem : " + e.getMessage()); |
| 716 | } |
| 717 | } catch (IOException e) { |
| 718 | _log.warn("Receiver IO problem : " + e.getMessage()); |
| 719 | } |
| 720 | } |
| 721 | _log.info("Receiver thread finished"); |
| 722 | } |
| 723 | |
| 724 | private String askServer( String message , long waitTime ) |
| 725 | throws IOException, InterruptedException |
| 726 | { |
| 727 | _requestsSent ++ ; |
| 728 | |
| 729 | int serial ; |
| 730 | synchronized( this ){ serial = (_serial++) ; } |
| 731 | |
| 732 | byte [] data = ( message+" -serial="+serial ).getBytes() ; |
| 733 | |
| 734 | StringBuffer b = new StringBuffer() ; |
| 735 | DatagramPacket packet = null ; |
| 736 | |
| 737 | Integer s = Integer.valueOf( serial ) ; |
| 738 | long rest = waitTime ; |
| 739 | long start = System.currentTimeMillis() ; |
| 740 | long now = 0 ; |
| 741 | |
| 742 | |
| 743 | _log.info( "Sending to "+_address+":"+_port+" : "+new String(data,0,data.length)); |
| 744 | |
| 745 | synchronized( b ){ |
| 746 | |
| 747 | packet = new DatagramPacket( data , data.length , _address , _port ) ; |
| 748 | _map.put( s , b ) ; |
| 749 | _socket.send( packet ) ; |
| 750 | while( rest > 0 ){ |
| 751 | b.wait( rest ) ; |
| 752 | if( b.length() > 0 ){ |
| 753 | _repliesReceived++ ; |
| 754 | _map.remove( s ) ; |
| 755 | return b.toString() ; |
| 756 | } |
| 757 | now = System.currentTimeMillis() ; |
| 758 | rest -= ( now - start ) ; |
| 759 | start = now ; |
| 760 | } |
| 761 | _map.remove(s); |
| 762 | } |
| 763 | throw new IOException( "Request timed out" ) ; |
| 764 | } |
| 765 | |
| 766 | /** |
| 767 | * Shutdown the client. Notice that the method will not wait |
| 768 | * for the worker thread to shut down. |
| 769 | */ |
| 770 | public void shutdown() |
| 771 | { |
| 772 | _thread.interrupt(); |
| 773 | _socket.close(); |
| 774 | } |
| 775 | |
| 776 | } |
| 777 | public class Client implements Runnable { |
| 778 | |
| 779 | private Thread _receiver = null; |
| 780 | private Thread _whatToDo = null; |
| 781 | private String _toDo = null ; |
| 782 | private String _registered = null ; |
| 783 | private int _state = 0 ; |
| 784 | private int _requestsReceived = 0 ; |
| 785 | private int _repliesSent = 0 ; |
| 786 | private int _totalExceptions = 0 ; |
| 787 | |
| 788 | private LocationManagerHandler _lmHandler = null ; |
| 789 | |
| 790 | private Client( InetAddress address , int port , Args args ) throws Exception { |
| 791 | |
| 792 | addCommandListener(this); |
| 793 | |
| 794 | _lmHandler = new LocationManagerHandler( address , port ) ; |
| 795 | _lmHandler.start() ; |
| 796 | |
| 797 | if( args.getOpt("noboot") == null ){ |
| 798 | _whatToDo = _nucleus.newThread(this,"WhatToDo"); |
| 799 | _whatToDo.start() ; |
| 800 | } |
| 801 | |
| 802 | } |
| 803 | public void getInfo( PrintWriter pw ){ |
| 804 | pw.println( " ToDo : "+(_state>-1?("Still Busy ("+_state+")"):_toDo)); |
| 805 | pw.println( " Registered : "+(_registered==null?"no":_registered) ) ; |
| 806 | pw.println( "RequestsReceived : "+_requestsReceived ) ; |
| 807 | pw.println( " RequestsSent : "+_lmHandler.getRequestsSent() ) ; |
| 808 | pw.println( " RepliesReceived : "+_lmHandler.getRepliesReceived() ) ; |
| 809 | pw.println( " RepliesSent : "+_repliesSent) ; |
| 810 | pw.println( " Exceptions : "+_totalExceptions) ; |
| 811 | } |
| 812 | public String toString(){ |
| 813 | return ""+(_state>-1?("Client<init>("+_state+")"):"ClientReady") ; |
| 814 | } |
| 815 | private class BackgroundServerRequest implements Runnable { |
| 816 | |
| 817 | private String _request = null ; |
| 818 | private CellMessage _message = null ; |
| 819 | |
| 820 | private BackgroundServerRequest( String request , CellMessage message ){ |
| 821 | _request = request ; |
| 822 | _message = message ; |
| 823 | } |
| 824 | public void run(){ |
| 825 | try{ |
| 826 | |
| 827 | String reply = _lmHandler.askServer( _request , 4000 ) ; |
| 828 | |
| 829 | _message.setMessageObject( reply ) ; |
| 830 | _message.revertDirection() ; |
| 831 | sendMessage(_message); |
| 832 | |
| 833 | _repliesSent++; |
| 834 | |
| 835 | }catch(Exception ee){ |
| 836 | _log.warn("Problem in 'whereIs' request : "+ee ) ; |
| 837 | _totalExceptions ++ ; |
| 838 | } |
| 839 | } |
| 840 | |
| 841 | } |
| 842 | public String ac_where_is_$_1( Args args ){ |
| 843 | |
| 844 | _requestsReceived++ ; |
| 845 | |
| 846 | String domainName = args.argv(0) ; |
| 847 | |
| 848 | _nucleus.newThread( |
| 849 | new BackgroundServerRequest( "whereIs "+domainName , getThisMessage() ) , |
| 850 | "where-is" ).start() ; |
| 851 | |
| 852 | return null ; |
| 853 | } |
| 854 | // |
| 855 | // |
| 856 | // create dmg.cells.services.LocationManager lm "11111" |
| 857 | // |
| 858 | // create dmg.cells.network.LocationMgrTunnel connect "dCache lm" |
| 859 | // |
| 860 | // create dmg.cells.services.login.LoginManager listen |
| 861 | // "0 dmg.cells.network.LocationMgrTunnel -prot=raw -lm=lm" |
| 862 | // |
| 863 | public String ac_listening_on_$_2( Args args ){ |
| 864 | |
| 865 | CellMessage msg = getThisMessage() ; |
| 866 | String portString = args.argv(1) ; |
| 867 | |
| 868 | try{ |
| 869 | _registered = InetAddress.getLocalHost().getHostName()+":"+portString ; |
| 870 | }catch( java.net.UnknownHostException uhe ){ |
| 871 | _log.warn("Couldn't resolve hostname : "+uhe); |
| 872 | return null ; |
| 873 | } |
| 874 | |
| 875 | String request = "listeningOn "+getCellDomainName()+" "+_registered ; |
| 876 | |
| 877 | _requestsReceived++ ; |
| 878 | |
| 879 | _nucleus.newThread( new BackgroundServerRequest( request , msg ) ).start() ; |
| 880 | |
| 881 | return null ; |
| 882 | } |
| 883 | private void startListener( int port , String securityContext ) throws Exception { |
| 884 | String cellName = "l*" ; |
| 885 | String inetClass = "dmg.cells.services.login.LoginManager" ; |
| 886 | String cellClass = "dmg.cells.network.LocationMgrTunnel" ; |
| 887 | String protocol = null ; |
| 888 | if( ( securityContext == null ) || |
| 889 | ( securityContext.length() == 0 ) || |
| 890 | ( securityContext.equalsIgnoreCase("none") ) ){ |
| 891 | |
| 892 | protocol = "-prot=raw" ; |
| 893 | |
| 894 | }else if( securityContext.equalsIgnoreCase("ssh") || |
| 895 | securityContext.equalsIgnoreCase("ssh1") ){ |
| 896 | |
| 897 | protocol = "-prot=ssh -auth=dmg.cells.services.login.SshSAuth_A" ; |
| 898 | |
| 899 | }else{ |
| 900 | protocol = securityContext ; |
| 901 | } |
| 902 | String cellArgs = ""+port+" "+cellClass+" "+protocol+" -lm="+getCellName(); |
| 903 | _log.info(" LocationManager starting acceptor with "+cellArgs ) ; |
| 904 | Cell c = _nucleus.createNewCell( inetClass , cellName , cellArgs , true ) ; |
| 905 | _log.info( "Created : "+c ) ; |
| 906 | return ; |
| 907 | } |
| 908 | |
| 909 | private void startConnector(final String remoteDomain) |
| 910 | throws Exception |
| 911 | { |
| 912 | String cellName = "c-"+remoteDomain+"*"; |
| 913 | String cellClass = "dmg.cells.network.LocationManagerConnector"; |
| 914 | |
| 915 | String clientKey = _args.getOpt("clientKey") ; |
| 916 | clientKey = ( clientKey != null ) && ( clientKey.length() > 0 ) ? |
| 917 | ("-clientKey="+clientKey ) : "" ; |
| 918 | String clientName = _args.getOpt("clientUserName") ; |
| 919 | clientName = ( clientName != null ) && ( clientName.length() > 0 ) ? |
| 920 | ("-clientUserName="+clientName ) : "" ; |
| 921 | |
| 922 | String cellArgs = |
| 923 | "-domain=" + remoteDomain + " " |
| 924 | + "-lm=" + getCellName() + " " |
| 925 | + clientKey + " " |
| 926 | + clientName; |
| 927 | |
| 928 | _log.info("LocationManager starting connector with " + cellArgs); |
| 929 | Cell c = _nucleus.createNewCell(cellClass, cellName, cellArgs, true); |
| 930 | _log.info("Created : " + c); |
| 931 | } |
| 932 | |
| 933 | private void setDefaultRoute( String domain ) throws Exception { |
| 934 | _nucleus.routeAdd( new CellRoute( null , "*@"+domain , CellRoute.DEFAULT ) ) ; |
| 935 | } |
| 936 | public void run(){ |
| 937 | if( Thread.currentThread() == _whatToDo )runWhatToDo() ; |
| 938 | } |
| 939 | /** |
| 940 | * loop until it gets a reasonable 'what to do' list. |
| 941 | */ |
| 942 | private void runWhatToDo(){ |
| 943 | |
| 944 | String request = "whatToDo "+getCellDomainName() ; |
| 945 | |
| 946 | while( true ){ |
| 947 | |
| 948 | _state ++ ; |
| 949 | |
| 950 | try{ |
| 951 | |
| 952 | String reply = _lmHandler.askServer( request , 5000 ) ; |
| 953 | _log.info( "whatToDo got : "+reply ) ; |
| 954 | |
| 955 | Args args = new Args( reply ) ; |
| 956 | |
| 957 | if( args.argc() < 2 ) |
| 958 | throw new |
| 959 | IllegalArgumentException( "No enough arg. : "+reply ) ; |
| 960 | |
| 961 | if( ( ! args.argv(0).equals("do" ) ) || |
| 962 | ( ! ( args.argv(1).equals(getCellDomainName()) || |
| 963 | args.argv(1).equals("*") ) ) ) |
| 964 | throw new |
| 965 | IllegalArgumentException("Not a 'do' or not for us : "+reply ) ; |
| 966 | |
| 967 | if( args.argc() == 2 ){ |
| 968 | _log.info("Nothing to do for us"); |
| 969 | return ; |
| 970 | } |
| 971 | |
| 972 | executeToDoList( args ) ; |
| 973 | |
| 974 | _toDo = reply ; |
| 975 | _state = -1 ; |
| 976 | |
| 977 | return ; |
| 978 | |
| 979 | }catch(InterruptedException ie ){ |
| 980 | _log.warn( _toDo = "whatToDo : interrupted" ) ; |
| 981 | break ; |
| 982 | }catch(InterruptedIOException ie ){ |
| 983 | _log.warn( _toDo = "whatToDo : interrupted(io)" ) ; |
| 984 | break ; |
| 985 | }catch(Exception ee ){ |
| 986 | _log.warn(_toDo = "whatToDo : exception : "+ee ) ; |
| 987 | } |
| 988 | try{ |
| 989 | Thread.sleep(10000) ; |
| 990 | }catch(InterruptedException iie ){ |
| 991 | _log.warn(_toDo = "whatToDo : interrupted sleep") ; |
| 992 | break ; |
| 993 | } |
| 994 | } |
| 995 | _log.info( "whatToDo finished" ) ; |
| 996 | |
| 997 | } |
| 998 | /** |
| 999 | * Gets the reply from the 'server' and can |
| 1000 | * i) create a connector |
| 1001 | * ii) listens to a given port |
| 1002 | * iii) sets a default route |
| 1003 | * |
| 1004 | * or all of it. |
| 1005 | */ |
| 1006 | private void executeToDoList( Args args ) throws Exception { |
| 1007 | for( int i = 2 ; i < args.argc() ; i++ ){ |
| 1008 | |
| 1009 | String arg = args.argv(i) ; |
| 1010 | |
| 1011 | try{ |
| 1012 | // |
| 1013 | // expected formats |
| 1014 | // l:[<portNumber>]:[<securityContext>] |
| 1015 | // c:<DomainName> |
| 1016 | // d:<DomainName> |
| 1017 | // |
| 1018 | if( arg.startsWith("l") ){ |
| 1019 | int port = 0 ; |
| 1020 | StringTokenizer st = new StringTokenizer(arg,":"); |
| 1021 | // |
| 1022 | // get rid of the 'l' |
| 1023 | // |
| 1024 | st.nextToken() ; |
| 1025 | // |
| 1026 | // get the port if availble |
| 1027 | // |
| 1028 | if( st.hasMoreTokens() ){ |
| 1029 | String tmp = st.nextToken() ; |
| 1030 | if( tmp.length() > 0 ) |
| 1031 | try{ |
| 1032 | port = Integer.parseInt(tmp); |
| 1033 | }catch(Exception e ){ |
| 1034 | _log.warn("Got illegal port numnber <"+arg+">, using random"); |
| 1035 | } |
| 1036 | } |
| 1037 | // |
| 1038 | // get the security context |
| 1039 | // |
| 1040 | String securityContext = null ; |
| 1041 | if( st.hasMoreTokens() )securityContext = st.nextToken() ; |
| 1042 | |
| 1043 | startListener( port , securityContext ) ; |
| 1044 | |
| 1045 | }else if( ( arg.length() > 2 ) && |
| 1046 | arg.startsWith("c:") ){ |
| 1047 | |
| 1048 | startConnector(arg.substring(2)) ; |
| 1049 | |
| 1050 | }else if( ( arg.length() > 2 ) && |
| 1051 | arg.startsWith("d:") ){ |
| 1052 | |
| 1053 | setDefaultRoute(arg.substring(2)) ; |
| 1054 | |
| 1055 | } |
| 1056 | }catch(InterruptedIOException ioee ){ |
| 1057 | throw ioee ; |
| 1058 | }catch(InterruptedException iee ){ |
| 1059 | throw iee ; |
| 1060 | }catch(Exception ee ){ |
| 1061 | _log.warn("Command >"+arg+"< received : "+ee ) ; |
| 1062 | } |
| 1063 | } |
| 1064 | |
| 1065 | } |
| 1066 | |
| 1067 | /** |
| 1068 | * Shutdown the client. Notice that the method will not wait |
| 1069 | * for the worker thread to shut down. |
| 1070 | */ |
| 1071 | public void shutdown() |
| 1072 | { |
| 1073 | _lmHandler.shutdown(); |
| 1074 | } |
| 1075 | |
| 1076 | } |
| 1077 | /** |
| 1078 | * Usage : ... [<host>] <port> -noclient |
| 1079 | * Server Options : -strict=[yes|no] -perm=<helpFilename> -setup=<setupFile> |
| 1080 | * |
| 1081 | */ |
| 1082 | public LocationManager( String name , String args )throws Exception { |
| 1083 | super( name , args , false ) ; |
| 1084 | _args = getArgs() ; |
| 1085 | _nucleus = getNucleus() ; |
| 1086 | String tmp = null ; |
| 1087 | try{ |
| 1088 | int port = 0 ; |
| 1089 | InetAddress host = null ; |
| 1090 | if( _args.argc() < 1 ) |
| 1091 | throw new |
| 1092 | IllegalArgumentException("Usage : ... [<host>] <port> [-noclient]") ; |
| 1093 | |
| 1094 | if( _args.argc() == 1 ){ |
| 1095 | // |
| 1096 | // we are a server and a client |
| 1097 | // |
| 1098 | port = Integer.parseInt( _args.argv(0) ); |
| 1099 | host = InetAddress.getByName("localhost") ; |
| 1100 | _server = new Server( port , _args ) ; |
| 1101 | _log.info("Server Setup Done") ; |
| 1102 | }else{ |
| 1103 | port = Integer.parseInt( _args.argv(1) ); |
| 1104 | host = InetAddress.getByName( _args.argv(0) ) ; |
| 1105 | } |
| 1106 | if( _args.getOpt("noclient") == null ){ |
| 1107 | _client = new Client( host , port , _args ) ; |
| 1108 | _log.info("Client started"); |
| 1109 | } |
| 1110 | }catch(Exception ee){ |
| 1111 | _log.warn(ee.toString(), ee) ; |
| 1112 | start() ; |
| 1113 | kill() ; |
| 1114 | throw ee; |
| 1115 | } |
| 1116 | start() ; |
| 1117 | } |
| 1118 | public void getInfo( PrintWriter pw ){ |
| 1119 | if( _client != null ){ |
| 1120 | pw.println( "Client\n--------") ; |
| 1121 | _client.getInfo( pw ) ; |
| 1122 | } |
| 1123 | if( _server != null ){ |
| 1124 | pw.println( "Server\n--------") ; |
| 1125 | _server.getInfo( pw ) ; |
| 1126 | } |
| 1127 | return ; |
| 1128 | } |
| 1129 | |
| 1130 | public void cleanUp() |
| 1131 | { |
| 1132 | if (_server != null) |
| 1133 | _server.shutdown(); |
| 1134 | if (_client != null) |
| 1135 | _client.shutdown(); |
| 1136 | } |
| 1137 | |
| 1138 | public String toString(){ |
| 1139 | StringBuffer sb = new StringBuffer() ; |
| 1140 | if( _client != null ) |
| 1141 | sb.append(_client.toString()). |
| 1142 | append(_server!=null?";":""); |
| 1143 | if( _server != null )sb.append(_server.toString()) ; |
| 1144 | return sb.toString(); |
| 1145 | } |
| 1146 | |
| 1147 | static class XXClient { |
| 1148 | XXClient( InetAddress address , int port , String message )throws Exception { |
| 1149 | byte [] data = message.getBytes() ; |
| 1150 | DatagramPacket packet = |
| 1151 | new DatagramPacket( data , data.length , address , port ) ; |
| 1152 | |
| 1153 | DatagramSocket socket = new DatagramSocket() ; |
| 1154 | |
| 1155 | socket.send( packet ) ; |
| 1156 | packet = new DatagramPacket( new byte[1024] , 1024 ) ; |
| 1157 | socket.receive( packet ) ; |
| 1158 | data = packet.getData() ; |
| 1159 | System.out.println(new String(data,0,data.length) ); |
| 1160 | } |
| 1161 | } |
| 1162 | public static void main(String [] args )throws Exception { |
| 1163 | if( args.length < 3 ) |
| 1164 | throw new |
| 1165 | IllegalArgumentException("Usage : ... <host> <port> <message>" ) ; |
| 1166 | InetAddress address = InetAddress.getByName( args[0] ) ; |
| 1167 | int port = Integer.parseInt( args[1] ) ; |
| 1168 | String message = args[2] ; |
| 1169 | |
| 1170 | new XXClient( address , port , message ) ; |
| 1171 | System.exit(0); |
| 1172 | } |
| 1173 | } |