From 855ec85dbc40c226db0b4888e5a004929e9f6ffa Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Fri, 16 May 2014 11:33:35 +0900 Subject: [PATCH] implement net_io_counters on Windows. --- common.go | 24 ++++++++++++++++++++++ common_windows.go | 11 ++++++++++ net_windows.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/common.go b/common.go index 9130303..4f05543 100644 --- a/common.go +++ b/common.go @@ -9,6 +9,7 @@ package gopsutil import ( "bufio" "os" + "reflect" "strconv" "strings" ) @@ -77,3 +78,26 @@ func stringContains(target []string, src string) bool { } return false } + +// get struct attributes. +// This method is used only for debugging platform dependent code. +func attributes(m interface{}) map[string]reflect.Type { + typ := reflect.TypeOf(m) + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + + attrs := make(map[string]reflect.Type) + if typ.Kind() != reflect.Struct { + return nil + } + + for i := 0; i < typ.NumField(); i++ { + p := typ.Field(i) + if !p.Anonymous { + attrs[p.Name] = p.Type + } + } + + return attrs +} diff --git a/common_windows.go b/common_windows.go index 04fea1d..e84abc3 100644 --- a/common_windows.go +++ b/common_windows.go @@ -4,6 +4,7 @@ package gopsutil import ( "syscall" + "unsafe" ) var ( @@ -18,3 +19,13 @@ type FILETIME struct { DwLowDateTime uint32 DwHighDateTime uint32 } + +// borrowed from net/interface_windows.go +func bytePtrToString(p *uint8) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} diff --git a/net_windows.go b/net_windows.go index 329b544..c32f956 100644 --- a/net_windows.go +++ b/net_windows.go @@ -3,9 +3,65 @@ package gopsutil import ( - "errors" + "net" + "os" + "syscall" + "unsafe" ) func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { - return nil, errors.New("not implemented yet") + ifs, err := net.Interfaces() + if err != nil { + return nil, err + } + + ai, err := getAdapterList() + if err != nil { + return nil, err + } + var ret []NetIOCountersStat + + for _, ifi := range ifs { + name := ifi.Name + for ; ai != nil; ai = ai.Next { + name = bytePtrToString(&ai.Description[0]) + c := NetIOCountersStat{ + Name: name, + } + + row := syscall.MibIfRow{Index: ai.Index} + e := syscall.GetIfEntry(&row) + if e != nil { + return nil, os.NewSyscallError("GetIfEntry", e) + } + c.BytesSent = uint64(row.OutOctets) + c.BytesRecv = uint64(row.InOctets) + c.PacketsSent = uint64(row.OutUcastPkts) + c.PacketsRecv = uint64(row.InUcastPkts) + c.Errin = uint64(row.InErrors) + c.Errout = uint64(row.OutErrors) + c.Dropin = uint64(row.InDiscards) + c.Dropout = uint64(row.OutDiscards) + + ret = append(ret, c) + } + } + return ret, nil +} + +// borrowed from src/pkg/net/interface_windows.go +func getAdapterList() (*syscall.IpAdapterInfo, error) { + b := make([]byte, 1000) + l := uint32(len(b)) + a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0])) + err := syscall.GetAdaptersInfo(a, &l) + if err == syscall.ERROR_BUFFER_OVERFLOW { + b = make([]byte, l) + a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0])) + err = syscall.GetAdaptersInfo(a, &l) + } + if err != nil { + return nil, os.NewSyscallError("GetAdaptersInfo", err) + } + return a, nil }