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 }