192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly/*
292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * Copyright 2009, The Android Open Source Project
392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly *
492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * you may not use this file except in compliance with the License.
692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * You may obtain a copy of the License at
792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly *
892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly *     http://www.apache.org/licenses/LICENSE-2.0
992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly *
1092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * Unless required by applicable law or agreed to in writing, software
1192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
1292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * See the License for the specific language governing permissions and
1492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly * limitations under the License.
1592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly */
1692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
1792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <stdlib.h>
1892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <errno.h>
1992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <unistd.h>
2092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <fcntl.h>
2192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <sys/socket.h>
2292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include <sys/poll.h>
2392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
2492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly#include "cutils/abort_socket.h"
2592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
2692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellystruct asocket *asocket_init(int fd) {
2792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int abort_fd[2];
2892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int flags;
2992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    struct asocket *s;
3092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
3192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* set primary socket to non-blocking */
3292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    flags = fcntl(fd, F_GETFL);
3392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (flags == -1)
3492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return NULL;
3592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
3692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return NULL;
3792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
3892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* create pipe with non-blocking write, so that asocket_close() cannot
3992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly       block */
4092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pipe(abort_fd))
4192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return NULL;
4292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    flags = fcntl(abort_fd[1], F_GETFL);
4392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (flags == -1)
4492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return NULL;
4592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (fcntl(abort_fd[1], F_SETFL, flags | O_NONBLOCK))
4692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return NULL;
4792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
4892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s = malloc(sizeof(struct asocket));
4992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (!s)
5092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return NULL;
5192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
5292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s->fd = fd;
5392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s->abort_fd[0] = abort_fd[0];
5492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s->abort_fd[1] = abort_fd[1];
5592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
5692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    return s;
5792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
5892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
5992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_connect(struct asocket *s, const struct sockaddr *addr,
6092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        socklen_t addrlen, int timeout) {
6192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
6292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int ret;
6392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
6492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    do {
6592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        ret = connect(s->fd, addr, addrlen);
6692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    } while (ret && errno == EINTR);
6792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
6892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (ret && errno == EINPROGRESS) {
6992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* ready to poll() */
7092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        socklen_t retlen;
7192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        struct pollfd pfd[2];
7292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
7392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        pfd[0].fd = s->fd;
7492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        pfd[0].events = POLLOUT;
7592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        pfd[0].revents = 0;
7692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        pfd[1].fd = s->abort_fd[0];
7792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        pfd[1].events = POLLIN;
7892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        pfd[1].revents = 0;
7992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
8092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        do {
8192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            ret = poll(pfd, 2, timeout);
8292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        } while (ret < 0 && errno == EINTR);
8392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
8492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        if (ret < 0)
8592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            return -1;
8692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        else if (ret == 0) {
8792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* timeout */
8892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            errno = ETIMEDOUT;
8992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            return -1;
9092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        }
9192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
9292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        if (pfd[1].revents) {
9392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* abort due to asocket_abort() */
9492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            errno = ECANCELED;
9592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            return -1;
9692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        }
9792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
9892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        if (pfd[0].revents) {
9992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            if (pfd[0].revents & POLLOUT) {
10092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                /* connect call complete, read return code */
10192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                retlen = sizeof(ret);
10292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen))
10392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                    return -1;
10492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                /* got connect() return code */
10592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                if (ret) {
10692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                    errno = ret;
10792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                }
10892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            } else {
10992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                /* some error event on this fd */
11092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                errno = ECONNABORTED;
11192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                return -1;
11292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            }
11392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        }
11492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
11592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
11692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    return ret;
11792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
11892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
11992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_accept(struct asocket *s, struct sockaddr *addr,
12092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        socklen_t *addrlen, int timeout) {
12192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
12292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int ret;
12392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    struct pollfd pfd[2];
12492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
12592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].fd = s->fd;
12692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].events = POLLIN;
12792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].revents = 0;
12892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].fd = s->abort_fd[0];
12992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].events = POLLIN;
13092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].revents = 0;
13192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
13292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    do {
13392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        ret = poll(pfd, 2, timeout);
13492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    } while (ret < 0 && errno == EINTR);
13592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
13692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (ret < 0)
13792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
13892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    else if (ret == 0) {
13992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* timeout */
14092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        errno = ETIMEDOUT;
14192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
14292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
14392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
14492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pfd[1].revents) {
14592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* abort due to asocket_abort() */
14692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        errno = ECANCELED;
14792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
14892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
14992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
15092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pfd[0].revents) {
15192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        if (pfd[0].revents & POLLIN) {
15292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* ready to accept() without blocking */
15392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            do {
15492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                ret = accept(s->fd, addr, addrlen);
15592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            } while (ret < 0 && errno == EINTR);
15692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        } else {
15792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* some error event on this fd */
15892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            errno = ECONNABORTED;
15992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            return -1;
16092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        }
16192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
16292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
16392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    return ret;
16492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
16592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
16692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_read(struct asocket *s, void *buf, size_t count, int timeout) {
16792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int ret;
16892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    struct pollfd pfd[2];
16992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
17092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].fd = s->fd;
17192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].events = POLLIN;
17292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].revents = 0;
17392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].fd = s->abort_fd[0];
17492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].events = POLLIN;
17592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].revents = 0;
17692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
17792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    do {
17892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        ret = poll(pfd, 2, timeout);
17992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    } while (ret < 0 && errno == EINTR);
18092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
18192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (ret < 0)
18292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
18392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    else if (ret == 0) {
18492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* timeout */
18592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        errno = ETIMEDOUT;
18692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
18792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
18892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
18992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pfd[1].revents) {
19092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* abort due to asocket_abort() */
19192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        errno = ECANCELED;
19292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
19392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
19492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
19592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pfd[0].revents) {
19692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        if (pfd[0].revents & POLLIN) {
19792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* ready to read() without blocking */
19892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            do {
19992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                ret = read(s->fd, buf, count);
20092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            } while (ret < 0 && errno == EINTR);
20192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        } else {
20292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* some error event on this fd */
20392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            errno = ECONNABORTED;
20492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            return -1;
20592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        }
20692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
20792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
20892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    return ret;
20992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
21092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
21192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyint asocket_write(struct asocket *s, const void *buf, size_t count,
21292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        int timeout) {
21392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int ret;
21492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    struct pollfd pfd[2];
21592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
21692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].fd = s->fd;
21792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].events = POLLOUT;
21892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[0].revents = 0;
21992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].fd = s->abort_fd[0];
22092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].events = POLLIN;
22192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    pfd[1].revents = 0;
22292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
22392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    do {
22492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        ret = poll(pfd, 2, timeout);
22592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    } while (ret < 0 && errno == EINTR);
22692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
22792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (ret < 0)
22892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
22992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    else if (ret == 0) {
23092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* timeout */
23192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        errno = ETIMEDOUT;
23292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
23392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
23492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
23592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pfd[1].revents) {
23692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        /* abort due to asocket_abort() */
23792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        errno = ECANCELED;
23892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        return -1;
23992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
24092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
24192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    if (pfd[0].revents) {
242111bfcefc3cf0f14ad607a56fcf5d076131833a9Nick Pelly        if (pfd[0].revents & POLLOUT) {
24392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* ready to write() without blocking */
24492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            do {
24592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly                ret = write(s->fd, buf, count);
24692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            } while (ret < 0 && errno == EINTR);
24792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        } else {
24892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            /* some error event on this fd */
24992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            errno = ECONNABORTED;
25092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly            return -1;
25192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        }
25292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    }
25392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
25492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    return ret;
25592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
25692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
25792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyvoid asocket_abort(struct asocket *s) {
25892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    int ret;
25992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    char buf = 0;
26092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
26192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* Prevent further use of fd, without yet releasing the fd */
26292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    shutdown(s->fd, SHUT_RDWR);
26392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
26492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* wake up calls blocked at poll() */
26592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    do {
26692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly        ret = write(s->abort_fd[1], &buf, 1);
26792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    } while (ret < 0 && errno == EINTR);
26892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
26992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
27092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pellyvoid asocket_destroy(struct asocket *s) {
27192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    struct asocket s_copy = *s;
27292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
27392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* Clients should *not* be using these fd's after calling
27492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly       asocket_destroy(), but in case they do, set to -1 so they cannot use a
27592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly       stale fd */
27692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s->fd = -1;
27792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s->abort_fd[0] = -1;
27892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    s->abort_fd[1] = -1;
27992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
28092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* Call asocket_abort() in case there are still threads blocked on this
28192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly       socket. Clients should not rely on this behavior - it is racy because we
28292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly       are about to close() these sockets - clients should instead make sure
28392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly       all threads are done with the socket before calling asocket_destory().
28492a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly     */
28592a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    asocket_abort(&s_copy);
28692a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
28792a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    /* enough safety checks, close and release memory */
28892a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    close(s_copy.abort_fd[1]);
28992a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    close(s_copy.abort_fd[0]);
29092a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    close(s_copy.fd);
29192a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly
29292a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly    free(s);
29392a7541bce0f8ed7649dcbadd83b27d71e4f391fNick Pelly}
294