} d;
};
+static int getlocalname(int fd, struct sockaddr **namebuf, socklen_t *lenbuf);
+
static struct ufd *ufds = NULL;
static struct scons *rbatch, *wbatch, *cbatch;
int numsocks = 0;
new->refcount = 1;
new->state = -1;
new->dgram = dgram;
+ new->maxbuf = 65536;
numsocks++;
return(new);
}
linksock(&rbatch, sk->back);
}
-void sockeos(struct socket *sk)
-{
- sksetstate(sk, SOCK_STL);
- if(sk->back->eos == 0)
- sk->back->eos = 1;
- linksock(&rbatch, sk->back);
-}
-
-static void sockerror(struct socket *sk, int en)
+void sockerror(struct socket *sk, int en)
{
sksetstate(sk, SOCK_STL);
if(sk->back->errcb != NULL)
freedgbuf(dbuf);
if((ufd->type != UFD_SOCK) || !((ufd->d.s.family == AF_INET) || (ufd->d.s.family == AF_INET6)))
{
- sockeos(ufd->sk);
+ closesock(ufd->sk);
closeufd(ufd);
}
return;
{
free(buf);
closeufd(ufd);
- sockeos(ufd->sk);
+ closesock(ufd->sk);
return;
}
sockqueue(ufd->sk, buf, ret);
}
}
-static void sockflush(struct ufd *ufd)
+static int sockflush(struct ufd *ufd)
{
int ret;
struct dgrambuf *dbuf;
int dgram;
- if((dgram = ufddgram(ufd)) < 0)
- return;
+ if((dgram = ufddgram(ufd)) < 0) {
+ errno = EBADFD;
+ return(-1);
+ }
if(dgram) {
dbuf = sockgetdgbuf(ufd->sk);
sendto(ufd->fd, dbuf->data, dbuf->size, MSG_DONTWAIT | MSG_NOSIGNAL, dbuf->addr, dbuf->addrlen);
ret = send(ufd->fd, ufd->sk->buf.s.buf, ufd->sk->buf.s.datasize, MSG_DONTWAIT | MSG_NOSIGNAL);
else
ret = write(ufd->fd, ufd->sk->buf.s.buf, ufd->sk->buf.s.datasize);
- if(ret < 0) {
- /* For now, assume transient error, since
- * the socket is polled for errors */
- return;
- }
+ if(ret < 0)
+ return(-1);
if(ret > 0) {
memmove(ufd->sk->buf.s.buf, ((char *)ufd->sk->buf.s.buf) + ret, ufd->sk->buf.s.datasize -= ret);
sockread(ufd->sk);
}
}
+ return(0);
}
void closesock(struct socket *sk)
{
-/*
- struct sockaddr_un *un;
-
- if((sk->family == AF_UNIX) && !sockgetlocalname(sk, (struct sockaddr **)(void *)&un, NULL) && (un->sun_family == PF_UNIX))
- {
- if((sk->state == SOCK_LST) && strchr(un->sun_path, '/'))
- {
- if(unlink(un->sun_path))
- flog(LOG_WARNING, "could not unlink Unix socket %s: %s", un->sun_path, strerror(errno));
- }
- }
-*/
sksetstate(sk, SOCK_STL);
- sockeos(sk);
+ if(sk->back->eos == 0)
+ sk->back->eos = 1;
+ linksock(&rbatch, sk->back);
}
size_t sockgetdatalen(struct socket *sk)
return(ret);
}
-size_t sockqueuesize(struct socket *sk)
+/* size_t sockqueuesize(struct socket *sk) */
+/* { */
+/* return(sockgetdatalen(sk->back)); */
+/* } */
+
+ssize_t sockqueueleft(struct socket *sk)
{
- return(sockgetdatalen(sk->back));
+ return(sk->back->maxbuf - sockgetdatalen(sk->back));
}
/*
void closelport(struct lport *lp)
{
+ struct ufd *ufd;
+ struct sockaddr_un *un;
+
+ ufd = lp->ufd;
+ if((ufd->d.l.family == AF_UNIX) && !getlocalname(ufd->fd, (struct sockaddr **)(void *)&un, NULL) && (un->sun_family == PF_UNIX) && strchr(un->sun_path, '/')) {
+ if(unlink(un->sun_path))
+ flog(LOG_WARNING, "could not unlink Unix socket %s: %s", un->sun_path, strerror(errno));
+ }
freeufd(lp->ufd);
}
nsc = sc->n;
if(sc->s->conncb != NULL)
sc->s->conncb(sc->s, 0, sc->s->data);
+ putsock(sc->s);
free(sc);
}
for(sc = rbatch, rbatch = NULL; sc; sc = nsc) {
sc->s->errcb(sc->s, 0, sc->s->data);
sc->s->eos = 2;
}
+ putsock(sc->s);
free(sc);
}
for(sc = wbatch, wbatch = NULL; sc; sc = nsc) {
nsc = sc->n;
if(sc->s->writecb != NULL)
sc->s->writecb(sc->s, sc->s->data);
+ putsock(sc->s);
free(sc);
}
}
for(ufd = ufds; ufd != NULL; ufd = next) {
next = ufd->next;
- if(ufd->sk && (sockgetdatalen(ufd->sk) == 0)) {
+ if(ufd->sk && ((ufd->fd < 0) || (sockgetdatalen(ufd->sk) == 0))) {
if(ufd->sk->eos == 1) {
ufd->sk->eos = 2;
closeufd(ufd);
for(maxfd = 0, ufd = ufds; ufd != NULL; ufd = ufd->next) {
if(ufd->fd < 0)
continue;
- if(!ufd->ignread)
+ if(!ufd->ignread && ((ufd->sk == NULL) || (sockqueueleft(ufd->sk) > 0)))
FD_SET(ufd->fd, &rfds);
if(ufd->sk != NULL) {
if(sockgetdatalen(ufd->sk) > 0)
sockrecv(ufd);
if(ufd->fd == -1)
continue;
- if(FD_ISSET(ufd->fd, &wfds))
- sockflush(ufd);
+ if(FD_ISSET(ufd->fd, &wfds)) {
+ if(sockflush(ufd)) {
+ sockerror(ufd->sk, errno);
+ closeufd(ufd);
+ continue;
+ }
+ }
}
}
}
errno = EOPNOTSUPP;
return(-1);
}
- if(ufd1->d.s.family != ufd2->d.s.family)
+ if(ufd1->d.l.family != ufd2->d.s.family)
{
- flog(LOG_ERR, "using lstgetremotename2 with sockets of differing family: %i %i", ufd1->d.s.family, ufd2->d.s.family);
+ flog(LOG_ERR, "using lstgetremotename2 with sockets of differing family: %i %i", ufd1->d.l.family, ufd2->d.s.family);
return(-1);
}
if(getremotename(ufd1->fd, &name1, &len1))
return(0);
}
-void sockblock(struct socket *sk, int block)
-{
- struct ufd *ufd;
+/* void sockblock(struct socket *sk, int block) */
+/* { */
+/* struct ufd *ufd; */
- ufd = getskufd(sk);
- ufd->ignread = block;
-}
+/* ufd = getskufd(sk); */
+/* ufd->ignread = block; */
+/* } */
int sockfamily(struct socket *sk)
{