summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/samples/socket-api/wasm-src/multicast_client.c
blob: 43201dcbdca191cbd1bca1131220b0061fb27ea1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 */

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifdef __wasi__
#include <wasi_socket_ext.h>
#endif

static void
init_sockaddr_inet(struct sockaddr_in *addr)
{
    addr->sin_family = AF_INET;
    addr->sin_port = htons(1234);
}

static void
init_sockaddr_inet6(struct sockaddr_in6 *addr)
{
    addr->sin6_family = AF_INET6;
    addr->sin6_port = htons(1234);
}

static int
get_ip_addr_type(char *addr, char *buf)
{
    if (inet_pton(AF_INET6, addr, buf)) {
        return AF_INET6;
    }
    if (inet_pton(AF_INET, addr, buf)) {
        return AF_INET;
    }
    return -1;
}

static int
is_valid_addr_type(int addr_type)
{
    return !(addr_type == -1
             || (addr_type != AF_INET && addr_type != AF_INET6));
}

int
main(int argc, char *argv[])
{
    struct ipv6_mreq ipv6_group;
    struct ip_mreq ipv4_group;
    int sd;
    int datalen;
    char databuf[1024] = { 0 };
    char multicast_addr_buffer[16];
    struct sockaddr_storage local_address = { 0 };
    int addr_type = -1;
    int read_result;
    int bool_opt = 1;

    if (argc < 2) {
        printf("Usage is <Multicast IP>\n");
        return EXIT_FAILURE;
    }

    addr_type = get_ip_addr_type(argv[1], multicast_addr_buffer);

    if (!is_valid_addr_type(addr_type)) {
        printf("Not a valid ipv4 or ipv6 address\n");
        return EXIT_FAILURE;
    }

    if ((sd = socket(addr_type, SOCK_DGRAM, 0)) == -1) {
        perror("Failed opening socket");
        return EXIT_FAILURE;
    }

    if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &bool_opt, sizeof(bool_opt))
        == -1) {
        perror("Failed setting SO_REUSEADDR");
        goto fail;
    }

    if (addr_type == AF_INET) {
        init_sockaddr_inet((struct sockaddr_in *)&local_address);
        memcpy(&(ipv4_group.imr_multiaddr), multicast_addr_buffer, 4);
        ipv4_group.imr_interface.s_addr = htonl(INADDR_ANY);

        if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipv4_group,
                       sizeof(ipv4_group))
            == -1) {
            perror("Failed joining IPv4 multicast group");
            goto fail;
        }
    }
    else {
        init_sockaddr_inet6((struct sockaddr_in6 *)&local_address);
        memcpy(&(ipv6_group.ipv6mr_multiaddr), multicast_addr_buffer, 16);
        ipv6_group.ipv6mr_interface = 0;

        if (setsockopt(sd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &ipv6_group,
                       sizeof(ipv6_group))
            == -1) {
            perror("Failed joining IPv6 multicast group");
            goto fail;
        }
    }

    if (bind(sd, (struct sockaddr *)&local_address, sizeof(local_address))
        == -1) {
        perror("Failed binding socket");
        goto fail;
    }

    printf("Joined multicast group. Waiting for datagram...\n");

    datalen = sizeof(databuf) - 1;
    read_result = read(sd, databuf, datalen);

    if (read_result < 0) {
        perror("Failed binding socket");
        goto fail;
    }

    printf("Reading datagram message...OK.\n");
    printf("The message from multicast server is: \"%s\"\n", databuf);
    close(sd);
    return EXIT_SUCCESS;

fail:
    close(sd);
    return EXIT_FAILURE;
}