"Fossies" - the Fresh Open Source Software Archive 
Member "netxms-3.8.166/src/libnetxms/cch.cpp" (23 Feb 2021, 4556 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "cch.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
3.8.120_vs_3.8.166.
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003-2021 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: cch.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25
26 /**
27 * Abstract communication channel constructor
28 */
29 AbstractCommChannel::AbstractCommChannel()
30 {
31 }
32
33 /**
34 * Abstract communication channel destructor
35 */
36 AbstractCommChannel::~AbstractCommChannel()
37 {
38 }
39
40 /**
41 * Socket communication channel constructor
42 */
43 SocketCommChannel::SocketCommChannel(SOCKET socket, BackgroundSocketPollerHandle *socketPoller, Ownership owner) : AbstractCommChannel()
44 {
45 m_socket = socket;
46 m_owner = (owner == Ownership::True);
47 #ifndef _WIN32
48 if (pipe(m_controlPipe) != 0)
49 {
50 m_controlPipe[0] = -1;
51 m_controlPipe[1] = -1;
52 }
53 #endif
54 m_socketPoller = socketPoller;
55 }
56
57 /**
58 * Socket communication channel destructor
59 */
60 SocketCommChannel::~SocketCommChannel()
61 {
62 if (m_owner && (m_socket != INVALID_SOCKET))
63 closesocket(m_socket);
64 #ifndef _WIN32
65 if (m_controlPipe[0] != -1)
66 _close(m_controlPipe[0]);
67 if (m_controlPipe[1] != -1)
68 _close(m_controlPipe[1]);
69 #endif
70 if (m_socketPoller != nullptr)
71 InterlockedDecrement(&m_socketPoller->usageCount);
72 }
73
74 /**
75 * Send data
76 */
77 ssize_t SocketCommChannel::send(const void *data, size_t size, MUTEX mutex)
78 {
79 return SendEx(m_socket, data, size, 0, mutex);
80 }
81
82 /**
83 * Receive data
84 */
85 ssize_t SocketCommChannel::recv(void *buffer, size_t size, UINT32 timeout)
86 {
87 if (timeout == 0)
88 {
89 #ifdef _WIN32
90 int rc = ::recv(m_socket, reinterpret_cast<char*>(buffer), static_cast<int>(size), 0);
91 #else
92 int rc = ::recv(m_socket, reinterpret_cast<char*>(buffer), size, 0);
93 #endif
94 if (rc >= 0)
95 return rc;
96 return ((WSAGetLastError() == WSAEWOULDBLOCK) || (WSAGetLastError() == WSAEINPROGRESS)) ? -4 : -1;
97 }
98 #ifdef _WIN32
99 return RecvEx(m_socket, buffer, size, 0, timeout);
100 #else
101 return RecvEx(m_socket, buffer, size, 0, timeout, m_controlPipe[0]);
102 #endif
103 }
104
105 /**
106 * Poll channel
107 */
108 int SocketCommChannel::poll(UINT32 timeout, bool write)
109 {
110 if (m_socket == INVALID_SOCKET)
111 return -1;
112
113 SocketPoller sp(write);
114 sp.add(m_socket);
115 return sp.poll(timeout);
116 }
117
118 /**
119 * Shutdown channel
120 */
121 int SocketCommChannel::shutdown()
122 {
123 #ifndef _WIN32
124 // Cause select/poll to wake up
125 if (m_controlPipe[1] != -1)
126 _write(m_controlPipe[1], "X", 1);
127 #endif
128 return (m_socket != INVALID_SOCKET) ? ::shutdown(m_socket, SHUT_RDWR) : -1;
129 }
130
131 /**
132 * Close channel
133 */
134 void SocketCommChannel::close()
135 {
136 if (m_socket != INVALID_SOCKET)
137 {
138 if (m_socketPoller != nullptr)
139 m_socketPoller->poller.cancel(m_socket);
140 closesocket(m_socket);
141 m_socket = INVALID_SOCKET;
142 }
143 }
144
145 /**
146 * Wrapper context for background socket poll
147 */
148 struct BackgroundPollContext
149 {
150 SocketCommChannel *channel;
151 void (*callback)(BackgroundSocketPollResult, AbstractCommChannel*, void*);
152 void *context;
153 };
154
155 /**
156 * Wrapper callback for background socket poll
157 */
158 static void BackgroundPollWrapper(BackgroundSocketPollResult pollResult, SOCKET hSocket, BackgroundPollContext *context)
159 {
160 context->callback(pollResult, context->channel, context->context);
161 MemFree(context);
162 }
163
164 /**
165 * Start background poll
166 */
167 void SocketCommChannel::backgroundPoll(uint32_t timeout, void (*callback)(BackgroundSocketPollResult, AbstractCommChannel*, void*), void *context)
168 {
169 if ((m_socketPoller != nullptr) && (m_socket != INVALID_SOCKET))
170 {
171 auto wrapperContext = MemAllocStruct<BackgroundPollContext>();
172 wrapperContext->channel = this;
173 wrapperContext->callback = callback;
174 wrapperContext->context = context;
175 m_socketPoller->poller.poll(m_socket, timeout, BackgroundPollWrapper, wrapperContext);
176 }
177 else
178 {
179 callback(BackgroundSocketPollResult::FAILURE, this, context);
180 }
181 }