Skip to content

Commit

Permalink
HW11 is completed
Browse files Browse the repository at this point in the history
Signed-off-by: Pavel Pogodaev <[email protected]>
  • Loading branch information
Pavel Pogodaev committed Nov 19, 2024
1 parent 411b524 commit 878312f
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 6 deletions.
Empty file removed hw11_telnet_client/.sync
Empty file.
94 changes: 92 additions & 2 deletions hw11_telnet_client/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,96 @@
package main

import (
"bufio"
"bytes"
"context"
"flag"
"fmt"
"io"
"os"
"os/signal"
"sync"
"syscall"
"time"
)

func main() {
// Place your code here,
// P.S. Do not rush to throw context down, think think if it is useful with blocking operation?
flag.Parse()
port := os.Args[len(os.Args)-1]
host := os.Args[len(os.Args)-2]
duration := os.Args[len(os.Args)-3]

durVal, err := time.ParseDuration(duration)
if err != nil {
panic("wrong duration value " + duration)
}

in := &bytes.Buffer{}

ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT, os.Interrupt)
defer stop()

client := NewTelnetClient(host+":"+port, durVal, io.NopCloser(in), os.Stdout)
defer client.Close()

err = client.Connect()
if err != nil {
fmt.Printf("connection failed: %s\n", err)
return
}

var wg sync.WaitGroup

wg.Add(2)
go sendByTcp(ctx, stop, &wg, in, client)
go connectionHandler(ctx, &wg, client)

wg.Wait()
}

func sendByTcp(ctx context.Context, stop context.CancelFunc, wg *sync.WaitGroup, in *bytes.Buffer, t TelnetClient) {

Check warning on line 51 in hw11_telnet_client/main.go

View workflow job for this annotation

GitHub Actions / lint

var-naming: func sendByTcp should be sendByTCP (revive)
go func() {
<-ctx.Done()
err := t.Close()
if err != nil {
fmt.Printf("failed to colse connection %s", err)
}
wg.Done()
}()

reader := bufio.NewReader(os.Stdin)
for {
resp, err := reader.ReadString('\n')
if err != nil {
stop()
return
}

in.WriteString(resp)
err = t.Send()
if err != nil {
fmt.Println(err)
return
}
}
}

func connectionHandler(ctx context.Context, wg *sync.WaitGroup, t TelnetClient) {
errCh := make(chan error)
defer func() {
wg.Done()
}()

for {
select {
case <-ctx.Done():
return
case errCh <- t.Receive():
err := <-errCh
if err != nil {
fmt.Println(err)
return
}
}
}
}
63 changes: 60 additions & 3 deletions hw11_telnet_client/telnet.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package main

import (
"errors"
"fmt"
"io"
"net"
"time"
)

Expand All @@ -12,10 +15,64 @@ type TelnetClient interface {
Receive() error
}

type ConnectionParams struct {
Address string
Timeout time.Duration
In io.ReadCloser
Out io.Writer
Conn net.Conn
}

func NewTelnetClient(address string, timeout time.Duration, in io.ReadCloser, out io.Writer) TelnetClient {
// Place your code here.
return &ConnectionParams{
Address: address,
Timeout: timeout,
In: in,
Out: out,
}
}

func (c *ConnectionParams) Connect() error {
conn, err := net.DialTimeout("tcp", c.Address, c.Timeout)
if err != nil {
return fmt.Errorf("connection error: %w", err)
}

c.Conn = conn
fmt.Println("connected to ", c.Address)

return nil
}

// Place your code here.
// P.S. Author's solution takes no more than 50 lines.
func (c *ConnectionParams) Close() error {
if c.Conn != nil {
if err := c.Conn.Close(); err != nil {
return fmt.Errorf("close error: %w", err)
}
}

return nil
}

func (c *ConnectionParams) Send() error {
size, err := io.Copy(c.Conn, c.In)
if err != nil {
return fmt.Errorf("send error: %w", err)
}
fmt.Printf("sent %d bytes", size)
fmt.Println()

return nil
}

func (c *ConnectionParams) Receive() error {
_, err := io.Copy(c.Out, c.Conn)
if err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return fmt.Errorf("receive error: %w", err)
}

return nil
}
2 changes: 1 addition & 1 deletion hw11_telnet_client/telnet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require" //nolint:depguard
)

func TestTelnetClient(t *testing.T) {
Expand Down

0 comments on commit 878312f

Please sign in to comment.