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