-
-/**
- * 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("n = %d, did not receive pattern '%s'\n", n,
- pattern);
- if (n > 0)
- PARA_NOTICE_LOG("recvd: %s\n", buf);
- }
- free(buf);
- return ret;
-}
-
-static int resolve(const char *hostname, unsigned short port,
- struct sockaddr_in *addr)
-{
- struct hostent *host;
-
- assert(hostname);
- host = gethostbyname(hostname);
- if (!host)
- return -ERRNO_TO_PARA_ERROR(h_errno);
- if (addr) {
- memcpy(&addr->sin_addr, host->h_addr_list[0], host->h_length);
- addr->sin_port = port;
- }
- return 1;
-}
-
-/*
- * Create an UDP socket.
- *
- * If the given address is a multicast adress, the socket will be set
- * to use the multicast TTL ttl and sets the datagrams to loop back.
- *
- * \return The fd of the socket on success, negative on errors.
- */
-static int create_udp_socket(struct sockaddr_in *addr,
- unsigned short port, unsigned char ttl)
-{
- int ret, fd, yes = 1;
-
- assert(addr);
- ret = socket(PF_INET, SOCK_DGRAM, 0);
- if (ret < 0)
- return -ERRNO_TO_PARA_ERROR(errno);
- fd = ret;
- /* reuse addresses */
- ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
- if (ret < 0) {
- ret = -ERRNO_TO_PARA_ERROR(errno);
- goto err;
- }
- addr->sin_family = AF_INET;
- addr->sin_port = htons(port);
- /* set the TTL and turn on multicast loop */
- if (IN_MULTICAST(htonl(addr->sin_addr.s_addr))) {
- unsigned char loop = 1;
- ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
- sizeof(ttl));
- if (ret < 0) {
- ret = -ERRNO_TO_PARA_ERROR(errno);
- goto err;
- }
- ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
- sizeof(loop));
- if (ret < 0) {
- ret = -ERRNO_TO_PARA_ERROR(errno);
- goto err;
- }
- }
- return fd;
-err:
- close(fd);
- return ret;
-}
-
-/**
- * Create and connect a sending UDP socket.
- *
- * \param hostname Where to send to (name or IPv4 address).
- * \param port The udp port to use.
- * \param ttl Time to live (only relevant for multicast).
- *
- * \return The fd of the socket on success, negative on error.
- */
-int create_udp_send_socket(char *hostname, unsigned short port,
- unsigned char ttl)
-{
- struct sockaddr_in addr;
- int fd, ret = resolve(hostname, port, &addr);
-
- if (ret < 0)
- return ret;
- ret = create_udp_socket(&addr, port, ttl);
- if (ret < 0)
- return ret;
- fd = ret;
- ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
- if (ret >= 0)
- return fd;
- ret = -ERRNO_TO_PARA_ERROR(errno);
- close(fd);
- return ret;
-}
-
-/**
- * Create and bind a receiving UDP socket.
- *
- * Bind the created UDP socket to \a hostname, and add multicast membership if
- * hostname is a multicast hostname.
- *
- * \param hostname Name or IPv4 address to receive from.
- * \param port The udp port.
- *
- * \return The fd of the socket on success, negative on errors.
- */
-int create_udp_recv_socket(char *hostname, unsigned short port)
-{
- struct sockaddr_in addr;
- int fd, ret = resolve(hostname, port, &addr);
-
- if (ret < 0)
- memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
- ret = create_udp_socket(&addr, port, 1);
- if (ret < 0)
- return ret;
- fd = ret;
- ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
- if (ret < 0) {
- ret = -ERRNO_TO_PARA_ERROR(errno);
- goto err;
- }
- /* Add multicast membership */
- if (IN_MULTICAST(htonl(addr.sin_addr.s_addr))) {
- struct ip_mreq mreq;
-
- mreq.imr_multiaddr.s_addr = addr.sin_addr.s_addr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &mreq, sizeof(mreq));
- if (ret < 0) {
- ret = -ERRNO_TO_PARA_ERROR(errno);
- goto err;
- }
- }
- return fd;
-err:
- close(fd);
- return ret;
-}