/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation,
* YDC Corporation, IPA (Information-technology Promotion Agency, Japan).
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions and disclaimer are agreed and accepted by the user:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the names of the copyrighters, the name of the project which
* is related to this software (hereinafter referred to as "project") nor
* the names of the contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 4. No merchantable use may be permitted without prior written
* notification to the copyrighters. However, using this software for the
* purpose of testing or evaluating any products including merchantable
* products may be permitted without any notification to the copyrighters.
*
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
* BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT,STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $TAHI: v6eval/lib/Cm/CmSocket.cc,v 1.29 2001/10/29 01:41:33 akisada Exp $
*/
#include "CmSocket.h"
//IMPLEMENTATION
#if defined(__FreeBSD__)
#define setSALEN(s,l)s->sa_len=l
#else
#define setSALEN(s,l)
#endif
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <rpc/types.h>
#include <net/if.h>
//---PURE VIRTUAL FUNCTIONS---------------------------------------------
int CmSocket::socket() {return -1;}
int CmSocket::receive(STR ,int ) {return -1;}
int CmSocket::send(CSTR ,int ) {return -1;}
int CmSocket::sendAll(CSTR s,int l) {return send(s,l);}
int CmSocket::recvAll(STR s,int l) {return send(s,l);}
CmStream::CmStream(int l,const sock* s,int fd):CmSocket(l,s,fd),
self_(0),peer_(0) {}
CmStream::CmStream(const inSock& in,int fd):
CmSocket(sizeof(in),reinterpret_cast<const sock*>(&in),fd),
self_(0),peer_(0) {}
CmStream::CmStream(const in6Sock& in,int fd):
CmSocket(sizeof(in),reinterpret_cast<const sock*>(&in),fd),
self_(0),peer_(0) {}
CmDgram::CmDgram(int l,const sock* s,int fd):CmSocket(l,s,fd) {}
CmDgram::CmDgram(const inSock& in,int fd):
CmSocket(sizeof(in),reinterpret_cast<const sock*>(&in),fd) {}
CmDgram::CmDgram(const in6Sock& in,int fd):
CmSocket(sizeof(in),reinterpret_cast<const sock*>(&in),fd) {}
CmRaw::CmRaw(int l,const sock* s,int fd):CmDgram(l,s,fd) {}
int CmStream::socket() {return socketType(SOCK_STREAM);}
int CmDgram::socket() {return socketType(SOCK_DGRAM);}
int CmRaw::socket() {return socketType(SOCK_RAW);}
//---ATTRIBUTE MANUPULATION---------------------------------------------
u_short CmSockAddr::family() const {
sock* s=sockAddr();
return s?s->sa_family:0;}
bool CmSockAddr::family(u_short u) {
sock* s=sockAddr();
if(s) s->sa_family=u;
return this;}
u_short CmSockAddr::service() const {
u_short serv=0;
u_short f=family();
switch(f) {
case AF_INET: {
inSock* in=inetAddr();
if(in) serv=ntohs(in->sin_port);}
break;
case AF_INET6: {
in6Sock* in6=inet6Addr();
if(in6) serv=ntohs(in6->sin6_port);}
break;}
return serv;}
bool CmSockAddr::service(u_short u) {
u_short f=family();
switch(f) {
case AF_INET: {
inSock* in=inetAddr();
if(in!=0) {in->sin_port=htons(u);}}
break;
case AF_INET6: {
in6Sock* in6=inet6Addr();
if(in6!=0) {in6->sin6_port=htons(u);}}
break;}
return this;}
const in_addr CmSockAddr::address() const {
in_addr anAddr={0};
inSock* in=inetAddr();
if(in!=0) {
anAddr=in->sin_addr;}
return anAddr;}
bool CmSockAddr::address(const in_addr& anAddr) {
inSock* in=inetAddr();
if(in!=0) {
in->sin_addr=anAddr;}
return this;}
inSock* CmSockAddr::inetAddr() const {
u_short f=family();
return f==AF_INET?reinterpret_cast<inSock*>(addr_):0;}
in6Sock* CmSockAddr::inet6Addr() const {
u_short f=family();
return f==AF_INET6?reinterpret_cast<in6Sock*>(addr_):0;}
unSock* CmSockAddr::unixAddr() const {
u_short f=family();
return f==AF_UNIX?reinterpret_cast<unSock*>(addr_):0;}
//---Dictionary Interface-----------------------------------------------
uint32_t CmSockAddr::hash() const {
return basicHash((CSTR)sockAddr(),length());}
bool CmSockAddr::isEqual(const CmSockAddr* o) const {
int l=length();
int ol=o->length();
if(l!=ol) return false;
u_short f=family();
switch(f) {
case AF_UNIX: case AF_INET: {
return memcmp(sockAddr(),o->sockAddr(),l)==0;}
break;
case AF_INET6: {
if(memcmp(sockAddr(),o->sockAddr(),l)==0) {return true;}
in6Sock* mi=inet6Addr();
in6_addr* m6=&mi->sin6_addr;
if(!IN6_IS_ADDR_LINKLOCAL(m6)) {return false;}
in6Sock* oi=o->inet6Addr();
if(oi==0) {return false;}
if( mi->sin6_family!=oi->sin6_family ||
mi->sin6_port!=oi->sin6_port ||
mi->sin6_flowinfo!=oi->sin6_flowinfo) {return false;}
in6_addr* o6=&oi->sin6_addr;
in6_addr wm6=*m6, wo6=*o6;
SET_IN6_LINKLOCAL_IFINDEX(wm6,0); /* XXX */
SET_IN6_LINKLOCAL_IFINDEX(wo6,0); /* XXX */
return IN6_ARE_ADDR_EQUAL(&wm6,&wo6);}
break;}
return false;}
int CmSockAddr::compare(const CmSockAddr*) const {return 0;}
//---ERROR HANDLING-----------------------------------------------------
bool CmSocket::retryError() const {
int e=syserrno();
return (e==EINTR||e==ENOBUFS);}
int CmSocket::sysError(CSTR aFunc) {
syserrno_=errno;
if(!retryError()) {eerr(aFunc);}
return -1;}
//---Instance Constructin/Destruction-----------------------------------
CmSockAddr::CmSockAddr(int l,const sock* s):alloc_(0),length_(0),addr_(0) {
socketArea(l,s);}
CmSockAddr::~CmSockAddr() {
free(addr_); addr_=0; alloc_=0; length_=0;}
int CmSockAddr::initSocket(sock* s,size_t l,int f) {
memset(s, 0, l);
setSALEN(s,l);
s->sa_family=f;
return l;}
CmSockAddr* CmSockAddr::socketArea(int l,const sock* s) {
if(alloc_<l) {
if(addr_) {free(addr_),addr_=0,alloc_=0;}
addr_=(sock*)malloc(alloc_=l);}
if(l>0&&s!=0) {
memcpy(addr_,s,length_=l);}
return this;}
CmSocket::CmSocket(int l,const sock* s,int fd):CmSockAddr(l,s),fileDesc_(fd) {}
CmSocket::~CmSocket() {
close();}
//---Socket Creation----------------------------------------------------
int CmSocket::socketType(int aType,int aProtocol) {
int fd=myFD();
if(fd>=0) return fd;
int domain=family();
if((fd=::socket(domain,aType,aProtocol))<0) {
sysError("socket");}
fileDesc(fd);
return fd;}
//---PURE VIRTUAL ACCEPT------------------------------------------------
CmSocket* CmSocket::create(int,const sock*,int) {return 0;}
CmSocket* CmStream::create(int l,const sock* s,int fd) {
return new CmStream(l,s,fd);}
CmSocket* CmDgram::create(int l,const sock* s,int fd) {
return new CmDgram(l,s,fd);}
CmSocket* CmRaw::create(int l,const sock* s,int fd) {
return new CmRaw(l,s,fd);}
CmSocket* CmSocket::accept(int,const sock*,int) {return 0;}
CmSocket* CmStream::accept(int l,const sock* s,int fd) {
CmStream* from=(CmStream*)create(l,s,fd);
if(from!=0) {
from->self(this); from->peer(from);}
return from;}
//---BASIC OPERATION----------------------------------------------------
CmSocket* CmSocket::close() {
if(fileDesc_>=0) {
::close(fileDesc_),fileDesc_=-1;
SocketSet* set=bindedSockets();
CmSocket* f=set->find(this);
if(f!=0) {clearBind();}
set->remove(this);}
return this;}
CmSocket* CmSocket::accept() {
int fd;
char buf[BUFSIZ];
socklen_t len=BUFSIZ;
sock* p=(sock*)buf;
if((fd=::accept(myFD(),p,&len))<0) {
sysError("accept");
return 0;}
return accept(len,p,fd);}
int CmSocket::bind(bool reuse) {
int fd=socket();
if(reuse) setReuseAddrOpt();
if(fd>=0&&(::bind(fd,sockAddr(),length()))<0) {
return sysError("bind");}
SocketSet* set=bindedSockets();
set->add(this);
return fd;}
int CmSocket::listen(int aBacklog) {
int fd=myFD();
if(fd<0) fd=bind();
if(fd>=0&&(fd=::listen(fd,aBacklog))<0) {
sysError("listen");}
return fd;}
int CmSocket::connect(CmSockAddr* to) {
if(to==0) to=this;
int fd=socket();
if(fd>=0&&::connect(fd,to->sockAddr(),to->length())<0) {
return sysError("connect");}
return fd;}
int CmStream::connect(CmSockAddr* to) {
CmSockAddr* cn=to!=0?to:this;
peer(cn);
int fd=CmSocket::connect(cn);
if(fd>=0) {self(to!=0?(CmSockAddr*)this:getsockname());}
return fd;}
int CmSocket::recvfrom(STR s,int l,CmSockAddr*) {return receive(s,l);}
int CmSocket::sendto(CSTR s,int l,CmSockAddr*) {return send(s,l);}
//---OPTIONAL OPERATIONS------------------------------------------------
CmSockAddr* CmSocket::getsockname() {
int fd=myFD();
char buf[BUFSIZ];
socklen_t len=BUFSIZ;
sock* p=(sock*)buf;
if(fd>=0&&::getsockname(fd,p,&len)<0) {
sysError("getsockname");
return 0;}
return new CmSockAddr(len,p);}
CmSockAddr* CmSocket::getpeername() {
int fd;
char buf[BUFSIZ];
socklen_t len=BUFSIZ;
sock* p=(sock*)buf;
if((fd=::getpeername(myFD(),p,&len))<0) {
sysError("getpeername");
return 0;}
return new CmSockAddr(len,p);}
bool CmSocket::nonBlocking(int) {
int fd=myFD();
if(fd>=0&&::fcntl(fd,F_SETFL,O_NDELAY)<0) {
sysError("fcntl"); return false;}
return (fd>=0);}
inSock* CmSocket::broadcast(struct ifreq* p) {
int s=myFD();
if(s<0) return 0;
if(ioctl(s,SIOCGIFFLAGS,(STR)p)<0) {
eoutf("ioctl(get interface flags)\n");
return 0;}
if(!(p->ifr_flags&IFF_BROADCAST)) {return 0;}
if(ioctl(s,SIOCGIFBRDADDR,(STR)p)<0) {
eoutf("ioctl(get broadaddr)\n");
return 0;}
return reinterpret_cast<inSock*>(&p->ifr_broadaddr);}
int CmSocket::broadcasts(inSock** b) {
char buf[BUFSIZ];
struct ifconf ifc;
int s=myFD();
if(s<0) return 0;
ifc.ifc_len=sizeof(buf); ifc.ifc_buf=buf;
if(ioctl(s,SIOCGIFCONF,(STR)&ifc)<0) {
eoutf("ioctl(get interface configuration)\n");
return 0;}
struct ifreq* rp,* re;
int n,m=ifc.ifc_len/sizeof(struct ifreq);
inSock* a=new inSock[m],* r=a;
for(rp=ifc.ifc_req,re=rp+m;rp<re;rp++) {
inSock* in=broadcast(rp);
if(in) {*r=*in; r++;}}
if((n=r-a)>0) {*b=a; return n;}
delete [] a;
return 0;}
bool CmSocket::setReuseAddrOpt(bool bl) {
int on=bl?1:0;
if(setsockopt(myFD(),SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0) {
sysError("setsockopt(SO_REUSEADDR)"); return false;}
return true;}
bool CmSocket::setReusePortOpt(bool bl) {
int on=bl?1:0;
if(setsockopt(myFD(),SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on))<0) {
sysError("setsockopt(SO_REUSEPORT)"); return false;}
return true;}
bool CmSocket::setDebugOpt(bool bl) {
int on=bl?1:0;
if(setsockopt(myFD(),SOL_SOCKET,SO_DEBUG,&on,sizeof(on))<0) {
sysError("setsockopt(SO_DEBUG)"); return false;}
return true;}
//---send/receiv--------------------------------------------------------
int CmStream::send(CSTR s,int l) {
int fd=myFD();
int rc=::write(fd,s,l);
if(rc<0) {sysError("write");}
return rc;}
int CmStream::sendAll(CSTR s,int len) {
int32_t rem, l; CSTR p;
for(rem=len,p=s;rem>0;rem-=l,p+=l) {
l=send(p,rem);
if(l<0 && !retryError()) {l=0; continue;}
if(l<=0) return -1;}
return len;}
int CmStream::receive(STR s,int l) {
int fd=myFD();
int rc=::read(fd,s,l);
if(rc<0) {sysError("read");}
return rc;}
int CmStream::recvAll(STR s,int len) {
int32_t rem, l; STR p;
for(rem=len,p=s;rem>0;rem-=l,p+=l) {
l=receive(p,rem);
if(l<0 && !retryError()) {l=0; continue;}
if(l<=0) return -1;}
return len;}
int CmDgram::send(CSTR s,int l) {
int fd=myFD();
int rc=::send(fd,s,l,0);
if(rc<0) {sysError("send");}
return rc;}
int CmDgram::receive(STR s,int l) {
int fd=myFD();
int rc=::recv(fd,s,l,0);
if(rc<0) {sysError("recv");}
return rc;}
int CmDgram::sendto(CSTR s,int l,CmSockAddr* to) {
int fd=myFD();
int rc=::sendto(fd,s,l,0,to->sockAddr(),to->length());
if(rc<0) {sysError("sendto");}
return rc;}
int CmDgram::recvfrom(STR s,int l,CmSockAddr* from) {
char buf[BUFSIZ];
socklen_t len=BUFSIZ;
sock* p=(sock*)buf;
int fd=myFD();
int rc=::recvfrom(fd,s,l,0,p,&len);
if(rc<0) {sysError("recvfrom");}
else {from->socketArea(len,(sock*)p);}
return rc;}
int CmDgram::sendfrom(CSTR s,int l,CmSocket* from) {
int fd=from->fileDesc();
int rc=::sendto(fd,s,l,0,sockAddr(),length());
if(rc<0) {sysError("sendto");}
return rc;}
//---Debug Print--------------------------------------------------------
void CmSockAddr::print() const {
u_short f=family();
ooutf("len=%d family=%d ",length(),f);
switch(f) {
case AF_UNIX: {
unSock* u=unixAddr();
ooutf("AF_UNIX %s\n",u->sun_path);}
break;
case AF_INET: {
inSock* i=inetAddr();
ooutf("AF_INET port=%05d %s\n",
ntohs(i->sin_port),inet_ntoa(i->sin_addr));}
break;
case AF_INET6: {
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
in6Sock* i=inet6Addr();
inet_ntop(AF_INET6,&i->sin6_addr,tmp,sizeof(tmp));
ooutf("AF_INET6 port=%05d %s %d\n",
ntohs(i->sin6_port),tmp,i->sin6_scope_id);}
break;}}
void CmStream::print() const {
ooutf("CmStream(fd=%2d) ",myFD());
CmSockAddr::print();}
void CmDgram::print() const {
ooutf("CmDgram(fd=%2d) ",myFD());
CmSockAddr::print();}
void CmRaw::print() const {
ooutf("CmRaw(fd=%2d) ",myFD());
CmSockAddr::print();}
void CmSocket::printPeers() const {print();}
void CmStream::printPeers() const {
ooutf("fd=%2d\n",myFD());
CmSockAddr* s=self();
CmSockAddr* p=peer();
if(s!=0) {ooutf("\tself="); s->print();}
if(p!=0) {ooutf("\tpeer="); p->print();}}
//---AF_UNIX Socket Creation--------------------------------------------
int UnixSocket::initSocket(unSock& un) {
sock* s=reinterpret_cast<sock*>(&un);
return CmSocket::initSocket(s,sizeof(un),AF_UNIX);}
int UnixSocket::service(unSock& un,CSTR serv) {
initSocket(un);
size_t l=strlen(serv);
if(l>=sizeof(un.sun_path)) {
eoutf("serv name \'%s\' too big %d\n",serv,l);}
strncpy(un.sun_path,serv,sizeof(un.sun_path));
un.sun_path[sizeof(un.sun_path)-1]='\0';
return un.sun_path-(STR)&un+strlen(un.sun_path)+1;}
CmSocket* UnixSocket::stream() {unSock un;
sock* s=reinterpret_cast<sock*>(&un);
return new CmStream(initSocket(un),s);}
CmSocket* UnixSocket::stream(CSTR serv) {unSock un;
sock* s=reinterpret_cast<sock*>(&un);
return new CmStream(service(un,serv),s);}
CmDgram* UnixSocket::datagram() {unSock un;
sock* s=reinterpret_cast<sock*>(&un);
return new CmDgram(initSocket(un),s);}
CmDgram* UnixSocket::datagram(CSTR serv) {unSock un;
sock* s=reinterpret_cast<sock*>(&un);
return new CmDgram(service(un,serv),s);}
//---AF_INET Socket Creation--------------------------------------------
int InetSocket::initSocket(inSock& in) {
sock* s=reinterpret_cast<sock*>(&in);
return CmSocket::initSocket(s,sizeof(in),AF_INET);}
int InetSocket::initSocket(in6Sock& in) {
sock* s=reinterpret_cast<sock*>(&in);
return CmSocket::initSocket(s,sizeof(in),AF_INET6);}
int InetSocket::service(inSock& in,int serv) {
initSocket(in);
in.sin_port=htons(serv);
return sizeof(in);}
int InetSocket::service(in6Sock& in,int serv) {
initSocket(in);
in.sin6_port=htons(serv);
return sizeof(in);}
int InetSocket::serviceAddress(inSock& in,int serv,const in_addr& anAddr) {
int len=service(in,serv);
in.sin_addr=anAddr;
return len;}
int InetSocket::serviceAddress(in6Sock& in,int serv,const in6_addr& anAddr) {
int len=service(in,serv);
in.sin6_addr=anAddr;
if(IN6_IS_ADDR_LINKLOCAL(&anAddr)) {
int scope=IN6_LINKLOCAL_IFINDEX(anAddr);
if(scope!=0) {
in.sin6_scope_id=scope;
SET_IN6_LINKLOCAL_IFINDEX(in.sin6_addr,0);}}
return len;}
//----------------------------------------------------------------------
// HOST DEPEND SOCKET
inSock* InetSocket::serviceHost4(int serv,CSTR aHost,int& l) {
l=-1;
struct hostent* h=gethostbyname(aHost);
if(h==0) {return 0;}
static inSock in;
in_addr addr;
memcpy(&addr,h->h_addr,h->h_length);
l=serviceAddress(in,serv,addr);
return ∈}
in6Sock* InetSocket::serviceHost6(int serv,CSTR aHost,int& l) {
l=-1;
int err=0;
struct hostent* h=getipnodebyname(aHost,AF_INET6,0,&err);
if(h==0) {return 0;}
static in6Sock in6;
in6_addr addr;
memcpy(&addr,h->h_addr,h->h_length);
l=serviceAddress(in6,serv,addr);
return &in6;}
sock* InetSocket::serviceHost(int serv,CSTR aHost,int& l) {
l=-1;
sock* in=reinterpret_cast<sock*>(serviceHost6(serv,aHost,l));
if(in==0) {in=reinterpret_cast<sock*>(serviceHost4(serv,aHost,l));}
if(in==0) {eoutf("unknown hostname %s\n",aHost);}
return in;}
CmSocket* InetSocket::stream(int serv,CSTR aHost) {
int l=0;
sock* in=serviceHost(serv,aHost,l);
return (in!=0)?(new CmStream(l,in)):0;}
CmDgram* InetSocket::datagram(int serv,CSTR aHost) {
int l=0;
sock* in=serviceHost(serv,aHost,l);
return (in!=0)?(new CmDgram(l,in)):0;}
//----------------------------------------------------------------------
// INET DATABASE SERVICE
int InetSocket::getService(CSTR serv) {
struct servent* s=getservbyname(serv,0);
return (s)?ntohl(s->s_port):0;}
int InetSocket::defaultService(CSTR serv,CSTR debug,int def) {
STR e=getenv(debug);
int p=e?atoi(e):0;
p=p?p:getService(serv);
return p?p:def;}
CSTR InetSocket::myHostname() {
static STR myHostNamePtr=0;
static char myHostNameArea[MAXHOSTNAMELEN];
if(myHostNamePtr) return myHostNamePtr;
if(gethostname(myHostNameArea,MAXHOSTNAMELEN)<0) {
eoutf("cannot gethostname\n");
strcpy(myHostNameArea,"localhost");}
return myHostNamePtr=myHostNameArea;}
const in_addr InetSocket::myIpAddress() {
static in_addr myAddress={0};
struct hostent* h;
if(myAddress.s_addr) return myAddress;
CSTR s=myHostname();
if((h=gethostbyname(s))!=0) {
memcpy(&myAddress,h->h_addr,h->h_length);}
else {
eoutf("unknown hostname %s\n",s);
myAddress.s_addr=INADDR_LOOPBACK;}
return myAddress;}
//----------------------------------------------------------------------
CmSocket* InetSocket::stream() {inSock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmStream(initSocket(in),s);}
CmSocket* InetSocket::stream6() {in6Sock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmStream(initSocket(in),s);}
CmDgram* InetSocket::datagram() {inSock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmDgram(initSocket(in),s);}
CmDgram* InetSocket::datagram6() {in6Sock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmDgram(initSocket(in),s);}
//----------------------------------------------------------------------
CmSocket* InetSocket::stream(int serv) {inSock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmStream(service(in,serv),s);}
CmSocket* InetSocket::stream6(int serv) {in6Sock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmStream(service(in,serv),s);}
CmDgram* InetSocket::datagram(int serv) {inSock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmDgram(service(in,serv),s);}
CmDgram* InetSocket::datagram6(int serv) {in6Sock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmDgram(service(in,serv),s);}
//----------------------------------------------------------------------
CmSocket* InetSocket::stream(int serv,const in_addr& anAddr) {inSock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmStream(serviceAddress(in,serv,anAddr),s);}
CmDgram* InetSocket::datagram(int serv,const in_addr& anAddr) {inSock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmDgram(serviceAddress(in,serv,anAddr),s);}
CmSocket* InetSocket::stream(int serv,const in6_addr& anAddr) {in6Sock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmStream(serviceAddress(in,serv,anAddr),s);}
CmDgram* InetSocket::datagram(int serv,const in6_addr& anAddr) {in6Sock in;
sock* s=reinterpret_cast<sock*>(&in);
return new CmDgram(serviceAddress(in,serv,anAddr),s);}
//---Binded Socket Control----------------------------------------------
SocketSet* CmSocket::bindedSockets() {
if(bindedSockets_==0) {
bindedSockets_=new SocketSet;
atexit(&CmSocket::clearBinds);}
return bindedSockets_;}
void CmSocket::clearBind() {
unSock* u=unixAddr();
if(u!=0) {::unlink(u->sun_path);}}
void CmSocket::clearBinds() {
SocketSet* set=bindedSockets();
set->elementsPerform((CmSocketFunc)&CmSocket::clearBind);}
SocketSet* CmSocket::bindedSockets_=0;
implementCmSet(SocketSet,CmSocket);
syntax highlighted by Code2HTML, v. 0.9.1