pnpipe.cxx (5682B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 #ifdef WIN32 13 # include <windows.h> 14 #else 15 # include <sys/types.h> 16 # include <sys/socket.h> 17 # include <sys/un.h> 18 #endif 19 20 #include "pstreams.h" 21 22 23 namespace ptypes { 24 25 26 #ifdef WIN32 27 28 string ptdecl namedpipe::realpipename(const string& pipename, const string& svrname) 29 { 30 if (isempty(pipename)) 31 return nullstring; 32 string realname = pipename; 33 if (*pconst(pipename) == '/') 34 { 35 int i = rpos('/', realname); 36 del(realname, 0, i + 1); 37 } 38 string s; 39 if (isempty(svrname)) 40 s = '.'; 41 else 42 s = svrname; 43 return "\\\\" + s + "\\pipe\\" + realname; 44 } 45 46 47 #else 48 49 string ptdecl namedpipe::realpipename(const string& pipename) 50 { 51 if (isempty(pipename)) 52 return nullstring; 53 if (*pconst(pipename) == '/') 54 return pipename; 55 else 56 return DEF_NAMED_PIPES_DIR + pipename; 57 } 58 59 60 bool namedpipe::setupsockaddr(const string& pipename, void* isa) 61 { 62 sockaddr_un* sa = (sockaddr_un*)isa; 63 memset(sa, 0, sizeof(sockaddr_un)); 64 sa->sun_family = AF_UNIX; 65 #ifdef __FreeBSD__ 66 sa->sun_len = length(pipename); 67 #endif 68 69 // copy the path name into the sockaddr structure, 108 chars max (?) 70 if (length(pipename) + 1 > (int)sizeof(sa->sun_path)) 71 return false; 72 strcpy(sa->sun_path, pipename); 73 return true; 74 } 75 76 #endif 77 78 79 namedpipe::namedpipe() 80 : fdxstm(), pipename(), svhandle(invhandle) 81 { 82 initovr(); 83 } 84 85 86 namedpipe::namedpipe(const string& ipipename) 87 : fdxstm(), pipename(), svhandle(invhandle) 88 { 89 pipename = realpipename(ipipename); 90 initovr(); 91 } 92 93 94 #ifdef WIN32 95 96 namedpipe::namedpipe(const string& ipipename, const string& servername) 97 : fdxstm(), pipename(), svhandle(invhandle) 98 { 99 pipename = realpipename(ipipename, servername); 100 initovr(); 101 } 102 103 104 void namedpipe::initovr() 105 { 106 ovr.hEvent = CreateEvent(0, false, false, 0); 107 } 108 109 110 #endif 111 112 113 namedpipe::~namedpipe() 114 { 115 cancel(); 116 #ifdef WIN32 117 CloseHandle(ovr.hEvent); 118 #endif 119 } 120 121 122 int namedpipe::classid() 123 { 124 return CLASS3_NPIPE; 125 } 126 127 128 string namedpipe::get_streamname() 129 { 130 return pipename; 131 } 132 133 134 void namedpipe::set_pipename(const string& newvalue) 135 { 136 close(); 137 pipename = realpipename(newvalue); 138 } 139 140 141 void namedpipe::set_pipename(const char* newvalue) 142 { 143 close(); 144 pipename = realpipename(newvalue); 145 } 146 147 148 large namedpipe::doseek(large, ioseekmode) 149 { 150 return -1; 151 } 152 153 154 void namedpipe::doopen() 155 { 156 157 #ifdef WIN32 158 159 if (svhandle != invhandle) 160 handle = svhandle; 161 else 162 { 163 int tries = DEF_PIPE_OPEN_RETRY; 164 int delay = DEF_PIPE_OPEN_TIMEOUT / 2; 165 retry: 166 SECURITY_ATTRIBUTES sa; 167 sa.nLength = sizeof(SECURITY_ATTRIBUTES); 168 sa.lpSecurityDescriptor = NULL; 169 sa.bInheritHandle = TRUE; 170 171 handle = int(CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 172 0, &sa, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)); 173 if (handle == invhandle) 174 { 175 if (GetLastError() == ERROR_PIPE_BUSY) 176 { 177 if (--tries > 0) 178 { 179 delay *= 2; 180 Sleep(delay); 181 goto retry; 182 } 183 else 184 error(EIO, "Pipe busy"); 185 } 186 else 187 error(uerrno(), "Couldn't open named pipe"); 188 } 189 } 190 191 #else 192 if (svhandle != invhandle) 193 { 194 if ((handle = ::accept(svhandle, 0, 0)) < 0) 195 error(uerrno(), "Couldn't create local socket"); 196 } 197 198 else 199 { 200 sockaddr_un sa; 201 if (!setupsockaddr(pipename, &sa)) 202 error(ERANGE, "Socket name too long"); 203 204 // cteate a client socket 205 if ((handle = ::socket(sa.sun_family, SOCK_STREAM, 0)) < 0) 206 error(uerrno(), "Couldn't create local socket"); 207 208 // ... and connect to the local socket 209 if (::connect(handle, (sockaddr*)&sa, sizeof(sa)) < 0) 210 { 211 int e = uerrno(); 212 doclose(); 213 error(e, "Couldn't connect to local socket"); 214 } 215 } 216 217 #endif 218 } 219 220 221 #ifdef WIN32 222 223 int namedpipe::dorawread(char* buf, int count) 224 { 225 unsigned long ret = uint(-1); 226 ovr.Offset = 0; 227 ovr.OffsetHigh = 0; 228 if (!ReadFile(HANDLE(handle), buf, count, &ret, &ovr)) 229 { 230 if (GetLastError() == ERROR_IO_PENDING) 231 { 232 if (WaitForSingleObject(ovr.hEvent, DEF_PIPE_TIMEOUT) == WAIT_TIMEOUT) 233 error(EIO, "Timed out"); 234 if (!GetOverlappedResult(HANDLE(handle), &ovr, &ret, false)) 235 error(uerrno(), "Couldn't read"); 236 } 237 else 238 error(uerrno(), "Couldn't read"); 239 } 240 return ret; 241 } 242 243 244 int namedpipe::dorawwrite(const char* buf, int count) 245 { 246 unsigned long ret = uint(-1); 247 ovr.Offset = 0; 248 ovr.OffsetHigh = 0; 249 if (!WriteFile(HANDLE(handle), buf, count, &ret, &ovr)) 250 { 251 if (GetLastError() == ERROR_IO_PENDING) 252 { 253 if (WaitForSingleObject(ovr.hEvent, DEF_PIPE_TIMEOUT) == WAIT_TIMEOUT) 254 error(EIO, "Timed out"); 255 if (!GetOverlappedResult(HANDLE(handle), &ovr, &ret, false)) 256 error(uerrno(), "Couldn't write"); 257 } 258 else 259 error(uerrno(), "Couldn't write"); 260 } 261 return ret; 262 } 263 264 265 #endif 266 267 268 void namedpipe::doclose() 269 { 270 #ifdef WIN32 271 if (svhandle != invhandle) 272 DisconnectNamedPipe(HANDLE(handle)); 273 #endif 274 svhandle = invhandle; 275 fdxstm::doclose(); 276 } 277 278 279 void namedpipe::flush() 280 { 281 #ifdef WIN32 282 if (!cancelled) 283 FlushFileBuffers(HANDLE(handle)); 284 #endif 285 fdxstm::flush(); 286 } 287 288 289 290 }