diff options
Diffstat (limited to 'lib/server/SocketStream.cpp')
-rw-r--r-- | lib/server/SocketStream.cpp | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/lib/server/SocketStream.cpp b/lib/server/SocketStream.cpp index 5cb252bd..95b4b4f4 100644 --- a/lib/server/SocketStream.cpp +++ b/lib/server/SocketStream.cpp @@ -18,7 +18,11 @@ #include <string.h> #ifndef WIN32 -#include <poll.h> + #include <poll.h> +#endif + +#ifdef HAVE_UCRED_H + #include <ucred.h> #endif #include "SocketStream.h" @@ -123,20 +127,23 @@ void SocketStream::Attach(int socket) THROW_EXCEPTION(ServerException, SocketAlreadyOpen) } - mSocketHandle = socket; ResetCounters(); + + mSocketHandle = socket; + mReadClosed = false; + mWriteClosed = false; } // -------------------------------------------------------------------------- // // Function -// Name: SocketStream::Open(int, char *, int) +// Name: SocketStream::Open(Socket::Type, char *, int) // Purpose: Opens a connection to a listening socket (INET or UNIX) // Created: 2003/07/31 // // -------------------------------------------------------------------------- -void SocketStream::Open(int Type, const char *Name, int Port) +void SocketStream::Open(Socket::Type Type, const std::string& rName, int Port) { if(mSocketHandle != INVALID_SOCKET_VALUE) { @@ -147,12 +154,14 @@ void SocketStream::Open(int Type, const char *Name, int Port) int sockDomain = 0; SocketAllAddr addr; int addrLen = 0; - Socket::NameLookupToSockAddr(addr, sockDomain, Type, Name, Port, addrLen); + Socket::NameLookupToSockAddr(addr, sockDomain, Type, rName, Port, addrLen); // Create the socket - mSocketHandle = ::socket(sockDomain, SOCK_STREAM, 0 /* let OS choose protocol */); + mSocketHandle = ::socket(sockDomain, SOCK_STREAM, + 0 /* let OS choose protocol */); if(mSocketHandle == INVALID_SOCKET_VALUE) { + BOX_LOG_SYS_ERROR("Failed to create a network socket"); THROW_EXCEPTION(ServerException, SocketOpenError) } @@ -163,28 +172,24 @@ void SocketStream::Open(int Type, const char *Name, int Port) #ifdef WIN32 DWORD err = WSAGetLastError(); ::closesocket(mSocketHandle); -#else - int err = errno; + BOX_LOG_WIN_ERROR_NUMBER("Failed to connect to socket " + "(type " << Type << ", name " << rName << + ", port " << Port << ")", err); +#else // !WIN32 + BOX_LOG_SYS_ERROR("Failed to connect to socket (type " << + Type << ", name " << rName << ", port " << Port << + ")"); ::close(mSocketHandle); -#endif - -#ifdef WIN32 - BOX_ERROR("Failed to connect to socket (type " << Type << - ", name " << Name << ", port " << Port << "): " << - GetErrorMessage(err) - ); -#else - BOX_ERROR("Failed to connect to socket (type " << Type << - ", name " << Name << ", port " << Port << "): " << - strerror(err) << " (" << err << ")" - ); -#endif +#endif // WIN32 mSocketHandle = INVALID_SOCKET_VALUE; THROW_EXCEPTION(ConnectionException, Conn_SocketConnectError) } ResetCounters(); + + mReadClosed = false; + mWriteClosed = false; } // -------------------------------------------------------------------------- @@ -220,7 +225,9 @@ int SocketStream::Read(void *pBuffer, int NBytes, int Timeout) else { // Bad! - THROW_EXCEPTION(ServerException, SocketPollError) + BOX_LOG_SYS_ERROR("Failed to poll socket"); + THROW_EXCEPTION(ServerException, + SocketPollError) } break; @@ -250,9 +257,12 @@ int SocketStream::Read(void *pBuffer, int NBytes, int Timeout) else { // Other error - THROW_EXCEPTION(ConnectionException, Conn_SocketReadError) + BOX_LOG_SYS_ERROR("Failed to read from socket"); + THROW_EXCEPTION(ConnectionException, + Conn_SocketReadError); } } + // Closed for reading? if(r == 0) { @@ -297,7 +307,9 @@ void SocketStream::Write(const void *pBuffer, int NBytes) { // Error. mWriteClosed = true; // assume can't write again - THROW_EXCEPTION(ConnectionException, Conn_SocketWriteError) + BOX_LOG_SYS_ERROR("Failed to write to socket"); + THROW_EXCEPTION(ConnectionException, + Conn_SocketWriteError); } // Knock off bytes sent @@ -310,7 +322,9 @@ void SocketStream::Write(const void *pBuffer, int NBytes) // Need to wait until it can send again? if(bytesLeft > 0) { - TRACE3("Waiting to send data on socket %d, (%d to send of %d)\n", mSocketHandle, bytesLeft, NBytes); + BOX_TRACE("Waiting to send data on socket " << + mSocketHandle << " (" << bytesLeft << + " of " << NBytes << " bytes left)"); // Wait for data to send. struct pollfd p; @@ -323,7 +337,10 @@ void SocketStream::Write(const void *pBuffer, int NBytes) // Don't exception if it's just a signal if(errno != EINTR) { - THROW_EXCEPTION(ServerException, SocketPollError) + BOX_LOG_SYS_ERROR("Failed to poll " + "socket"); + THROW_EXCEPTION(ServerException, + SocketPollError) } } } @@ -350,7 +367,9 @@ void SocketStream::Close() if(::close(mSocketHandle) == -1) #endif { - THROW_EXCEPTION(ServerException, SocketCloseError) + BOX_LOG_SYS_ERROR("Failed to close socket"); + // don't throw an exception here, assume that the socket was + // already closed or closing. } mSocketHandle = INVALID_SOCKET_VALUE; } @@ -380,6 +399,7 @@ void SocketStream::Shutdown(bool Read, bool Write) // Shut it down! if(::shutdown(mSocketHandle, how) == -1) { + BOX_LOG_SYS_ERROR("Failed to shutdown socket"); THROW_EXCEPTION(ConnectionException, Conn_SocketShutdownError) } } @@ -458,18 +478,37 @@ bool SocketStream::GetPeerCredentials(uid_t &rUidOut, gid_t &rGidOut) struct ucred cred; socklen_t credLen = sizeof(cred); - if(::getsockopt(mSocketHandle, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == 0) + if(::getsockopt(mSocketHandle, SOL_SOCKET, SO_PEERCRED, &cred, + &credLen) == 0) { rUidOut = cred.uid; rGidOut = cred.gid; return true; } + + BOX_LOG_SYS_ERROR("Failed to get peer credentials on socket"); +#endif + +#if defined HAVE_UCRED_H && HAVE_GETPEERUCRED + ucred_t *pucred = NULL; + if(::getpeerucred(mSocketHandle, &pucred) == 0) + { + rUidOut = ucred_geteuid(pucred); + rGidOut = ucred_getegid(pucred); + ucred_free(pucred); + if (rUidOut == -1 || rGidOut == -1) + { + BOX_ERROR("Failed to get peer credentials on " + "socket: insufficient information"); + return false; + } + return true; + } + + BOX_LOG_SYS_ERROR("Failed to get peer credentials on socket"); #endif // Not available return false; } - - - |