00001
00002
00003
00004
00005
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
00044 if (pipe(_interrupt_pipe) < 0)
00045 {
00046 printf ("Error %d creating pipe\n", errno);
00047 exit (-1);
00048 }
00049
00050
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
00089 _portmap[iface] = port;
00090 _typemap[iface] = socktype;
00091
00092
00093 ibrcommon::LinkManager::getInstance().registerInterfaceEvent(iface, this);
00094
00095
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
00119 ibrcommon::LinkManager::getInstance().unregisterInterfaceEvent(iface, this);
00120
00121
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
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
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
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
00297 if (_cb != NULL) _cb->eventNotify(evt);
00298
00299
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
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
00422 fds.clear();
00423
00424 while (true)
00425 {
00426 FD_ZERO(&fds_read);
00427
00428
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
00470 char buf[2];
00471 ::read(sock._interrupt_pipe[0], buf, 2);
00472
00473 if (!sock._unbind_queue.empty())
00474 {
00475
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
00496 sock.relisten();
00497
00498
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
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
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
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
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
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
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
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
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
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
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;
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
00740
00741
00742
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;
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
00763
00764
00765
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
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
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 }