ac0d12e814ed3d3610e7866c762d2a239c59b8f8
[public/netxms.git] / src / libnetxms / nxproc_win32.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003-2017 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: nxproc_unix.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include <nxproc.h>
26
27 /**
28 * Create listener end for named pipe
29 */
30 NamedPipeListener *NamedPipeListener::create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg)
31 {
32 mode_t prevMask = 0;
33
34 int s = socket(AF_UNIX, SOCK_STREAM, 0);
35 if (s == INVALID_SOCKET)
36 {
37 nxlog_debug(2, _T("NamedPipeListener(%s): socket() call failed (%s)"), name, _tcserror(errno));
38 return NULL;
39 }
40
41 struct sockaddr_un addrLocal;
42 addrLocal.sun_family = AF_UNIX;
43 #ifdef UNICODE
44 sprintf(addrLocal.sun_path, "/tmp/.%S", name);
45 #else
46 sprintf(addrLocal.sun_path, "/tmp/.%s", name);
47 #endif
48 unlink(addrLocal.sun_path);
49 prevMask = umask(S_IWGRP | S_IWOTH);
50 if (bind(s, (struct sockaddr *)&addrLocal, SUN_LEN(&addrLocal)) == -1)
51 {
52 nxlog_debug(2, _T("NamedPipeListener(%s): bind failed (%s)"), name, _tcserror(errno));
53 umask(prevMask);
54 goto failure;
55 }
56 umask(prevMask);
57
58 if (listen(s, 5) == -1)
59 {
60 nxlog_debug(2, _T("NamedPipeListener(%s): listen() call failed (%s)"), name, _tcserror(errno));
61 goto failure;
62 }
63
64 return new NamedPipeListener(name, s, reqHandler, userArg);
65
66 failure:
67 close(s);
68 unlink(addrLocal.sun_path);
69 return NULL;
70 }
71
72 /**
73 * Pipe destructor
74 */
75 NamedPipeListener::~NamedPipeListener()
76 {
77 CloseHandle(m_handle);
78 stop();
79 }
80
81 /**
82 * Named pipe server thread
83 */
84 void NamedPipeListener::serverThread()
85 {
86 nxlog_debug(2, _T("NamedPipeListener(%s): waiting for connection"), m_name);
87 while(!m_stop)
88 {
89 }
90 }
91
92 /**
93 * Pipe destructor
94 */
95 NamedPipe::~NamedPipe()
96 {
97 CloseHandle(m_handle);
98 MutexDestroy(m_writeLock);
99 }
100
101 /**
102 * Create client end for named pipe
103 */
104 NamedPipe *NamedPipe::connect(const TCHAR *name, UINT32 timeout)
105 {
106 TCHAR path[MAX_PATH];
107 _sntprintf(path, MAX_PATH, _T("\\\\.\\pipe\\%s"), name);
108
109 reconnect:
110 HANDLE h = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
111 if (h == INVALID_HANDLE_VALUE)
112 {
113 if (GetLastError() == ERROR_PIPE_BUSY)
114 {
115 if (WaitNamedPipe(path, timeout))
116 goto reconnect;
117 }
118 return NULL;
119 }
120
121 DWORD pipeMode = PIPE_READMODE_MESSAGE;
122 SetNamedPipeHandleState(h, &pipeMode, NULL, NULL);
123 return new NamedPipe(name, h, false);
124 }
125
126 /**
127 * Write to pipe
128 */
129 bool NamedPipe::write(const void *data, size_t size)
130 {
131 DWORD bytes;
132 if (!WriteFile(s_handle, data, size, &bytes, NULL))
133 return false;
134 return bytes == (DWORD)size;
135 }