1 module libssh.logging; 2 3 import core.sync.rwmutex; 4 import std.algorithm.mutation; 5 import std.algorithm.searching; 6 7 import libssh.c_bindings.libssh; 8 import libssh.errors; 9 import libssh.utils; 10 11 enum LogLevel : int { 12 NoLog = SSH_LOG_NOLOG, 13 Rare = SSH_LOG_RARE, 14 Warning = SSH_LOG_WARNING, 15 Protocol = SSH_LOG_PROTOCOL, 16 Packet = SSH_LOG_PACKET, 17 Functions = SSH_LOG_FUNCTIONS, 18 } 19 20 alias LoggingCallbackDelegate = void delegate(LogLevel ll, string function_, string message); 21 alias LoggingCallbackFunction = void function(LogLevel ll, string function_, string message); 22 23 bool addLoggingHandler(LoggingCallbackDelegate d) { 24 synchronized(_handlersLock.writer) { 25 if (!_loggingDelegates.canFind(d)) { 26 _loggingDelegates ~= d; 27 return true; 28 } 29 return false; 30 } 31 } 32 33 bool addLoggingHandler(LoggingCallbackFunction d) { 34 synchronized(_handlersLock.writer) { 35 if (!_loggingFunctions.canFind(d)) { 36 _loggingFunctions ~= d; 37 return true; 38 } 39 return false; 40 } 41 } 42 43 void removeLoggingHandler(LoggingCallbackDelegate d) { 44 synchronized(_handlersLock.writer) { 45 _loggingDelegates = remove!(a => a == d)(_loggingDelegates); 46 } 47 } 48 49 void removeLoggingHandler(LoggingCallbackFunction d) { 50 synchronized(_handlersLock.writer) { 51 _loggingFunctions = remove!(a => a == d)(_loggingFunctions); 52 } 53 } 54 55 @property LogLevel logLevel() { 56 return cast(LogLevel) ssh_get_log_level(); 57 } 58 59 @property void logLevel(LogLevel ll) { 60 auto rc = ssh_set_log_level(ll); 61 if (rc != SSH_OK) { 62 throw new SSHException(rc); 63 } 64 } 65 66 private { 67 __gshared ReadWriteMutex _handlersLock; 68 69 __gshared LoggingCallbackDelegate[] _loggingDelegates; 70 __gshared LoggingCallbackFunction[] _loggingFunctions; 71 72 shared static this() { 73 _handlersLock = new ReadWriteMutex(); 74 _loggingDelegates = []; 75 _loggingFunctions = []; 76 } 77 78 extern(C) void nativeLoggingCallback(int priority, const char* function_, const char* buffer, 79 void*) { 80 synchronized (_handlersLock.reader) { 81 foreach(h; _loggingDelegates) { 82 h(cast(LogLevel) priority, fromStrZ(function_), fromStrZ(buffer)); 83 } 84 foreach(h; _loggingFunctions) { 85 h(cast(LogLevel) priority, fromStrZ(function_), fromStrZ(buffer)); 86 } 87 } 88 } 89 }