ruby-netmon-qt 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +10 -0
- data/.ruby-version +1 -0
- data/LICENSE +674 -0
- data/README.md +30 -0
- data/Rakefile +12 -0
- data/exe/netmon-qt +6 -0
- data/lib/netmon-qt/app/assets/README.md +6 -0
- data/lib/netmon-qt/app/assets/app.svg +1 -0
- data/lib/netmon-qt/app/assets/flags/ad.svg +148 -0
- data/lib/netmon-qt/app/assets/flags/ae.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/af.svg +81 -0
- data/lib/netmon-qt/app/assets/flags/ag.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/ai.svg +29 -0
- data/lib/netmon-qt/app/assets/flags/al.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/am.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/ao.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/aq.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/ar.svg +32 -0
- data/lib/netmon-qt/app/assets/flags/arab.svg +109 -0
- data/lib/netmon-qt/app/assets/flags/as.svg +73 -0
- data/lib/netmon-qt/app/assets/flags/asean.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/at.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/au.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/aw.svg +186 -0
- data/lib/netmon-qt/app/assets/flags/ax.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/az.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/ba.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/bb.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/bd.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/be.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/bf.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/bg.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/bh.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/bi.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/bj.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/bl.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/bm.svg +97 -0
- data/lib/netmon-qt/app/assets/flags/bn.svg +36 -0
- data/lib/netmon-qt/app/assets/flags/bo.svg +674 -0
- data/lib/netmon-qt/app/assets/flags/bq.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/br.svg +45 -0
- data/lib/netmon-qt/app/assets/flags/bs.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/bt.svg +89 -0
- data/lib/netmon-qt/app/assets/flags/bv.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/bw.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/by.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/bz.svg +145 -0
- data/lib/netmon-qt/app/assets/flags/ca.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/cc.svg +19 -0
- data/lib/netmon-qt/app/assets/flags/cd.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/cefta.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/cf.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/cg.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/ch.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/ci.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/ck.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/cl.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/cm.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/cn.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/co.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/cp.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/cr.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/cu.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/cv.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/cw.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/cx.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/cy.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/cz.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/de.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/dg.svg +130 -0
- data/lib/netmon-qt/app/assets/flags/dj.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/dk.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/dm.svg +152 -0
- data/lib/netmon-qt/app/assets/flags/do.svg +122 -0
- data/lib/netmon-qt/app/assets/flags/dz.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/eac.svg +48 -0
- data/lib/netmon-qt/app/assets/flags/ec.svg +138 -0
- data/lib/netmon-qt/app/assets/flags/ee.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/eg.svg +38 -0
- data/lib/netmon-qt/app/assets/flags/eh.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/er.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/es-ct.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/es-ga.svg +187 -0
- data/lib/netmon-qt/app/assets/flags/es-pv.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/es.svg +547 -0
- data/lib/netmon-qt/app/assets/flags/et.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/eu.svg +28 -0
- data/lib/netmon-qt/app/assets/flags/fi.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/fj.svg +123 -0
- data/lib/netmon-qt/app/assets/flags/fk.svg +89 -0
- data/lib/netmon-qt/app/assets/flags/fm.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/fo.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/fr.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/ga.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/gb-eng.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/gb-nir.svg +131 -0
- data/lib/netmon-qt/app/assets/flags/gb-sct.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/gb-wls.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/gb.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/gd.svg +27 -0
- data/lib/netmon-qt/app/assets/flags/ge.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/gf.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/gg.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/gh.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/gi.svg +32 -0
- data/lib/netmon-qt/app/assets/flags/gl.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/gm.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/gn.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/gp.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/gq.svg +23 -0
- data/lib/netmon-qt/app/assets/flags/gr.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/gs.svg +132 -0
- data/lib/netmon-qt/app/assets/flags/gt.svg +204 -0
- data/lib/netmon-qt/app/assets/flags/gu.svg +19 -0
- data/lib/netmon-qt/app/assets/flags/gw.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/gy.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/hk.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/hm.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/hn.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/hr.svg +56 -0
- data/lib/netmon-qt/app/assets/flags/ht.svg +116 -0
- data/lib/netmon-qt/app/assets/flags/hu.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/ic.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/id.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/ie.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/il.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/im.svg +36 -0
- data/lib/netmon-qt/app/assets/flags/in.svg +25 -0
- data/lib/netmon-qt/app/assets/flags/io.svg +130 -0
- data/lib/netmon-qt/app/assets/flags/iq.svg +10 -0
- data/lib/netmon-qt/app/assets/flags/ir.svg +219 -0
- data/lib/netmon-qt/app/assets/flags/is.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/it.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/je.svg +62 -0
- data/lib/netmon-qt/app/assets/flags/jm.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/jo.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/jp.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/ke.svg +23 -0
- data/lib/netmon-qt/app/assets/flags/kg.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/kh.svg +61 -0
- data/lib/netmon-qt/app/assets/flags/ki.svg +36 -0
- data/lib/netmon-qt/app/assets/flags/km.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/kn.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/kp.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/kr.svg +17 -0
- data/lib/netmon-qt/app/assets/flags/kw.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/ky.svg +103 -0
- data/lib/netmon-qt/app/assets/flags/kz.svg +36 -0
- data/lib/netmon-qt/app/assets/flags/la.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/lb.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/lc.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/li.svg +43 -0
- data/lib/netmon-qt/app/assets/flags/lk.svg +22 -0
- data/lib/netmon-qt/app/assets/flags/lr.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/ls.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/lt.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/lu.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/lv.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/ly.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/ma.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/mc.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/md.svg +71 -0
- data/lib/netmon-qt/app/assets/flags/me.svg +118 -0
- data/lib/netmon-qt/app/assets/flags/mf.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/mg.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/mh.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/mk.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/ml.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/mm.svg +10 -0
- data/lib/netmon-qt/app/assets/flags/mn.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/mo.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/mp.svg +86 -0
- data/lib/netmon-qt/app/assets/flags/mq.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/mr.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/ms.svg +25 -0
- data/lib/netmon-qt/app/assets/flags/mt.svg +56 -0
- data/lib/netmon-qt/app/assets/flags/mu.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/mv.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/mw.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/mx.svg +377 -0
- data/lib/netmon-qt/app/assets/flags/my.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/mz.svg +21 -0
- data/lib/netmon-qt/app/assets/flags/na.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/nc.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/ne.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/nf.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/ng.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/ni.svg +129 -0
- data/lib/netmon-qt/app/assets/flags/nl.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/no.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/np.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/nr.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/nu.svg +10 -0
- data/lib/netmon-qt/app/assets/flags/nz.svg +36 -0
- data/lib/netmon-qt/app/assets/flags/om.svg +115 -0
- data/lib/netmon-qt/app/assets/flags/pa.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/pc.svg +33 -0
- data/lib/netmon-qt/app/assets/flags/pe.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/pf.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/pg.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/ph.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/pk.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/pl.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/pm.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/pn.svg +53 -0
- data/lib/netmon-qt/app/assets/flags/pr.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/ps.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/pt.svg +57 -0
- data/lib/netmon-qt/app/assets/flags/pw.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/py.svg +156 -0
- data/lib/netmon-qt/app/assets/flags/qa.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/re.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/ro.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/rs.svg +296 -0
- data/lib/netmon-qt/app/assets/flags/ru.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/rw.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/sa.svg +25 -0
- data/lib/netmon-qt/app/assets/flags/sb.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/sc.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/sd.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/se.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/sg.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/sh-ac.svg +690 -0
- data/lib/netmon-qt/app/assets/flags/sh-hl.svg +164 -0
- data/lib/netmon-qt/app/assets/flags/sh-ta.svg +76 -0
- data/lib/netmon-qt/app/assets/flags/sh.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/si.svg +18 -0
- data/lib/netmon-qt/app/assets/flags/sj.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/sk.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/sl.svg +12 -0
- data/lib/netmon-qt/app/assets/flags/sm.svg +73 -0
- data/lib/netmon-qt/app/assets/flags/sn.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/so.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/sr.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/ss.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/st.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/sv.svg +593 -0
- data/lib/netmon-qt/app/assets/flags/sx.svg +56 -0
- data/lib/netmon-qt/app/assets/flags/sy.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/sz.svg +34 -0
- data/lib/netmon-qt/app/assets/flags/tc.svg +50 -0
- data/lib/netmon-qt/app/assets/flags/td.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/tf.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/tg.svg +14 -0
- data/lib/netmon-qt/app/assets/flags/th.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/tj.svg +26 -0
- data/lib/netmon-qt/app/assets/flags/tk.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/tl.svg +13 -0
- data/lib/netmon-qt/app/assets/flags/tm.svg +205 -0
- data/lib/netmon-qt/app/assets/flags/tn.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/to.svg +10 -0
- data/lib/netmon-qt/app/assets/flags/tr.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/tt.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/tv.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/tw.svg +32 -0
- data/lib/netmon-qt/app/assets/flags/tz.svg +15 -0
- data/lib/netmon-qt/app/assets/flags/ua.svg +6 -0
- data/lib/netmon-qt/app/assets/flags/ug.svg +30 -0
- data/lib/netmon-qt/app/assets/flags/um.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/un.svg +16 -0
- data/lib/netmon-qt/app/assets/flags/us.svg +9 -0
- data/lib/netmon-qt/app/assets/flags/uy.svg +28 -0
- data/lib/netmon-qt/app/assets/flags/uz.svg +30 -0
- data/lib/netmon-qt/app/assets/flags/va.svg +190 -0
- data/lib/netmon-qt/app/assets/flags/vc.svg +8 -0
- data/lib/netmon-qt/app/assets/flags/ve.svg +26 -0
- data/lib/netmon-qt/app/assets/flags/vg.svg +59 -0
- data/lib/netmon-qt/app/assets/flags/vi.svg +28 -0
- data/lib/netmon-qt/app/assets/flags/vn.svg +11 -0
- data/lib/netmon-qt/app/assets/flags/vu.svg +21 -0
- data/lib/netmon-qt/app/assets/flags/wf.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/ws.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/xk.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/xx.svg +4 -0
- data/lib/netmon-qt/app/assets/flags/ye.svg +7 -0
- data/lib/netmon-qt/app/assets/flags/yt.svg +5 -0
- data/lib/netmon-qt/app/assets/flags/za.svg +17 -0
- data/lib/netmon-qt/app/assets/flags/zm.svg +27 -0
- data/lib/netmon-qt/app/assets/flags/zw.svg +21 -0
- data/lib/netmon-qt/app/components/connstableview/sortfilterproxymodel.rb +67 -0
- data/lib/netmon-qt/app/components/connstableview/statusbar.rb +73 -0
- data/lib/netmon-qt/app/components/connstableview/store.rb +236 -0
- data/lib/netmon-qt/app/components/connstableview.rb +239 -0
- data/lib/netmon-qt/app/components.rb +1 -0
- data/lib/netmon-qt/app/services/conns_lookup_service.rb +46 -0
- data/lib/netmon-qt/app/services.rb +1 -0
- data/lib/netmon-qt/app/views/mainwindow.rb +40 -0
- data/lib/netmon-qt/app/views.rb +1 -0
- data/lib/netmon-qt/app.rb +26 -0
- data/lib/netmon-qt/config/initializers/qt6.rb +8 -0
- data/lib/netmon-qt/config/settings.rb +33 -0
- data/lib/netmon-qt/config.rb +8 -0
- data/lib/netmon-qt/lib/contrib/sighandler.rb +24 -0
- data/lib/netmon-qt/lib/contrib.rb +1 -0
- data/lib/netmon-qt/lib/netmon/connection.rb +57 -0
- data/lib/netmon-qt/lib/netmon/localaddresscheck.rb +19 -0
- data/lib/netmon-qt/lib/netmon/procnet.rb +49 -0
- data/lib/netmon-qt/lib/netmon.rb +3 -0
- data/lib/netmon-qt/lib.rb +2 -0
- data/lib/netmon-qt/version.rb +3 -0
- data/lib/netmon-qt.rb +7 -0
- data/misc/screenshots/mainwindow.png +0 -0
- metadata +373 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
require_relative "connstableview/sortfilterproxymodel"
|
|
2
|
+
require_relative "connstableview/statusbar"
|
|
3
|
+
require_relative "connstableview/store"
|
|
4
|
+
|
|
5
|
+
class ConnsTableView < RubyQt6::Bando::QWidget
|
|
6
|
+
QSS_BUTTON_AUTOREFRESH = "
|
|
7
|
+
QPushButton {
|
|
8
|
+
background: #EFF0F1;
|
|
9
|
+
color: #7F8C8D;
|
|
10
|
+
border: 1px solid #BCBEBF;
|
|
11
|
+
border-bottom: 3px solid #B0B0B0;
|
|
12
|
+
border-radius: 3px;
|
|
13
|
+
padding: 6px;
|
|
14
|
+
font-weight: bold;
|
|
15
|
+
}
|
|
16
|
+
QPushButton:checked {
|
|
17
|
+
background: #FFFFFF;
|
|
18
|
+
color: #31363B;
|
|
19
|
+
}
|
|
20
|
+
"
|
|
21
|
+
|
|
22
|
+
q_object do
|
|
23
|
+
slot "_on_filter_changed()"
|
|
24
|
+
slot "_on_autorefreshbtn_toggled(bool)"
|
|
25
|
+
slot "_on_autorefresh_timer_timeout()"
|
|
26
|
+
slot "_on_tableview_custom_context_menu_requested(QPoint)"
|
|
27
|
+
slot "_on_endprocess_action_triggered()"
|
|
28
|
+
slot "_on_whois_action_triggered()"
|
|
29
|
+
slot "_on_copy_action_triggered()"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_reader :processfilter, :protocolfilter, :statefilter, :userfilter
|
|
33
|
+
attr_reader :statusbar
|
|
34
|
+
|
|
35
|
+
def initialize
|
|
36
|
+
super
|
|
37
|
+
|
|
38
|
+
@lastindex = nil
|
|
39
|
+
|
|
40
|
+
initialize_store
|
|
41
|
+
initialize_actions
|
|
42
|
+
initialize_toolbar
|
|
43
|
+
initialize_tableview
|
|
44
|
+
initialize_statusbar
|
|
45
|
+
initialize_timer_autorefresh
|
|
46
|
+
|
|
47
|
+
mainlayout = QVBoxLayout.new(self)
|
|
48
|
+
mainlayout.add_widget(@toolbar)
|
|
49
|
+
mainlayout.add_widget(@tableview)
|
|
50
|
+
|
|
51
|
+
@userfilter.set_current_text(Etc.getpwuid.name)
|
|
52
|
+
@autorefreshbtn.set_checked(true)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def initialize_store
|
|
58
|
+
@store = Store.new(self)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def initialize_actions
|
|
62
|
+
@endprocess_action = initialize_actions_act(QIcon::ThemeIcon::ApplicationExit, "End Process", :_on_endprocess_action_triggered)
|
|
63
|
+
@whois_action = initialize_actions_act(QIcon::ThemeIcon::EditFind, "", :_on_whois_action_triggered)
|
|
64
|
+
@copy_action = initialize_actions_act(QIcon::ThemeIcon::EditCopy, "", :_on_copy_action_triggered)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize_actions_act(icon, text, slot)
|
|
68
|
+
action = QAction.new(QIcon.from_theme(icon), text, self)
|
|
69
|
+
action.triggered.connect(self, slot)
|
|
70
|
+
action
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def initialize_toolbar
|
|
74
|
+
@processfilter = QComboBox.new
|
|
75
|
+
@processfilter.set_fixed_width(128)
|
|
76
|
+
@processfilter.add_item("*")
|
|
77
|
+
@store.active_processes.each { |process| @processfilter.add_item(process) }
|
|
78
|
+
@processfilter.current_text_changed.connect(self, :_on_filter_changed)
|
|
79
|
+
|
|
80
|
+
@protocolfilter = QComboBox.new
|
|
81
|
+
@protocolfilter.add_item("*")
|
|
82
|
+
@store.active_protocols.each { |protocol| @protocolfilter.add_item(protocol) }
|
|
83
|
+
@protocolfilter.set_fixed_width(128)
|
|
84
|
+
@protocolfilter.current_text_changed.connect(self, :_on_filter_changed)
|
|
85
|
+
|
|
86
|
+
@statefilter = QComboBox.new
|
|
87
|
+
@statefilter.add_item("*")
|
|
88
|
+
@store.active_states.each { |state| @statefilter.add_item(state) }
|
|
89
|
+
@statefilter.set_fixed_width(128)
|
|
90
|
+
@statefilter.current_text_changed.connect(self, :_on_filter_changed)
|
|
91
|
+
|
|
92
|
+
@userfilter = QComboBox.new
|
|
93
|
+
@userfilter.set_fixed_width(128)
|
|
94
|
+
@userfilter.add_item("*")
|
|
95
|
+
@store.active_users.each { |user| @userfilter.add_item(user) }
|
|
96
|
+
@userfilter.current_text_changed.connect(self, :_on_filter_changed)
|
|
97
|
+
|
|
98
|
+
@autorefreshbtn = QPushButton.new("")
|
|
99
|
+
@autorefreshbtn.set_fixed_width(192)
|
|
100
|
+
@autorefreshbtn.set_style_sheet(QSS_BUTTON_AUTOREFRESH)
|
|
101
|
+
@autorefreshbtn.set_checkable(true)
|
|
102
|
+
@autorefreshbtn.toggled.connect(self, :_on_autorefreshbtn_toggled)
|
|
103
|
+
|
|
104
|
+
@toolbar = QWidget.new
|
|
105
|
+
@toolbarlayout = QHBoxLayout.new(@toolbar)
|
|
106
|
+
@toolbarlayout.add_widget(initialize_toolbar_label("Process:"))
|
|
107
|
+
@toolbarlayout.add_widget(@processfilter)
|
|
108
|
+
@toolbarlayout.add_spacing(8)
|
|
109
|
+
@toolbarlayout.add_widget(initialize_toolbar_label("Protocol:"))
|
|
110
|
+
@toolbarlayout.add_widget(@protocolfilter)
|
|
111
|
+
@toolbarlayout.add_spacing(8)
|
|
112
|
+
@toolbarlayout.add_widget(initialize_toolbar_label("State:"))
|
|
113
|
+
@toolbarlayout.add_widget(@statefilter)
|
|
114
|
+
@toolbarlayout.add_spacing(8)
|
|
115
|
+
@toolbarlayout.add_widget(initialize_toolbar_label("User:"))
|
|
116
|
+
@toolbarlayout.add_widget(@userfilter)
|
|
117
|
+
@toolbarlayout.add_stretch
|
|
118
|
+
@toolbarlayout.add_widget(@autorefreshbtn)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def initialize_toolbar_label(text)
|
|
122
|
+
label = QLabel.new(text)
|
|
123
|
+
label.set_fixed_width(64)
|
|
124
|
+
label
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def initialize_tableview
|
|
128
|
+
@tableview = QTableView.new
|
|
129
|
+
@tableview.set_selection_behavior(QAbstractItemView::SelectRows)
|
|
130
|
+
@tableview.set_selection_mode(QAbstractItemView::SingleSelection)
|
|
131
|
+
@tableview.set_context_menu_policy(Qt::ContextMenuPolicy::CustomContextMenu)
|
|
132
|
+
@tableview.custom_context_menu_requested.connect(self, :_on_tableview_custom_context_menu_requested)
|
|
133
|
+
|
|
134
|
+
@storeproxymodel = SortFilterProxyModel.new(self)
|
|
135
|
+
@storeproxymodel.set_source_model(@store.itemmodel)
|
|
136
|
+
@tableview.set_model(@storeproxymodel)
|
|
137
|
+
|
|
138
|
+
@tableview.horizontal_header.hide_section(0)
|
|
139
|
+
@tableview.vertical_header.set_visible(false)
|
|
140
|
+
@tableview.set_column_width(COLUMN_PROCESS_NAME, 128)
|
|
141
|
+
@tableview.set_column_width(COLUMN_LOCAL_ADDRESS, 192)
|
|
142
|
+
@tableview.set_column_width(COLUMN_REMOTE_ADDRESS, 192)
|
|
143
|
+
|
|
144
|
+
@tableview.sort_by_column(COLUMN_PROCESS_NAME, Qt::AscendingOrder)
|
|
145
|
+
@tableview.set_sorting_enabled(true)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def initialize_statusbar
|
|
149
|
+
@statusbar = StatusBar.new(@storeproxymodel)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def initialize_timer_autorefresh
|
|
153
|
+
@timer = QTimer.new(self)
|
|
154
|
+
@timer.set_interval(NetmonQt.settings.GET_connections_check_interval)
|
|
155
|
+
@timer.timeout.connect(self, :_on_autorefresh_timer_timeout)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def update_filter_additem(filter, items)
|
|
159
|
+
index = filter.count - 1
|
|
160
|
+
items.reverse_each do |item|
|
|
161
|
+
loop do
|
|
162
|
+
case filter.item_text(index) <=> item
|
|
163
|
+
when +0 then break
|
|
164
|
+
when +1 then (index -= 1) || next
|
|
165
|
+
when -1 then filter.insert_item(index + 1, item) || break
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def _on_filter_changed
|
|
172
|
+
@storeproxymodel.invalidate
|
|
173
|
+
@statusbar.refresh
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def _on_autorefreshbtn_toggled(checked)
|
|
177
|
+
if checked
|
|
178
|
+
@autorefreshbtn.set_text("Auto Refresh: ON")
|
|
179
|
+
@timer.start
|
|
180
|
+
_on_autorefresh_timer_timeout
|
|
181
|
+
else
|
|
182
|
+
@autorefreshbtn.set_text("Auto Refresh: OFF")
|
|
183
|
+
@timer.stop
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def _on_autorefresh_timer_timeout
|
|
188
|
+
@store.refresh
|
|
189
|
+
|
|
190
|
+
update_filter_additem(@processfilter, @store.active_processes)
|
|
191
|
+
update_filter_additem(@userfilter, @store.active_users)
|
|
192
|
+
_on_filter_changed
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def _on_tableview_custom_context_menu_requested(position)
|
|
196
|
+
@lastindex = @tableview.index_at(position)
|
|
197
|
+
return unless @lastindex.valid?
|
|
198
|
+
|
|
199
|
+
menu = QMenu.new("", self)
|
|
200
|
+
menu.set_attribute(Qt::WA_DeleteOnClose)
|
|
201
|
+
|
|
202
|
+
pid = @lastindex.sibling_at_column(COLUMN_PROCESS_ID).data.value.to_s
|
|
203
|
+
remote_address = @lastindex.sibling_at_column(COLUMN_REMOTE_ADDRESS).data.value
|
|
204
|
+
remote_address = remote_address.contains(".") ? remote_address : "#{remote_address[0, 12]}..."
|
|
205
|
+
|
|
206
|
+
@endprocess_action.set_enabled(pid.to_i.nonzero?)
|
|
207
|
+
@whois_action.set_text("Whois #{remote_address} - via IPinfo")
|
|
208
|
+
@copy_action.set_text("Copy \"#{@lastindex.data.value}\"")
|
|
209
|
+
|
|
210
|
+
menu.add_action(@endprocess_action)
|
|
211
|
+
menu.add_separator
|
|
212
|
+
menu.add_action(@whois_action)
|
|
213
|
+
menu.add_action(@copy_action)
|
|
214
|
+
|
|
215
|
+
menu.exec(@tableview.viewport.map_to_global(position))
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def _on_endprocess_action_triggered
|
|
219
|
+
return unless @lastindex.valid?
|
|
220
|
+
|
|
221
|
+
pid = @lastindex.sibling_at_column(COLUMN_PROCESS_ID).data.value
|
|
222
|
+
QProcess.execute("kill", QStringList.new << "-9" << pid)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def _on_whois_action_triggered
|
|
226
|
+
return unless @lastindex.valid?
|
|
227
|
+
|
|
228
|
+
remote_address = @lastindex.sibling_at_column(COLUMN_REMOTE_ADDRESS).data.value
|
|
229
|
+
url = QUrl.new("https://ipinfo.io/#{remote_address}")
|
|
230
|
+
QDesktopServices.open_url(url)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def _on_copy_action_triggered
|
|
234
|
+
return unless @lastindex.valid?
|
|
235
|
+
|
|
236
|
+
text = @lastindex.data.value
|
|
237
|
+
QApplication.clipboard.set_text(text)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "components/connstableview"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class ConnsLookupService
|
|
2
|
+
def perform
|
|
3
|
+
conns = {}
|
|
4
|
+
ino2conn = {}
|
|
5
|
+
|
|
6
|
+
%w[tcp tcp6 udp udp6].each do |filename|
|
|
7
|
+
str = File.read("/proc/net/#{filename}")
|
|
8
|
+
sockets = Netmon::ProcNet.sockets_form_str(str)
|
|
9
|
+
sockets.each do |socket|
|
|
10
|
+
conn = Netmon::Connection.new(socket)
|
|
11
|
+
conn.protocol = conn_protocol(filename)
|
|
12
|
+
conns[conn.key] = conn
|
|
13
|
+
ino2conn[conn.inode] = conn
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Dir.glob("/proc/[1-9]*/fd/[1-9]*") do |dir|
|
|
18
|
+
ino = File.stat(dir).ino
|
|
19
|
+
conn = ino2conn[ino]
|
|
20
|
+
next if conn.nil?
|
|
21
|
+
|
|
22
|
+
conn.pid = dir.split("/")[2].to_i
|
|
23
|
+
conn.comm = File.read("/proc/#{conn.pid}/comm").strip
|
|
24
|
+
rescue Errno::EACCES, Errno::ENOENT
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
conns
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def conn_protocol(str)
|
|
33
|
+
case str
|
|
34
|
+
when "tcp"
|
|
35
|
+
Netmon::Connection::PROTOCOL_TCP4
|
|
36
|
+
when "tcp6"
|
|
37
|
+
Netmon::Connection::PROTOCOL_TCP6
|
|
38
|
+
when "udp"
|
|
39
|
+
Netmon::Connection::PROTOCOL_UDP4
|
|
40
|
+
when "udp6"
|
|
41
|
+
Netmon::Connection::PROTOCOL_UDP6
|
|
42
|
+
else
|
|
43
|
+
""
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "services/conns_lookup_service"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class MainWindow < RubyQt6::Bando::QMainWindow
|
|
2
|
+
q_object do
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
initialize_central_widget
|
|
9
|
+
initialize_statusbar
|
|
10
|
+
|
|
11
|
+
set_context_menu_policy(Qt::NoContextMenu)
|
|
12
|
+
NetmonQt.settings.GET_mainwindow_geometry_and_restore_to(self)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def close_event(evt)
|
|
16
|
+
NetmonQt.settings.PUT_mainwindow_geometry(self)
|
|
17
|
+
|
|
18
|
+
_close_event(evt)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def initialize_central_widget
|
|
24
|
+
@connstableview = ConnsTableView.new
|
|
25
|
+
|
|
26
|
+
centralwidget = QWidget.new
|
|
27
|
+
mainlayout = QHBoxLayout.new(centralwidget)
|
|
28
|
+
mainlayout.add_widget(@connstableview)
|
|
29
|
+
|
|
30
|
+
set_central_widget(centralwidget)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def initialize_statusbar
|
|
34
|
+
statusbar = QStatusBar.new
|
|
35
|
+
statusbar.set_contents_margins(12, 0, 12, 0)
|
|
36
|
+
statusbar.add_permanent_widget(@connstableview.statusbar, 1)
|
|
37
|
+
|
|
38
|
+
set_status_bar(statusbar)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "views/mainwindow"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require_relative "config"
|
|
2
|
+
require_relative "lib"
|
|
3
|
+
|
|
4
|
+
require_relative "app/components"
|
|
5
|
+
require_relative "app/services"
|
|
6
|
+
require_relative "app/views"
|
|
7
|
+
|
|
8
|
+
module NetmonQt
|
|
9
|
+
class Application
|
|
10
|
+
def self.run
|
|
11
|
+
new.exec
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@app = QApplication.new
|
|
16
|
+
@mainwindow = MainWindow.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def exec
|
|
20
|
+
Contrib::SigHandler.new(@app)
|
|
21
|
+
|
|
22
|
+
@mainwindow.show
|
|
23
|
+
@app.exec
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
QApplication.set_organization_name("souk4711")
|
|
2
|
+
QApplication.set_application_name("NetmonQt")
|
|
3
|
+
|
|
4
|
+
root_path = File.expand_path("../..", __dir__)
|
|
5
|
+
QDir.add_search_path("assets", File.join(root_path, "app/assets"))
|
|
6
|
+
|
|
7
|
+
icon = QIcon.new("assets:/app.svg")
|
|
8
|
+
QApplication.set_window_icon(icon)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module NetmonQt
|
|
2
|
+
class Settings
|
|
3
|
+
def GET_mainwindow_geometry_and_restore_to(mainwindow)
|
|
4
|
+
settings = QSettings.new
|
|
5
|
+
mainwindow.restore_geometry(settings.value("MainWindow/geometry", QByteArray.new("")))
|
|
6
|
+
mainwindow.restore_state(settings.value("MainWindow/windowState", QByteArray.new("")))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def PUT_mainwindow_geometry(mainwindow)
|
|
10
|
+
settings = QSettings.new
|
|
11
|
+
settings.set_value("MainWindow/geometry", mainwindow.save_geometry)
|
|
12
|
+
settings.set_value("MainWindow/windowState", mainwindow.save_state)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def GET_connections_check_interval
|
|
16
|
+
default_connections_check_interval
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def GET_geolite2_mmdb
|
|
20
|
+
default_geolite2_mmdb
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def default_connections_check_interval
|
|
26
|
+
4_000
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def default_geolite2_mmdb
|
|
30
|
+
"/usr/share/GeoIP/GeoLite2-Country.mmdb"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Contrib
|
|
2
|
+
class SigHandler < RubyQt6::Bando::QObject
|
|
3
|
+
q_object do
|
|
4
|
+
slot "_noop()"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def initialize(parent)
|
|
8
|
+
super
|
|
9
|
+
|
|
10
|
+
["INT", "TERM"].each do |sig|
|
|
11
|
+
Signal.trap(sig) { |_| QApplication.quit }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
timer = QTimer.new(self)
|
|
15
|
+
timer.timeout.connect(self, :_noop)
|
|
16
|
+
timer.start(1_000)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def _noop
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "contrib/sighandler"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Netmon
|
|
2
|
+
class Connection
|
|
3
|
+
# rubocop:disable Layout
|
|
4
|
+
PROTOCOL_TCP = "TCP"
|
|
5
|
+
PROTOCOL_UDP = "UDP"
|
|
6
|
+
PROTOCOL_TCP4 = "TCP v4"
|
|
7
|
+
PROTOCOL_TCP6 = "TCP v6"
|
|
8
|
+
PROTOCOL_UDP4 = "UDP v4"
|
|
9
|
+
PROTOCOL_UDP6 = "UDP v6"
|
|
10
|
+
|
|
11
|
+
STATE_ESTABLISHED = "ESTABLISHED"
|
|
12
|
+
STATE_LISTEN = "LISTEN"
|
|
13
|
+
STATE_SYN_SENT = "SYN_SENT"
|
|
14
|
+
STATE_SYN_RECV = "SYN_RECV"
|
|
15
|
+
STATE_FIN_WAIT1 = "FIN_WAIT1"
|
|
16
|
+
STATE_FIN_WAIT2 = "FIN_WAIT2"
|
|
17
|
+
STATE_CLOSING = "CLOSING"
|
|
18
|
+
STATE_CLOSE_WAIT = "CLOSE_WAIT"
|
|
19
|
+
STATE_LAST_ACK = "LAST_ACK"
|
|
20
|
+
STATE_TIME_WAIT = "TIME_WAIT"
|
|
21
|
+
STATE_CLOSE = "CLOSE"
|
|
22
|
+
|
|
23
|
+
COMM_DEFUNCT = "<defunct>"
|
|
24
|
+
COMM_UNKNOWN = "<unknown>"
|
|
25
|
+
# rubocop:enable Layout
|
|
26
|
+
|
|
27
|
+
attr_accessor :protocol
|
|
28
|
+
attr_accessor :local_address, :local_port
|
|
29
|
+
attr_accessor :remote_address, :remote_port
|
|
30
|
+
attr_accessor :state, :uid, :inode
|
|
31
|
+
attr_accessor :pid, :comm
|
|
32
|
+
|
|
33
|
+
def initialize(attrs)
|
|
34
|
+
attrs.each do |attr, value|
|
|
35
|
+
public_send("#{attr}=", value)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def key
|
|
40
|
+
"#{protocol}: #{local_address}:#{local_port} <=> #{remote_address}:#{remote_port}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def uname
|
|
44
|
+
Etc.getpwuid(uid).name
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def pid_text
|
|
48
|
+
return pid.to_s if pid
|
|
49
|
+
inode.zero? ? COMM_DEFUNCT : COMM_UNKNOWN
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def comm_text
|
|
53
|
+
return comm if comm
|
|
54
|
+
inode.zero? ? COMM_DEFUNCT : COMM_UNKNOWN
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "ipaddr"
|
|
2
|
+
|
|
3
|
+
module Netmon
|
|
4
|
+
CIDR_LIST = [
|
|
5
|
+
IPAddr.new("224.0.0.0/24"), # Local Multicast - IPv4
|
|
6
|
+
IPAddr.new("ff02::/16"), # Local Multicast - IPv6
|
|
7
|
+
IPAddr.new("0.0.0.0"), # Unspecified - IPv4
|
|
8
|
+
IPAddr.new("::") # Unspecified - IPv6
|
|
9
|
+
].freeze
|
|
10
|
+
|
|
11
|
+
def self.local_address?(address)
|
|
12
|
+
ip = IPAddr.new(address)
|
|
13
|
+
return true if ip.link_local?
|
|
14
|
+
return true if ip.loopback?
|
|
15
|
+
return true if ip.private?
|
|
16
|
+
return true if CIDR_LIST.any? { |cidr| cidr.include?(address) }
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Netmon
|
|
2
|
+
module ProcNet
|
|
3
|
+
TCP_STATE = {
|
|
4
|
+
"01" => Connection::STATE_ESTABLISHED,
|
|
5
|
+
"02" => Connection::STATE_SYN_SENT,
|
|
6
|
+
"03" => Connection::STATE_SYN_RECV,
|
|
7
|
+
"04" => Connection::STATE_FIN_WAIT1,
|
|
8
|
+
"05" => Connection::STATE_FIN_WAIT2,
|
|
9
|
+
"06" => Connection::STATE_TIME_WAIT,
|
|
10
|
+
"07" => Connection::STATE_CLOSE,
|
|
11
|
+
"08" => Connection::STATE_CLOSE_WAIT,
|
|
12
|
+
"09" => Connection::STATE_LAST_ACK,
|
|
13
|
+
"0A" => Connection::STATE_LISTEN,
|
|
14
|
+
"0B" => Connection::STATE_CLOSING
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
def self.sockets_form_str(str)
|
|
18
|
+
str.lines[1..].map do |line|
|
|
19
|
+
linesplit = line.split
|
|
20
|
+
local_address, local_port = linesplit[1].split(":")
|
|
21
|
+
remote_address, remote_port = linesplit[2].split(":")
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
local_address: format_address(local_address),
|
|
25
|
+
local_port: format_port(local_port),
|
|
26
|
+
remote_address: format_address(remote_address),
|
|
27
|
+
remote_port: format_port(remote_port),
|
|
28
|
+
state: TCP_STATE[linesplit[3]],
|
|
29
|
+
uid: linesplit[7].to_i,
|
|
30
|
+
inode: linesplit[9].to_i
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.format_address(str)
|
|
36
|
+
case str.size
|
|
37
|
+
when 8 then str.scan(/.{2}/).reverse.map { |s| s.to_i(16) }.join(".")
|
|
38
|
+
when 32 then str.scan(/.{8}/).map { |s| s.scan(/.{2}/).reverse }.join.scan(/.{4}/).join(":")
|
|
39
|
+
else raise "Invalid address str: #{str}"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
private_class_method :format_address
|
|
43
|
+
|
|
44
|
+
def self.format_port(str)
|
|
45
|
+
str.to_i(16)
|
|
46
|
+
end
|
|
47
|
+
private_class_method :format_port
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/netmon-qt.rb
ADDED
|
Binary file
|