/*************************************************************************** KRSocket.cpp - description ------------------- begin : Tue May 2 2000 copyright : (C) 2000 by Martin Heni email : martin@heni-online.de ***************************************************************************/ /*************************************************************************** * * * This program 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. * * * ***************************************************************************/ /*************************************************************************** FILENAME| - description ------------------- begin : Tue Apr 4 2000 copyright : (C) |1995-2000 by Martin Heni email : martin@heni-online.de ***************************************************************************/ /*************************************************************************** * * * This program 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 file is part of the KDE libraries * Copyright (C) 1997 Torben Weis (weis@kde.org) * * $Id$ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. **/ #include #include #include // on Linux/libc5, this includes linux/socket.h where SOMAXCONN is defined #include #include #include #include #include #include #include "KRSocket.h" #include #include #include // defines MAXDNAME under Solaris #include #include #include #include #include #include #include #ifdef HAVE_SYSENT_H #include #endif #ifdef TIME_WITH_SYS_TIME #include #endif // Play it safe, use a reasonable default, if SOMAXCONN was nowhere defined. #ifndef SOMAXCONN #warning Your header files do not seem to support SOMAXCONN #define SOMAXCONN 5 #endif #include #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 108 // this is the value, I found under Linux #endif #include KRServerSocket::KRServerSocket( const char *_path, int optname, int value, int level) : notifier( 0L ), sock( -1 ) { domain = PF_UNIX; if ( !init ( _path,optname,value,level ) ) { tqFatal("Error constructing PF_UNIX domain server socket\n"); return; } notifier = new TQSocketNotifier( sock, TQSocketNotifier::Read ); connect( notifier, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( slotAccept(int) ) ); } KRServerSocket::KRServerSocket( const char *_path ) : notifier( 0L ), sock( -1 ) { domain = PF_UNIX; if ( !init ( _path ) ) { tqFatal("Error constructing PF_UNIX domain server socket\n"); return; } notifier = new TQSocketNotifier( sock, TQSocketNotifier::Read ); connect( notifier, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( slotAccept(int) ) ); } KRServerSocket::KRServerSocket( unsigned short int _port ) : notifier( 0L ), sock( -1 ) { domain = PF_INET; if ( !init ( _port ) ) { // fatal("Error constructing\n"); return; } notifier = new TQSocketNotifier( sock, TQSocketNotifier::Read ); connect( notifier, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( slotAccept(int) ) ); } KRServerSocket::KRServerSocket( unsigned short int _port,int optname,int value,int level ) : notifier( 0L ), sock( -1 ) { domain = PF_INET; if ( !init ( _port,optname,value,level ) ) { // fatal("Error constructing\n"); return; } notifier = new TQSocketNotifier( sock, TQSocketNotifier::Read ); connect( notifier, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( slotAccept(int) ) ); } bool KRServerSocket::init( const char *_path ) { return init(_path,0); } bool KRServerSocket::init( const char *_path,int optname,int value,int level ) { if ( domain != PF_UNIX ) return false; int l = strlen( _path ); if ( l > UNIX_PATH_MAX - 1 ) { kdWarning() << "Too long PF_UNIX domain name: " << _path << endl; return false; } sock = ::socket( PF_UNIX, SOCK_STREAM, 0 ); if (sock < 0) { kdWarning() << "Could not create socket" << endl; return false; } // Heni - 05042000 if (optname>0) { socklen_t len=sizeof(value); if (-1==setsockopt(sock,level,optname,(char*)&value,len )) { kdWarning() << "Could not set socket options." << endl; } } // end Heni unlink(_path ); struct sockaddr_un name; name.sun_family = AF_UNIX; strcpy( name.sun_path, _path ); if ( bind( sock, (struct sockaddr*) &name,sizeof( name ) ) < 0 ) { kdWarning() << "Could not bind to socket." << endl; ::close( sock ); sock = -1; return false; } if ( chmod( _path, 0600) < 0 ) { kdWarning() << "Could not setupt premissions for server socket." << endl; ::close( sock ); sock = -1; return false; } if ( listen( sock, SOMAXCONN ) < 0 ) { kdWarning() << "Error listening on socket." << endl; ::close( sock ); sock = -1; return false; } return true; } bool KRServerSocket::init( unsigned short int _port ) { return init(_port,0); } bool KRServerSocket::init( unsigned short int _port,int optname,int value,int level ) { if ( #ifdef INET6 ( domain != PF_INET6 ) && #endif ( domain != PF_INET ) ) return false; sock = ::socket( domain, SOCK_STREAM, 0 ); if (sock < 0) { kdWarning() << "Could not create socket" << endl; return false; } // Heni - 05042000 if (optname>0) { socklen_t len=sizeof(value); if (-1==setsockopt(sock,level,optname,(char*)&value,len )) { kdWarning() << "Could not set socket options." << endl; } } // end Heni if (domain == AF_INET) { sockaddr_in name; name.sin_family = domain; name.sin_port = htons( _port ); name.sin_addr.s_addr = htonl(INADDR_ANY); if ( bind( sock, (struct sockaddr*) &name,sizeof( name ) ) < 0 ) { kdWarning() << "Could not bind to socket." << endl; ::close( sock ); sock = -1; return false; } } #ifdef INET6 else if (domain == AF_INET6) { sockaddr_in6 name; name.sin6_family = domain; name.sin6_flowinfo = 0; name.sin6_port = htons(_port); memcpy(&name.sin6_addr, &in6addr_any, sizeof(in6addr_any)); if ( bind( sock, (struct sockaddr*) &name,sizeof( name ) ) < 0 ) { kdWarning() << "Could not bind to socket!" << endl; ::close( sock ); sock = -1; return false; } } #endif if ( listen( sock, SOMAXCONN ) < 0 ) { kdWarning() << "Error listening on socket" << endl; ::close( sock ); sock = -1; return false; } return true; } unsigned short int KRServerSocket::port() { if ( domain != PF_INET ) return false; ksockaddr_in name; socklen_t len = sizeof(name); getsockname(sock, (struct sockaddr *) &name, &len); return ntohs(get_sin_port(name)); } unsigned long KRServerSocket::ipv4_addr() { if ( domain != PF_INET ) return 0; sockaddr_in name; socklen_t len = sizeof(name); getsockname(sock, (struct sockaddr *) &name, &len); if (name.sin_family == AF_INET) // It's IPv4 return ntohl(name.sin_addr.s_addr); #ifdef INET6 else if (name.sin_family == AF_INET6) // It's IPv6 Ah. return 0; #endif else // We dunno what it is return 0; } void KRServerSocket::slotAccept( int ) { if ( domain == PF_INET ) { ksockaddr_in clientname; int new_sock; socklen_t size = sizeof(clientname); if ((new_sock = accept (sock, (struct sockaddr *) &clientname, &size)) < 0) { kdWarning() << "Error accepting" << endl; return; } emit accepted( new TDESocket( new_sock ) ); } else if ( domain == PF_UNIX ) { struct sockaddr_un clientname; int new_sock; socklen_t size = sizeof(clientname); if ((new_sock = accept (sock, (struct sockaddr *) &clientname, &size)) < 0) { kdWarning() << "Error accepting" << endl; return; } emit accepted( new TDESocket( new_sock ) ); } } KRServerSocket::~KRServerSocket() { delete notifier; close( sock ); } #include "KRSocket.moc"