X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=net.c;h=59b7f367fb2f119e338d9411f2060a71b39209fc;hp=b9729b6988f894a3e346a591b477ed0fb9012149;hb=60ef885705932a682097ad2b9f2379282d814e79;hpb=05029e5af523f92849b4f691a15a963cb6a10e1f diff --git a/net.c b/net.c index b9729b69..59b7f367 100644 --- a/net.c +++ b/net.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2009 Andre Noll + * Copyright (C) 2005-2010 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -436,6 +436,7 @@ int makesock(unsigned l4type, bool passive, if (passive && setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { rc = errno; + close(sockfd); PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n", strerror(rc)); return -ERRNO_TO_PARA_ERROR(rc); @@ -755,50 +756,68 @@ int recv_buffer(int fd, char *buf, size_t size) * Wrapper around the accept system call. * * \param fd The listening socket. + * \param rfds An optional fd_set pointer. * \param addr Structure which is filled in with the address of the peer socket. * \param size Should contain the size of the structure pointed to by \a addr. + * \param new_fd Result pointer. * - * Accept incoming connections on \a addr. Retry if interrupted. + * Accept incoming connections on \a addr, retry if interrupted. If \a rfds is + * not \p NULL, return 0 if \a fd is not set in \a rfds without calling accept(). * - * \return The new file descriptor on success, negative on errors. + * \return Negative on errors, zero if no connections are present to be accepted, + * one otherwise. * * \sa accept(2). */ -int para_accept(int fd, void *addr, socklen_t size) +int para_accept(int fd, fd_set *rfds, void *addr, socklen_t size, int *new_fd) { - int new_fd; + int ret; + if (rfds && !FD_ISSET(fd, rfds)) + return 0; do - new_fd = accept(fd, (struct sockaddr *) addr, &size); - while (new_fd < 0 && errno == EINTR); - return new_fd < 0? -ERRNO_TO_PARA_ERROR(errno) : new_fd; + ret = accept(fd, (struct sockaddr *) addr, &size); + while (ret < 0 && errno == EINTR); + + if (ret >= 0) { + *new_fd = ret; + return 1; + } + if (errno == EAGAIN || errno == EWOULDBLOCK) + return 0; + return -ERRNO_TO_PARA_ERROR(errno); } /** - * Probe the list of DCCP CCIDs supported locally by the host. - * \param ccids Array to be filled in. - * \param nccids Length of \a ccids. - * \return Pointer to \a ccids, NULL on failure. + * Probe the list of DCCP CCIDs configured on this host. + * \param ccid_array Pointer to return statically allocated array in. + * \return Number of elements returned in \a ccid_array or error. * * NB: This feature is only available on Linux > 2.6.30; on older kernels * ENOPROTOOPT ("Protocol not available") will be returned. */ -const uint8_t *dccp_available_ccids(uint8_t *ccids, uint8_t *nccids) +int dccp_available_ccids(uint8_t **ccid_array) { - int fd = makesock(IPPROTO_DCCP, 1, NULL, 0, NULL); + static uint8_t ccids[DCCP_MAX_HOST_CCIDS]; + socklen_t nccids = sizeof(ccids); + int ret, fd; - if (fd < 0) - return NULL; + ret = fd = makesock(IPPROTO_DCCP, 1, NULL, 0, NULL); + if (ret < 0) + return ret; if (getsockopt(fd, SOL_DCCP, DCCP_SOCKOPT_AVAILABLE_CCIDS, - ccids, (socklen_t *)nccids) < 0) { + ccids, &nccids) < 0) { + ret = errno; + close(fd); PARA_ERROR_LOG("No DCCP_SOCKOPT_AVAILABLE_CCIDS: %s\n", - strerror(errno)); - *nccids = 0; + strerror(ret)); + return -ERRNO_TO_PARA_ERROR(ret); } - close(fd); - return *nccids ? ccids : NULL; + close(fd); + *ccid_array = ccids; + return nccids; } /** @@ -1011,41 +1030,3 @@ int recv_cred_buffer(int fd, char *buf, size_t size) return result; } #endif /* HAVE_UCRED */ - -/** - * Receive a buffer and check for a pattern. - * - * \param fd The file descriptor to receive from. - * \param pattern The expected pattern. - * \param bufsize The size of the internal buffer. - * - * \return Positive if \a pattern was received, negative otherwise. - * - * This function tries to receive at most \a bufsize bytes from file descriptor - * \a fd. If at least \p strlen(\a pattern) bytes were received, the beginning - * of the received buffer is compared with \a pattern, ignoring case. - * - * \sa recv_buffer(), \sa strncasecmp(3). - */ -int recv_pattern(int fd, const char *pattern, size_t bufsize) -{ - size_t len = strlen(pattern); - char *buf = para_malloc(bufsize + 1); - int ret = -E_RECV_PATTERN, n = recv_buffer(fd, buf, bufsize + 1); - - if (n < len) - goto out; - if (strncasecmp(buf, pattern, len)) - goto out; - ret = 1; -out: - if (ret < 0) { - PARA_NOTICE_LOG("did not receive pattern '%s'\n", pattern); - if (n > 0) - PARA_NOTICE_LOG("recvd %d bytes: %s\n", n, buf); - else if (n < 0) - PARA_NOTICE_LOG("%s\n", para_strerror(-n)); - } - free(buf); - return ret; -}