/** @file * @brief Modem context helper driver * * A modem context driver allowing application to handle all * aspects of received protocol data. */ /* * Copyright (c) 2019 Foundries.io * * SPDX-License-Identifier: Apache-2.0 */ #include LOG_MODULE_REGISTER(modem_context, CONFIG_MODEM_LOG_LEVEL); #include #include "modem_context.h" static struct modem_context *contexts[CONFIG_MODEM_CONTEXT_MAX_NUM]; int modem_context_sprint_ip_addr(const struct sockaddr *addr, char *buf, size_t buf_size) { static const char unknown_str[] = "unk"; if (addr->sa_family == AF_INET6) { if (buf_size < NET_IPV6_ADDR_LEN) { return -ENOMEM; } if (net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr, buf, buf_size) == NULL) { return -ENOMEM; } return 0; } if (addr->sa_family == AF_INET) { if (buf_size < NET_IPV4_ADDR_LEN) { return -ENOMEM; } if (net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr, buf, buf_size) == NULL) { return -ENOMEM; } return 0; } LOG_ERR("Unknown IP address family:%d", addr->sa_family); if (buf_size < sizeof(unknown_str)) { return -ENOMEM; } strcpy(buf, unknown_str); return 0; } int modem_context_get_addr_port(const struct sockaddr *addr, uint16_t *port) { if (!addr || !port) { return -EINVAL; } if (addr->sa_family == AF_INET6) { *port = ntohs(net_sin6(addr)->sin6_port); return 0; } else if (addr->sa_family == AF_INET) { *port = ntohs(net_sin(addr)->sin_port); return 0; } return -EPROTONOSUPPORT; } /** * @brief Finds modem context which owns the iface device. * * @param dev: device used by the modem iface. * * @retval Modem context or NULL. */ struct modem_context *modem_context_from_iface_dev(const struct device *dev) { int i; for (i = 0; i < ARRAY_SIZE(contexts); i++) { if (contexts[i] && contexts[i]->iface.dev == dev) { return contexts[i]; } } return NULL; } /** * @brief Assign a modem context if there is free space. * * @note Amount of stored modem contexts is determined by * CONFIG_MODEM_CONTEXT_MAX_NUM. * * @param ctx: modem context to persist. * * @retval 0 if ok, < 0 if error. */ static int modem_context_get(struct modem_context *ctx) { int i; for (i = 0; i < ARRAY_SIZE(contexts); i++) { if (!contexts[i]) { contexts[i] = ctx; return 0; } } return -ENOMEM; } struct modem_context *modem_context_from_id(int id) { if (id >= 0 && id < ARRAY_SIZE(contexts)) { return contexts[id]; } else { return NULL; } } int modem_context_register(struct modem_context *ctx) { if (!ctx) { return -EINVAL; } return modem_context_get(ctx); }