void MSListener::doClose(void) { if (fd()<0) { removeRetryTimer(); } else { if (acceptChannel()!=0) { removeAcceptChannel(); _deafTod=todsec(); _listenedTime+=(deafTod()-listenTod()); } delete [] _localName; _localName=(struct sockaddr *)(0); _localNamelen=0; MSChannel::fdsfresh(fd()); #if defined(MS_WINSOCK) if (::closesocket(fd())==SOCKET_ERROR) #else if (::close(fd())<0) #endif { MSMessageLog::warningMessage("MSListener::close(%s) : warning: close(%d)\n",name().string(),fd()); } _fd=-1; _closeTod=todsec(); _closeCount++; _openedTime+=(closeTod()-openTod()); } if (retry()==MSListener::Yes) doRetry(); }
MSListener::MSListener(const char *name_,int pri_,MSListener::LRetry retry_,int firstRetry_, int lastRetry_,int domain_,int type_,int protocol_) : _name((name_==0)?"<UNKNOWN>":name_), _pri(pri_), _retryTime(firstRetry_,lastRetry_), _retry(retry_), _domain(domain_), _type(type_), _protocol(protocol_), _remoteNamelen(DefaultRemoteNameLength), _remoteName((struct sockaddr *)(0)), _retryTimer(0), _fd(-1), _localNamelen(0), _localName((struct sockaddr *)(0)), _acceptChannel(0), _openTod((time_t)(0)), _listenTod((time_t)(0)), _acceptTod((time_t)(0)), _deafTod((time_t)(0)), _closeTod((time_t)(0)), _openedTime((time_t)(0)), _listenedTime((time_t)(0)), _openCount((unsigned)(0)), _listenCount((unsigned)(0)), _acceptCount((unsigned)(0)), _deafCount((unsigned)(0)), _closeCount((unsigned)(0)) { _createTod=todsec(); }
/* internal function definitions */ static void acpt(struct lstn * p) { static char fnc[] = "acpt"; int r_namelen = p->r_namelen; struct sockaddr *r_name; int fd; int l_namelen = p->l_namelen; struct sockaddr *l_name; r_name = (struct sockaddr *) balloc(r_namelen); if ((fd = accept(p->fd, r_name, &r_namelen)) < 0) { if ((errno == EWOULDBLOCK) || (errno == EINTR)) { /* nothing to report */ } else if ((errno == EMFILE) || (errno == ENFILE) || (errno == ENXIO) || (errno == EIO)) { Warn("%t %s(%s): warn: accept(%d): %m\n", fnc, p->name, p->fd); } else { Warn("%t %s(%s): error: accept(%d): %m\n", fnc, p->name, p->fd); lstnclose(p); } bfree((char *) r_name); return; } l_name = (struct sockaddr *) balloc(l_namelen); if (getsockname(fd, l_name, &l_namelen) < 0) { Warn("%t %s(%s): error: getsockname(%d): %m\n", fnc, p->name, fd); doclose(fd); bfree((char *) l_name); bfree((char *) r_name); return; } p->acpttod = todsec(); (p->acptcount)++; r_name = (struct sockaddr *) brealloc((char *) r_name, r_namelen); l_name = (struct sockaddr *) brealloc((char *) l_name, l_namelen); (*(p->acptfunc)) (p, fd, r_name, r_namelen, l_name, l_namelen); return; }
/* external function definitions */ void lstnopen(struct lstn * p) { static char fnc[] = "lstnopen"; if ((p != (struct lstn *) (0)) || (p->fd >= 0)) { int fd; int toggle; p->retry_tp = (struct timer *) (0); if ((fd = socket(p->domain, p->type, p->protocol)) < 0) { Warn("%t %s(%s): error: socket(): %m\n", fnc, p->name); lstnclose(p); return; } p->opentod = todsec(); (p->opencount)++; fdsfresh(fd); p->fd = fd; toggle = 1; if (ioctl(fd, FIONBIO, &toggle) < 0) { Warn("%t %s(%s): warning: ioctl(%d, FIONBIO): %m\n", fnc, p->name, fd); } toggle = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) (&toggle), sizeof(toggle)) < 0) { Warn("%t %s(%s): warning: setsockopt(%d, REUSEADDR): %m\n", fnc, p->name, fd); } if ((*(p->l_namefunc)) (p) != 0) { lstnclose(p); return; } if (p->l_name == (struct sockaddr *) (0)) { p->l_name = (struct sockaddr *) balloc(p->l_namelen); bzero((char *) (p->l_name), p->l_namelen); } else { if (bind(fd, p->l_name, p->l_namelen) < 0) { Warn("%t %s(%s): error: bind(%d): %m\n", fnc, p->name, fd); lstnclose(p); return; } } if (listen(fd, 5) < 0) { Warn("%t %s(%s): error: listen(%d): %m\n", fnc, p->name, fd); lstnclose(p); return; } if (getsockname(fd, p->l_name, &(p->l_namelen)) < 0) { Warn("%t %s(%s): error: getsockname(%d): %m\n", fnc, p->name, fd); lstnclose(p); return; } if ((*(p->l_regfunc)) (p) != 0) { lstnclose(p); return; } p->lstntod = todsec(); (p->lstncount)++; p->acptchan = chanopen(p->name, fd, p->pri, CHAN_R, (void (*)(void *))acpt, (void *) p); chanenbl(p->acptchan); exboreset(p->retry_time); } return; }
void MSListener::doOpen(void) { if (fd()<0) { int lfd; initRetryTimer(); if ((lfd=socket(domain(),type(),protocol()))<0) { MSMessageLog::warningMessage("MSListener::open(%s): error: socket()\n",name().string()); close(); return; } _openTod=todsec(); _openCount++; MSChannel::fdsfresh(lfd); _fd=lfd; setBlockingMode(_fd); int toggle=1; if (setsockopt(fd(),SOL_SOCKET,SO_REUSEADDR,(char *)(&toggle),sizeof(toggle))<0) { MSMessageLog::warningMessage("MSListener::open(%s): warning: setsockopt(%d,REUSEADDR)\n",name().string(),fd()); } if (establish()==MSFalse) { close(); return; } if (localName()==(struct sockaddr *)(0)) { _localName=(struct sockaddr *)new char[localNamelen()]; memset((char *)(localName()),0,localNamelen()); } else { if (bind(fd(),localName(),localNamelen())<0) { MSMessageLog::warningMessage("MSListener::open(%s): error: bind(%d)\n",name().string(),fd()); close(); return; } } if (listen(fd(),5)<0) { MSMessageLog::warningMessage("MSListener::open(%s): error: listen(%d)\n",name().string(),fd()); close(); return; } #if defined(HAVE_SOCKLEN_T) if (getsockname(fd(),localName(),(socklen_t *)&_localNamelen)<0) #else if (getsockname(fd(),localName(),&_localNamelen)<0) #endif { MSMessageLog::warningMessage("MSListener::open(%s): error: getsockname(%d)\n",name().string(),fd()); close(); return; } if (publish()==MSFalse) { close(); return; } _listenTod=todsec(); _listenCount++; createAcceptChannel(); _retryTime.reset(); } }
void MSListener::processAccept(void) { int rfd; int rlen=remoteNamelen(); struct sockaddr *rname; struct sockaddr *lname; int llen=localNamelen(); rname=(struct sockaddr *)new char[rlen]; #if defined(HAVE_SOCKLEN_T) if ((rfd=::accept(fd(),rname,(socklen_t *)&rlen))<0) #else if ((rfd=::accept(fd(),rname,&rlen))<0) #endif { #if defined(MS_WINSOCK) int err=WSAGetLastError(); if(err==WSAEWOULDBLOCK||err==WSAEINTR){} else if(err==WSAEMFILE) #else if ((errno==EWOULDBLOCK)||(errno==EINTR)) {} // nothing to report else if ((errno==EMFILE)||(errno==ENFILE)||(errno==ENXIO)||(errno==EIO)) #endif { MSMessageLog::warningMessage("MSListener::accept(%s): error: accept(%d)\n",name().string(),fd()); } else { MSMessageLog::warningMessage("MSListener::accept(%s): error: accept(%d)\n",name().string(),fd()); close(); } delete [] rname; return; } lname=(struct sockaddr *)new char [llen]; #if defined(HAVE_SOCKLEN_T) if (getsockname(rfd,lname,(socklen_t *)&llen)<0) #else if (getsockname(rfd,lname,&llen)<0) #endif { MSMessageLog::warningMessage("MSListener::accept(%s): error: getsockname(%d)\n",name().string(),fd()); #if defined(MS_WINSOCK) ::closesocket(fd()); #else ::close(fd()); #endif delete [] rname; delete [] lname; return; } _acceptTod=todsec(); _acceptCount++; struct sockaddr *rn=(struct sockaddr *)new char[rlen]; struct sockaddr *ln=(struct sockaddr *)new char[llen]; memcpy((char *)rn,(char *)rname,rlen); memcpy((char *)ln,(char *)lname,llen); delete [] rname; delete [] lname; acceptNotify(rfd,rn,rlen,ln,llen); delete [] rn; delete [] ln; }