Go to the documentation of this file.00001
00002
00003
00004
00005
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
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
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
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
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
00124 sock_address.sin_family = AF_INET;
00125
00126
00127 net.getAddress(&sock_address.sin_addr);
00128
00129
00130 sock_address.sin_port = htons(port);
00131
00132
00133 _socket = ::socket(sock_address.sin_family, SOCK_STREAM, 0);
00134
00135
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
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
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
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
00217 ::listen (_socket, 5);
00218
00219
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 }