Create connection closing without fails

This commit is contained in:
qowevisa 2024-03-14 02:18:51 +02:00
parent d4a1792087
commit 14888b4fce
5 changed files with 70 additions and 14 deletions

View File

@ -4,6 +4,7 @@ const (
MY_SIGNAL_EXIT = iota MY_SIGNAL_EXIT = iota
MY_SIGNAL_MESSAGE MY_SIGNAL_MESSAGE
MY_SIGNAL_CONNECT MY_SIGNAL_CONNECT
MY_SIGNAL_CLOSE
) )
const ( const (

View File

@ -1,12 +1,14 @@
package tui package tui
import ( import (
"context"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"log" "log"
"os" "os"
"strconv" "strconv"
"sync"
"git.qowevisa.me/Qowevisa/gotell/env" "git.qowevisa.me/Qowevisa/gotell/env"
"git.qowevisa.me/Qowevisa/gotell/errors" "git.qowevisa.me/Qowevisa/gotell/errors"
@ -74,17 +76,28 @@ func FE_ConnectTLS(t *TUI, data dataT) error {
if err != nil { if err != nil {
return errors.WrapErr("tls.Dial", err) return errors.WrapErr("tls.Dial", err)
} }
// log.Printf("Set connection to %#v\n", conn)
t.tlsConnection = conn t.tlsConnection = conn
if t.stateChannel == nil { if t.stateChannel == nil {
return errors.WrapErr("t.stateChannel", errors.NOT_INIT) return errors.WrapErr("t.stateChannel", errors.NOT_INIT)
} }
t.stateChannel <- "TLS Connected" t.stateChannel <- "TLS Connected"
t.isConnected = true t.isConnected = true
go t.launchReadingMessagesFromConnection() ctx, cancel := context.WithCancel(context.Background())
wg := &sync.WaitGroup{}
wg.Add(1)
t.tlsConnCloseData = closeData{
wg: wg,
cancel: cancel,
}
go t.launchReadingMessagesFromConnection(ctx, wg)
return nil return nil
} }
func CloseConnection(wg *sync.WaitGroup, cancel context.CancelFunc) {
cancel()
wg.Wait()
}
func AddToStorageEasy(key string, val *[]rune) (dataProcessHandler, dataT) { func AddToStorageEasy(key string, val *[]rune) (dataProcessHandler, dataT) {
// that's why I create wrapper around it. // that's why I create wrapper around it.
// try to understand that, dear viewer! // try to understand that, dear viewer!

View File

@ -1,26 +1,46 @@
package tui package tui
import ( import (
"context"
"io" "io"
"net"
"sync"
"time"
"git.qowevisa.me/Qowevisa/gotell/errors" "git.qowevisa.me/Qowevisa/gotell/errors"
) )
// NOTE: should be launched as goroutine // NOTE: should be launched as goroutine
func (t *TUI) launchReadingMessagesFromConnection() { func (t *TUI) launchReadingMessagesFromConnection(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done() // Mark this goroutine as done when it exits
if t.messageChannel == nil { if t.messageChannel == nil {
t.errors <- errors.WrapErr("t.messageChannel", errors.NOT_INIT) t.errors <- errors.WrapErr("t.messageChannel", errors.NOT_INIT)
return return
} }
buf := make([]byte, CONST_MESSAGE_LEN) buf := make([]byte, CONST_MESSAGE_LEN)
for { for {
n, err := t.tlsConnection.Read(buf) select {
if err != nil { case <-ctx.Done(): // Check if context cancellation has been requested
if err != io.EOF { return
t.errors <- errors.WrapErr("t.tlsConnection.Read", err) default:
timeoutDuration := 5 * time.Second
err := t.tlsConnection.SetReadDeadline(time.Now().Add(timeoutDuration))
if err != nil {
t.errors <- errors.WrapErr("SetReadDeadline", err)
return
} }
break n, err := t.tlsConnection.Read(buf)
if err != nil {
if err != io.EOF {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
continue
}
t.errors <- errors.WrapErr("t.tlsConnection.Read", err)
}
return
}
t.messageChannel <- buf[:n]
} }
t.messageChannel <- buf[:n]
} }
} }

View File

@ -2,6 +2,7 @@ package tui
import ( import (
"bufio" "bufio"
"context"
"crypto/tls" "crypto/tls"
"os" "os"
"sync" "sync"
@ -83,6 +84,11 @@ type widgetConfig struct {
FinaleData dataT FinaleData dataT
} }
type closeData struct {
wg *sync.WaitGroup
cancel context.CancelFunc
}
type TUI struct { type TUI struct {
width int width int
height int height int
@ -108,4 +114,5 @@ type TUI struct {
selectedNotifier *notifier selectedNotifier *notifier
storage map[string]string storage map[string]string
tlsConnection *tls.Conn tlsConnection *tls.Conn
tlsConnCloseData closeData
} }

View File

@ -138,6 +138,15 @@ func (t *TUI) Run() error {
t.errors <- errors.WrapErr("t.drawSelectedWidget", err) t.errors <- errors.WrapErr("t.drawSelectedWidget", err)
} }
} }
case MY_SIGNAL_CLOSE:
if t.isConnected {
CloseConnection(t.tlsConnCloseData.wg, t.tlsConnCloseData.cancel)
t.isConnected = false
t.errors <- t.tlsConnection.Close()
t.stateChannel <- "Disconnected"
}
default:
} }
} }
// //
@ -239,12 +248,18 @@ func (t *TUI) setRoutines() error {
Type: MY_SIGNAL_EXIT, Type: MY_SIGNAL_EXIT,
} }
case 'c': case 'c':
t.mySignals <- mySignal{ if t.isConnected {
Type: MY_SIGNAL_CONNECT, t.mySignals <- mySignal{
Type: MY_SIGNAL_CLOSE,
}
} else {
t.mySignals <- mySignal{
Type: MY_SIGNAL_CONNECT,
}
readInputMu.Lock()
readInput = true
readInputMu.Unlock()
} }
readInputMu.Lock()
readInput = true
readInputMu.Unlock()
case 'm': case 'm':
t.mySignals <- mySignal{ t.mySignals <- mySignal{
Type: MY_SIGNAL_MESSAGE, Type: MY_SIGNAL_MESSAGE,