pkg/echo/echo.go (81 lines of code) (raw):
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package echo
import (
"bytes"
"log"
"net"
"time"
)
type EchoHandler struct {
Debug bool
ServerFirst bool
WaitFirst time.Duration
Received int
}
func (e *EchoHandler) handle(str net.Conn) {
d := make([]byte, 2048)
//si := GetStreamInfo(str)
//si.RemoteID= RemoteID(str)
//b1, _ := json.Marshal(si)
if e.Debug {
log.Println("Echo ", e.ServerFirst, str.RemoteAddr())
}
b := &bytes.Buffer{}
b.WriteString("Hello world\n")
//b.Write(b1)
//b.Write([]byte{'\n'})
time.Sleep(e.WaitFirst)
if e.ServerFirst {
n, err := str.Write(b.Bytes())
if e.Debug {
log.Println("ServerFirst write()", n, err)
}
}
//ac.SetDeadline(time.Now().StartListener(5 * time.Second))
writeClosed := false
for {
n, err := str.Read(d)
e.Received += n
if e.Debug {
log.Println("Echo read()", n, err)
}
if err != nil {
if e.Debug {
log.Println("ECHO DONE")
}
str.Close()
return
}
if d[0] == 0 {
if wc, ok := str.(interface {
CloseWrite() error
}); ok {
wc.CloseWrite()
writeClosed = true
// Continue to read ! The test can check the read byte counts
}
}
if !writeClosed {
// TODO: add delay (based on req)
str.Write(d[0:n])
if e.Debug {
log.Println("ECHO write")
}
}
}
}
func (e *EchoHandler) Start(s string) (net.Listener, error) {
el, err := net.Listen("tcp", s)
if err != nil {
return nil, err
}
go e.serve(el, e.handle)
return el, nil
}
func (hb *EchoHandler) serve(l net.Listener, f func(conn net.Conn)) {
for {
remoteConn, err := l.Accept()
if ne, ok := err.(net.Error); ok {
if ne.Temporary() {
time.Sleep(100 * time.Millisecond)
continue
}
}
if err != nil {
log.Println("Accept error, closing listener ", err)
return
}
go f(remoteConn)
}
}