github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/client/www/templates/net.html (about)

     1  <style>
     2  .dbg {
     3  	//display:table-cell;
     4  	display:none;
     5  }
     6  td.agent {
     7  	max-width: 200px;
     8  	overflow: hidden;
     9  	text-overflow: ellipsis;
    10  	white-space: nowrap
    11  }
    12  </style>
    13  <script type="text/javascript" src="webui/jquery.min.js"></script>
    14  <script type="text/javascript" src="webui/jquery.flot.min.js"></script>
    15  
    16  <div style="width:100%;line-height:24px;white-space:nowrap;">
    17  
    18  <span style="float:right;display:none" id="connect_buttons">
    19  <input type="button" id="edit_friends" value="Edit Friends" onclick="edit_friends()">
    20  <input type="button" id="unban_peer_but" value="Unban" onclick="unban_peer()">
    21  <input type="button" id="conn_peer_but" value="Connect Peer" onclick="connect_peer()">
    22  </span>
    23  
    24  
    25  <b>{EXTERNAL_ADDR}</b>
    26  <==>
    27  <b id="out_connections"></b> <img title="outgoing" src="webui/outgoing.png"> + <b id="in_connections"></b> <img title="incoming" src="webui/incoming.png"> connections<br>
    28  <input type="text" id="autocopy" style="display:none;font-size:1px;float:right;width:10px;height:4px">
    29  Listening for incoming TCP connections: <b>{LISTEN_TCP}</b>
    30  <span id="el_tcp_listen_switch" style="display:none">[<a href="javascript:config('lonoff')">Switch ON/OFF</a>]</span><br>
    31  </div>
    32  
    33  
    34  <div style="display:none" id="friends_form">
    35  <table width="100%" cellspacing="0" cellpadding="0"><tr><td align="right">
    36  <form method="post" action="cfg" >
    37  <table cellspacing="0" cellpadding="0">
    38  <tr><td colspan="2" align="right">
    39  	<textarea name="friends_file" id="friends_file_el" style="width:600px" rows="12">{FRIENDS_TXT}</textarea>
    40  	<br>
    41  	<i>Valid lines contain <b>hostname:port</b>, <b>@AuthKey</b>, <b>+IP</b> or <b>*AgentPrefix</b>. Use # for comments.</i>
    42  <tr><td align="center">
    43  	<td align="right">
    44  	<input type="button" value="Cancel" onclick="cancel_friends()">
    45  	<input type="submit" name="apply" value="Save & Connect">
    46  </table>
    47  </form>
    48  </table>
    49  </div>
    50  
    51  <table style="margin-top:5px" width="100%" border="0" cellspacing="0" cellpadding="0">
    52  <tr>
    53  <td align="left"><span id="bw_dl_speed_now_span">
    54  Downloading at <b id="bw_dl_speed_now"></b> KB/s</span>
    55  &nbsp;&bull;&nbsp;
    56  <span id="bw_ul_speed_now_span">Uploading at
    57  <b id="bw_ul_speed_now"></b> KB/s</span>
    58  
    59  <span id="get_mp_in_progress" style="display:none">&nbsp;&bull;&nbsp;<b>GetMPInProgress:<span id="get_mp_conn_id"></span></b></span>
    60  
    61  </td>
    62  <td align="right">
    63  Resolution:
    64  <select id="bw_chart_seconds" onchange="draw_chart()">
    65  	<option value="1">1 second</option>
    66  	<option value="5">5 seconds</option>
    67  	<option value="30">30 seconds</option>
    68  	<option value="300">5 minutes</option>
    69  </select>
    70  </td>
    71  </tr>
    72  <tr>
    73  <td colspan="2">
    74  <div id="chart" style="height:180px;margin:0px"></div>
    75  </td>
    76  </tr>
    77  </table>
    78  
    79  <table style="width:100%">
    80  <tr>
    81  <td align="left" valign="top">
    82  <span class="hand" onclick="stat_freeze.click()">
    83  	<input type="checkbox" id="stat_freeze" onchange="freeze_stats()" onclick="event.stopPropagation()">Freeze table
    84  </span>
    85  &nbsp;&bull;&nbsp;
    86  <span class="hand" onclick="hide_incoming_cb.click()">
    87  	<input type="checkbox" id="hide_incoming_cb" onchange="switch_hidden(this)" onclick="event.stopPropagation()">Hide <img src="webui/incoming.png">
    88  </span>
    89  &nbsp;
    90  <span class="hand" onclick="hide_outgoing_cb.click()">
    91  	<input type="checkbox" id="hide_outgoing_cb" onchange="switch_hidden(this)" onclick="event.stopPropagation()">Hide <img src="webui/outgoing.png">
    92  </span>
    93  <!--
    94  &nbsp;&bull;&nbsp;
    95  <input type="checkbox" id="show_debug_mode" onchange="switch_debug_mode()"><span class="hand" onclick="show_debug_mode.click()">More info</span>
    96  -->
    97  </td>
    98  <td align="right">
    99  <span onclick="net_list_order_sp.click()" class="hand">
   100  	<input type="radio" name="net_list_order" id="net_list_order_sp" onchange="switch_order_type()" onclick="event.stopPropagation()"> Sort by speed
   101  </span>
   102  &nbsp;&bull;&nbsp;
   103  <span onclick="net_list_order_id.click()" class="hand">
   104  	<input type="radio" name="net_list_order" id="net_list_order_id" onchange="switch_order_type()" onclick="event.stopPropagation()"> Sort by age
   105  </span>
   106  </td>
   107  </tr>
   108  </table>
   109  <table class="netcons bord" width="100%" id="netcons">
   110  <tr>
   111  	<th width="30">ID
   112  	<th width="80">Age
   113  	<th width="130" colspan="2">Peer Address
   114  	<th width="20">Ping
   115  	<th class="dbg">Rcvd
   116  	<th class="dbg">Sent
   117  	<th width="60" >Tot In
   118  	<th width="60" >Tot Out
   119  	<th colspan="3">Node Version
   120  	<th width="60" colspan="2" title="Received / In Progress">Blks
   121  	<th >Txs
   122  	<th class="dbg" title="Bytes waiting to be sent">ToSend
   123  	<th class="dbg" title="Max bytes waiting to be sent">MaxSend
   124  	<th class="r"><img title="Refresh table" src="webui/refresh.png" style="cursor:hand" onclick="refresh_conns()">
   125  </tr>
   126  <!--PEER_ROW-->
   127  </table>
   128  
   129  
   130  <table width="100%"><tr>
   131  <td class="small">
   132  Node Version Legend:<br>
   133  &bull; <b>N</b> - Capable of serving the complete block chain<br>
   134  &bull; <b>n</b> - Limited network (can only serve last 288 blocks)<br>
   135  &bull; <b>H</b> - Requested BIP130 mode (via <code>sendheaders</code> message)<br>
   136  &bull; <b>B</b> - Supports Bloom Filtering (for serving SPV clients)<br>
   137  &bull; <b>1,2</b> - Supports Compact Blocks (<b>+</b> for high bandwidth mode)<br>
   138  &bull; <b>W</b> - Supports Segregate Witness functionality<br>
   139  &bull; <b>X</b> - Supports Xtreme Thinblocks functionality<br>
   140  &bull; <b>O</b> - Blocks only mode (node does not request transactions)<br>
   141  </td>
   142  </tr>
   143  <tr>
   144  <td>
   145  <a name="rawdiv"></a>
   146  <div id="rawdivon" style="position:relative;width:100%;height:auto;display:none">
   147  <img title="Refresh peer info" src="webui/refresh.png" style="position:absolute;right:25px;top:5px;z-index:2000;cursor:hand" onclick="refresh_raw()">
   148  <img title="Hide peer info" src="webui/close.png" style="position:absolute;right:5px;top:5px;z-index:2000;cursor:hand" onclick="hide_peer_info()">
   149  <pre id="rawdiv" class="mono" style="left:0px;top: 0px;z-index:1000;width:100%;"></pre>
   150  </div>
   151  </td></tr></table>
   152  
   153  
   154  <script>
   155  if (!server_mode) {
   156  	el_tcp_listen_switch.style.display='inline'
   157  }
   158  
   159  var raw_timer = null
   160  var curr_monitor_id = -1
   161  var friends_file_bak = ''
   162  var loading_new_rawdivon = false
   163  
   164  function connect_peer() {
   165  	var ip = prompt("Enter IP of the peer to connect to");
   166  	if (ip!=null) {
   167  		var aj = ajax()
   168  		aj.onload=function() {
   169  			console.log(aj.responseText)
   170  		}
   171  		aj.open("GET",'cfg?conn='+encodeURI(ip)+'&sid='+sid, true);
   172  		aj.send(null);
   173  	}
   174  }
   175  
   176  function unban_peer() {
   177  	var ip = prompt("Enter IP of the peer to unban or 'all'");
   178  	if (ip!=null) {
   179  		var aj = ajax()
   180  		aj.onload=function() {
   181  			console.log(aj.responseText)
   182  		}
   183  		aj.open("GET",'cfg?unban='+encodeURI(ip)+'&sid='+sid, true);
   184  		aj.send(null);
   185  	}
   186  }
   187  
   188  function edit_friends() {
   189  	friends_file_bak = friends_file_el.value
   190  	friends_form.style.display = 'block'
   191  }
   192  
   193  function cancel_friends() {
   194  	friends_form.style.display = 'none'
   195  	friends_file_el.value = friends_file_bak
   196  }
   197  
   198  function freeze_stats() {
   199  	if (!stat_freeze.checked) {
   200  		refreshconnections(false)
   201  		if (curr_monitor_id!=-1) {
   202  			raw_load(curr_monitor_id,false)
   203  		}
   204  	}
   205  }
   206  
   207  function switch_hidden(cb) {
   208  	if (hide_incoming_cb.checked && hide_outgoing_cb.checked) {
   209  		if (cb.id=="hide_incoming_cb") {
   210  			hide_outgoing_cb.checked = !hide_outgoing_cb.checked
   211  		} else {
   212  			hide_incoming_cb.checked = !hide_incoming_cb.checked
   213  		}
   214  	}
   215  	hide_peer_info()
   216  	refreshconnections(false)
   217  	return false
   218  }
   219  
   220  function hide_peer_info() {
   221  	if (raw_timer!=null) {
   222  		clearTimeout(raw_timer)
   223  		raw_timer = null
   224  	}
   225  	rawdiv.innerHTML = ''
   226  	curr_monitor_id = -1
   227  	rawdivon.style.display = 'none'
   228  }
   229  
   230  function refresh_raw() {
   231  	if (!stat_freeze.checked) {
   232  		stat_freeze.click()
   233  	}
   234  	raw_load(curr_monitor_id,true)
   235  }
   236  
   237  function refresh_conns() {
   238  	if (!stat_freeze.checked) {
   239  		stat_freeze.click()
   240  	}
   241  	refreshconnections(true)
   242  }
   243  
   244  function show_info(id) {
   245  	loading_new_rawdivon = true
   246  	raw_load(id,true)
   247  }
   248  
   249  function update_connection_info(ci) {
   250  	var s = 'Connection ID ' + ci.ID + ':\n'
   251  
   252  	s += ci.LocalAddr + (ci.Incomming ? ' <== ' : ' ==> ') + ci.RemoteAddr + '\n'
   253  	s += 'Connected at ' + tim2str(Date.parse(ci.ConnectedAt)/1000) + ' | Ticks: ' + ci.Ticks + '\n'
   254  	s += 'Node Version: ' + ci.Version + ' | Services: 0x' + ci.Services.toString(16) + ' | Chain Height: ' + ci.Height + '\n'
   255  	s += 'User Agent: ' + ci.Agent + ' | Reported IP: ' + int2ip(ci.ReportedIp4) + '\n'
   256  	s += 'SendHeaders: ' + ci.SendHeaders + ' | SendCmpctVer: ' + ci.SendCmpctVer + ' | HighBandwidth: ' + ci.HighBandwidth + '\n'
   257  	s += 'Last command rcvd at ' + tim2str(Date.parse(ci.LastDataGot)/1000, true) + ' - ' + ci.LastCmdRcvd + ':' + ci.LastBtsRcvd + '\n'
   258  	s += 'Last command sent at ' + tim2str(Date.parse(ci.LastSent)/1000, true) + ' - ' + ci.LastCmdSent + ':' + ci.LastBtsSent + '\n'
   259  
   260  	s += 'Total Received:' + ci.BytesReceived + ' / Sent:' + ci.BytesSent + '   Bytes to send:' + ci.BytesToSend + ' (' + ci.MaxSentBufSize + ' max)\n'
   261  
   262  	s += 'Invs:  Done=' + ci.InvsDone + '   Recieved=' + ci.InvsRecieved + '  Pending=' + ci.InvsToSend +  '\n'
   263  	s += 'Get Headers:' + '  InProgress=' + ci.GetHeadersInProgress + '  AllReceived=' + ci.AllHeadersReceived + '  LastEmpty=' + ci.LastHeadersEmpty + '\n'
   264  	s += 'Get Blocks:' + '  InProgress=' + ci.BlocksInProgress + '  GetDataNow=' + ci.GetBlocksDataNow + '\n'
   265  
   266  	s += 'Authorized:' + ci.Authorized + '  AuthAckGot:' + ci.AuthAckGot + '  ChainSynced:' + ci.ChainSynchronized + '  GetMPInProgress:' + ci.GetMPInProgress + '\n'
   267  	s += 'GetAddrDone:' + ci.GetAddrDone + ' / MinFeeSPKB:' + ci.MinFeeSPKB  + ' / LastMinFeeSent:' + ci.LastMinFeePerKByte + '\n'
   268  	s += 'Ping history:'
   269  
   270  	var idx = ci.PingHistoryIdx
   271  	for (var i=0; i<ci.PingHistory.length; i++) {
   272  		if (ci.PingHistory[idx]>0) {
   273  			s += ' ' + ci.PingHistory[idx]
   274  		}
   275  		idx = (idx+1)%ci.PingHistory.length
   276  	}
   277  	s += ' -> ' + ci.AveragePing + ' ms\n'
   278  
   279  	var cnts = ''
   280  	var msgs = new Array()
   281  	var has_counters = false
   282  
   283  	for (var k in ci.Counters) {
   284  		if (k[4]=='_') {
   285  			if (isNaN(msgs[k.substr(5)])) msgs[k.substr(5)] = new Array()
   286  			msgs[k.substr(5)][k.substr(0,4)] = ci.Counters[k]
   287  		} else {
   288  			if (cnts!='') cnts+=',  '
   289  			cnts += k + '=' + ci.Counters[k]
   290  		}
   291  		has_counters = true
   292  	}
   293  	if (!has_counters) {
   294  		s += 'No counters yet or counters disabled in config file (Stats.NoCounters)'
   295  	} else {
   296  		if (cnts!='') {
   297  			s += 'Counters: ' + cnts + '\n'
   298  		}
   299  		s += '----------------------------------------------------------------\n'
   300  		s += ' Network message     Received from peer          Sent to peer\n'
   301  		s += '----------------------------------------------------------------\n'
   302  		var kks = []
   303  		for (var k in msgs) {
   304  			kks.push(k)
   305  		}
   306  		kks.sort()
   307  		for (var i=0; i<kks.length; i++) {
   308  			var v
   309  			var k = kks[i]
   310  			s += ' ' + rightpad(k,  ' ', 16) + ' '
   311  			v = msgs[k]["rcvd"]
   312  			s += leftpad(isNaN(v)?' ':v, ' ', 8)
   313  			v = msgs[k]["rbts"]
   314  			s += ' ' + leftpad(isNaN(v)?' ':v,  ' ', 12)
   315  			s += '   '
   316  
   317  
   318  			v = msgs[k]["sent"]
   319  			s += leftpad(isNaN(v)?' ':v, ' ', 8)
   320  			v = msgs[k]["sbts"]
   321  			s += ' ' + leftpad(isNaN(v)?' ':v,  ' ', 12)
   322  			s += '\n'
   323  		}
   324  		s += '----------------------------------------------------------------\n'
   325  	}
   326  	
   327  	rawdiv.innerHTML = s
   328  	rawdivon.style.display = 'block'
   329  	if (loading_new_rawdivon) {
   330  		window.scrollTo(0,document.body.scrollHeight)
   331  		loading_new_rawdivon = false
   332  	}
   333  }
   334  
   335  function raw_load(id,force) {
   336  	//console.log(this)
   337  	if (raw_timer!=null) {
   338  		clearTimeout(raw_timer)
   339  		raw_timer = null
   340  	}
   341  	if (!force && stat_freeze.checked) {
   342  		return
   343  	}
   344  	curr_monitor_id = id
   345  	var aj = ajax()
   346  	aj.onload=function() {
   347  		try {
   348  			var ci = JSON.parse(aj.responseText)
   349  			update_connection_info(ci)
   350  		} catch (e) {
   351  			console.log("Closing peer info because", e)
   352  			hide_peer_info()
   353  		}
   354  		raw_timer = setTimeout('raw_load('+id+',false)', 900)
   355  	}
   356  	aj.open("GET","peerst.json?id="+id, true);
   357  	aj.send(null);
   358  }
   359  
   360  function net_drop(id) {
   361  	if (server_mode) {
   362  		alert('Droping connections is not available in Server Mode')
   363  		return
   364  	}
   365  	if (confirm("Drop Connection ID "+id+" and ban its IP")) {
   366  		document.location = 'cfg?drop='+id+'&sid='+sid
   367  	}
   368  	return false
   369  }
   370  
   371  function net_getmp(id) {
   372  	if (!confirm("Request all missing transactions from Connection ID "+id)) {
   373  		return
   374  	}
   375  	var aj = ajax()
   376  	aj.open("GET", 'cfg?getmp='+id+'&sid='+sid, true)
   377  	aj.send(null)
   378  }
   379  
   380  function refreshconnections(force) {
   381  	if (!force && stat_freeze.checked) {
   382  		return
   383  	}
   384  
   385  	if (loading_new_rawdivon) {
   386  		setTimeout('refreshconnections(false)', 2500)
   387  		return
   388  	}
   389  
   390  	var aj = ajax()
   391  	aj.onerror=function() {
   392  		setTimeout('refreshconnections(false)', 5000)
   393  	}
   394  	aj.onload=function() {
   395  		try {
   396  			var cs = JSON.parse(aj.responseText)
   397  
   398  			if (net_list_order_id.checked) {
   399  				cs.sort(function(a,b){
   400  					return (a.ID>b.ID) ? 1 : -1;
   401  				})
   402  			}
   403  
   404  			while (netcons.rows.length>1) netcons.deleteRow(1)
   405  
   406  			var ins=0, outs=0
   407  			var id_found = false
   408  
   409  			for (var i=0; i<cs.length; i++) {
   410  				if (cs[i].Incomming) {
   411  					ins++
   412  					if (hide_incoming_cb.checked) continue
   413  				} else {
   414  					outs++
   415  					if (hide_outgoing_cb.checked) continue
   416  				}
   417  
   418  				var td, row = netcons.insertRow(-1)
   419  				var id = cs[i].ID
   420  
   421  				if (curr_monitor_id==id) {
   422  					update_connection_info(cs[i])
   423  					id_found = true
   424  				}
   425  
   426  				row.id = id
   427  				row.className = 'hov small'
   428  
   429  				// id
   430  				td = row.insertCell(-1)
   431  				td.style.textAlign = 'right'
   432  				td.className = 'nodeid'
   433  				td.innerHTML = '&nbsp;<b>'+id+'</b>&nbsp;'
   434  
   435  
   436  				// age
   437  				td = row.insertCell(-1)
   438  				td.noWrap = true
   439  				td.style.textAlign = 'right'
   440  				if (cs[i].ConnectedAt.substr(0,4)!="0001" && typeof(time_now)=="number") {
   441  					var secs = time_now - parseInt(Date.parse(cs[i].ConnectedAt)/1000)
   442  					if (secs<0)  secs = 0
   443  					if (secs<120) {
   444  						td.innerHTML = (secs/60).toFixed(1) + ' min'
   445  					} else {
   446  						td.innerHTML = period2str( secs )
   447  					}
   448  				}
   449  
   450  				// addr
   451  				td = row.insertCell(-1)
   452  				td.style.textAlign = 'right'
   453  				td.innerHTML = cs[i].PeerIp
   454  				td.title = "Click to Copy"
   455  				td.className = 'hand'
   456  				td["peerip"] = cs[i].PeerIp
   457  				td.addEventListener("click", function(e) {
   458  					autocopy.style.display = 'inline'
   459  					autocopy.value = e.srcElement["peerip"]
   460  					autocopy.select()
   461  					document.execCommand('copy')
   462  					autocopy.style.display = 'none'
   463  				})
   464  
   465  				// direction
   466  				td = row.insertCell(-1)
   467  				if (cs[i].Incomming) {
   468  					td.innerHTML = "<img src=\"webui/incoming.png\">"
   469  				} else {
   470  					td.innerHTML = "<img src=\"webui/outgoing.png\">"
   471  				}
   472  
   473  				// ping
   474  				td = row.insertCell(-1)
   475  				td.style.textAlign = 'right'
   476  				td.innerHTML = '<i>'+cs[i].AveragePing+'&nbsp;ms</i>'
   477  
   478  				// last_cmd_rcvd
   479  				td = row.insertCell(-1)
   480  				td.className = 'dbg mono'
   481  				td.title = cs[i].LastBtsRcvd
   482  				td.innerHTML = cs[i].LastCmdRcvd
   483  
   484  				// last_cmd_sent
   485  				td = row.insertCell(-1)
   486  				td.className = 'dbg mono'
   487  				td.title = cs[i].LastBtsSent
   488  				td.innerHTML = cs[i].LastCmdSent
   489  
   490  				// total_rcvd
   491  				td = row.insertCell(-1)
   492  				td.style.textAlign = 'right'
   493  				td.noWrap = true
   494  				td.innerHTML = bignum(cs[i].BytesReceived)+'B'
   495  
   496  				// total_sent
   497  				td = row.insertCell(-1)
   498  				td.style.textAlign = 'right'
   499  				td.noWrap = true
   500  				td.innerHTML = bignum(cs[i].BytesSent)+'B'
   501  
   502  				// node_version
   503  				td = row.insertCell(-1)
   504  				td.style.textAlign = 'right'
   505  				td.innerHTML = cs[i].Version
   506  				td.title = 'Services : 0x' + cs[i].Services.toString(16)
   507  
   508  				//Flags: X-compact blocks,  W - SegWit
   509  				td = row.insertCell(-1)
   510  				td.className = 'bold'
   511  				td.style.textAlign = 'center'
   512  				var s = ''
   513  				if (cs[i].Services&1)  s += 'N'
   514  				else  if (cs[i].Services&0x400)  s += 'n'
   515  				if (cs[i].SendHeaders) s += 'H'
   516  				if (cs[i].Services&4) s += 'B'
   517  				if (cs[i].SendCmpctVer) {
   518  					s += cs[i].SendCmpctVer
   519  					if (cs[i].HighBandwidth)  s += '+'
   520  				}
   521  				if (cs[i].Services&8)  s += 'W'
   522  				if (cs[i].Services&0x10)  s += 'X'
   523  				if (cs[i].DoNotRelayTxs)  s += 'O'
   524  				td.innerText = s
   525  
   526  				// user agent
   527  				td = row.insertCell(-1)
   528  				td.style.overay = 'auto'
   529  				td.className = 'agent'
   530  				td.title = td.innerText = cs[i].Agent//.substr(0,20)
   531  
   532  				// blocks received
   533  				td = row.insertCell(-1)
   534  				td.style.textAlign = 'right'
   535  				td.noWrap = true
   536  				if (cs[i].BlocksReceived>0) td.innerHTML = cs[i].BlocksReceived
   537  
   538  				// blocks in progress
   539  				td = row.insertCell(-1)
   540  				td.style.textAlign = 'right'
   541  				td.noWrap = true
   542  				if (cs[i].BlocksInProgress>0) {
   543  					td.innerHTML = cs[i].BlocksInProgress + ( cs[i].GetHeadersInProgress ? '*' : '')
   544  				} else if (cs[i].GetHeadersInProgress) {
   545  					td.innerHTML = '*'
   546  				}
   547  
   548  				/*
   549  				td = row.insertCell(-1)
   550  				td.style.textAlign = 'right'
   551  				td.noWrap = true
   552  				td.innerHTML = cs[i].TotalNewHeadersCount
   553  
   554  				td = row.insertCell(-1)
   555  				td.style.textAlign = 'right'
   556  				td.innerHTML = cs[i].LastHeadersEmpty
   557  				td.title = cs[i].LastHeadersHeightAsk
   558  				*/
   559  
   560  				td = row.insertCell(-1)
   561  				td.style.textAlign = 'right'
   562  				td.noWrap = true
   563  				if (cs[i].TxsReceived!=0) td.innerText = cs[i].TxsReceived + ( cs[i].GetMPInProgress ? '..' : '' )
   564  				//td.innerText = cs[i].NewAddrsRcvd
   565  
   566  				td = row.insertCell(-1)
   567  				td.className = "dbg"
   568  				td.style.textAlign = 'right'
   569  				td.noWrap = true
   570  				if (cs[i].BytesToSend>0) td.innerHTML = cs[i].BytesToSend
   571  
   572  				td = row.insertCell(-1)
   573  				td.className = "dbg"
   574  				td.style.textAlign = 'right'
   575  				td.noWrap = true
   576  				td.innerHTML = cs[i].MaxSentBufSize
   577  
   578  				// action icons
   579  				var peer_ip = cs[i].PeerIp.split(':')[0]
   580  				td = row.insertCell(-1)
   581  				td.className = "r nw"
   582  				td.innerHTML = '<img title="Drop this connection and ban peer" class="hand" src="webui/del.png" onclick="net_drop('+id+')"> ' +
   583  					'<img title="Connection Details" class="hand" src="webui/info.png" onclick="show_info('+id+')"> '
   584  				if ( cs[i].IsGocoin && !cs[i].GetMPInProgress ) {
   585  					var img = document.createElement('img');
   586  					img.src = "webui/request.png"
   587  					img.title = "Request missing transactions"
   588  					img.classList.add('hand')
   589  					img["connid"] = id
   590  					img.addEventListener("click", function(e) {
   591  						net_getmp(e.srcElement["connid"])
   592  						e.stopPropagation()
   593  					})
   594  					td.insertBefore(img, td.firstChild)
   595  				}
   596  
   597  				if (cs[i].Authorized) {
   598  					row.classList.add("secure")
   599  				} else if (cs[i].IsSpecial) {
   600  					row.classList.add("special")
   601  				} else if (cs[i].HasImmunity) {
   602  					row.classList.add("immune")
   603  				}
   604  			}
   605  
   606  			if (curr_monitor_id!=-1 && !id_found) {
   607  				//console.log(curr_monitor_id, "not found - hide")
   608  				hide_peer_info()
   609  			}
   610  
   611  			in_connections.innerText = ins
   612  			out_connections.innerText = outs
   613  		} catch(e) {
   614  			console.log(e)
   615  		}
   616  		setTimeout('refreshconnections(false)', 2500)
   617  	}
   618  	aj.open("GET","netcon.json",true)
   619  	aj.send(null)
   620  }
   621  
   622  function switch_debug_mode() {
   623  	if (false/*show_debug_mode.checked*/) {
   624  		css('.dbg', 'display', 'table-cell')
   625  		css('td.agent', 'max-width', '100px')
   626  	} else {
   627  		css('.dbg', 'display', 'none')
   628  		css('td.agent', 'max-width', '350px')
   629  	}
   630  }
   631  
   632  function draw_chart() {
   633  	var seconds = parseInt(bw_chart_seconds.value)
   634  
   635  	localStorage.setItem("net_bw_seconds", seconds)
   636  
   637  	var aj = ajax()
   638  	aj.onerror=function() {
   639  		setTimeout(draw_chart, 1000)
   640  	}
   641  
   642  	aj.onload=function() {
   643  		try {
   644  			cs = JSON.parse(aj.responseText)
   645  
   646  			var plot_data = [
   647  				{ data : [], color:3, lines: {show:true, fill:true} },
   648  				{ data : [], color:2, lines: {show:true, fill:true} }
   649  				];
   650  			var plot_options = {
   651  				xaxis: { tickSize:60,  tickFormatter : function(a,b) {
   652  					if (a==0) return ''
   653  					if (seconds>60) {
   654  						return (parseInt(-a*seconds/3600) + 'h')
   655  					}
   656  					return (parseInt(-a*seconds/60) + 'min')
   657  				} },
   658  				yaxis : {labelWidth : 40, min : 0, position : "right",  label:"kB/s" },
   659  				legend: { position: 'nw' }
   660  			}
   661  
   662  			/*if (cs.MaxUL && cs.MaxUL > cs.MaxDL) {
   663  				plot_options.yaxis.max = cs.MaxUL/900
   664  			} else {
   665  				plot_options.yaxis.max = cs.MaxDL/900
   666  			}*/
   667  
   668  			var tot_dl = 0
   669  			var tot_ul = 0
   670  			for (var i=0; i<200; i++) {
   671  				plot_data[0].data.push([-i, cs.DL[i]/1e3])
   672  				plot_data[1].data.push([-i, cs.UL[i]/1e3])
   673  				tot_dl += cs.DL[i]
   674  				tot_ul += cs.UL[i]
   675  			}
   676  
   677  			plot_data[0].label = 'Downloading in kB/s - avg ' + (tot_dl / 256e3).toFixed(1)
   678  			plot_data[1].label = 'Uploading in kB/s - avg ' + (tot_ul / 256e3).toFixed(1)
   679  
   680  			$.plot($("#chart"), plot_data, plot_options)
   681  
   682  		} catch(e) {
   683  			console.log(e)
   684  		}
   685  		setTimeout(draw_chart, 990*seconds)
   686  	}
   687  	aj.open("GET","bwchar.json?seconds="+seconds, true)
   688  	aj.send(null)
   689  }
   690  
   691  function refreshbwinfo() {
   692  	var aj = ajax()
   693  	aj.onerror=function() {
   694  		setTimeout(refreshbwinfo, 5000)
   695  	}
   696  	aj.onload=function() {
   697  		try {
   698  			var bw = JSON.parse(aj.responseText)
   699  
   700  			in_connections.innerText = bw.Open_conns_in
   701  			out_connections.innerText = bw.Open_conns_out
   702  
   703  			bw_dl_speed_now.innerText = bw.Dl_speed_now >> 10
   704  			var sl = bw.Dl_speed_max==0 ? "not limited" : "limited to " + (bw.Dl_speed_max >> 10) + "KB/s"
   705  			bw_dl_speed_now_span.title = "Total " + bignum(bw.Dl_total) + 'B / Download speed ' + sl
   706  
   707  			bw_ul_speed_now.innerText = bw.Ul_speed_now >> 10
   708  			sl = bw.Ul_speed_max==0 ? "not limited" : "limited to " + (bw.Ul_speed_max >> 10) + "KB/s"
   709  			bw_ul_speed_now_span.title = "Total " + bignum(bw.Ul_total) + 'B / Upload speed ' + sl
   710  
   711  			if (bw.GetMPInProgress) {
   712  				get_mp_conn_id.innerText = bw.GetMPConnID
   713  				get_mp_in_progress.style.display = "inline"
   714  			} else {
   715  				get_mp_in_progress.style.display = "none"
   716  			}
   717  		} catch(e) {
   718  			console.log(e)
   719  		}
   720  		setTimeout(refreshbwinfo, 1000)
   721  	}
   722  	aj.open("GET","bwidth.json",true)
   723  	aj.send(null)
   724  }
   725  
   726  
   727  if (!server_mode) {
   728  	connect_buttons.style.display = 'inline'
   729  }
   730  
   731  function switch_order_type() {
   732  	if (net_list_order_sp.checked) {
   733  		localStorage.setItem("net_order", "sp")
   734  	} else {
   735  		localStorage.setItem("net_order", "id")
   736  	}
   737  	refreshconnections(true)
   738  }
   739  function remember_info_setting() {
   740  	var mod = localStorage.getItem("net_order")
   741  	if ((mod+'').length!=2) mod = "sp"
   742  	document.getElementById('net_list_order_'+mod).checked = true
   743  
   744  	// bw chart resolution:
   745  	var seconds = localStorage.getItem("net_bw_seconds")
   746  	for (var i=0; i<bw_chart_seconds.options.length; i++) {
   747  		if (bw_chart_seconds.options[i].value==seconds) {
   748  			bw_chart_seconds.selectedIndex = i
   749  			break
   750  		}
   751  	}
   752  }
   753  remember_info_setting()
   754  switch_order_type()
   755  switch_debug_mode()
   756  draw_chart()
   757  refreshbwinfo()
   758  
   759  </script>