source: rtems-libbsd/testsuite/foobarclient/test_main.c @ 3951c97

4.115-freebsd-12freebsd-9.3
Last change on this file since 3951c97 was 3951c97, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 22, 2014 at 8:43:51 AM

mDNS: Add basic support

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <mDNSEmbeddedAPI.h>
33#include <mDNSPosix.h>
34
35#include <sys/select.h>
36#include <sys/socket.h>
37
38#include <netinet/in.h>
39
40#include <assert.h>
41#include <errno.h>
42#include <netdb.h>
43#include <stdbool.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
49#define TEST_NAME "LIBBSD FOOBAR CLIENT"
50
51static mDNS mDNSStorage;
52
53static mDNS_PlatformSupport PlatformStorage;
54
55static CacheEntity rr_cache[64];
56
57static const char * const qc_results[] = {
58        "rmv",
59        "add",
60        "addnocache",
61        "forceresponse",
62        "dnssec",
63        "nodnssec",
64        "suppressed"
65};
66
67typedef struct service_info_query {
68        struct service_info_query *next;
69        ServiceInfoQuery query;
70        ServiceInfo info;
71} service_info_query;
72
73static service_info_query *service_info_query_list;
74
75static mDNSBool
76eval_service_name(const domainname *fqdn, domainlabel *name)
77{
78        domainname type;
79        domainname domain;
80        mDNSBool ok = DeconstructServiceName(fqdn, name, &type, &domain);
81
82        if (ok) {
83                char name_str[MAX_DOMAIN_LABEL + 1];
84                char type_str[MAX_ESCAPED_DOMAIN_NAME];
85                char domain_str[MAX_ESCAPED_DOMAIN_NAME];
86
87                ConvertDomainLabelToCString_unescaped(name, name_str);
88                ConvertDomainNameToCString(&type, type_str);
89                ConvertDomainNameToCString(&domain, domain_str);
90
91                printf("name = '%s', type = '%s', domain = '%s'",
92                    name_str, type_str, domain_str);
93        } else {
94                printf("?");
95        }
96
97        return ok;
98}
99
100static void
101foobar_action(const struct sockaddr_storage *addr)
102{
103        static const char foobar[] = "FooBar!";
104
105        int sd;
106        int rv;
107
108        sd = socket(addr->ss_family, SOCK_STREAM, 0);
109        assert(sd >= 0);
110
111        rv = connect(sd, (struct sockaddr *) addr, addr->ss_len);
112        if (rv == 0) {
113                char buf[sizeof(foobar)];
114                ssize_t n;
115
116                n = read(sd, &buf[0], sizeof(buf));
117                if (n == (ssize_t) sizeof(buf)) {
118                        assert(memcmp(&buf[0], &foobar[0], sizeof(buf)) == 0);
119                        printf("foobar client: read: %s\n", &buf[0]);
120                } else if (n >= 0) {
121                        printf("foobar client: partial read: %zi\n", n);
122                } else {
123                        printf("foobar client: read error: %s\n",
124                            strerror(errno));
125                }
126        } else {
127                printf("foobar client: connect error: %s\n", strerror(errno));
128        }
129
130        rv = close(sd);
131        assert(rv == 0);
132}
133
134static void
135foobar_service_info(mDNS *const m, ServiceInfoQuery *query)
136{
137        const ServiceInfo *i = query->info;
138        struct sockaddr_storage addr;
139        char host[NI_MAXHOST];
140        domainlabel name;
141        int rv;
142
143        memset(&addr, 0, sizeof(addr));
144
145        if (i->ip.type == mDNSAddrType_IPv4) {
146                struct sockaddr_in *s = (struct sockaddr_in *) &addr;
147
148                s->sin_len = sizeof(*s);
149                s->sin_family = AF_INET;
150                s->sin_port = i->port.NotAnInteger;
151                s->sin_addr.s_addr = i->ip.ip.v4.NotAnInteger;
152        } else {
153                struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &addr;
154
155                sin6->sin6_len = sizeof(*sin6);
156                sin6->sin6_family = AF_INET6;
157                sin6->sin6_port = i->port.NotAnInteger;
158                sin6->sin6_addr = *(struct in6_addr *) &i->ip.ip.v6;
159        }
160
161        rv = getnameinfo((struct sockaddr *) &addr, addr.ss_len, host,
162            sizeof(host), NULL, 0, NI_NUMERICHOST);
163        assert(rv == 0);
164
165        printf("foobar client: service info: ");
166        eval_service_name(&i->name, &name);
167        printf(", addr = %s, port = %i\n", &host[0], mDNSVal16(i->port));
168
169        foobar_action(&addr);
170}
171
172static void
173foobar_manage_service(mDNS *m, const ResourceRecord *answer,
174    const domainlabel *name, bool add)
175{
176        if (add) {
177                mStatus status;
178                service_info_query *siq =
179                    calloc(1, sizeof(*siq));
180
181                assert(siq != NULL);
182
183                siq->next = service_info_query_list;
184                service_info_query_list = siq;
185
186                siq->info.name = answer->rdata->u.name;
187                siq->info.InterfaceID = answer->InterfaceID;
188
189                status = mDNS_StartResolveService(m, &siq->query, &siq->info,
190                    foobar_service_info, NULL);
191                assert(status == mStatus_NoError);
192        } else {
193                service_info_query *cur = service_info_query_list;
194                service_info_query *prev = cur;
195
196                while (cur != NULL && !SameDomainLabel(&name->c[0],
197                    &cur->info.name.c[0])) {
198                        prev = cur;
199                        cur = cur->next;
200                }
201
202                if (cur != NULL) {
203                        if (prev != cur) {
204                                prev->next = cur->next;
205                        } else {
206                                service_info_query_list = cur->next;
207                        }
208
209                        mDNS_StopResolveService(m, &cur->query);
210                        free(cur);
211                }
212        }
213}
214
215static void
216foobar_browse(mDNS *m, DNSQuestion *question,
217    const ResourceRecord *answer, QC_result res)
218{
219        (void) question;
220
221        printf("foobar client: %s: ", qc_results[res]);
222
223        if (answer->rrtype == kDNSType_PTR &&
224            (res == QC_rmv || res == QC_add)) {
225                domainlabel name;
226                mDNSBool ok = eval_service_name(&answer->rdata->u.name, &name);
227
228                if (ok) {
229                        foobar_manage_service(m, answer, &name, res == QC_add);
230                }
231
232                printf("\n");
233        }
234}
235
236static void
237foobar_register(DNSQuestion *question)
238{
239        mStatus status;
240        domainname type;
241        domainname domain;
242
243        MakeDomainNameFromDNSNameString(&type, "_foobar._tcp");
244        MakeDomainNameFromDNSNameString(&domain, "local.");
245
246        status = mDNS_StartBrowse(&mDNSStorage, question, &type, &domain,
247            mDNSNULL, mDNSInterface_Any, 0, mDNSfalse, mDNSfalse,
248            foobar_browse, NULL);
249        assert(status == mStatus_NoError);
250}
251
252static void
253test_main(void)
254{
255        mStatus status;
256        DNSQuestion question;
257
258        status = mDNS_Init(&mDNSStorage, &PlatformStorage, &rr_cache[0],
259            sizeof(rr_cache) / sizeof(rr_cache[0]),
260            mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback,
261            mDNS_Init_NoInitCallbackContext);
262        assert(status == mStatus_NoError);
263
264        foobar_register(&question);
265
266        while (1) {
267                struct timeval timeout = { .tv_sec = 0x3fffffff, .tv_usec = 0 };
268                sigset_t signals;
269                mDNSBool got_something;
270
271                mDNSPosixRunEventLoopOnce(&mDNSStorage, &timeout, &signals, &got_something);
272        }
273}
274
275#define DEFAULT_NETWORK_DHCPCD_ENABLE
276#define DEFAULT_NETWORK_DHCPCD_NO_DHCP_DISCOVERY
277#define DEFAULT_NETWORK_SHELL
278
279#include <rtems/bsd/test/default-network-init.h>
Note: See TracBrowser for help on using the repository browser.