diff --git a/lpr_daemon.go b/lpr_daemon.go index d0edc5a..7aabb89 100644 --- a/lpr_daemon.go +++ b/lpr_daemon.go @@ -1,7 +1,6 @@ package lprlib import ( - "context" "errors" "fmt" "io" @@ -33,10 +32,6 @@ type QueueState func(queue string, list string, long bool) string type ExternalIDCallbackFunc func() uint64 -func init() { - rand.Seed(time.Now().UnixMicro()) -} - // LprDaemon structure type LprDaemon struct { finishedConns chan *LprConnection @@ -287,10 +282,6 @@ type LprConnection struct { // SaveName The File name of the new file SaveName string - // ctx is the lpr daemon's context. - // The connection must be closed once the context is canceled. - ctx context.Context - // daemon contains a reference to the LprDaemon daemon *LprDaemon @@ -376,16 +367,27 @@ func (lpr *LprConnection) RunConnection() { } defer traceFile.Close() logDebugf("Created trace file %s", traceFile.Name()) - traceFile.WriteString(fmt.Sprintf("LPR connection trace %s\n", time.Now())) + + _, err = fmt.Fprintf(traceFile, "LPR connection trace %s\n", time.Now()) + if err != nil { + logErrorf("failed to write to trace file %s: %v", traceFile.Name(), err) + } } for lpr.Status != Error && lpr.Status != End { command, err := lpr.ReadCommand() if traceFile != nil { - traceFile.WriteString(fmt.Sprintf("received message %d:\n", len(command))) + _, traceErr := fmt.Fprintf(traceFile, "received message %d:\n", len(command)) + if traceErr != nil { + logErrorf("failed to write to trace file %s: %v", traceFile.Name(), traceErr) + } + if err != nil { - traceFile.WriteString(fmt.Sprintf("error: %v\n", err)) + _, traceErr = fmt.Fprintf(traceFile, "error: %v\n", err) + if traceErr != nil { + logErrorf("failed to write to trace file %s: %v", traceFile.Name(), traceErr) + } } else { traceFile.WriteString("-----\n") traceFile.Write(command) diff --git a/lpr_daemon_test.go b/lpr_daemon_test.go index e70b838..01eee5f 100644 --- a/lpr_daemon_test.go +++ b/lpr_daemon_test.go @@ -156,7 +156,7 @@ func TestDaemonLargeFileConnection(t *testing.T) { conn := <-lprd.FinishedConnections() - out, err = ioutil.ReadFile(conn.SaveName) + out, err = os.ReadFile(conn.SaveName) if err != nil { t.Error(err) } else { @@ -243,7 +243,7 @@ func TestDaemonMultipleConnection(t *testing.T) { i := 0 for conn := range lprd.FinishedConnections() { - out, err = ioutil.ReadFile(conn.SaveName) + out, err = os.ReadFile(conn.SaveName) if err != nil { t.Error(err) } else { @@ -288,7 +288,7 @@ func generateTempFile(dir, prefix, text string) (string, error) { var err error var file *os.File - file, err = ioutil.TempFile(dir, prefix) + file, err = os.CreateTemp(dir, prefix) if err != nil { return "", err } @@ -413,6 +413,9 @@ func TestDaemonClose(t *testing.T) { conn := <-lprd.FinishedConnections() require.Equal(t, End, conn.Status) + err = os.Remove(conn.SaveName) + require.Nil(t, err) + // no new connection may be opened lprs = LprSend{} err = lprs.Init("127.0.0.1", name, port, "raw", "TestUser", time.Minute) @@ -457,7 +460,7 @@ func TestDaemonFileSize(t *testing.T) { con := <-lprd.FinishedConnections() require.Equal(t, End, con.Status) - out, err = ioutil.ReadFile(con.SaveName) + out, err = os.ReadFile(con.SaveName) require.Nil(t, err) err = os.Remove(con.SaveName) require.Nil(t, err) @@ -501,7 +504,7 @@ func TestDaemonFileSize(t *testing.T) { con = <-lprd.FinishedConnections() require.Equal(t, End, con.Status) - out, err = ioutil.ReadFile(con.SaveName) + out, err = os.ReadFile(con.SaveName) require.Nil(t, err) err = os.Remove(con.SaveName) require.Nil(t, err) diff --git a/lpr_status.go b/lpr_status.go index d8f9a27..3a3eeaf 100644 --- a/lpr_status.go +++ b/lpr_status.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "net" - "strings" "time" ) @@ -99,7 +98,10 @@ func GetStatus(hostname string, port uint16, queue string, long bool, timeout ti opErr := &net.OpError{} if errors.As(err, &opErr) { - if strings.Contains(opErr.Error(), "connection was forcibly closed by the remote host") || strings.Contains(opErr.Error(), "connection reset by peer") { + // Check for connection reset errors at the syscall level + // This works cross-platform: ECONNRESET on Unix-like systems, + // WSAECONNRESET on Windows + if isConnResetErr(opErr) { logDebugf("Ignoring forceful connection closure by server") break } diff --git a/lpr_status_other.go b/lpr_status_other.go new file mode 100644 index 0000000..391a8f9 --- /dev/null +++ b/lpr_status_other.go @@ -0,0 +1,14 @@ +//go:build !windows +// +build !windows + +package lprlib + +import ( + "errors" + "net" + "syscall" +) + +func isConnResetErr(err *net.OpError) bool { + return errors.Is(err.Err, syscall.ECONNRESET) +} diff --git a/lpr_status_windows.go b/lpr_status_windows.go new file mode 100644 index 0000000..40b5b79 --- /dev/null +++ b/lpr_status_windows.go @@ -0,0 +1,11 @@ +package lprlib + +import ( + "errors" + "net" + "syscall" +) + +func isConnResetErr(err *net.OpError) bool { + return errors.Is(err.Err, syscall.ECONNRESET) || errors.Is(err.Err, syscall.WSAECONNRESET) +}