| 1 | // -------------------------------------------------------------------------- |
|---|
| 2 | // |
|---|
| 3 | // File |
|---|
| 4 | // Name: SocketStream.cpp |
|---|
| 5 | // Purpose: I/O stream interface for sockets |
|---|
| 6 | // Created: 2003/07/31 |
|---|
| 7 | // |
|---|
| 8 | // -------------------------------------------------------------------------- |
|---|
| 9 | |
|---|
| 10 | #include "Box.h" |
|---|
| 11 | |
|---|
| 12 | #ifdef HAVE_UNISTD_H |
|---|
| 13 | #include <unistd.h> |
|---|
| 14 | #endif |
|---|
| 15 | |
|---|
| 16 | #include <sys/types.h> |
|---|
| 17 | #include <errno.h> |
|---|
| 18 | #include <string.h> |
|---|
| 19 | |
|---|
| 20 | #ifndef WIN32 |
|---|
| 21 | #include <poll.h> |
|---|
| 22 | #endif |
|---|
| 23 | |
|---|
| 24 | #ifdef HAVE_UCRED_H |
|---|
| 25 | #include <ucred.h> |
|---|
| 26 | #endif |
|---|
| 27 | |
|---|
| 28 | #include "SocketStream.h" |
|---|
| 29 | #include "ServerException.h" |
|---|
| 30 | #include "CommonException.h" |
|---|
| 31 | #include "Socket.h" |
|---|
| 32 | |
|---|
| 33 | #include "MemLeakFindOn.h" |
|---|
| 34 | |
|---|
| 35 | // -------------------------------------------------------------------------- |
|---|
| 36 | // |
|---|
| 37 | // Function |
|---|
| 38 | // Name: SocketStream::SocketStream() |
|---|
| 39 | // Purpose: Constructor (create stream ready for Open() call) |
|---|
| 40 | // Created: 2003/07/31 |
|---|
| 41 | // |
|---|
| 42 | // -------------------------------------------------------------------------- |
|---|
| 43 | SocketStream::SocketStream() |
|---|
| 44 | : mSocketHandle(INVALID_SOCKET_VALUE), |
|---|
| 45 | mReadClosed(false), |
|---|
| 46 | mWriteClosed(false), |
|---|
| 47 | mBytesRead(0), |
|---|
| 48 | mBytesWritten(0) |
|---|
| 49 | { |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | // -------------------------------------------------------------------------- |
|---|
| 53 | // |
|---|
| 54 | // Function |
|---|
| 55 | // Name: SocketStream::SocketStream(int) |
|---|
| 56 | // Purpose: Create stream from existing socket handle |
|---|
| 57 | // Created: 2003/07/31 |
|---|
| 58 | // |
|---|
| 59 | // -------------------------------------------------------------------------- |
|---|
| 60 | SocketStream::SocketStream(int socket) |
|---|
| 61 | : mSocketHandle(socket), |
|---|
| 62 | mReadClosed(false), |
|---|
| 63 | mWriteClosed(false), |
|---|
| 64 | mBytesRead(0), |
|---|
| 65 | mBytesWritten(0) |
|---|
| 66 | { |
|---|
| 67 | if(socket < 0) |
|---|
| 68 | { |
|---|
| 69 | THROW_EXCEPTION(ServerException, BadSocketHandle); |
|---|
| 70 | } |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | // -------------------------------------------------------------------------- |
|---|
| 74 | // |
|---|
| 75 | // Function |
|---|
| 76 | // Name: SocketStream::SocketStream(const SocketStream &) |
|---|
| 77 | // Purpose: Copy constructor (dup()s socket) |
|---|
| 78 | // Created: 2003/07/31 |
|---|
| 79 | // |
|---|
| 80 | // -------------------------------------------------------------------------- |
|---|
| 81 | SocketStream::SocketStream(const SocketStream &rToCopy) |
|---|
| 82 | : mSocketHandle(::dup(rToCopy.mSocketHandle)), |
|---|
| 83 | mReadClosed(rToCopy.mReadClosed), |
|---|
| 84 | mWriteClosed(rToCopy.mWriteClosed), |
|---|
| 85 | mBytesRead(rToCopy.mBytesRead), |
|---|
| 86 | mBytesWritten(rToCopy.mBytesWritten) |
|---|
| 87 | |
|---|
| 88 | { |
|---|
| 89 | if(rToCopy.mSocketHandle < 0) |
|---|
| 90 | { |
|---|
| 91 | THROW_EXCEPTION(ServerException, BadSocketHandle); |
|---|
| 92 | } |
|---|
| 93 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 94 | { |
|---|
| 95 | THROW_EXCEPTION(ServerException, DupError); |
|---|
| 96 | } |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | // -------------------------------------------------------------------------- |
|---|
| 100 | // |
|---|
| 101 | // Function |
|---|
| 102 | // Name: SocketStream::~SocketStream() |
|---|
| 103 | // Purpose: Destructor, closes stream if open |
|---|
| 104 | // Created: 2003/07/31 |
|---|
| 105 | // |
|---|
| 106 | // -------------------------------------------------------------------------- |
|---|
| 107 | SocketStream::~SocketStream() |
|---|
| 108 | { |
|---|
| 109 | if(mSocketHandle != INVALID_SOCKET_VALUE) |
|---|
| 110 | { |
|---|
| 111 | Close(); |
|---|
| 112 | } |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | // -------------------------------------------------------------------------- |
|---|
| 116 | // |
|---|
| 117 | // Function |
|---|
| 118 | // Name: SocketStream::Attach(int) |
|---|
| 119 | // Purpose: Attach a socket handle to this stream |
|---|
| 120 | // Created: 11/12/03 |
|---|
| 121 | // |
|---|
| 122 | // -------------------------------------------------------------------------- |
|---|
| 123 | void SocketStream::Attach(int socket) |
|---|
| 124 | { |
|---|
| 125 | if(mSocketHandle != INVALID_SOCKET_VALUE) |
|---|
| 126 | { |
|---|
| 127 | THROW_EXCEPTION(ServerException, SocketAlreadyOpen) |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | ResetCounters(); |
|---|
| 131 | |
|---|
| 132 | mSocketHandle = socket; |
|---|
| 133 | mReadClosed = false; |
|---|
| 134 | mWriteClosed = false; |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | |
|---|
| 138 | // -------------------------------------------------------------------------- |
|---|
| 139 | // |
|---|
| 140 | // Function |
|---|
| 141 | // Name: SocketStream::Open(Socket::Type, char *, int) |
|---|
| 142 | // Purpose: Opens a connection to a listening socket (INET or UNIX) |
|---|
| 143 | // Created: 2003/07/31 |
|---|
| 144 | // |
|---|
| 145 | // -------------------------------------------------------------------------- |
|---|
| 146 | void SocketStream::Open(Socket::Type Type, const std::string& rName, int Port) |
|---|
| 147 | { |
|---|
| 148 | if(mSocketHandle != INVALID_SOCKET_VALUE) |
|---|
| 149 | { |
|---|
| 150 | THROW_EXCEPTION(ServerException, SocketAlreadyOpen) |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | // Setup parameters based on type, looking up names if required |
|---|
| 154 | int sockDomain = 0; |
|---|
| 155 | SocketAllAddr addr; |
|---|
| 156 | int addrLen = 0; |
|---|
| 157 | Socket::NameLookupToSockAddr(addr, sockDomain, Type, rName, Port, |
|---|
| 158 | addrLen); |
|---|
| 159 | |
|---|
| 160 | // Create the socket |
|---|
| 161 | mSocketHandle = ::socket(sockDomain, SOCK_STREAM, |
|---|
| 162 | 0 /* let OS choose protocol */); |
|---|
| 163 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 164 | { |
|---|
| 165 | BOX_LOG_SOCKET_ERROR(Type, rName, Port, |
|---|
| 166 | "Failed to create a network socket"); |
|---|
| 167 | THROW_EXCEPTION(ServerException, SocketOpenError) |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | // Connect it |
|---|
| 171 | if(::connect(mSocketHandle, &addr.sa_generic, addrLen) == -1) |
|---|
| 172 | { |
|---|
| 173 | // Dispose of the socket |
|---|
| 174 | BOX_LOG_SOCKET_ERROR(Type, rName, Port, |
|---|
| 175 | "Failed to connect to socket"); |
|---|
| 176 | #ifdef WIN32 |
|---|
| 177 | ::closesocket(mSocketHandle); |
|---|
| 178 | #else // !WIN32 |
|---|
| 179 | ::close(mSocketHandle); |
|---|
| 180 | #endif // WIN32 |
|---|
| 181 | |
|---|
| 182 | mSocketHandle = INVALID_SOCKET_VALUE; |
|---|
| 183 | THROW_EXCEPTION(ConnectionException, Conn_SocketConnectError) |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | ResetCounters(); |
|---|
| 187 | |
|---|
| 188 | mReadClosed = false; |
|---|
| 189 | mWriteClosed = false; |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | // -------------------------------------------------------------------------- |
|---|
| 193 | // |
|---|
| 194 | // Function |
|---|
| 195 | // Name: SocketStream::Read(void *pBuffer, int NBytes) |
|---|
| 196 | // Purpose: Reads data from stream. Maybe returns less than asked for. |
|---|
| 197 | // Created: 2003/07/31 |
|---|
| 198 | // |
|---|
| 199 | // -------------------------------------------------------------------------- |
|---|
| 200 | int SocketStream::Read(void *pBuffer, int NBytes, int Timeout) |
|---|
| 201 | { |
|---|
| 202 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 203 | { |
|---|
| 204 | THROW_EXCEPTION(ServerException, BadSocketHandle) |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | if(Timeout != IOStream::TimeOutInfinite) |
|---|
| 208 | { |
|---|
| 209 | struct pollfd p; |
|---|
| 210 | p.fd = mSocketHandle; |
|---|
| 211 | p.events = POLLIN; |
|---|
| 212 | p.revents = 0; |
|---|
| 213 | switch(::poll(&p, 1, (Timeout == IOStream::TimeOutInfinite)?INFTIM:Timeout)) |
|---|
| 214 | { |
|---|
| 215 | case -1: |
|---|
| 216 | // error |
|---|
| 217 | if(errno == EINTR) |
|---|
| 218 | { |
|---|
| 219 | // Signal. Just return 0 bytes |
|---|
| 220 | return 0; |
|---|
| 221 | } |
|---|
| 222 | else |
|---|
| 223 | { |
|---|
| 224 | // Bad! |
|---|
| 225 | BOX_LOG_SYS_ERROR("Failed to poll socket"); |
|---|
| 226 | THROW_EXCEPTION(ServerException, |
|---|
| 227 | SocketPollError) |
|---|
| 228 | } |
|---|
| 229 | break; |
|---|
| 230 | |
|---|
| 231 | case 0: |
|---|
| 232 | // no data |
|---|
| 233 | return 0; |
|---|
| 234 | break; |
|---|
| 235 | |
|---|
| 236 | default: |
|---|
| 237 | // good to go! |
|---|
| 238 | break; |
|---|
| 239 | } |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | #ifdef WIN32 |
|---|
| 243 | int r = ::recv(mSocketHandle, (char*)pBuffer, NBytes, 0); |
|---|
| 244 | #else |
|---|
| 245 | int r = ::read(mSocketHandle, pBuffer, NBytes); |
|---|
| 246 | #endif |
|---|
| 247 | if(r == -1) |
|---|
| 248 | { |
|---|
| 249 | if(errno == EINTR) |
|---|
| 250 | { |
|---|
| 251 | // Nothing could be read |
|---|
| 252 | return 0; |
|---|
| 253 | } |
|---|
| 254 | else |
|---|
| 255 | { |
|---|
| 256 | // Other error |
|---|
| 257 | BOX_LOG_SYS_ERROR("Failed to read from socket"); |
|---|
| 258 | THROW_EXCEPTION(ConnectionException, |
|---|
| 259 | Conn_SocketReadError); |
|---|
| 260 | } |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | // Closed for reading? |
|---|
| 264 | if(r == 0) |
|---|
| 265 | { |
|---|
| 266 | mReadClosed = true; |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | mBytesRead += r; |
|---|
| 270 | return r; |
|---|
| 271 | } |
|---|
| 272 | |
|---|
| 273 | // -------------------------------------------------------------------------- |
|---|
| 274 | // |
|---|
| 275 | // Function |
|---|
| 276 | // Name: SocketStream::Write(void *pBuffer, int NBytes) |
|---|
| 277 | // Purpose: Writes data, blocking until it's all done. |
|---|
| 278 | // Created: 2003/07/31 |
|---|
| 279 | // |
|---|
| 280 | // -------------------------------------------------------------------------- |
|---|
| 281 | void SocketStream::Write(const void *pBuffer, int NBytes) |
|---|
| 282 | { |
|---|
| 283 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 284 | { |
|---|
| 285 | THROW_EXCEPTION(ServerException, BadSocketHandle) |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | // Buffer in byte sized type. |
|---|
| 289 | ASSERT(sizeof(char) == 1); |
|---|
| 290 | const char *buffer = (char *)pBuffer; |
|---|
| 291 | |
|---|
| 292 | // Bytes left to send |
|---|
| 293 | int bytesLeft = NBytes; |
|---|
| 294 | |
|---|
| 295 | while(bytesLeft > 0) |
|---|
| 296 | { |
|---|
| 297 | // Try to send. |
|---|
| 298 | #ifdef WIN32 |
|---|
| 299 | int sent = ::send(mSocketHandle, buffer, bytesLeft, 0); |
|---|
| 300 | #else |
|---|
| 301 | int sent = ::write(mSocketHandle, buffer, bytesLeft); |
|---|
| 302 | #endif |
|---|
| 303 | if(sent == -1) |
|---|
| 304 | { |
|---|
| 305 | // Error. |
|---|
| 306 | mWriteClosed = true; // assume can't write again |
|---|
| 307 | BOX_LOG_SYS_ERROR("Failed to write to socket"); |
|---|
| 308 | THROW_EXCEPTION(ConnectionException, |
|---|
| 309 | Conn_SocketWriteError); |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | // Knock off bytes sent |
|---|
| 313 | bytesLeft -= sent; |
|---|
| 314 | // Move buffer pointer |
|---|
| 315 | buffer += sent; |
|---|
| 316 | |
|---|
| 317 | mBytesWritten += sent; |
|---|
| 318 | |
|---|
| 319 | // Need to wait until it can send again? |
|---|
| 320 | if(bytesLeft > 0) |
|---|
| 321 | { |
|---|
| 322 | BOX_TRACE("Waiting to send data on socket " << |
|---|
| 323 | mSocketHandle << " (" << bytesLeft << |
|---|
| 324 | " of " << NBytes << " bytes left)"); |
|---|
| 325 | |
|---|
| 326 | // Wait for data to send. |
|---|
| 327 | struct pollfd p; |
|---|
| 328 | p.fd = mSocketHandle; |
|---|
| 329 | p.events = POLLOUT; |
|---|
| 330 | p.revents = 0; |
|---|
| 331 | |
|---|
| 332 | if(::poll(&p, 1, 16000 /* 16 seconds */) == -1) |
|---|
| 333 | { |
|---|
| 334 | // Don't exception if it's just a signal |
|---|
| 335 | if(errno != EINTR) |
|---|
| 336 | { |
|---|
| 337 | BOX_LOG_SYS_ERROR("Failed to poll " |
|---|
| 338 | "socket"); |
|---|
| 339 | THROW_EXCEPTION(ServerException, |
|---|
| 340 | SocketPollError) |
|---|
| 341 | } |
|---|
| 342 | } |
|---|
| 343 | } |
|---|
| 344 | } |
|---|
| 345 | } |
|---|
| 346 | |
|---|
| 347 | // -------------------------------------------------------------------------- |
|---|
| 348 | // |
|---|
| 349 | // Function |
|---|
| 350 | // Name: SocketStream::Close() |
|---|
| 351 | // Purpose: Closes connection to remote socket |
|---|
| 352 | // Created: 2003/07/31 |
|---|
| 353 | // |
|---|
| 354 | // -------------------------------------------------------------------------- |
|---|
| 355 | void SocketStream::Close() |
|---|
| 356 | { |
|---|
| 357 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 358 | { |
|---|
| 359 | THROW_EXCEPTION(ServerException, BadSocketHandle) |
|---|
| 360 | } |
|---|
| 361 | #ifdef WIN32 |
|---|
| 362 | if(::closesocket(mSocketHandle) == -1) |
|---|
| 363 | #else |
|---|
| 364 | if(::close(mSocketHandle) == -1) |
|---|
| 365 | #endif |
|---|
| 366 | { |
|---|
| 367 | BOX_LOG_SYS_ERROR("Failed to close socket"); |
|---|
| 368 | // don't throw an exception here, assume that the socket was |
|---|
| 369 | // already closed or closing. |
|---|
| 370 | } |
|---|
| 371 | mSocketHandle = INVALID_SOCKET_VALUE; |
|---|
| 372 | } |
|---|
| 373 | |
|---|
| 374 | // -------------------------------------------------------------------------- |
|---|
| 375 | // |
|---|
| 376 | // Function |
|---|
| 377 | // Name: SocketStream::Shutdown(bool, bool) |
|---|
| 378 | // Purpose: Shuts down a socket for further reading and/or writing |
|---|
| 379 | // Created: 2003/07/31 |
|---|
| 380 | // |
|---|
| 381 | // -------------------------------------------------------------------------- |
|---|
| 382 | void SocketStream::Shutdown(bool Read, bool Write) |
|---|
| 383 | { |
|---|
| 384 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 385 | { |
|---|
| 386 | THROW_EXCEPTION(ServerException, BadSocketHandle) |
|---|
| 387 | } |
|---|
| 388 | |
|---|
| 389 | // Do anything? |
|---|
| 390 | if(!Read && !Write) return; |
|---|
| 391 | |
|---|
| 392 | int how = SHUT_RDWR; |
|---|
| 393 | if(Read && !Write) how = SHUT_RD; |
|---|
| 394 | if(!Read && Write) how = SHUT_WR; |
|---|
| 395 | |
|---|
| 396 | // Shut it down! |
|---|
| 397 | if(::shutdown(mSocketHandle, how) == -1) |
|---|
| 398 | { |
|---|
| 399 | BOX_LOG_SYS_ERROR("Failed to shutdown socket"); |
|---|
| 400 | THROW_EXCEPTION(ConnectionException, Conn_SocketShutdownError) |
|---|
| 401 | } |
|---|
| 402 | } |
|---|
| 403 | |
|---|
| 404 | |
|---|
| 405 | // -------------------------------------------------------------------------- |
|---|
| 406 | // |
|---|
| 407 | // Function |
|---|
| 408 | // Name: SocketStream::StreamDataLeft() |
|---|
| 409 | // Purpose: Still capable of reading data? |
|---|
| 410 | // Created: 2003/08/02 |
|---|
| 411 | // |
|---|
| 412 | // -------------------------------------------------------------------------- |
|---|
| 413 | bool SocketStream::StreamDataLeft() |
|---|
| 414 | { |
|---|
| 415 | return !mReadClosed; |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | // -------------------------------------------------------------------------- |
|---|
| 419 | // |
|---|
| 420 | // Function |
|---|
| 421 | // Name: SocketStream::StreamClosed() |
|---|
| 422 | // Purpose: Connection been closed? |
|---|
| 423 | // Created: 2003/08/02 |
|---|
| 424 | // |
|---|
| 425 | // -------------------------------------------------------------------------- |
|---|
| 426 | bool SocketStream::StreamClosed() |
|---|
| 427 | { |
|---|
| 428 | return mWriteClosed; |
|---|
| 429 | } |
|---|
| 430 | |
|---|
| 431 | |
|---|
| 432 | // -------------------------------------------------------------------------- |
|---|
| 433 | // |
|---|
| 434 | // Function |
|---|
| 435 | // Name: SocketStream::GetSocketHandle() |
|---|
| 436 | // Purpose: Returns socket handle for this stream (derived classes only). |
|---|
| 437 | // Will exception if there's no valid socket. |
|---|
| 438 | // Created: 2003/08/06 |
|---|
| 439 | // |
|---|
| 440 | // -------------------------------------------------------------------------- |
|---|
| 441 | tOSSocketHandle SocketStream::GetSocketHandle() |
|---|
| 442 | { |
|---|
| 443 | if(mSocketHandle == INVALID_SOCKET_VALUE) |
|---|
| 444 | { |
|---|
| 445 | THROW_EXCEPTION(ServerException, BadSocketHandle) |
|---|
| 446 | } |
|---|
| 447 | return mSocketHandle; |
|---|
| 448 | } |
|---|
| 449 | |
|---|
| 450 | |
|---|
| 451 | // -------------------------------------------------------------------------- |
|---|
| 452 | // |
|---|
| 453 | // Function |
|---|
| 454 | // Name: SocketStream::GetPeerCredentials(uid_t &, gid_t &) |
|---|
| 455 | // Purpose: Returns true if the peer credientials are available. |
|---|
| 456 | // (will work on UNIX domain sockets only) |
|---|
| 457 | // Created: 19/2/04 |
|---|
| 458 | // |
|---|
| 459 | // -------------------------------------------------------------------------- |
|---|
| 460 | bool SocketStream::GetPeerCredentials(uid_t &rUidOut, gid_t &rGidOut) |
|---|
| 461 | { |
|---|
| 462 | #ifdef HAVE_GETPEEREID |
|---|
| 463 | uid_t remoteEUID = 0xffff; |
|---|
| 464 | gid_t remoteEGID = 0xffff; |
|---|
| 465 | |
|---|
| 466 | if(::getpeereid(mSocketHandle, &remoteEUID, &remoteEGID) == 0) |
|---|
| 467 | { |
|---|
| 468 | rUidOut = remoteEUID; |
|---|
| 469 | rGidOut = remoteEGID; |
|---|
| 470 | return true; |
|---|
| 471 | } |
|---|
| 472 | #endif |
|---|
| 473 | |
|---|
| 474 | #if HAVE_DECL_SO_PEERCRED |
|---|
| 475 | struct ucred cred; |
|---|
| 476 | socklen_t credLen = sizeof(cred); |
|---|
| 477 | |
|---|
| 478 | if(::getsockopt(mSocketHandle, SOL_SOCKET, SO_PEERCRED, &cred, |
|---|
| 479 | &credLen) == 0) |
|---|
| 480 | { |
|---|
| 481 | rUidOut = cred.uid; |
|---|
| 482 | rGidOut = cred.gid; |
|---|
| 483 | return true; |
|---|
| 484 | } |
|---|
| 485 | |
|---|
| 486 | BOX_LOG_SYS_ERROR("Failed to get peer credentials on socket"); |
|---|
| 487 | #endif |
|---|
| 488 | |
|---|
| 489 | #if defined HAVE_UCRED_H && HAVE_GETPEERUCRED |
|---|
| 490 | ucred_t *pucred = NULL; |
|---|
| 491 | if(::getpeerucred(mSocketHandle, &pucred) == 0) |
|---|
| 492 | { |
|---|
| 493 | rUidOut = ucred_geteuid(pucred); |
|---|
| 494 | rGidOut = ucred_getegid(pucred); |
|---|
| 495 | ucred_free(pucred); |
|---|
| 496 | if (rUidOut == -1 || rGidOut == -1) |
|---|
| 497 | { |
|---|
| 498 | BOX_ERROR("Failed to get peer credentials on " |
|---|
| 499 | "socket: insufficient information"); |
|---|
| 500 | return false; |
|---|
| 501 | } |
|---|
| 502 | return true; |
|---|
| 503 | } |
|---|
| 504 | |
|---|
| 505 | BOX_LOG_SYS_ERROR("Failed to get peer credentials on socket"); |
|---|
| 506 | #endif |
|---|
| 507 | |
|---|
| 508 | // Not available |
|---|
| 509 | return false; |
|---|
| 510 | } |
|---|
| 511 | |
|---|