Prechádzať zdrojové kódy

Updated so Windows passes tests without errors.

We were getting a Write error because we were writing before the
close was detected.
Steve Thielemann 3 rokov pred
rodič
commit
14136f337a

+ 1 - 1
door/door_linux.go

@@ -9,5 +9,5 @@ func (d *Door) setupChannels() {
 		d.wg.Add(1)
 	}
 	go Reader(d.Config.Comm_handle, d)
-	go Writer(d.Config.Comm_handle, d)
+	go Writer(d)
 }

+ 7 - 4
door/door_windows.go

@@ -1,8 +1,11 @@
 package door
 
-import "syscall"
-
 func (d *Door) setupChannels() {
-	go Reader(syscall.Handle(d.Config.Comm_handle), &d.readerChannel)
-	go Writer(syscall.Handle(d.Config.Comm_handle), &d.writerChannel)
+	if d.ReaderCanClose {
+		d.wg.Add(2)
+	} else {
+		d.wg.Add(1)
+	}
+	go Reader(d)
+	go Writer(d)
 }

+ 5 - 0
door/help_windows_test.go

@@ -13,3 +13,8 @@ func socket_to_fd(socket net.Conn) int {
 	})
 	return fd
 }
+
+// nothing to close in Windows
+func close_fd(fd int) {
+
+}

+ 28 - 5
door/input_windows.go

@@ -2,10 +2,21 @@ package door
 
 import (
 	"log"
+	"sync/atomic"
 	"syscall"
 )
 
-func Reader(handle syscall.Handle, readerChannel *chan byte) {
+func Reader(d *Door) {
+	// handle syscall.Handle, readerChannel *chan byte
+	var handle syscall.Handle = syscall.Handle(d.Config.Comm_handle)
+
+	defer func() {
+		log.Printf("~Reader")
+		if d.ReaderCanClose {
+			d.wg.Done()
+		}
+	}()
+
 	defer func() {
 		if err := recover(); err != nil {
 			log.Printf("Reader: %#v\n", err)
@@ -21,16 +32,28 @@ func Reader(handle syscall.Handle, readerChannel *chan byte) {
 		err := syscall.WSARecv(handle, &WSA_Buffer, 1, &read, &flags, nil, nil)
 		if err != nil {
 			log.Printf("Reader ERR: %#v\n", err)
-			close(*readerChannel)
+			close(d.readerChannel)
+			if !d.Disconnect() {
+				log.Println("Reader close writerChannel")
+				atomic.StoreInt32(&d.Disconnected, 1)
+				d.closeChannel <- true
+				return
+			}
 			break
 		}
 
 		if read == 1 {
-			*readerChannel <- buffer[0]
+			d.readerChannel <- buffer[0]
 		} else {
 			log.Printf("READ FAILED %d\n", read)
-			close(*readerChannel)
-			break
+			close(d.readerChannel)
+			if !d.Disconnect() {
+				log.Println("Reader close writerChannel")
+				atomic.StoreInt32(&d.Disconnected, 1)
+				d.closeChannel <- true
+				return
+			}
+			return
 		}
 	}
 }

+ 1 - 1
door/menu_test.go

@@ -331,6 +331,6 @@ func TestMenuConnection(t *testing.T) {
 	// output = string(buffer[:r])
 	server.Close()
 	client.Close()
-	d.Write("\x00")
+	// d.Write("\x00")
 	time.Sleep(time.Millisecond)
 }

+ 3 - 2
door/write_linux.go

@@ -9,8 +9,9 @@ import (
 
 // https://go101.org/article/channel-closing.html
 
-func Writer(handle int, d *Door) {
-	log.Println("Writer2")
+func Writer(d *Door) {
+	var handle int = d.Config.Comm_handle
+	log.Println("Writer")
 	defer d.wg.Done()
 	for {
 		select {

+ 76 - 13
door/write_windows.go

@@ -2,24 +2,87 @@ package door
 
 import (
 	"fmt"
+	"log"
+	"strings"
+	"sync/atomic"
 	"syscall"
 )
 
-func Writer(handle syscall.Handle, writerChannel *chan string) {
-	for output := range *writerChannel {
-		l := uint32(len(output))
-		buffer := []byte(output)
-		WSA_Buffer := syscall.WSABuf{Len: uint32(l), Buf: &buffer[0]}
-		UitnZero_1 := uint32(0)
-		DataWrite := uint32(0)
-		err := syscall.WSASend(handle, &WSA_Buffer, 1, &DataWrite, UitnZero_1, nil, nil)
-		if err != nil {
-			fmt.Printf("write: %d bytes, error: %#v\n", DataWrite, err)
+func Writer(d *Door) {
+	var handle syscall.Handle = syscall.Handle(d.Config.Comm_handle)
+	// handle syscall.Handle, writerChannel *chan string
+	log.Println("Writer")
+	defer d.wg.Done()
+
+	for {
+		select {
+		case <-d.closeChannel:
+			close(d.writerChannel)
+			log.Println("~Writer")
+			return
+		default:
 		}
 
-		if (err != nil) || (l != DataWrite) {
-			close(*writerChannel)
-			break
+		select {
+		case <-d.closeChannel:
+			close(d.writerChannel)
+			log.Println("~Writer")
+			return
+		case output, ok := <-d.writerChannel:
+			if !ok {
+				log.Println("closeChannel")
+				if !d.Disconnect() {
+					atomic.StoreInt32(&d.Disconnected, 1)
+				}
+				log.Println("~Writer")
+				return
+			} else {
+				if strings.HasSuffix(output, RestorePos) {
+					output += Color(d.LastColor...)
+				} else {
+					d.UpdateLastColor(output, &d.LastColor)
+				}
+
+				l := uint32(len(output))
+				buffer := []byte(output)
+				WSA_Buffer := syscall.WSABuf{Len: uint32(l), Buf: &buffer[0]}
+
+				UitnZero_1 := uint32(0)
+				DataWrite := uint32(0)
+				err := syscall.WSASend(handle, &WSA_Buffer, 1, &DataWrite, UitnZero_1, nil, nil)
+				if err != nil {
+					fmt.Printf("write: %d bytes, error: %#v\n", DataWrite, err)
+				}
+
+				if (err != nil) || (l != DataWrite) {
+					log.Println("CloseChannel")
+					if !d.Disconnect() {
+						atomic.StoreInt32(&d.Disconnected, 1)
+						close(d.writerChannel)
+					}
+					log.Println("~Writer")
+					return
+				}
+			}
 		}
 	}
+
+	/*
+		for output := range *writerChannel {
+			l := uint32(len(output))
+			buffer := []byte(output)
+			WSA_Buffer := syscall.WSABuf{Len: uint32(l), Buf: &buffer[0]}
+			UitnZero_1 := uint32(0)
+			DataWrite := uint32(0)
+			err := syscall.WSASend(handle, &WSA_Buffer, 1, &DataWrite, UitnZero_1, nil, nil)
+			if err != nil {
+				fmt.Printf("write: %d bytes, error: %#v\n", DataWrite, err)
+			}
+
+			if (err != nil) || (l != DataWrite) {
+				close(*writerChannel)
+				break
+			}
+		}
+	*/
 }