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

ibrcommon/ibrcommon/net/vsocket.cpp

Go to the documentation of this file.
00001 /*
00002  * vsocket.cpp
00003  *
00004  *  Created on: 14.12.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/net/vsocket.h"
00009 #include <ibrcommon/thread/MutexLock.h>
00010 #include <ibrcommon/Logger.h>
00011 #include <algorithm>
00012 
00013 #include <netdb.h>
00014 #include <sys/socket.h>
00015 #include <sys/types.h>
00016 #include <netinet/tcp.h>
00017 #include <sys/un.h>
00018 #include <errno.h>
00019 #include <sstream>
00020 #include <string.h>
00021 #include <fcntl.h>
00022 #include <signal.h>
00023 #include <arpa/inet.h>
00024 
00025 namespace ibrcommon
00026 {
00027         vsocket::vsocket()
00028          : _options(0), interrupt(false)
00029         { }
00030 
00031         vsocket::~vsocket()
00032         {
00033                 ibrcommon::LinkManager::getInstance().unregisterAllEvents(this);
00034         }
00035 
00036         int vsocket::bind(const vsocket::vbind &b)
00037         {
00038                 _binds.push_back(b);
00039                 vsocket::vbind &vb = _binds.back();
00040 
00041                 try {
00042                         if (_options & VSOCKET_REUSEADDR) vb.set(VSOCKET_REUSEADDR);
00043                         if (_options & VSOCKET_BROADCAST) vb.set(VSOCKET_BROADCAST);
00044                         if (_options & VSOCKET_MULTICAST) vb.set(VSOCKET_MULTICAST);
00045                         if (_options & VSOCKET_MULTICAST_V6) vb.set(VSOCKET_MULTICAST_V6);
00046 
00047                         vb.bind();
00048 
00049                         if (_options & VSOCKET_LINGER) vb.set(VSOCKET_LINGER);
00050                         if (_options & VSOCKET_NODELAY) vb.set(VSOCKET_NODELAY);
00051                         if (_options & VSOCKET_NONBLOCKING) vb.set(VSOCKET_NONBLOCKING);
00052 
00053                         return vb._fd;
00054                 } catch (const vsocket_exception&) {
00055                         _binds.pop_back();
00056                         throw;
00057                 }
00058         }
00059 
00060         void vsocket::unbind(const vsocket::vbind &b)
00061         {
00062                 std::list<vsocket::vbind>::iterator iter = std::find( _binds.begin(), _binds.end(), b );
00063                 if (iter == _binds.end()) return;
00064                 vsocket::vbind &itm = (*iter);
00065                 itm.close();
00066                 _binds.erase(iter);
00067         }
00068 
00069         void vsocket::bind(const vinterface &iface, const int port, unsigned int socktype)
00070         {
00071                 if (iface.empty()) { bind(port); return; }
00072 
00073                 // watch at events on this interface
00074                 ibrcommon::LinkManager::getInstance().registerInterfaceEvent(iface, this);
00075 
00076                 // bind on all interfaces of "iface"!
00077                 const std::list<vaddress> addrlist = iface.getAddresses();
00078 
00079                 for (std::list<vaddress>::const_iterator iter = addrlist.begin(); iter != addrlist.end(); iter++)
00080                 {
00081                         if (!iter->isBroadcast())
00082                         {
00083                                 if (port == 0)
00084                                 {
00085                                         vsocket::vbind vb(iface, (*iter), socktype);
00086                                         bind( vb );
00087                                 }
00088                                 else
00089                                 {
00090                                         vsocket::vbind vb(iface, (*iter), port, socktype);
00091                                         bind( vb );
00092                                 }
00093                         }
00094                 }
00095         }
00096 
00097         void vsocket::unbind(const vinterface &iface, const int port)
00098         {
00099                 // delete the watch at events on this interface
00100                 ibrcommon::LinkManager::getInstance().unregisterInterfaceEvent(iface, this);
00101 
00102                 // unbind all interfaces on interface "iface"!
00103                 const std::list<vaddress> addrlist = iface.getAddresses();
00104 
00105                 for (std::list<vaddress>::const_iterator iter = addrlist.begin(); iter != addrlist.end(); iter++)
00106                 {
00107                         if (!iter->isBroadcast())
00108                         {
00109                                 unbind( *iter, port );
00110                         }
00111                 }
00112         }
00113 
00114         int vsocket::bind(const int port, unsigned int socktype)
00115         {
00116                 vaddress addr;
00117                 return bind( addr, port, socktype );
00118         }
00119 
00120         void vsocket::unbind(const int port)
00121         {
00122                 vaddress addr;
00123                 unbind( addr, port );
00124         }
00125 
00126         int vsocket::bind(const vaddress &address, const int port, unsigned int socktype)
00127         {
00128                 vsocket::vbind vb(address, port, socktype);
00129                 return bind( vb );
00130         }
00131 
00132         int vsocket::bind(const ibrcommon::File &file, unsigned int socktype)
00133         {
00134                 vsocket::vbind vb(file, socktype);
00135                 return bind( vb );
00136         }
00137 
00138         void vsocket::unbind(const vaddress &address, const int port)
00139         {
00140                 vsocket::vbind vb(address, port, 0);
00141                 unbind( vb );
00142         }
00143 
00144         void vsocket::unbind(const ibrcommon::File &file)
00145         {
00146                 vsocket::vbind vb(file, 0);
00147                 unbind( vb );
00148         }
00149 
00150         void vsocket::add(const int fd)
00151         {
00152                 vsocket::vbind vb(fd);
00153                 bind(vb);
00154         }
00155 
00156         void vsocket::listen(int connections)
00157         {
00158                 ibrcommon::MutexLock l(_bind_lock);
00159                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00160                                 iter != _binds.end(); iter++)
00161                 {
00162                         ibrcommon::vsocket::vbind &bind = (*iter);
00163                         bind.listen(connections);
00164                 }
00165         }
00166 
00167         void vsocket::set(const Option &o)
00168         {
00169                 // set options
00170                 _options |= o;
00171 
00172                 ibrcommon::MutexLock l(_bind_lock);
00173                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00174                                 iter != _binds.end(); iter++)
00175                 {
00176                         ibrcommon::vsocket::vbind &bind = (*iter);
00177                         bind.set(o);
00178                 }
00179         }
00180 
00181         void vsocket::unset(const Option &o)
00182         {
00183                 // unset options
00184                 _options &= ~(o);
00185 
00186                 ibrcommon::MutexLock l(_bind_lock);
00187                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00188                                 iter != _binds.end(); iter++)
00189                 {
00190                         ibrcommon::vsocket::vbind &bind = (*iter);
00191                         bind.unset(o);
00192                 }
00193         }
00194 
00195         void vsocket::close()
00196         {
00197                 ibrcommon::MutexLock l(_bind_lock);
00198                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00199                                 iter != _binds.end(); iter++)
00200                 {
00201                         ibrcommon::vsocket::vbind &bind = (*iter);
00202                         bind.close();
00203                         _binds.erase(iter++);
00204                 }
00205         }
00206 
00207         void vsocket::shutdown()
00208         {
00209                 ibrcommon::MutexLock l(_bind_lock);
00210                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00211                                 iter != _binds.end(); iter++)
00212                 {
00213                         ibrcommon::vsocket::vbind &bind = (*iter);
00214                         bind.shutdown();
00215                 }
00216 
00217                 interrupt = true;
00218         }
00219 
00220         int vsocket::fd()
00221         {
00222                 if (_binds.empty()) return -1;
00223                 return _binds.front()._fd;
00224         }
00225 
00226         void vsocket::eventInterfaceChanged(const vinterface &iface)
00227         {
00228                 IBRCOMMON_LOGGER_DEBUG(5) << "update socket cause of interface " << iface.toString() << IBRCOMMON_LOGGER_ENDL;
00229         }
00230 
00231         const std::list<int> vsocket::get(const ibrcommon::vinterface &iface, const ibrcommon::vaddress::Family f)
00232         {
00233                 std::list<int> ret;
00234 
00235                 ibrcommon::MutexLock l(_bind_lock);
00236                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00237                                 iter != _binds.end(); iter++)
00238                 {
00239                         ibrcommon::vsocket::vbind &bind = (*iter);
00240                         if (bind._interface == iface)
00241                         {
00242                                 if ((f == vaddress::VADDRESS_UNSPEC) || (f == bind._vaddress.getFamily())) ret.push_back(bind._fd);
00243                         }
00244                 }
00245 
00246                 return ret;
00247         }
00248 
00249         const std::list<int> vsocket::get(const ibrcommon::vaddress::Family f)
00250         {
00251                 std::list<int> ret;
00252 
00253                 ibrcommon::MutexLock l(_bind_lock);
00254                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = _binds.begin();
00255                                 iter != _binds.end(); iter++)
00256                 {
00257                         ibrcommon::vsocket::vbind &bind = (*iter);
00258                         if ((f == vaddress::VADDRESS_UNSPEC) || (f == bind._vaddress.getFamily())) ret.push_back(bind._fd);
00259                 }
00260 
00261                 return ret;
00262         }
00263 
00264         int sendto(ibrcommon::vsocket &sock, const void *buf, size_t n, const ibrcommon::vaddress &address, const unsigned int port)
00265         {
00266                 try {
00267                         size_t ret = 0;
00268                         int flags = 0;
00269 
00270                         struct addrinfo hints, *ainfo;
00271                         memset(&hints, 0, sizeof hints);
00272 
00273                         hints.ai_socktype = SOCK_DGRAM;
00274                         ainfo = address.addrinfo(&hints, port);
00275 
00276                         ibrcommon::MutexLock l(sock._bind_lock);
00277                         for (std::list<ibrcommon::vsocket::vbind>::iterator iter = sock._binds.begin();
00278                                         iter != sock._binds.end(); iter++)
00279                         {
00280                                 ibrcommon::vsocket::vbind &bind = (*iter);
00281                                 if (bind._vaddress.getFamily() == address.getFamily())
00282                                 {
00283                                         std::cout << "send to interface " << bind._interface.toString() << "; " << bind._vaddress.toString() << std::endl;
00284                                         ret = sendto(bind._fd, buf, n, flags, ainfo->ai_addr, ainfo->ai_addrlen);
00285                                 }
00286                         }
00287 
00288                         freeaddrinfo(ainfo);
00289 
00290                         return ret;
00291                 } catch (const vsocket_exception&) {
00292                         IBRCOMMON_LOGGER_DEBUG(5) << "can not send message to " << address.toString() << IBRCOMMON_LOGGER_ENDL;
00293                 }
00294 
00295                 return -1;
00296         }
00297 
00298         int recvfrom(int fd, char* data, size_t maxbuffer, std::string &address)
00299         {
00300                 struct sockaddr_in clientAddress;
00301                 socklen_t clientAddressLength = sizeof(clientAddress);
00302 
00303                 // data waiting
00304                 int ret = recvfrom(fd, data, maxbuffer, MSG_WAITALL, (struct sockaddr *) &clientAddress, &clientAddressLength);
00305 
00306                 char str[INET_ADDRSTRLEN];
00307                 inet_ntop(AF_INET, &(clientAddress.sin_addr), str, INET_ADDRSTRLEN);
00308 
00309                 address = std::string(str);
00310 
00311                 return ret;
00312         }
00313 
00314         void interrupt(ibrcommon::vsocket &sock, ibrcommon::Thread &th)
00315         {
00316                 sock.interrupt = true;
00317                 th.interrupt();
00318         }
00319 
00320         void select(ibrcommon::vsocket &sock, std::list<int> &fds, struct timespec *tv)
00321         {
00322                 sigset_t emptyset, blockset;
00323 
00324                 sigemptyset(&blockset);
00325                 sigaddset(&blockset, SIGINT);
00326                 pthread_sigmask(SIG_BLOCK, &blockset, NULL);
00327 
00328                 if (sock.interrupt)
00329                 {
00330                         sock.interrupt = false;
00331                         throw vsocket_interrupt("select interrupted");
00332                 }
00333 
00334                 fd_set fds_read;
00335 
00336                 int high_fd = 0;
00337                 int fd_count = 0;
00338 
00339                 // clear the fds list
00340                 fds.clear();
00341 
00342                 while (true)
00343                 {
00344                         FD_ZERO(&fds_read);
00345 
00346                         {
00347                                 ibrcommon::MutexLock l(sock._bind_lock);
00348                                 std::list<ibrcommon::vsocket::vbind> &socks = sock._binds;
00349                                 for (std::list<ibrcommon::vsocket::vbind>::iterator iter = socks.begin();
00350                                                 iter != socks.end(); iter++)
00351                                 {
00352                                         ibrcommon::vsocket::vbind &bind = (*iter);
00353 
00354                                         FD_SET(bind._fd, &fds_read);
00355                                         if (high_fd < bind._fd) high_fd = bind._fd;
00356 
00357                                         fd_count++;
00358                                 }
00359                         }
00360 
00361                         if (fd_count == 0)
00362                                 throw vsocket_exception("select error");
00363 
00364                         sigemptyset(&emptyset);
00365                         int res = ::pselect(high_fd + 1, &fds_read, NULL, NULL, tv, &emptyset);
00366 
00367                         if (sock.interrupt)
00368                         {
00369                                 sock.interrupt = false;
00370                                 throw vsocket_interrupt("select interrupted");
00371                         }
00372 
00373                         if (res < 0)
00374                                 throw vsocket_exception("select error");
00375 
00376                         if (res == 0)
00377                                 throw vsocket_timeout("select timeout");
00378 
00379                         ibrcommon::MutexLock l(sock._bind_lock);
00380                         std::list<ibrcommon::vsocket::vbind> &socks = sock._binds;
00381                         for (std::list<ibrcommon::vsocket::vbind>::iterator iter = socks.begin();
00382                                         iter != socks.end(); iter++)
00383                         {
00384                                 ibrcommon::vsocket::vbind &bind = (*iter);
00385 
00386                                 if (FD_ISSET(bind._fd, &fds_read))
00387                                 {
00388                                         fds.push_back(bind._fd);
00389                                 }
00390                         }
00391 
00392                         if (fds.size() > 0) return;
00393                 }
00394         }
00395 
00396         vsocket::vbind::vbind(const int fd)
00397          : _type(BIND_CUSTOM), _vaddress(), _port(), _fd(fd)
00398         {
00399                 // check for errors
00400                 if (_fd < 0) try {
00401                         check_socket_error( _fd );
00402                 } catch (...) {
00403                         close();
00404                         throw;
00405                 }
00406         }
00407 
00408         vsocket::vbind::vbind(const vaddress &address, unsigned int socktype)
00409          : _type(BIND_ADDRESS_NOPORT), _vaddress(address), _port(0), _fd(0)
00410         {
00411                 _fd = socket(address.getFamily(), socktype, 0);
00412 
00413                 // check for errors
00414                 if (_fd < 0) try {
00415                         check_socket_error( _fd );
00416                 } catch (...) {
00417                         close();
00418                         throw;
00419                 }
00420         }
00421 
00422         vsocket::vbind::vbind(const vaddress &address, const int port, unsigned int socktype)
00423          : _type(BIND_ADDRESS), _vaddress(address), _port(port), _fd(0)
00424         {
00425                 _fd = socket(address.getFamily(), socktype, 0);
00426 
00427                 // check for errors
00428                 if (_fd < 0) try {
00429                         check_socket_error( _fd );
00430                 } catch (...) {
00431                         close();
00432                         throw;
00433                 }
00434         }
00435 
00436         vsocket::vbind::vbind(const ibrcommon::vinterface &iface, const vaddress &address, unsigned int socktype)
00437          : _type(BIND_ADDRESS_NOPORT), _vaddress(address), _port(0), _interface(iface), _fd(0)
00438         {
00439                 _fd = socket(address.getFamily(), socktype, 0);
00440 
00441                 // check for errors
00442                 if (_fd < 0) try {
00443                         check_socket_error( _fd );
00444                 } catch (...) {
00445                         close();
00446                         throw;
00447                 }
00448         }
00449 
00450         vsocket::vbind::vbind(const ibrcommon::vinterface &iface, const vaddress &address, const int port, unsigned int socktype)
00451          : _type(BIND_ADDRESS), _vaddress(address), _port(port), _interface(iface), _fd(0)
00452         {
00453                 _fd = socket(address.getFamily(), socktype, 0);
00454 
00455                 // check for errors
00456                 if (_fd < 0) try {
00457                         check_socket_error( _fd );
00458                 } catch (...) {
00459                         close();
00460                         throw;
00461                 }
00462         }
00463 
00464         vsocket::vbind::vbind(const ibrcommon::File &file, unsigned int socktype)
00465          : _type(BIND_FILE), _port(0), _file(file), _fd(0)
00466         {
00467                 _fd = socket(AF_UNIX, socktype, 0);
00468 
00469                 // check for errors
00470                 if (_fd < 0) try {
00471                         check_socket_error( _fd );
00472                 } catch (...) {
00473                         close();
00474                         throw;
00475                 }
00476         }
00477 
00478         vsocket::vbind::~vbind()
00479         {
00480         }
00481 
00482         void vsocket::vbind::bind()
00483         {
00484                 int bind_ret = 0;
00485 
00486                 switch (_type)
00487                 {
00488                         case BIND_CUSTOM:
00489                         {
00490                                 // custom fd, do nothing
00491                                 break;
00492                         }
00493 
00494                         case BIND_ADDRESS_NOPORT:
00495                         {
00496                                 struct addrinfo hints, *res;
00497                                 memset(&hints, 0, sizeof hints);
00498 
00499                                 hints.ai_family = _vaddress.getFamily();
00500                                 hints.ai_socktype = SOCK_STREAM;
00501                                 hints.ai_flags = AI_PASSIVE;
00502 
00503                                 res = _vaddress.addrinfo(&hints);
00504                                 bind_ret = ::bind(_fd, res->ai_addr, res->ai_addrlen);
00505                                 freeaddrinfo(res);
00506                                 break;
00507                         }
00508 
00509                         case BIND_ADDRESS:
00510                         {
00511                                 struct addrinfo hints, *res;
00512                                 memset(&hints, 0, sizeof hints);
00513 
00514                                 hints.ai_family = _vaddress.getFamily();
00515                                 hints.ai_socktype = SOCK_STREAM;
00516                                 hints.ai_flags = AI_PASSIVE;
00517 
00518                                 res = _vaddress.addrinfo(&hints, _port);
00519                                 bind_ret = ::bind(_fd, res->ai_addr, res->ai_addrlen);
00520                                 freeaddrinfo(res);
00521                                 break;
00522                         }
00523 
00524                         case BIND_FILE:
00525                         {
00526                                 // remove old sockets
00527                                 unlink(_file.getPath().c_str());
00528 
00529                                 struct sockaddr_un address;
00530                                 size_t address_length;
00531 
00532                                 address.sun_family = AF_UNIX;
00533                                 strcpy(address.sun_path, _file.getPath().c_str());
00534                                 address_length = sizeof(address.sun_family) + strlen(address.sun_path);
00535 
00536                                 // bind to the socket
00537                                 bind_ret = ::bind(_fd, (struct sockaddr *) &address, address_length);
00538 
00539                                 break;
00540                         }
00541                 }
00542 
00543                 if ( bind_ret < 0) check_bind_error( bind_ret );
00544         }
00545 
00546         void vsocket::vbind::listen(int connections)
00547         {
00548                 if(::listen(_fd, connections) != 0)
00549                 {
00550                         throw ibrcommon::vsocket_exception("cannot listen to socket");
00551                 }
00552         }
00553 
00554         void vsocket::vbind::set(const vsocket::Option &o)
00555         {
00556                 switch (o)
00557                 {
00558                         case VSOCKET_REUSEADDR:
00559                         {
00560                                 int on = 1;
00561                                 if (::setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
00562                                 {
00563                                         throw vsocket_exception("setsockopt(SO_REUSEADDR) failed");
00564                                 }
00565                                 break;
00566                         }
00567 
00568                         case VSOCKET_LINGER:
00569                         {
00570                                 int set = 1;
00571                                 ::setsockopt(_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set));
00572                                 break;
00573                         }
00574 
00575                         case VSOCKET_NODELAY:
00576                         {
00577                                 // set linger option to the socket
00578                                 struct linger linger;
00579 
00580                                 linger.l_onoff = 1;
00581                                 linger.l_linger = 1;
00582                                 ::setsockopt(_fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
00583                                 break;
00584                         }
00585 
00586                         case VSOCKET_BROADCAST:
00587                         {
00588                                 int b = 1;
00589                                 if ( ::setsockopt(_fd, SOL_SOCKET, SO_BROADCAST, (char*)&b, sizeof(b)) == -1 )
00590                                 {
00591                                         throw vsocket_exception("cannot enable broadcasts");
00592                                 }
00593                                 break;
00594                         }
00595 
00596                         case VSOCKET_NONBLOCKING:
00597                         {
00598                                 int opts;
00599 
00600                                 opts = fcntl(_fd,F_GETFL);
00601                                 if (opts < 0) {
00602                                         throw vsocket_exception("cannot set non-blocking");
00603                                 }
00604                                 opts = (opts | O_NONBLOCK);
00605                                 if (fcntl(_fd,F_SETFL,opts) < 0) {
00606                                         throw vsocket_exception("cannot set non-blocking");
00607                                 }
00608                                 break;
00609                         }
00610 
00611                         case VSOCKET_MULTICAST:
00612                         {
00613                                 int val = 1;
00614                                 if ( ::setsockopt(_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
00615                                 {
00616                                         throw vsocket_exception("setsockopt(IP_MULTICAST_LOOP)");
00617                                 }
00618 
00619                                 u_char ttl = 255; // Multicast TTL
00620                                 if ( ::setsockopt(_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0 )
00621                                 {
00622                                         throw vsocket_exception("setsockopt(IP_MULTICAST_TTL)");
00623                                 }
00624 
00625 //                              u_char ittl = 255; // IP TTL
00626 //                              if ( ::setsockopt(_fd, IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl)) < 0 )
00627 //                              {
00628 //                                      throw vsocket_exception("setsockopt(IP_TTL)");
00629 //                              }
00630                                 break;
00631                         }
00632 
00633                         case VSOCKET_MULTICAST_V6:
00634                         {
00635                                 int val = 1;
00636                                 if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
00637                                 {
00638                                         throw vsocket_exception("setsockopt(IPV6_MULTICAST_LOOP)");
00639                                 }
00640 
00641                                 u_char ttl = 255; // Multicast TTL
00642                                 if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0 )
00643                                 {
00644                                         throw vsocket_exception("setsockopt(IPV6_MULTICAST_HOPS)");
00645                                 }
00646                                 
00647 
00648 //                              u_char ittl = 255; // IP TTL
00649 //                              if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &ittl, sizeof(ittl)) < 0 )
00650 //                              {
00651 //                                      throw vsocket_exception("setsockopt(IPV6_HOPLIMIT)");
00652 //                              }
00653                                 break;
00654                         }
00655                 }
00656         }
00657 
00658         void vsocket::vbind::unset(const vsocket::Option &o)
00659         {
00660                 switch (o)
00661                 {
00662                         case VSOCKET_REUSEADDR:
00663                         {
00664                                 int on = 0;
00665                                 if (::setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
00666                                 {
00667                                         throw vsocket_exception("setsockopt(SO_REUSEADDR) failed");
00668                                 }
00669                                 break;
00670                         }
00671 
00672                         case VSOCKET_LINGER:
00673                         {
00674                                 int set = 0;
00675                                 ::setsockopt(_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set));
00676                                 break;
00677                         }
00678 
00679                         case VSOCKET_NODELAY:
00680                         {
00681                                 // set linger option to the socket
00682                                 struct linger linger;
00683 
00684                                 linger.l_onoff = 0;
00685                                 linger.l_linger = 0;
00686                                 ::setsockopt(_fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
00687                                 break;
00688                         }
00689 
00690                         case VSOCKET_BROADCAST:
00691                         {
00692                                 int b = 0;
00693                                 if ( ::setsockopt(_fd, SOL_SOCKET, SO_BROADCAST, (char*)&b, sizeof(b)) == -1 )
00694                                 {
00695                                         throw vsocket_exception("cannot disable broadcasts");
00696                                 }
00697                         }
00698 
00699                         case VSOCKET_NONBLOCKING:
00700                         {
00701                                 int opts;
00702 
00703                                 opts = fcntl(_fd,F_GETFL);
00704                                 if (opts < 0) {
00705                                         throw vsocket_exception("cannot unset non-blocking");
00706                                 }
00707                                 opts = (opts & (~O_NONBLOCK));
00708                                 if (fcntl(_fd,F_SETFL,opts) < 0) {
00709                                         throw vsocket_exception("cannot unset non-blocking");
00710                                 }
00711                                 break;
00712                         }
00713 
00714                         case VSOCKET_MULTICAST:
00715                         {
00716                                 int val = 0;
00717                                 if ( ::setsockopt(_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
00718                                 {
00719                                         throw vsocket_exception("setsockopt(IP_MULTICAST_LOOP)");
00720                                 }
00721                         }
00722 
00723                         case VSOCKET_MULTICAST_V6:
00724                         {
00725                                 int val = 0;
00726                                 if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
00727                                 {
00728                                         throw vsocket_exception("setsockopt(IPV6_MULTICAST_LOOP)");
00729                                 }
00730                         }
00731                 }
00732         }
00733 
00734         void vsocket::vbind::close()
00735         {
00736                 if (_fd == -1) return;
00737 		::close(_fd);
00738                 _fd = -1;
00739         }
00740 
00741         void vsocket::vbind::shutdown()
00742         {
00743 		::shutdown(_fd, SHUT_RDWR);
00744         }
00745 
00746         bool vsocket::vbind::operator==(const vbind &obj) const
00747         {
00748                 if (obj._type != _type) return false;
00749                 if (obj._port != _port) return false;
00750                 if (obj._vaddress != _vaddress) return false;
00751                 if (obj._file.getPath() != _file.getPath()) return false;
00752 
00753                 return true;
00754         }
00755 
00756         void vsocket::vbind::check_socket_error(const int err) const
00757         {
00758                 switch (err)
00759                 {
00760                 case EACCES:
00761                         throw vsocket_exception("Permission  to create a socket of the specified type and/or protocol is denied.");
00762 
00763                 case EAFNOSUPPORT:
00764                         throw vsocket_exception("The implementation does not support the specified address family.");
00765 
00766                 case EINVAL:
00767                         throw vsocket_exception("Unknown protocol, or protocol family not available.");
00768 
00769                 case EMFILE:
00770                         throw vsocket_exception("Process file table overflow.");
00771 
00772                 case ENFILE:
00773                         throw vsocket_exception("The system limit on the total number of open files has been reached.");
00774 
00775                 case ENOBUFS:
00776                 case ENOMEM:
00777                         throw vsocket_exception("Insufficient memory is available. The socket cannot be created until sufficient resources are freed.");
00778 
00779                 case EPROTONOSUPPORT:
00780                         throw vsocket_exception("The protocol type or the specified protocol is not supported within this domain.");
00781 
00782                 default:
00783                         throw vsocket_exception("cannot create socket");
00784                 }
00785         }
00786 
00787         void vsocket::vbind::check_bind_error(const int err) const
00788         {
00789                 switch ( err )
00790                 {
00791                 case EBADF:
00792                         throw vsocket_exception("sockfd ist kein gueltiger Deskriptor.");
00793 
00794                 // Die  folgenden  Fehlermeldungen  sind  spezifisch fr UNIX-Domnensockets (AF_UNIX)
00795 
00796                 case EINVAL:
00797                         throw vsocket_exception("Die addr_len war  falsch  oder  der  Socket  gehrte  nicht  zur AF_UNIX Familie.");
00798 
00799                 case EROFS:
00800                         throw vsocket_exception("Die Socket \"Inode\" sollte auf einem schreibgeschtzten Dateisystem residieren.");
00801 
00802                 case EFAULT:
00803                         throw vsocket_exception("my_addr  weist  auf  eine  Adresse  auerhalb  des  erreichbaren Adressraumes zu.");
00804 
00805                 case ENAMETOOLONG:
00806                         throw vsocket_exception("my_addr ist zu lang.");
00807 
00808                 case ENOENT:
00809                         throw vsocket_exception("Die Datei existiert nicht.");
00810 
00811                 case ENOMEM:
00812                         throw vsocket_exception("Nicht genug Kernelspeicher vorhanden.");
00813 
00814                 case ENOTDIR:
00815                         throw vsocket_exception("Eine Komponente des Pfad-Prfixes ist kein Verzeichnis.");
00816 
00817                 case EACCES:
00818                         throw vsocket_exception("Keine  berechtigung  um  eine  Komponente  des Pfad-prefixes zu durchsuchen.");
00819 
00820                 case ELOOP:
00821                         throw vsocket_exception("my_addr enthlt eine Kreis-Referenz (zum  Beispiel  durch  einen symbolischen Link)");
00822 
00823                 default:
00824                         throw vsocket_exception("cannot bind socket");
00825                 }
00826         }
00827 }

Generated on Thu Mar 10 2011 15:44:03 for IBR-DTNSuite by  doxygen 1.7.1