📄 socket.c
字号:
//// Implemention of threaded sockets#include "threads/socket.h"#include "threads/exception.h"#if( GCC_VERSION >= 2096 )#include <sstream>#else#include <strstream>#endif#include <cstdio>#include <cerrno>extern "C" {# include <netipx/ipx.h># include <sys/stat.h># include <sys/socket.h># include <sys/un.h># include <netdb.h>};namespace cpp_threads { typedef union { struct sockaddr sa; struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_ipx ipx; struct sockaddr_un un; } socket_types; MessageHeader::MessageHeader() { } MessageHeader::~MessageHeader() { } void MessageHeader::setName(SocketAddress* p_sa) { if( p_sa == 0 ) { _Header.msg_name = 0; _Header.msg_namelen = 0; } else { _Header.msg_name = (struct sockaddr *)*p_sa; _Header.msg_namelen = p_sa->length(); } } void MessageHeader::setControl(void *p_ca,int p_cl) { _Header.msg_control = p_ca; _Header.msg_controllen = p_cl; } void MessageHeader::setFlags(int p_flags) { _Header.msg_flags = p_flags; } int MessageHeader::getFlags() { return _Header.msg_flags; } MessageHeader& MessageHeader::operator |= (Flags p_fl) { _Header.msg_flags |= p_fl; return *this; } MessageHeader& MessageHeader::operator &= (Flags p_fl) { _Header.msg_flags &= p_fl; return *this; } MessageHeader::operator struct msghdr& () { return _Header; } MessageHeader::operator struct msghdr* () { return &_Header; } SocketAddress::SocketAddress(int fd_p) { socklen_t size; _Sin = (struct sockaddr*)new socket_types; getsockname(fd_p,_Sin,&size); if( size != length() ) exception::warning("unknown protocol"); } SocketAddress::SocketAddress(t_afamily fam_p) { _Sin = 0; initFamily(fam_p); } SocketAddress::SocketAddress(SocketAddress& sa_p) { _Sin = 0; initFamily(sa_p.family()); memcpy(_Sin,(struct sockaddr *)sa_p,length()); } SocketAddress::~SocketAddress() { if( _Sin ) delete _Sin; _Sin = 0; } void SocketAddress::assign_Sin(struct sockaddr* sin_p) { if( _Sin ) delete _Sin; _Sin = sin_p; } void SocketAddress::initFamily(t_afamily fam_p) { switch( fam_p ) { case local: assign_Sin( (struct sockaddr*)new struct sockaddr_un ); break; case inet: assign_Sin( (struct sockaddr*)new struct sockaddr_in ); break; case inet6: assign_Sin( (struct sockaddr*)new struct sockaddr_in6 ); break; default: exception::fatal( "Not implemented" ); } _Sin->sa_family = fam_p; Pthread::debug("socket address in tree %d",fam_p); } SocketAddress::operator struct sockaddr *() { return _Sin; } uint SocketAddress::length() { switch( _Sin->sa_family ) { case local: return SUN_LEN((struct sockaddr_un *)_Sin); case inet: return sizeof(struct sockaddr_in); case inet6: return sizeof(struct sockaddr_in6); default: return 0; }; } SocketAddress& SocketAddress::operator =(SocketAddress& ref_p) { if( _Sin ) delete _Sin; initFamily( ref_p.family() ); memcpy( _Sin,(struct sockaddr *)ref_p,length() ); return *this; } SocketAddress::t_afamily SocketAddress::family() { return t_afamily(_Sin->sa_family); } void* SocketAddress::host_address(const char *addr_p,t_afamily type_p) { struct hostent* hostinfo; hostinfo = gethostbyname2( addr_p,type_p ); if( hostinfo == 0 ) exception::fatal( "Address unknown" ); return (void *)hostinfo->h_addr; } void SocketAddress::setPort(const char *addr_p, int port_p) { struct sockaddr_un *sun; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; switch( _Sin->sa_family ) { case local: sun = (struct sockaddr_un *)_Sin; strncpy(sun->sun_path,addr_p,sizeof(sun->sun_path)); break; case inet: sin = (struct sockaddr_in *)_Sin; sin->sin_port = htons(port_p); sin->sin_addr = *(struct in_addr *)host_address(addr_p,inet); break; case inet6: sin6 = (struct sockaddr_in6 *)_Sin; sin6->sin6_port = htons(port_p); sin6->sin6_addr = *(struct in6_addr *)host_address(addr_p,inet6); break; default:#if( GCC_VERSION >= 2096 ) std::stringstream sstr;#else std::strstream sstr;#endif sstr << "Family " << _Sin->sa_family << " not implemented." << std::endl; exception::fatal( sstr.str() ); } } void SocketAddress::setPort(int port_p) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; switch( _Sin->sa_family ) { case local: break; case inet: sin = (struct sockaddr_in*)_Sin; sin->sin_port = htons(port_p); sin->sin_addr.s_addr = htonl( INADDR_ANY ); break; case inet6: sin6 = (struct sockaddr_in6*)_Sin; sin6->sin6_port = htons(port_p); sin6->sin6_addr = in6addr_any; break; default: exception::fatal( "Not implemented" ); } } Socket::Socket() { _Sin = 0; _File_descriptor = -1; } Socket::Socket(int fd_p) { _Sin = new SocketAddress(fd_p); _File_descriptor = fd_p; } Socket::Socket(Socket& sock_p) { _Sin = new SocketAddress( *(SocketAddress *)sock_p ); _File_descriptor = sock_p; } Socket::Socket(SocketAddress::t_afamily fam_p,__socket_type typ_p,int proto_p) { _File_descriptor = ::socket(fam_p,typ_p,proto_p); if( _File_descriptor < 0 ) exception::fatal( errno ); _Sin = new SocketAddress(fam_p); } void Socket::assign_Sin(SocketAddress* sin_p) { if( _Sin ) delete _Sin; _Sin = sin_p; } void Socket::open(int fd_p) { if( !isNull() ) exception::warning( "unclosed socket" ); if( _Sin ) delete _Sin; _File_descriptor = fd_p; assign_Sin( new SocketAddress(fd_p) ); } void Socket::open(SocketAddress::t_afamily fam_p,__socket_type typ_p,int proto_p) { Pthread::debug("socket::open"); if( !isNull() ) exception::warning( "unclosed socket" ); _File_descriptor = ::socket(fam_p,typ_p,proto_p); if( _File_descriptor < 0 ) exception::fatal( errno ); if( _Sin ) delete _Sin; Pthread::debug("socket obtained %d",_File_descriptor); assign_Sin( new SocketAddress(fam_p) ); } void Socket::close() { Pthread::debug("socket::close(%d)",_File_descriptor); if( _File_descriptor > 0 ) ::close( _File_descriptor ); _File_descriptor = -1; } Socket::~Socket() { Pthread::debug("Socket::~Socket"); if( _Sin ) delete _Sin; } int Socket::getOption(t_options opt_p) { socklen_t len = sizeof(int); int value; errno = EPERM; if( opt_p == s_linger ) return -1; if( getsockopt(_File_descriptor,SOL_SOCKET,opt_p,&value,&len) ) return -1; return value; } bool Socket::setOption(t_options opt_p, int val_p) { socklen_t len = sizeof(int); errno = EPERM; if( opt_p == s_linger ) return false; if( setsockopt(_File_descriptor,SOL_SOCKET,opt_p,&val_p,len) ) return false; return true; } bool Socket::linger(bool onoff_p, int timeout_p) { socklen_t len = sizeof(struct linger); struct linger l; l.l_onoff = onoff_p?1:0; l.l_linger = timeout_p; if( setsockopt(_File_descriptor,SOL_SOCKET,s_linger,&l,len) ) return false; return true; } SocketAddress * Socket::peer() { socklen_t len; SocketAddress *sa; if( isNull() ) return 0; sa = new SocketAddress(_Sin->family()); len = sa->length(); if( getpeername(_File_descriptor,*sa,&len) ) { delete sa; sa = 0; } return sa; } int Socket::send(const char *data_p,int len_p,int flags_p) { int len; _Write_lock.lock(); len = ::send(_File_descriptor,data_p,len_p,flags_p); _Write_lock.unLock(); return len; } int Socket::send(const std::string& str_p,int flags_p) { return send(str_p.c_str(),str_p.length(),flags_p); } int Socket::sendTo(const char *data_p,int len_p,int flags_p,SocketAddress& s_p) { int len; _Write_lock.lock(); len = ::sendto(_File_descriptor,data_p,len_p,flags_p,s_p,s_p.length()); _Write_lock.unLock(); return len; } int Socket::sendTo(const std::string& str_p,int flags_p,SocketAddress& s_p) { return sendTo(str_p.c_str(),str_p.length(),flags_p,s_p); } int Socket::sendMsg(MessageHeader& mh_p,int flags_p) { int len; _Write_lock.lock(); len = ::sendmsg(_File_descriptor,mh_p,flags_p); _Write_lock.lock(); return len; } int Socket::recv(void *buf_p,int len_p,uint flags_p) { int len; _Read_lock.lock(); len = ::recv(_File_descriptor,buf_p,len_p,flags_p); _Read_lock.unLock(); return len; } int Socket::recvFrom(void *buf_p,int len_p,uint flags_p,SocketAddress& s_p) { int len; socklen_t slen; _Read_lock.lock(); len = ::recvfrom(_File_descriptor,buf_p,len_p,flags_p,s_p,&slen); _Read_lock.unLock(); // Does not need to be fatal, but requires an interception. if( slen != s_p.length() ) exception::warning("unknown protocol type"); return len; } int Socket::recvMsg(MessageHeader& mh_p,int flags_p) { int len; _Read_lock.lock(); len = ::recvmsg(_File_descriptor,mh_p,flags_p); _Read_lock.unLock(); return len; } int Socket::read(const char *data_p,int len_p) { int len; verifySocket(); _Read_lock.lock(); len = ::read(_File_descriptor,(void *)data_p,len_p); _Read_lock.unLock(); return len; } int Socket::write(const char *data_p,int len_p) { int len; Pthread::debug("write(%d,'%s',%d)",_File_descriptor,data_p,len_p); verifySocket(); _Write_lock.lock(); len = ::write(_File_descriptor,data_p,len_p); _Write_lock.unLock(); return len; } int Socket::write(const std::string& str_p) { return write(str_p.c_str(),str_p.length()); } void Socket::connect(const char *name_p, int port_p) { verifySocket(); _Sin->setPort( name_p,port_p ); if( ::connect(_File_descriptor,*_Sin,_Sin->length()) == -1 ) exception::fatal( errno ); } void Socket::bind(int port_p) { verifySocket(); _Sin->setPort( port_p ); if( ::bind(_File_descriptor,*_Sin,_Sin->length()) == -1 ) exception::fatal( errno ); } void Socket::listen(int queue_p) { verifySocket(); if( ::listen(_File_descriptor,queue_p) == -1 ) exception::fatal( errno ); } Socket* Socket::accept() { struct sockaddr_in clientname; struct sockaddr_in6 client6name; socklen_t size; int fd = 0; verifySocket(); switch( _Sin->family() ) { case SocketAddress::inet: size = sizeof(clientname); fd = ::accept(_File_descriptor,(struct sockaddr*)&clientname,&size); break; case SocketAddress::inet6: size = sizeof(client6name); fd = ::accept(_File_descriptor,(struct sockaddr*)&client6name,&size); break; default: exception::fatal( "Not implemented" ); } return (new Socket(fd)); } void Socket::verifySocket() { if( !isNull() ) return; exception::fatal( "Operation on null socket" ); } bool Socket::isNull() { if( _Sin == 0 || _File_descriptor < 0 ) return true; return false; } Socket::operator int() { return _File_descriptor; } Socket::operator SocketAddress *() { return _Sin; } Socket& Socket::operator =(Socket& ref_p) { assign_Sin( new SocketAddress(*(SocketAddress *)ref_p) ); _File_descriptor = ref_p; return *this; } bool Socket::operator ==(Socket& ref_p) { return _File_descriptor == (int)ref_p; } Socket::operator bool() { struct stat sbuf; if( fstat( _File_descriptor,&sbuf ) ) return false; if( !S_ISSOCK(sbuf.st_mode) ) return false; return true; }};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -