1 module libssh.poll;
2 
3 import libssh.c_bindings.libssh;
4 import libssh.c_bindings.poll;
5 import libssh.errors;
6 import libssh.utils;
7 import libssh.session;
8 
9 enum PollEvents : short {
10     In = POLLIN,
11     Pro = POLLPRI,
12     Out = POLLOUT,
13 }
14 
15 class SSHEvent : Disposable {
16     alias EventCallback = bool delegate(socket_t fd, PollEvents revents);
17 
18     void addFd(socket_t fd, PollEvents events, EventCallback cb) {
19         this._eventCallbacks[fd] = cb;
20         scope(failure) this._eventCallbacks.remove(fd);
21 
22         auto rc = ssh_event_add_fd(this._event, fd, events, &nativeEventCallback, 
23             cast(void*) &this._eventCallbacks[fd]);
24         checkForRCError(rc, rc);
25     }
26 
27     void removeFd(socket_t fd) {
28         scope(exit) this._eventCallbacks.remove(fd);
29         auto rc = ssh_event_remove_fd(this._event, fd);
30         checkForRCError(rc, rc);
31     }
32 
33     void addSession(SSHSession session) {
34         auto rc = ssh_event_add_session(this._event, session._session);
35         checkForRCError(rc, rc);
36     }
37 
38     void removeSession(SSHSession session) {
39         auto rc = ssh_event_remove_session(this._event, session._session);
40         checkForRCError(rc, rc);
41     }
42 
43     void doPoll(int timeout) {
44         auto rc = ssh_event_dopoll(this._event, timeout);
45         checkForRCError(rc, rc);
46     }
47 
48     this() {
49         auto event = ssh_event_new();
50         if (event is null) {
51             throw new SSHException("Error while creating new event");
52         }
53         this(event);
54     }
55 
56     ~this() {
57         this._dispose(true);
58     }
59 
60     override void dispose() {
61         this._dispose(false);
62     }
63 
64     private {
65         void _dispose(bool fromDtor) {
66             if (this._event !is null) {
67                 ssh_event_free(this._event);
68                 this._event = null;
69             }
70         }
71 
72         this(ssh_event event) {
73             this._event = event;
74         }
75 
76         ssh_event _event;
77         EventCallback[socket_t] _eventCallbacks;
78     }
79 }
80 
81 private {
82     extern(C) int nativeEventCallback(socket_t fd, int revents, void *userdata) {
83         auto cb = cast(SSHEvent.EventCallback*) userdata;
84 
85         try {
86             return (*cb)(fd, cast(PollEvents) revents) ? SSH_OK : SSH_ERROR;
87         } catch (Exception) {
88             return SSH_ERROR;
89         }
90     }
91 }