1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2019 - 2021 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci * 24d4afb5ceSopenharmony_ci * Client Connection Latency and DNS reporting 25d4afb5ceSopenharmony_ci */ 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci/* 28d4afb5ceSopenharmony_ci * We want to allocate copies for and append DNS results that we don't already 29d4afb5ceSopenharmony_ci * have. We take this approach because a) we may be getting duplicated results 30d4afb5ceSopenharmony_ci * from multiple DNS servers, and b) we may be getting results stacatto over 31d4afb5ceSopenharmony_ci * time. 32d4afb5ceSopenharmony_ci * 33d4afb5ceSopenharmony_ci * We capture DNS results from either getaddrinfo or ASYNC_DNS the same here, 34d4afb5ceSopenharmony_ci * before they are sorted and filtered. 35d4afb5ceSopenharmony_ci * 36d4afb5ceSopenharmony_ci * Because this is relatively expensive, we only do it on client wsi that 37d4afb5ceSopenharmony_ci * explicitly indicated that they want it with the LCCSCF_CONMON flag. 38d4afb5ceSopenharmony_ci */ 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ci#include <private-lib-core.h> 41d4afb5ceSopenharmony_ci 42d4afb5ceSopenharmony_ciint 43d4afb5ceSopenharmony_cilws_conmon_append_copy_new_dns_results(struct lws *wsi, 44d4afb5ceSopenharmony_ci const struct addrinfo *cai) 45d4afb5ceSopenharmony_ci{ 46d4afb5ceSopenharmony_ci if (!(wsi->flags & LCCSCF_CONMON)) 47d4afb5ceSopenharmony_ci return 0; 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci /* 50d4afb5ceSopenharmony_ci * Let's go through the incoming guys, seeing if we already have them, 51d4afb5ceSopenharmony_ci * or if we want to take a copy 52d4afb5ceSopenharmony_ci */ 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ci while (cai) { 55d4afb5ceSopenharmony_ci struct addrinfo *ai = wsi->conmon.dns_results_copy; 56d4afb5ceSopenharmony_ci char skip = 0; 57d4afb5ceSopenharmony_ci 58d4afb5ceSopenharmony_ci /* do we already have this guy? */ 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci while (ai) { 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_ci if (ai->ai_family != cai->ai_family && 63d4afb5ceSopenharmony_ci ai->ai_addrlen != cai->ai_addrlen && 64d4afb5ceSopenharmony_ci ai->ai_protocol != cai->ai_protocol && 65d4afb5ceSopenharmony_ci ai->ai_socktype != cai->ai_socktype && 66d4afb5ceSopenharmony_ci /* either ipv4 or v6 address must match */ 67d4afb5ceSopenharmony_ci ((ai->ai_family == AF_INET && 68d4afb5ceSopenharmony_ci ((struct sockaddr_in *)ai->ai_addr)-> 69d4afb5ceSopenharmony_ci sin_addr.s_addr == 70d4afb5ceSopenharmony_ci ((struct sockaddr_in *)cai->ai_addr)-> 71d4afb5ceSopenharmony_ci sin_addr.s_addr) 72d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) 73d4afb5ceSopenharmony_ci || 74d4afb5ceSopenharmony_ci (ai->ai_family == AF_INET6 && 75d4afb5ceSopenharmony_ci !memcmp(((struct sockaddr_in6 *)ai->ai_addr)-> 76d4afb5ceSopenharmony_ci sin6_addr.s6_addr, 77d4afb5ceSopenharmony_ci ((struct sockaddr_in6 *)cai->ai_addr)-> 78d4afb5ceSopenharmony_ci sin6_addr.s6_addr, 16)) 79d4afb5ceSopenharmony_ci#endif 80d4afb5ceSopenharmony_ci )) { 81d4afb5ceSopenharmony_ci /* yes, we already got a copy then */ 82d4afb5ceSopenharmony_ci skip = 1; 83d4afb5ceSopenharmony_ci break; 84d4afb5ceSopenharmony_ci } 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci ai = ai->ai_next; 87d4afb5ceSopenharmony_ci } 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci if (!skip) { 90d4afb5ceSopenharmony_ci /* 91d4afb5ceSopenharmony_ci * No we don't already have a copy of this one, let's 92d4afb5ceSopenharmony_ci * allocate and append it then 93d4afb5ceSopenharmony_ci */ 94d4afb5ceSopenharmony_ci size_t al = sizeof(struct addrinfo) + 95d4afb5ceSopenharmony_ci (size_t)cai->ai_addrlen; 96d4afb5ceSopenharmony_ci size_t cl = cai->ai_canonname ? 97d4afb5ceSopenharmony_ci strlen(cai->ai_canonname) + 1 : 0; 98d4afb5ceSopenharmony_ci 99d4afb5ceSopenharmony_ci ai = lws_malloc(al + cl + 1, __func__); 100d4afb5ceSopenharmony_ci if (!ai) { 101d4afb5ceSopenharmony_ci lwsl_wsi_warn(wsi, "OOM"); 102d4afb5ceSopenharmony_ci return 1; 103d4afb5ceSopenharmony_ci } 104d4afb5ceSopenharmony_ci *ai = *cai; 105d4afb5ceSopenharmony_ci ai->ai_addr = (struct sockaddr *)&ai[1]; 106d4afb5ceSopenharmony_ci memcpy(ai->ai_addr, cai->ai_addr, (size_t)cai->ai_addrlen); 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci if (cl) { 109d4afb5ceSopenharmony_ci ai->ai_canonname = ((char *)ai->ai_addr) + 110d4afb5ceSopenharmony_ci cai->ai_addrlen; 111d4afb5ceSopenharmony_ci memcpy(ai->ai_canonname, cai->ai_canonname, 112d4afb5ceSopenharmony_ci cl + 1); 113d4afb5ceSopenharmony_ci } 114d4afb5ceSopenharmony_ci ai->ai_next = wsi->conmon.dns_results_copy; 115d4afb5ceSopenharmony_ci wsi->conmon.dns_results_copy = ai; 116d4afb5ceSopenharmony_ci } 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci cai = cai->ai_next; 119d4afb5ceSopenharmony_ci } 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci return 0; 122d4afb5ceSopenharmony_ci} 123d4afb5ceSopenharmony_ci 124d4afb5ceSopenharmony_civoid 125d4afb5ceSopenharmony_cilws_conmon_addrinfo_destroy(struct addrinfo *ai) 126d4afb5ceSopenharmony_ci{ 127d4afb5ceSopenharmony_ci while (ai) { 128d4afb5ceSopenharmony_ci struct addrinfo *ai1 = ai->ai_next; 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_ci lws_free(ai); 131d4afb5ceSopenharmony_ci ai = ai1; 132d4afb5ceSopenharmony_ci } 133d4afb5ceSopenharmony_ci} 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_civoid 136d4afb5ceSopenharmony_cilws_conmon_wsi_take(struct lws *wsi, struct lws_conmon *dest) 137d4afb5ceSopenharmony_ci{ 138d4afb5ceSopenharmony_ci memcpy(dest, &wsi->conmon, sizeof(*dest)); 139d4afb5ceSopenharmony_ci dest->peer46 = wsi->sa46_peer; 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_ci /* wsi no longer has to free it... */ 142d4afb5ceSopenharmony_ci wsi->conmon.dns_results_copy = NULL; 143d4afb5ceSopenharmony_ci wsi->perf_done = 1; 144d4afb5ceSopenharmony_ci} 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_civoid 147d4afb5ceSopenharmony_cilws_conmon_release(struct lws_conmon *conmon) 148d4afb5ceSopenharmony_ci{ 149d4afb5ceSopenharmony_ci if (!conmon) 150d4afb5ceSopenharmony_ci return; 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ci lws_conmon_addrinfo_destroy(conmon->dns_results_copy); 153d4afb5ceSopenharmony_ci conmon->dns_results_copy = NULL; 154d4afb5ceSopenharmony_ci} 155