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

ibrcommon/ibrcommon/net/vsocket.cpp

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

Generated on Wed Mar 30 2011 11:11:49 for IBR-DTNSuite by  doxygen 1.7.1