minTransactionLen = 22 // minimum length of any transaction
)
+// dontPanic recovers and logs panics instead of crashing
+// TODO: remove this after known issues are fixed
+func dontPanic(logger *zap.SugaredLogger) {
+ if r := recover(); r != nil {
+ fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
+ logger.Errorw("PANIC", "err", r, "trace", string(debug.Stack()))
+ }
+}
+
// handleNewConnection takes a new net.Conn and performs the initial login sequence
func (s *Server) handleNewConnection(conn net.Conn) error {
- handshakeBuf := make([]byte, 12) // handshakes are always 12 bytes in length
- if _, err := conn.Read(handshakeBuf); err != nil {
+ defer dontPanic(s.Logger)
+
+ handshakeBuf := make([]byte, 12)
+ if _, err := io.ReadFull(conn, handshakeBuf); err != nil {
return err
}
- if err := Handshake(conn, handshakeBuf[:12]); err != nil {
+ if err := Handshake(conn, handshakeBuf); err != nil {
return err
}
buf := make([]byte, 1024)
+ // TODO: fix potential short read with io.ReadFull
readLen, err := conn.Read(buf)
if readLen < minTransactionLen {
return err
c := s.NewClientConn(conn)
defer c.Disconnect()
- defer func() {
- if r := recover(); r != nil {
- fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
- c.Server.Logger.Errorw("PANIC", "err", r, "trace", string(debug.Stack()))
- c.Disconnect()
- }
- }()
encodedLogin := clientLogin.GetField(fieldUserLogin).Data
encodedPassword := clientLogin.GetField(fieldUserPassword).Data
}
}()
- defer func() {
- if r := recover(); r != nil {
- fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
- s.Logger.Errorw("PANIC", "err", r, "trace", string(debug.Stack()))
- }
- }()
+ defer dontPanic(s.Logger)
txBuf := make([]byte, 16)
if _, err := io.ReadFull(conn, txBuf); err != nil {
s.Logger.Infow("Start folder download", "path", fullFilePath, "ReferenceNumber", fileTransfer.ReferenceNumber)
nextAction := make([]byte, 2)
- if _, err := conn.Read(nextAction); err != nil {
+ if _, err := io.ReadFull(conn, nextAction); err != nil {
return err
}
}
// Read the client's Next Action request
- if _, err := conn.Read(nextAction); err != nil {
+ if _, err := io.ReadFull(conn, nextAction); err != nil {
return err
}
// client asked to resume this file
var frd FileResumeData
// get size of resumeData
- if _, err := conn.Read(nextAction); err != nil {
+ if _, err := io.ReadFull(conn, nextAction); err != nil {
return err
}
resumeDataLen := binary.BigEndian.Uint16(nextAction)
resumeDataBytes := make([]byte, resumeDataLen)
- if _, err := conn.Read(resumeDataBytes); err != nil {
+ if _, err := io.ReadFull(conn, resumeDataBytes); err != nil {
return err
}
// TODO: optionally send resource fork header and resource fork data
// Read the client's Next Action request. This is always 3, I think?
- if _, err := conn.Read(nextAction); err != nil {
+ if _, err := io.ReadFull(conn, nextAction); err != nil {
return err
}
readBuffer := make([]byte, 1024)
for i := 0; i < fileTransfer.ItemCount(); i++ {
-
+ // TODO: fix potential short read with io.ReadFull
_, err := conn.Read(readBuffer)
if err != nil {
return err
return err
}
- if _, err := conn.Read(fileSize); err != nil {
+ if _, err := io.ReadFull(conn, fileSize); err != nil {
return err
}