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