• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

ibrcommon/ibrcommon/net/tcpserver.cpp

Go to the documentation of this file.
00001 /*
00002  * tcpserver.cpp
00003  *
00004  *  Created on: 30.07.2009
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/net/tcpserver.h"
00010 #include <string.h>
00011 #include <sys/types.h>
00012 #include <sys/socket.h>
00013 #include <sys/un.h>
00014 #include <arpa/inet.h>
00015 #include <fcntl.h>
00016 #include <errno.h>
00017 #include <sys/poll.h>
00018 
00019 #ifndef HAVE_BZERO
00020 #define bzero(s,n) (memset((s), '\0', (n)), (void) 0)
00021 #endif
00022 
00023 namespace ibrcommon
00024 {
00025         tcpserver::tcpserver(const ibrcommon::File &s)
00026          : _socket(0), _closed(false)
00027         {
00028                 struct sockaddr_un address;
00029                 size_t address_length;
00030 
00031                 _socket = socket(PF_UNIX, SOCK_STREAM, 0);
00032 
00033                 // check for errors
00034                 if (_socket < 0)
00035                 switch (_socket)
00036                 {
00037                 case EACCES:
00038                         throw SocketException("Permission  to create a socket of the specified type and/or protocol is denied.");
00039 
00040                 case EAFNOSUPPORT:
00041                         throw SocketException("The implementation does not support the specified address family.");
00042 
00043                 case EINVAL:
00044                         throw SocketException("Unknown protocol, or protocol family not available.");
00045 
00046                 case EMFILE:
00047                         throw SocketException("Process file table overflow.");
00048 
00049                 case ENFILE:
00050                         throw SocketException("The system limit on the total number of open files has been reached.");
00051 
00052                 case ENOBUFS:
00053                 case ENOMEM:
00054                         throw SocketException("Insufficient memory is available. The socket cannot be created until sufficient resources are freed.");
00055 
00056                 case EPROTONOSUPPORT:
00057                         throw SocketException("The protocol type or the specified protocol is not supported within this domain.");
00058 
00059                 default:
00060                         throw SocketException("cannot create listen socket");
00061                 }
00062 
00063                 // remove old sockets
00064                 unlink(s.getPath().c_str());
00065 
00066                 address.sun_family = AF_UNIX;
00067                 strcpy(address.sun_path, s.getPath().c_str());
00068                 address_length = sizeof(address.sun_family) + strlen(address.sun_path);
00069 
00070                 // bind to the socket
00071                 int bind_ret = ::bind(_socket, (struct sockaddr *) &address, address_length);
00072 
00073                 if ( bind_ret < 0) switch ( bind_ret )
00074                 {
00075                 case EBADF:
00076                         throw SocketException("sockfd ist kein gueltiger Deskriptor.");
00077 
00078                 // Die  folgenden  Fehlermeldungen  sind  spezifisch fr UNIX-Domnensockets (AF_UNIX)
00079 
00080                 case EINVAL:
00081                         throw SocketException("Die addr_len war  falsch  oder  der  Socket  gehrte  nicht  zur AF_UNIX Familie.");
00082 
00083                 case EROFS:
00084                         throw SocketException("Die Socket \"Inode\" sollte auf einem schreibgeschtzten Dateisystem residieren.");
00085 
00086                 case EFAULT:
00087                         throw SocketException("my_addr  weist  auf  eine  Adresse  auerhalb  des  erreichbaren Adressraumes zu.");
00088 
00089                 case ENAMETOOLONG:
00090                         throw SocketException("my_addr ist zu lang.");
00091 
00092                 case ENOENT:
00093                         throw SocketException("Die Datei existiert nicht.");
00094 
00095                 case ENOMEM:
00096                         throw SocketException("Nicht genug Kernelspeicher vorhanden.");
00097 
00098                 case ENOTDIR:
00099                         throw SocketException("Eine Komponente des Pfad-Prfixes ist kein Verzeichnis.");
00100 
00101                 case EACCES:
00102                         throw SocketException("Keine  berechtigung  um  eine  Komponente  des Pfad-prefixes zu durchsuchen.");
00103 
00104                 case ELOOP:
00105                         throw SocketException("my_addr enthlt eine Kreis-Referenz (zum  Beispiel  durch  einen symbolischen Link)");
00106 
00107                 default:
00108                         throw SocketException("cannot bind socket");
00109                 }
00110 
00111                 if(listen(_socket, 5) != 0)
00112                 {
00113                         throw SocketException("cannot listen to socket");
00114                 }
00115         }
00116 
00117         tcpserver::tcpserver(NetInterface net, int port, bool reuseaddr)
00118          : _socket(0), _closed(false)
00119         {
00120                 struct sockaddr_in sock_address;
00121                 bzero((char *) &sock_address, sizeof(sock_address));
00122 
00123                 // define the protocol family
00124                 sock_address.sin_family = AF_INET;
00125 
00126                 // set the local interface address
00127                 net.getAddress(&sock_address.sin_addr);
00128 
00129                 // set the local port
00130                 sock_address.sin_port = htons(port);
00131 
00132                 // Create socket for listening for client connection requests.
00133                 _socket = ::socket(sock_address.sin_family, SOCK_STREAM, 0);
00134 
00135                 // check for errors
00136                 if (_socket < 0)
00137                 switch (_socket)
00138                 {
00139                 case EACCES:
00140                         throw SocketException("Permission  to create a socket of the specified type and/or protocol is denied.");
00141 
00142                 case EAFNOSUPPORT:
00143                         throw SocketException("The implementation does not support the specified address family.");
00144 
00145                 case EINVAL:
00146                         throw SocketException("Unknown protocol, or protocol family not available.");
00147 
00148                 case EMFILE:
00149                         throw SocketException("Process file table overflow.");
00150 
00151                 case ENFILE:
00152                         throw SocketException("The system limit on the total number of open files has been reached.");
00153 
00154                 case ENOBUFS:
00155                 case ENOMEM:
00156                         throw SocketException("Insufficient memory is available. The socket cannot be created until sufficient resources are freed.");
00157 
00158                 case EPROTONOSUPPORT:
00159                         throw SocketException("The protocol type or the specified protocol is not supported within this domain.");
00160 
00161                 default:
00162                         throw SocketException("cannot create listen socket");
00163                 }
00164 
00165                 // enable reuse address if requested
00166                 if (reuseaddr)
00167                 {
00168                         int on = 1;
00169                         if (::setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
00170                         {
00171                                 throw SocketException("setsockopt(SO_REUSEADDR) failed");
00172                         }
00173                 }
00174 
00175                 // bind to the socket
00176                 int bind_ret = ::bind(_socket, (struct sockaddr *) &sock_address, sizeof(sock_address));
00177                 if (bind_ret < 0)
00178                 switch ( bind_ret )
00179                 {
00180                 case EBADF:
00181                         throw SocketException("sockfd ist kein gueltiger Deskriptor.");
00182 
00183                 // Die  folgenden  Fehlermeldungen  sind  spezifisch fr UNIX-Domnensockets (AF_UNIX)
00184 
00185                 case EINVAL:
00186                         throw SocketException("Die addr_len war  falsch  oder  der  Socket  gehrte  nicht  zur AF_UNIX Familie.");
00187 
00188                 case EROFS:
00189                         throw SocketException("Die Socket \"Inode\" sollte auf einem schreibgeschtzten Dateisystem residieren.");
00190 
00191                 case EFAULT:
00192                         throw SocketException("my_addr  weist  auf  eine  Adresse  auerhalb  des  erreichbaren Adressraumes zu.");
00193 
00194                 case ENAMETOOLONG:
00195                         throw SocketException("my_addr ist zu lang.");
00196 
00197                 case ENOENT:
00198                         throw SocketException("Die Datei existiert nicht.");
00199 
00200                 case ENOMEM:
00201                         throw SocketException("Nicht genug Kernelspeicher vorhanden.");
00202 
00203                 case ENOTDIR:
00204                         throw SocketException("Eine Komponente des Pfad-Prfixes ist kein Verzeichnis.");
00205 
00206                 case EACCES:
00207                         throw SocketException("Keine  berechtigung  um  eine  Komponente  des Pfad-prefixes zu durchsuchen.");
00208 
00209                 case ELOOP:
00210                         throw SocketException("my_addr enthlt eine Kreis-Referenz (zum  Beispiel  durch  einen symbolischen Link)");
00211 
00212                 default:
00213                         throw SocketException("cannot bind socket");
00214                 }
00215 
00216                 // listen on the socket, max. 5 concurrent awaiting connections
00217                 ::listen (_socket, 5);
00218 
00219                 // set linger option to the socket
00220                 struct linger linger;
00221 
00222                 linger.l_onoff = 1;
00223                 linger.l_linger = 1;
00224                 ::setsockopt(_socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
00225         }
00226 
00227         tcpserver::~tcpserver()
00228         {
00229                 close();
00230         }
00231 
00232         void tcpserver::close()
00233         {
00234                 _closed = true;
00235 		::close(_socket);
00236         }
00237 
00238         void tcpserver::shutdown()
00239         {
00240 		::shutdown(_socket, SHUT_RDWR);
00241         }
00242 
00243         tcpstream* tcpserver::accept()
00244         {
00245                 struct sockaddr_in cliaddr;
00246                 socklen_t len;
00247                 len = sizeof(cliaddr);
00248 
00249                 int ret = ::accept(_socket, (struct sockaddr *) &cliaddr, &len );
00250 
00251                 if (ret <= 0)
00252                 {
00253                         throw SocketException("socket closed");
00254                 }
00255 
00256                 return new tcpstream(ret);
00257         }
00258 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1