⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wysockfile.cpp

📁 一个不错
💻 CPP
字号:
/* Copyright is licensed under GNU LGPL.                 by I.J.Wang 2003   Note: Implement assume that the open socket on PF_??? access address of         AF_??? (exact value and name).*/#define WYLIB_SOURCE#include "wysockfile.h"#include "wy_atdestroy.h"#include <netinet/in.h> #include <new>                // for _alloc#include <typeinfo>#include "wysockaddrlocal.h"  // for sockname(..)const char WySockFile::class_name[]="WySockFile";Wy__FtBits WySockFile::cftbits(void) WY__NOTHROW__{ static const Wy__FtBits fb( Wy__FtBits(S_IFSOCK) ); return(fb);};// [Internal] Get the socket family (::getsockname) of fd and store //            into the argument given reference family//// [Ret] errno//       EBADF//       EMFILE   (this is converted from ENOBUFS=Insufficient resource..//                 to EMFILE=Too many open fd, so impl. need not convert//                 again)//static int get_sockfamily(int& family, Wy__TypeFD fd){ struct ::sockaddr addr; socklen_t slen=sizeof(addr); if(::getsockname(fd,&addr,&slen)!=0) {   switch(errno) {     case ENOBUFS: return(EMFILE);     case EBADF:    // FALL_THROUGH     case ENOTSOCK: // FALL_THROUGH     default: return(EBADF);   } } family=addr.sa_family; return(0);};WySockFile::WySockFile()try : WyByteFlow(cftbits()), _family(DefaultFamily) {}catch(const WyByteFlow::Reply& e) {  WY_THROW( Reply(e) );}catch(const WyRet& e) { WY_NDEBUG_MSG(e);  WY_THROW( WyRet(e) );};WySockFile::WySockFile(WyFileHandle fh)try : WyByteFlow(fh,cftbits()), _family(DefaultFamily) { if(fh.is_default()==false) {   const int v( get_sockfamily(_family,this->wy_fd()) );   if(v!=0) {     WY_THROW( Reply(WyReply(v)) );   } }}catch(const Reply&) {  throw;}catch(const WyByteFlow::Reply& e) {   WY_THROW( Reply(e) );}catch(const WyRet& e) { WY_NDEBUG_MSG(e);  WY_THROW( WyRet(e) );};WySockFile::WySockFile(const WySysFile& sktf)try : WyByteFlow(sktf,cftbits()), _family(DefaultFamily) { if(this->is_default()==false) {   const int v( get_sockfamily(_family,this->wy_fd()) );   if(v!=0) {     WY_THROW( Reply(WyReply(v)) );   } }}catch(const Reply&) { throw;}catch(const WyByteFlow::Reply& e) {  WY_THROW( Reply(e) );}catch(const WyRet& e) { WY_NDEBUG_MSG(e);  WY_THROW( WyRet(e) );};WySockFile::WySockFile(int domain, int type, int proto)try : WyByteFlow(cftbits()), _family(DefaultFamily) { WyRet r(this->reset(domain,type,proto)); if(r!=Ok) {   WY_THROW( Reply(r) ); }}catch(const Reply&) {  throw;}catch(const WyByteFlow::Reply& e) {  WY_THROW( Reply(e) );}catch(...) {  WY_THROW( WyRet() );};WySockFile::WySockFile(const WySockFile& sktf)try : WyByteFlow(sktf,cftbits()), _family(sktf._family) {}catch(const WyByteFlow::Reply& e) {  WY_THROW( Reply(e) );}catch(const WyRet& e) { WY_NDEBUG_MSG(e);  WY_THROW( WyRet(e) );};WySockFile::WySockFile(WySockFile& sktf, Wy::ByMove_t) WY__TSPC() : WyByteFlow(sktf,Wy::ByMove), _family(sktf._family){};WyRet WySockFile::reset(void){ _family=DefaultFamily; const WyRet r( WyByteFlow::reset() ); if(r!=Ok) {   WY_RETURN(r); } return(Ok);};WyRet WySockFile::reset(WyFileHandle fh){ if(fh.is_default()) {   this->reset();   return(Ok); } int t_family; const int v( get_sockfamily(t_family,fh.fd()) ); if(v!=0) {   WY_RETURN(WyReply(v)); } const WyRet r( WyByteFlow::reset(fh) ); if(r!=Ok) {   WY_RETURN(r); } _family=t_family; return(Ok);};WyRet WySockFile::reset(const WySysFile& sktf){ if(sktf.is_default()) {   // note: can't this->reset(), for type check reason.   const WyRet r( WyByteFlow::reset(sktf) );   if(r!=Ok) {     WY_RETURN(r);   }   _family=DefaultFamily;   return(Ok); } int t_family; const WySockFile* p= dynamic_cast<const WySockFile*>(&sktf); if(p==0) {   const int v( get_sockfamily(t_family,sktf.wy_fd()) );   if(v!=0) {     WY_RETURN(WyReply(v));   } } else {   t_family=p->family(); } const WyRet r( WyByteFlow::reset(sktf) ); if(r!=Ok) {   WY_RETURN(r); } _family=t_family; return(Ok);};WyRet WySockFile::reset(int domain, int type, int proto){ const Wy__TypeFD s=::socket(domain,type,proto); if(s==-1) {   WY_RETURN(errno); } int t_family; const int v( get_sockfamily(t_family,s) ); if(v!=0) {   WY_RETURN(WyReply(v)); } if(t_family!=domain) {   WY_THROW( WyRet() );    // WySockFile assumes domain==family (value) } const WyRet r( WyByteFlow::reset( WyFileHandle(s) ) ); if(r!=Ok) {   WY_RETURN(r); } _family=t_family; return(Ok);};WyRet WySockFile::_swap(WySysFile& sktf) WY__TSPC(){ WyRet r( WyByteFlow::_swap(sktf) ); if(r!=Ok) {   WY_RETURN(r); } Wy__Base::vswap(_family,dynamic_cast<WySockFile&>(sktf)._family); return(Ok);};WySockFile* WySockFile::_alloc(WyRet& r) consttry { if(WY__EQU_TYPEID(*this,WySockFile)==false) {   r=Wym_ENOSYS; WY_HERE(r);        // _alloc not overridden   return(NULL); } WySockFile* p=new(std::nothrow) WySockFile(); if(p==NULL) {   r=Wym_ENOMEM; WY_HERE(r); } else {   r=Ok; } return(p);}catch(const Reply& e) { r=e; WY_HERE(r); return(NULL);}catch(const WyRet& e) { WY_NDEBUG_MSG(e); WY_THROW( WyRet(e) );};int WySockFile::family(void) const WY__TSPC(){ return _family;};WyRet WySockFile::shutdown(int how){ if(::shutdown(this->wy_fd(),how)==0) {   return(Ok); } WY_RETURN(errno);};WyRet WySockFile::bind(const Wy_SockAddr& addr){ if(this->is_default()) {   WY_RETURN(Wym_EBADF);       // Prevent Wym_EAFNOSUPPORT reported first }                             // this step may be unnecessary if(addr.c_sockaddr().sa_family!=_family) {   WY_RETURN(Wym_EAFNOSUPPORT); } if(::bind(this->wy_fd(),&addr.c_sockaddr(),                           addr.c_addrlen())!=0) {   WY_RETURN(errno); } return(Ok);};WyRet WySockFile::listen(int backlog){ if(::listen(this->wy_fd(),backlog)==0) {   return(Ok); } WY_RETURN(errno);};WyRet WySockFile::accept(WySockFile &sktf, Wy_SockAddr& addr)try { WyRet r; if(this->is_default()) {   WY_RETURN(Wym_EBADF);       // prevent Wym_EAFNOSUPPORT reported first } // note: PF_XXX bound socket expect to use AF_XXX address family // if(addr.c_sockaddr().sa_family!=_family) {   WY_RETURN(Wym_EAFNOSUPPORT); }  Wy_SockAddr* pac( addr._alloc(r) ); if(r!=Ok) {   WY_RETURN(r); } Wy_AtDestroy<void,Wy_SockAddr*> rrad_pac(Wy::_delete_one,pac); // Direct access of addr. The ::accept is thought to return the exact address // family of the socket protocol family (value). // pac->c_addrlen()=pac->c_sockaddr_size(); const Wy__TypeFD s=::accept(this->wy_fd(),&pac->c_sockaddr(), &pac->c_addrlen()); if(s<0) {   // assume addr intact if failed   WY_RETURN(errno); } Wy_AtDestroy<int,const Wy__TypeFD&> rrad_s(WySysFile::wy_close,s); if(pac->c_sockaddr().sa_family!=_family) {   // Previously throws WyRet(). For now return an error because modification   // is done with the copy. If this do happen, my knowledge need to update   WY_RETURN(Wym_EAFNOSUPPORT); } // The algorithm have output dup from s because the argument sktf may be // a base, direct manipulation of s into sktf is not right WySockFile* cp_skt( sktf._alloc(r) ); if(r!=Ok) {   WY_RETURN(r); } Wy_AtDestroy<void,WySockFile*> rrad_cp_skt(Wy::_delete_one,cp_skt); if((r=cp_skt->reset( WyFileHandle(s) ))!=Ok) {   WY_RETURN(r); } if((r=cp_skt->_swap(sktf))!=Ok) {   WY_THROW(r);   // assertion failure } if((r=pac->_swap(addr))!=Ok) {   WY_THROW(r);   // assertion failure } return(Ok);}catch(const WyRet& e) { WY_NDEBUG_MSG(e); WY_THROW( WyRet(e) );};WyRet WySockFile::connect(const Wy_SockAddr& peer_addr){ if(this->is_default()) {   WY_RETURN(Wym_EBADF);       // prevent Wym_EAFNOSUPPORT reported first } if(::connect(this->wy_fd(),&peer_addr.c_sockaddr(),                               peer_addr.c_addrlen())!=0) {   WY_RETURN(errno); } return(Ok);};WyRet WySockFile::sockname(Wy_SockAddr& addr) const{ if(WyByteFlow::is_default()) {   WY_RETURN(Wym_EBADF);       // prevent Wym_EAFNOSUPPORT reported first } if(addr.c_sockaddr().sa_family!=_family) {   WY_RETURN(Wym_EAFNOSUPPORT); } addr.c_addrlen()=addr.c_sockaddr_size(); if(::getsockname(this->wy_fd(),&addr.c_sockaddr(),                                   &addr.c_addrlen())!=0) {   WY_RETURN(errno); } if(addr.c_sockaddr().sa_family!=_family) {   WY_THROW( WyRet() );  // assertion failure (note1) } if(addr.c_sockaddr().sa_family==AF_LOCAL) {   //   // ::getsockname(..)/::getpeername(..) found to return z-string pathname   // with the trailing 0 counted. This code rescan sun_path    // and reset _slen   // (g++ 3.2.2 RedHat Linux 3.3.3-5)   //   WySockAddrLocal* p=dynamic_cast<WySockAddrLocal*>(&addr);   if(p==0) {     WY_THROW( WyRet() );   }   p->wy_adj_slen(); } return(Ok);};WyRet WySockFile::peername(Wy_SockAddr& addr) const{ if(WyByteFlow::is_default()) {   WY_RETURN(Wym_EBADF);       // prevent Wym_EAFNOSUPPORT reported first } if(addr.c_sockaddr().sa_family!=_family) {   WY_RETURN(Wym_EAFNOSUPPORT); } addr.c_addrlen()=addr.c_sockaddr_size(); if(::getpeername(this->wy_fd(),&addr.c_sockaddr(),                                   &addr.c_addrlen())!=0) {   WY_RETURN(errno); } if(addr.c_sockaddr().sa_family!=_family) {   WY_THROW( WyRet() );  // assertion failure (note1) } if(addr.c_sockaddr().sa_family==AF_LOCAL) {   //   // ::getsockname(..)/::getpeername(..) found to return z-string pathname   // with the trailing 0 counted. This code rescan sun_path    // and reset _slen   // (g++ 3.2.2 RedHat Linux 3.3.3-5)   //   WySockAddrLocal* p=dynamic_cast<WySockAddrLocal*>(&addr);   if(p==0) {     WY_THROW( WyRet() );   }   p->wy_adj_slen(); } return(Ok);};WyRet WySockFile::sendto(const void* msg, size_t len, int flags, const Wy_SockAddr* to, size_t& n_sent){ n_sent=0; if(this->is_default()) {   WY_RETURN(Wym_EBADF);       // prevent Wym_EAFNOSUPPORT reported first } const int v( to==NULL?              (::sendto(WyByteFlow::wy_fd(),msg,len,flags,                 (const ::sockaddr*)NULL,(socklen_t)0))             :(::sendto(WyByteFlow::wy_fd(),msg,len,flags,                &to->c_sockaddr(),to->c_addrlen())) ); if(v==-1) {   WY_RETURN(errno); } n_sent=v; return(Ok);};// Note: ::recvfrom(..) is not clear a cancellation point or not//       but seemd ok with this member//WyRet WySockFile::recvfrom(void* buf, size_t blen, int flags, Wy_SockAddr* from, size_t& n_recv){ n_recv=0; if(this->is_default()) {   WY_RETURN(Wym_EBADF);       // prevent Wym_EAFNOSUPPORT reported first } int v; if(from==NULL) {   v=::recvfrom(this->wy_fd(),buf,blen,flags,                (struct ::sockaddr*)NULL,(socklen_t*)NULL); } else {   // Direct access of addr. The ::recvfrom is thought to return the exact   // address family of the socket protocol family (value).   //   const int OrgFamily(from->c_sockaddr().sa_family);   if(OrgFamily!=this->_family) {  // this check may/should probably be omitted     WY_RETURN(Wym_EAFNOSUPPORT);   }   from->c_addrlen()=from->c_sockaddr_size();   v=::recvfrom(this->wy_fd(),buf,blen,flags,                &from->c_sockaddr(),&from->c_addrlen());   if(from->c_sockaddr().sa_family!=OrgFamily) {     WY_THROW( WyRet() );  // assertion failure   } } if(v<0) {   if(v==-1) {     WY_RETURN(errno);   }   WY_RETURN(errno); } n_recv=v; return(Ok);};static void wy__close_fds(const Wy__TypeFD& fd0, const Wy__TypeFD& fd1){ WySysFile::wy_close(fd0); WySysFile::wy_close(fd1);};WyRet WySockFile::sockpair(int domain, int type, int proto,                          WySockFile& s1, WySockFile& s2)try { if(static_cast<WySockFile*>(&s1)==static_cast<WySockFile*>(&s2)) {   WY_RETURN( Wym_EINVAL );    // s1/s2 are the same object } WyRet r; int fds[2]; if(::socketpair(domain,type,proto,fds)!=0) {   WY_RETURN(errno); } Wy_AtDestroy2<void,const Wy__TypeFD&,const Wy__TypeFD&>                                   rrad_fds(wy__close_fds,fds[0],fds[1]); // Note: the algorithm uses reset instead of overwriting fd to save dup(..) //       is because of polymorphism of the argument objects // WySockFile* p1( s1._alloc(r) ); if(r!=Ok) {   WY_RETURN(r); } Wy_AtDestroy<void,WySysFile*> rrad_p1(Wy::_delete_one,p1); WySockFile* p2( s2._alloc(r) ); if(r!=Ok) {   WY_RETURN(r); } Wy_AtDestroy<void,WySysFile*> rrad_p2(Wy::_delete_one,p2); if((r=p1->reset( WyFileHandle(fds[0]) ))!=Ok) {   WY_RETURN(r); } if((r=p2->reset( WyFileHandle(fds[1]) ))!=Ok) {   WY_RETURN(r); } if((r=p1->_swap(s1))!=Ok) {   WY_THROW(r);   // assertion failure } if((r=p2->_swap(s2))!=Ok) {   WY_THROW(r);   // assertion failure } return(Ok);}catch(const WyRet& e) { WY_NDEBUG_MSG(e); WY_THROW( WyRet(e) );};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -