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