package main import ( "fmt" "io" "log" "net" "sync" "time" ) const ( notice = "ownme.ipredator.se:80" web = "ownme.ipredator.se:443" server = "ownme.ipredator.se:10000" client = "ownme.ipredator.se:10001" // will callback to port 40001 clientRev = "ownme.ipredator.se:10002" ) type Direction string const ( ServerClient Direction = "Server → Client" ClientServer Direction = "Client → Server" ) type Data struct { Round int Dir Direction Data []byte Size int RTime time.Duration WTime time.Duration } func dump(dir Direction, src, dst net.Conn, data chan<- Data) error { buf := make([]byte, 1) for k := 1; ; k++ { now := time.Now() n, err := src.Read(buf) rtime := time.Since(now) if err != nil { if err == io.EOF { return nil } return fmt.Errorf("READ %v", err) } time.Sleep(200 * time.Millisecond) now = time.Now() _, err = dst.Write(buf[:n]) wtime := time.Since(now) if err != nil { return fmt.Errorf("WRITE %v", err) } data <- Data{Round: k, Dir: dir, Data: buf[:n], Size: n, RTime: rtime, WTime: wtime} } } func main() { var wg sync.WaitGroup srv, err := net.Dial("tcp", server) if err != nil { log.Fatal(err) } defer srv.Close() cnt, err := net.Dial("tcp", clientRev) if err != nil { log.Fatal(err) } defer cnt.Close() data := make(chan Data, 1) wg.Add(2) go func() { wg.Wait() close(data) }() go func(dir Direction) { if err := dump(dir, srv, cnt, data); err != nil { fmt.Println("ERROR", dir, err) } wg.Done() }(ServerClient) go func(dir Direction) { if err := dump(dir, cnt, srv, data); err != nil { fmt.Println("ERROR", dir, err) } wg.Done() }(ClientServer) for d := range data { fmt.Println("#", d.Round, d.Dir, d.Size, "bytes", "Read", d.RTime, "Write", d.WTime, d.Data) //fmt.Println(hex.Dump(d.Data)) } }