diff --git a/README.md b/README.md index ee8e5f4..0fac996 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ please keep up with these changes, as they will not be backward compatible and r - [ ] Elligator2 - [ ] HKDF - [ ] HMAC - - [/] Noise subsystem + - [X] Noise subsystem - End-to-End Crypto - [ ] Garlic messages - [ ] ElGamal/AES+SessionTag @@ -94,7 +94,7 @@ please keep up with these changes, as they will not be backward compatible and r - [X] Session Tag ## Verbosity ## -Logging can be enabled and configured using the DEBUG_I2P environment variable. By default, logging is disabled. +Logging can be enabled and configured using the `DEBUG_I2P` environment variable. By default, logging is disabled. There are three available log levels: @@ -113,6 +113,17 @@ export DEBUG_I2P=error If DEBUG_I2P is set to an unrecognized variable, it will fall back to "debug". +## Fast-Fail mode ## + +Fast-Fail mode can be activated by setting `WARNFAIL_I2P` to any non-empty value. When set, every warning or error is Fatal. +It is unsafe for production use, and intended only for debugging and testing purposes. + +```shell +export WARNFAIL_I2P=true +``` + +If `WARNFAIL_I2P` is set and `DEBUG_I2P` is unset, `DEBUG_I2P` will be set to `debug`. + ## Contributing See CONTRIBUTING.md for more information. diff --git a/lib/common/certificate/certificate.go b/lib/common/certificate/certificate.go index d50a85f..4f7e7e8 100644 --- a/lib/common/certificate/certificate.go +++ b/lib/common/certificate/certificate.go @@ -212,39 +212,39 @@ func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, er // NewCertificate creates a new Certificate with default NULL type func NewCertificate() *Certificate { - return &Certificate{ - kind: Integer([]byte{CERT_NULL}), - len: Integer([]byte{0}), - payload: make([]byte, 0), - } + return &Certificate{ + kind: Integer([]byte{CERT_NULL}), + len: Integer([]byte{0}), + payload: make([]byte, 0), + } } // NewCertificateWithType creates a new Certificate with specified type and payload func NewCertificateWithType(certType uint8, payload []byte) (*Certificate, error) { - // Validate certificate type - switch certType { - case CERT_NULL, CERT_HASHCASH, CERT_HIDDEN, CERT_SIGNED, CERT_MULTIPLE, CERT_KEY: - // Valid type - default: - return nil, fmt.Errorf("invalid certificate type: %d", certType) - } + // Validate certificate type + switch certType { + case CERT_NULL, CERT_HASHCASH, CERT_HIDDEN, CERT_SIGNED, CERT_MULTIPLE, CERT_KEY: + // Valid type + default: + return nil, fmt.Errorf("invalid certificate type: %d", certType) + } - // For NULL certificates, payload should be empty - if certType == CERT_NULL && len(payload) > 0 { - return nil, errors.New("NULL certificates must have empty payload") - } + // For NULL certificates, payload should be empty + if certType == CERT_NULL && len(payload) > 0 { + return nil, errors.New("NULL certificates must have empty payload") + } length, _ := NewIntegerFromInt(len(payload), 2) - - cert := &Certificate{ - kind: Integer([]byte{certType}), - len: *length, - payload: make([]byte, len(payload)), - } - // Copy payload if present - if len(payload) > 0 { - copy(cert.payload, payload) - } + cert := &Certificate{ + kind: Integer([]byte{certType}), + len: *length, + payload: make([]byte, len(payload)), + } - return cert, nil -} \ No newline at end of file + // Copy payload if present + if len(payload) > 0 { + copy(cert.payload, payload) + } + + return cert, nil +} diff --git a/lib/common/keys_and_cert/keys_and_cert.go b/lib/common/keys_and_cert/keys_and_cert.go index 3f5e4eb..25e09ce 100644 --- a/lib/common/keys_and_cert/keys_and_cert.go +++ b/lib/common/keys_and_cert/keys_and_cert.go @@ -165,4 +165,3 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, return } - diff --git a/lib/transport/noise/session.go b/lib/transport/noise/session.go index bb5c3f6..990a70d 100644 --- a/lib/transport/noise/session.go +++ b/lib/transport/noise/session.go @@ -21,11 +21,11 @@ type NoiseSession struct { *sync.Cond *NoiseTransport // The parent transport, which "Dialed" the connection to the peer whith whom we established the session *HandshakeState - RecvQueue *cb.Queue - SendQueue *cb.Queue - VerifyCallback VerifyCallbackFunc - activeCall int32 - Conn net.Conn + RecvQueue *cb.Queue + SendQueue *cb.Queue + VerifyCallback VerifyCallbackFunc + activeCall int32 + Conn net.Conn } // RemoteAddr implements net.Conn diff --git a/lib/util/logger/log.go b/lib/util/logger/log.go index 16f6215..329f966 100644 --- a/lib/util/logger/log.go +++ b/lib/util/logger/log.go @@ -1,7 +1,7 @@ package logger import ( - "io/ioutil" + "io" "os" "strings" "sync" @@ -10,18 +10,96 @@ import ( ) var ( - log *logrus.Logger - once sync.Once + log *Logger + once sync.Once + failFast string ) +// Logger wraps logrus.Logger and adds the ability to make all warnings fatal +type Logger struct { + *logrus.Logger +} + +// Entry wraps logrus.Entry and enables it to use our Logger +type Entry struct { + Logger + entry *logrus.Entry +} + +// Warn wraps logrus.Warn and logs a fatal error if failFast is set +func (l *Logger) Warn(args ...interface{}) { + warnFatal(args) + l.Logger.Warn(args...) +} + +// Warnf wraps logrus.Warnf and logs a fatal error if failFast is set +func (l *Logger) Warnf(format string, args ...interface{}) { + warnFatalf(format, args...) + l.Logger.Warnf(format, args...) +} + +// Error wraps logrus.Error and logs a fatal error if failFast is set +func (l *Logger) Error(args ...interface{}) { + warnFatal(args) + l.Logger.Error(args...) +} + +// Errorf wraps logrus.Errorf and logs a fatal error if failFast is set +func (l *Logger) Errorf(format string, args ...interface{}) { + warnFatalf(format, args...) + l.Logger.Errorf(format, args...) +} + +// WithField wraps logrus.WithField and returns an Entry +func (l *Logger) WithField(key string, value interface{}) *Entry { + entry := l.Logger.WithField(key, value) + return &Entry{*l, entry} +} + +// WithFields wraps logrus.WithFields and returns an Entry +func (l *Logger) WithFields(fields logrus.Fields) *Entry { + entry := l.Logger.WithFields(fields) + return &Entry{*l, entry} +} + +// WithError wraps logrus.WithError and returns an Entry +func (l *Logger) WithError(err error) *Entry { + entry := l.Logger.WithError(err) + return &Entry{*l, entry} +} + +func warnFatal(args ...interface{}) { + if failFast != "" { + log.Fatal(args) + } +} + +func warnFatalf(format string, args ...interface{}) { + if failFast != "" { + log.Fatalf(format, args...) + } +} + +func warnFail() { + if failFast != "" { + log.Error("FATAL ERROR") + } +} + +// InitializeGoI2PLogger sets up all the necessary logging func InitializeGoI2PLogger() { once.Do(func() { - log = logrus.New() + log = &Logger{} + log.Logger = logrus.New() // We do not want to log by default - log.SetOutput(ioutil.Discard) + log.SetOutput(io.Discard) log.SetLevel(logrus.PanicLevel) // Check if DEBUG_I2P is set if logLevel := os.Getenv("DEBUG_I2P"); logLevel != "" { + failFast = os.Getenv("WARNFAIL_I2P") + if failFast != "" && logLevel == "" { + logLevel = "debug" + } log.SetOutput(os.Stdout) switch strings.ToLower(logLevel) { case "debug": @@ -38,8 +116,8 @@ func InitializeGoI2PLogger() { }) } -// GetGoI2PLogger returns the initialized logger -func GetGoI2PLogger() *logrus.Logger { +// GetGoI2PLogger returns the initialized Logger +func GetGoI2PLogger() *Logger { if log == nil { InitializeGoI2PLogger() }