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_MESSAGE
MY_SIGNAL_CONNECT
MY_SIGNAL_CLOSE
)
const (

View File

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

View File

@ -1,26 +1,46 @@
package tui
import (
"context"
"io"
"net"
"sync"
"time"
"git.qowevisa.me/Qowevisa/gotell/errors"
)
// 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 {
t.errors <- errors.WrapErr("t.messageChannel", errors.NOT_INIT)
return
}
buf := make([]byte, CONST_MESSAGE_LEN)
for {
select {
case <-ctx.Done(): // Check if context cancellation has been requested
return
default:
timeoutDuration := 5 * time.Second
err := t.tlsConnection.SetReadDeadline(time.Now().Add(timeoutDuration))
if err != nil {
t.errors <- errors.WrapErr("SetReadDeadline", err)
return
}
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)
}
break
return
}
t.messageChannel <- buf[:n]
}
}
}

View File

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

View File

@ -138,6 +138,15 @@ func (t *TUI) Run() error {
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,
}
case 'c':
if t.isConnected {
t.mySignals <- mySignal{
Type: MY_SIGNAL_CLOSE,
}
} else {
t.mySignals <- mySignal{
Type: MY_SIGNAL_CONNECT,
}
readInputMu.Lock()
readInput = true
readInputMu.Unlock()
}
case 'm':
t.mySignals <- mySignal{
Type: MY_SIGNAL_MESSAGE,