2015-05-06 03:53:30 +00:00
var ZeroTierNode = React . createClass ( {
getInitialState : function ( ) {
return {
address : '----------' ,
online : false ,
2015-05-07 00:28:11 +00:00
version : '_._._' ,
_networks : [ ] ,
_peers : [ ]
2015-05-06 03:53:30 +00:00
} ;
} ,
2015-05-07 00:28:11 +00:00
ago : function ( ms ) {
2015-05-07 00:42:29 +00:00
if ( ms > 0 ) {
var tmp = Math . round ( ( Date . now ( ) - ms ) / 1000 ) ;
return ( ( tmp > 0 ) ? tmp : 0 ) ;
} else return 0 ;
2015-05-07 00:28:11 +00:00
} ,
updatePeers : function ( ) {
Ajax . call ( {
url : 'peer?auth=' + this . props . authToken ,
cache : false ,
type : 'GET' ,
success : function ( data ) {
if ( data ) {
var pl = JSON . parse ( data ) ;
if ( Array . isArray ( pl ) ) {
this . setState ( { _peers : pl } ) ;
}
}
} . bind ( this ) ,
error : function ( ) {
} . bind ( this )
} ) ;
} ,
updateNetworks : function ( ) {
Ajax . call ( {
url : 'network?auth=' + this . props . authToken ,
cache : false ,
type : 'GET' ,
success : function ( data ) {
if ( data ) {
var nwl = JSON . parse ( data ) ;
if ( Array . isArray ( nwl ) ) {
this . setState ( { _networks : nwl } ) ;
}
}
} . bind ( this ) ,
error : function ( ) {
} . bind ( this )
} ) ;
} ,
2015-05-06 03:53:30 +00:00
updateAll : function ( ) {
Ajax . call ( {
url : 'status?auth=' + this . props . authToken ,
cache : false ,
type : 'GET' ,
success : function ( data ) {
2015-05-08 16:39:07 +00:00
this . alertedToFailure = false ;
2015-05-07 02:39:45 +00:00
if ( data ) {
var status = JSON . parse ( data ) ;
this . setState ( status ) ;
document . title = 'ZeroTier One [' + status . address + ']' ;
}
2015-05-07 00:28:11 +00:00
this . updateNetworks ( ) ;
this . updatePeers ( ) ;
2015-05-06 03:53:30 +00:00
} . bind ( this ) ,
error : function ( ) {
2015-05-08 16:39:07 +00:00
this . setState ( this . getInitialState ( ) ) ;
if ( ! this . alertedToFailure ) {
this . alertedToFailure = true ;
alert ( 'Authorization token invalid or ZeroTier One service not running.' ) ;
}
2015-05-06 03:53:30 +00:00
} . bind ( this )
2015-05-07 00:28:11 +00:00
} ) ;
} ,
joinNetwork : function ( event ) {
event . preventDefault ( ) ;
2015-05-07 02:39:45 +00:00
if ( ( this . networkToJoin ) && ( this . networkToJoin . length === 16 ) ) {
Ajax . call ( {
url : 'network/' + this . networkToJoin + '?auth=' + this . props . authToken ,
cache : false ,
type : 'POST' ,
success : function ( data ) {
2015-05-08 16:39:07 +00:00
this . networkToJoin = '' ;
if ( this . networkInputElement )
this . networkInputElement . value = '' ;
this . updateNetworks ( ) ;
2015-05-07 02:39:45 +00:00
} . bind ( this ) ,
error : function ( ) {
} . bind ( this )
} ) ;
2015-05-08 16:39:07 +00:00
} else {
alert ( 'To join a network, enter its 16-digit network ID.' ) ;
2015-05-07 02:39:45 +00:00
}
2015-05-07 00:28:11 +00:00
} ,
handleNetworkIdEntry : function ( event ) {
2015-05-08 16:39:07 +00:00
this . networkInputElement = event . target ;
2015-05-08 21:47:01 +00:00
var nid = this . networkInputElement . value ;
2015-05-07 00:28:11 +00:00
if ( nid ) {
nid = nid . toLowerCase ( ) ;
var nnid = '' ;
for ( var i = 0 ; ( ( i < nid.length ) & & ( i < 16 ) ) ; + + i ) {
if ( "0123456789abcdef" . indexOf ( nid . charAt ( i ) ) >= 0 )
nnid += nid . charAt ( i ) ;
}
this . networkToJoin = nnid ;
2015-05-08 21:47:01 +00:00
this . networkInputElement . value = nnid ;
2015-05-07 00:28:11 +00:00
} else {
this . networkToJoin = '' ;
2015-05-08 21:47:01 +00:00
this . networkInputElement . value = '' ;
2015-05-07 00:28:11 +00:00
}
2015-05-06 03:53:30 +00:00
} ,
2015-05-08 16:39:07 +00:00
handleNetworkDelete : function ( nwid ) {
var networks = [ ] ;
for ( var i = 0 ; i < this.state._networks.length ; + + i ) {
if ( this . state . _networks [ i ] . nwid !== nwid )
networks . push ( this . state . _networks [ i ] ) ;
}
this . setState ( { _networks : networks } ) ;
} ,
2015-05-06 03:53:30 +00:00
componentDidMount : function ( ) {
2015-05-07 00:28:11 +00:00
this . tabIndex = 0 ;
2015-05-06 03:53:30 +00:00
this . updateAll ( ) ;
2015-05-07 00:42:29 +00:00
this . updateIntervalId = setInterval ( this . updateAll , 2500 ) ;
2015-05-06 03:53:30 +00:00
} ,
componentWillUnmount : function ( ) {
2015-05-07 00:28:11 +00:00
clearInterval ( this . updateIntervalId ) ;
2015-05-06 03:53:30 +00:00
} ,
render : function ( ) {
2015-05-08 16:39:07 +00:00
/ * W e i m p l e m e n t t a b s i n a v e r y s i m p l e w a y h e r e w i t h a R e a c t J S X c o n d i t i o n a l . T h e t a b I n d e x
* local variable indicates the tab , and switching it determines which set of things we
* render in the main middle portion . On tab switch calls forceUpdate ( ) . * /
2015-05-06 03:53:30 +00:00
return (
2015-05-07 00:28:11 +00:00
< div className = "zeroTierNode" >
< div className = "top" > & nbsp ; & nbsp ;
< button disabled = { this . tabIndex === 0 } onClick = { function ( ) { this . tabIndex = 0 ; this . forceUpdate ( ) ; } . bind ( this ) } > Networks < / button >
< button disabled = { this . tabIndex === 1 } onClick = { function ( ) { this . tabIndex = 1 ; this . forceUpdate ( ) ; } . bind ( this ) } > Peers < / button >
< / div >
2015-05-08 21:47:01 +00:00
< div className = "middle" > < div className = "middleCell" >
2015-05-07 00:28:11 +00:00
< div className = "middleScroll" >
{
( this . tabIndex === 1 ) ? (
2015-05-08 17:03:35 +00:00
< div className = "peers" key = "_peers" >
< div className = "peerHeader" key = "_peersHeader" >
2015-05-07 00:42:29 +00:00
< div className = "f" > Address < / div >
< div className = "f" > Version < / div >
< div className = "f" > Latency < / div >
2015-05-08 16:39:07 +00:00
< div className = "f" > Data & nbsp ; Paths < / div >
2015-05-08 22:01:05 +00:00
< div className = "f" > Last & nbsp ; Unicast < / div >
< div className = "f" > Last & nbsp ; Multicast < / div >
2015-05-07 00:42:29 +00:00
< div className = "f" > Role < / div >
2015-05-07 00:28:11 +00:00
< / div >
{
this . state . _peers . map ( function ( peer ) {
return (
2015-05-08 17:03:35 +00:00
< div className = "peer" key = { peer [ 'address' ] } >
2015-05-07 00:28:11 +00:00
< div className = "f zeroTierAddress" > { peer [ 'address' ] } < / div >
< div className = "f" > { ( peer [ 'version' ] === '-1.-1.-1' ) ? '-' : peer [ 'version' ] } < / div >
< div className = "f" > { peer [ 'latency' ] } < / div >
< div className = "f" >
{
( peer [ 'paths' ] . length === 0 ) ? (
2015-05-08 16:39:07 +00:00
< div className = "peerPath" > < / div >
2015-05-07 00:28:11 +00:00
) : (
< div >
{
peer [ 'paths' ] . map ( function ( path ) {
2015-05-08 16:39:07 +00:00
var cn = ( ( path . active ) || ( path . fixed ) ) ? ( path . preferred ? 'peerPathPreferred' : 'peerPathActive' ) : 'peerPathInactive' ;
return (
< div className = { cn } > { path . address } & nbsp ; & nbsp ; { this . ago ( path . lastSend ) } / { this . ago ( path . lastReceive ) } < / div >
) ;
2015-05-07 00:28:11 +00:00
} . bind ( this ) )
}
< / div >
)
}
< / div >
2015-05-08 16:39:07 +00:00
< div className = "f" > { this . ago ( peer [ 'lastUnicastFrame' ] ) } < / div >
2015-05-08 22:01:05 +00:00
< div className = "f" > { this . ago ( peer [ 'lastMulticastFrame' ] ) } < / div >
2015-05-07 00:28:11 +00:00
< div className = "f" > { peer [ 'role' ] } < / div >
< / div >
) ;
} . bind ( this ) )
}
< / div >
) : (
2015-05-08 17:03:35 +00:00
< div className = "networks" key = "_networks" >
2015-05-07 00:28:11 +00:00
{
this . state . _networks . map ( function ( network ) {
2015-05-07 02:39:45 +00:00
network [ 'authToken' ] = this . props . authToken ;
2015-05-08 16:39:07 +00:00
network [ 'onNetworkDeleted' ] = this . handleNetworkDelete ;
2015-05-08 17:03:35 +00:00
return React . createElement ( 'div' , { className : 'network' , key : network . nwid } , React . createElement ( ZeroTierNetwork , network ) ) ;
2015-05-07 00:28:11 +00:00
} . bind ( this ) )
}
< / div >
)
}
< / div >
2015-05-08 21:47:01 +00:00
< / div > < / div >
2015-05-07 00:28:11 +00:00
< div className = "bottom" >
< div className = "left" >
2015-06-03 23:47:07 +00:00
< span className = "statusLine" > < span className = "zeroTierAddress" > { this . state . address } < / span > & nbsp ; & nbsp ; { this . state . online ? ( this . state . tcpFallbackActive ? 'TUNNELED' : 'ONLINE' ) : 'OFFLINE' } & nbsp ; & nbsp ; { this . state . version } < / span >
2015-05-06 03:53:30 +00:00
< / div >
2015-05-07 00:28:11 +00:00
< div className = "right" >
2015-05-08 21:47:01 +00:00
< form onSubmit = { this . joinNetwork } > < input type = "text" maxlength = "16" placeholder = "[ Network ID ]" onChange = { this . handleNetworkIdEntry } size = "16" / > < button type = "button" onClick = { this . joinNetwork } > Join < / button > < / form >
2015-05-06 03:53:30 +00:00
< / div >
< / div >
< / div >
) ;
}
} ) ;