IBR-DTNSuite 0.6

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