123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
-
- #ifdef WIN32
- //#include <io.h>
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #define errorNumber WSAGetLastError()
- #else
- #define errorNumber errno
- #define closesocket close
- #include <sys/socket.h>
- #endif
-
- #include <unistd.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <errno.h>
-
- #include <network/Socket.h>
-
- using namespace network;
-
- // -=- Socket initialisation
- static bool socketsInitialised = false;
- void network::initSockets() {
- if (socketsInitialised)
- return;
- #ifdef WIN32
- WORD requiredVersion = MAKEWORD(2,0);
- WSADATA initResult;
-
- if (WSAStartup(requiredVersion, &initResult) != 0)
- throw SocketException("unable to initialise Winsock2", errorNumber);
- #else
- signal(SIGPIPE, SIG_IGN);
- #endif
- socketsInitialised = true;
- }
-
- bool network::isSocketListening(int sock)
- {
- int listening = 0;
- socklen_t listening_size = sizeof(listening);
- if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN,
- (char *)&listening, &listening_size) < 0)
- return false;
- return listening != 0;
- }
-
- Socket::Socket(int fd)
- : instream(0), outstream(0),
- isShutdown_(false), queryConnection(false)
- {
- initSockets();
- setFd(fd);
- }
-
- Socket::Socket()
- : instream(0), outstream(0),
- isShutdown_(false), queryConnection(false)
- {
- initSockets();
- }
-
- Socket::~Socket()
- {
- if (instream && outstream)
- closesocket(getFd());
- delete instream;
- delete outstream;
- }
-
- // if shutdown() is overridden then the override MUST call on to here
- void Socket::shutdown()
- {
- isShutdown_ = true;
- ::shutdown(getFd(), 2);
- }
-
- bool Socket::isShutdown() const
- {
- return isShutdown_;
- }
-
- // Was there a "?" in the ConnectionFilter used to accept this Socket?
- void Socket::setRequiresQuery()
- {
- queryConnection = true;
- }
-
- bool Socket::requiresQuery() const
- {
- return queryConnection;
- }
-
- void Socket::setFd(int fd)
- {
- #ifndef WIN32
- // - By default, close the socket on exec()
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- #endif
-
- instream = new rdr::FdInStream(fd);
- outstream = new rdr::FdOutStream(fd);
- isShutdown_ = false;
- }
-
- SocketListener::SocketListener(int fd)
- : fd(fd), filter(0)
- {
- initSockets();
- }
-
- SocketListener::SocketListener()
- : fd(-1), filter(0)
- {
- initSockets();
- }
-
- SocketListener::~SocketListener()
- {
- if (fd != -1)
- closesocket(fd);
- }
-
- void SocketListener::shutdown()
- {
- #ifdef WIN32
- closesocket(fd);
- fd = -1;
- #else
- ::shutdown(fd, 2);
- #endif
- }
-
- Socket* SocketListener::accept() {
- int new_sock = -1;
-
- // Accept an incoming connection
- if ((new_sock = ::accept(fd, 0, 0)) < 0)
- throw SocketException("unable to accept new connection", errorNumber);
-
- // Create the socket object & check connection is allowed
- Socket* s = createSocket(new_sock);
- if (filter && !filter->verifyConnection(s)) {
- delete s;
- return NULL;
- }
-
- return s;
- }
-
- void SocketListener::listen(int sock)
- {
- // - Set it to be a listening socket
- if (::listen(sock, 5) < 0) {
- int e = errorNumber;
- closesocket(sock);
- throw SocketException("unable to set socket to listening mode", e);
- }
-
- fd = sock;
- }
|