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