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