1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * SNMP thread synchronization implementation. 4195972f6Sopenharmony_ci */ 5195972f6Sopenharmony_ci 6195972f6Sopenharmony_ci/* 7195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 8195972f6Sopenharmony_ci * All rights reserved. 9195972f6Sopenharmony_ci * 10195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 11195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 12195972f6Sopenharmony_ci * 13195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 14195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 15195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 16195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 17195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 18195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 19195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 20195972f6Sopenharmony_ci * 21195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30195972f6Sopenharmony_ci * OF SUCH DAMAGE. 31195972f6Sopenharmony_ci * 32195972f6Sopenharmony_ci * Author: Dirk Ziegelmeier <dziegel@gmx.de> 33195972f6Sopenharmony_ci */ 34195972f6Sopenharmony_ci 35195972f6Sopenharmony_ci#include "lwip/apps/snmp_opts.h" 36195972f6Sopenharmony_ci 37195972f6Sopenharmony_ci#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ 38195972f6Sopenharmony_ci 39195972f6Sopenharmony_ci#include "lwip/apps/snmp_threadsync.h" 40195972f6Sopenharmony_ci#include "lwip/apps/snmp_core.h" 41195972f6Sopenharmony_ci#include "lwip/sys.h" 42195972f6Sopenharmony_ci#include <string.h> 43195972f6Sopenharmony_ci 44195972f6Sopenharmony_cistatic void 45195972f6Sopenharmony_cicall_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) 46195972f6Sopenharmony_ci{ 47195972f6Sopenharmony_ci sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); 48195972f6Sopenharmony_ci call_data->threadsync_node->instance->sync_fn(fn, call_data); 49195972f6Sopenharmony_ci sys_sem_wait(&call_data->threadsync_node->instance->sem); 50195972f6Sopenharmony_ci sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); 51195972f6Sopenharmony_ci} 52195972f6Sopenharmony_ci 53195972f6Sopenharmony_cistatic void 54195972f6Sopenharmony_cithreadsync_get_value_synced(void *ctx) 55195972f6Sopenharmony_ci{ 56195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)ctx; 57195972f6Sopenharmony_ci 58195972f6Sopenharmony_ci if (call_data->proxy_instance.get_value != NULL) { 59195972f6Sopenharmony_ci call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); 60195972f6Sopenharmony_ci } else { 61195972f6Sopenharmony_ci call_data->retval.s16 = -1; 62195972f6Sopenharmony_ci } 63195972f6Sopenharmony_ci 64195972f6Sopenharmony_ci sys_sem_signal(&call_data->threadsync_node->instance->sem); 65195972f6Sopenharmony_ci} 66195972f6Sopenharmony_ci 67195972f6Sopenharmony_cistatic s16_t 68195972f6Sopenharmony_cithreadsync_get_value(struct snmp_node_instance *instance, void *value) 69195972f6Sopenharmony_ci{ 70195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; 71195972f6Sopenharmony_ci 72195972f6Sopenharmony_ci call_data->arg1.value = value; 73195972f6Sopenharmony_ci call_synced_function(call_data, threadsync_get_value_synced); 74195972f6Sopenharmony_ci 75195972f6Sopenharmony_ci return call_data->retval.s16; 76195972f6Sopenharmony_ci} 77195972f6Sopenharmony_ci 78195972f6Sopenharmony_cistatic void 79195972f6Sopenharmony_cithreadsync_set_test_synced(void *ctx) 80195972f6Sopenharmony_ci{ 81195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)ctx; 82195972f6Sopenharmony_ci 83195972f6Sopenharmony_ci if (call_data->proxy_instance.set_test != NULL) { 84195972f6Sopenharmony_ci call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); 85195972f6Sopenharmony_ci } else { 86195972f6Sopenharmony_ci call_data->retval.err = SNMP_ERR_NOTWRITABLE; 87195972f6Sopenharmony_ci } 88195972f6Sopenharmony_ci 89195972f6Sopenharmony_ci sys_sem_signal(&call_data->threadsync_node->instance->sem); 90195972f6Sopenharmony_ci} 91195972f6Sopenharmony_ci 92195972f6Sopenharmony_cistatic snmp_err_t 93195972f6Sopenharmony_cithreadsync_set_test(struct snmp_node_instance *instance, u16_t len, void *value) 94195972f6Sopenharmony_ci{ 95195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; 96195972f6Sopenharmony_ci 97195972f6Sopenharmony_ci call_data->arg1.value = value; 98195972f6Sopenharmony_ci call_data->arg2.len = len; 99195972f6Sopenharmony_ci call_synced_function(call_data, threadsync_set_test_synced); 100195972f6Sopenharmony_ci 101195972f6Sopenharmony_ci return call_data->retval.err; 102195972f6Sopenharmony_ci} 103195972f6Sopenharmony_ci 104195972f6Sopenharmony_cistatic void 105195972f6Sopenharmony_cithreadsync_set_value_synced(void *ctx) 106195972f6Sopenharmony_ci{ 107195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)ctx; 108195972f6Sopenharmony_ci 109195972f6Sopenharmony_ci if (call_data->proxy_instance.set_value != NULL) { 110195972f6Sopenharmony_ci call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); 111195972f6Sopenharmony_ci } else { 112195972f6Sopenharmony_ci call_data->retval.err = SNMP_ERR_NOTWRITABLE; 113195972f6Sopenharmony_ci } 114195972f6Sopenharmony_ci 115195972f6Sopenharmony_ci sys_sem_signal(&call_data->threadsync_node->instance->sem); 116195972f6Sopenharmony_ci} 117195972f6Sopenharmony_ci 118195972f6Sopenharmony_cistatic snmp_err_t 119195972f6Sopenharmony_cithreadsync_set_value(struct snmp_node_instance *instance, u16_t len, void *value) 120195972f6Sopenharmony_ci{ 121195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; 122195972f6Sopenharmony_ci 123195972f6Sopenharmony_ci call_data->arg1.value = value; 124195972f6Sopenharmony_ci call_data->arg2.len = len; 125195972f6Sopenharmony_ci call_synced_function(call_data, threadsync_set_value_synced); 126195972f6Sopenharmony_ci 127195972f6Sopenharmony_ci return call_data->retval.err; 128195972f6Sopenharmony_ci} 129195972f6Sopenharmony_ci 130195972f6Sopenharmony_cistatic void 131195972f6Sopenharmony_cithreadsync_release_instance_synced(void *ctx) 132195972f6Sopenharmony_ci{ 133195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)ctx; 134195972f6Sopenharmony_ci 135195972f6Sopenharmony_ci call_data->proxy_instance.release_instance(&call_data->proxy_instance); 136195972f6Sopenharmony_ci 137195972f6Sopenharmony_ci sys_sem_signal(&call_data->threadsync_node->instance->sem); 138195972f6Sopenharmony_ci} 139195972f6Sopenharmony_ci 140195972f6Sopenharmony_cistatic void 141195972f6Sopenharmony_cithreadsync_release_instance(struct snmp_node_instance *instance) 142195972f6Sopenharmony_ci{ 143195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; 144195972f6Sopenharmony_ci 145195972f6Sopenharmony_ci if (call_data->proxy_instance.release_instance != NULL) { 146195972f6Sopenharmony_ci call_synced_function(call_data, threadsync_release_instance_synced); 147195972f6Sopenharmony_ci } 148195972f6Sopenharmony_ci} 149195972f6Sopenharmony_ci 150195972f6Sopenharmony_cistatic void 151195972f6Sopenharmony_ciget_instance_synced(void *ctx) 152195972f6Sopenharmony_ci{ 153195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)ctx; 154195972f6Sopenharmony_ci const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node *)(const void *)call_data->proxy_instance.node; 155195972f6Sopenharmony_ci 156195972f6Sopenharmony_ci call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); 157195972f6Sopenharmony_ci 158195972f6Sopenharmony_ci sys_sem_signal(&call_data->threadsync_node->instance->sem); 159195972f6Sopenharmony_ci} 160195972f6Sopenharmony_ci 161195972f6Sopenharmony_cistatic void 162195972f6Sopenharmony_ciget_next_instance_synced(void *ctx) 163195972f6Sopenharmony_ci{ 164195972f6Sopenharmony_ci struct threadsync_data *call_data = (struct threadsync_data *)ctx; 165195972f6Sopenharmony_ci const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node *)(const void *)call_data->proxy_instance.node; 166195972f6Sopenharmony_ci 167195972f6Sopenharmony_ci call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); 168195972f6Sopenharmony_ci 169195972f6Sopenharmony_ci sys_sem_signal(&call_data->threadsync_node->instance->sem); 170195972f6Sopenharmony_ci} 171195972f6Sopenharmony_ci 172195972f6Sopenharmony_cistatic snmp_err_t 173195972f6Sopenharmony_cido_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance, snmp_threadsync_called_fn fn) 174195972f6Sopenharmony_ci{ 175195972f6Sopenharmony_ci const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node *)(const void *)instance->node; 176195972f6Sopenharmony_ci struct threadsync_data *call_data = &threadsync_node->instance->data; 177195972f6Sopenharmony_ci 178195972f6Sopenharmony_ci if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { 179195972f6Sopenharmony_ci LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); 180195972f6Sopenharmony_ci return SNMP_ERR_NOSUCHINSTANCE; 181195972f6Sopenharmony_ci } 182195972f6Sopenharmony_ci 183195972f6Sopenharmony_ci memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); 184195972f6Sopenharmony_ci 185195972f6Sopenharmony_ci instance->reference.ptr = call_data; 186195972f6Sopenharmony_ci snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); 187195972f6Sopenharmony_ci 188195972f6Sopenharmony_ci call_data->proxy_instance.node = &threadsync_node->target->node; 189195972f6Sopenharmony_ci call_data->threadsync_node = threadsync_node; 190195972f6Sopenharmony_ci 191195972f6Sopenharmony_ci call_data->arg1.root_oid = root_oid; 192195972f6Sopenharmony_ci call_data->arg2.root_oid_len = root_oid_len; 193195972f6Sopenharmony_ci call_synced_function(call_data, fn); 194195972f6Sopenharmony_ci 195195972f6Sopenharmony_ci if (call_data->retval.err == SNMP_ERR_NOERROR) { 196195972f6Sopenharmony_ci instance->access = call_data->proxy_instance.access; 197195972f6Sopenharmony_ci instance->asn1_type = call_data->proxy_instance.asn1_type; 198195972f6Sopenharmony_ci instance->release_instance = threadsync_release_instance; 199195972f6Sopenharmony_ci instance->get_value = (call_data->proxy_instance.get_value != NULL) ? threadsync_get_value : NULL; 200195972f6Sopenharmony_ci instance->set_value = (call_data->proxy_instance.set_value != NULL) ? threadsync_set_value : NULL; 201195972f6Sopenharmony_ci instance->set_test = (call_data->proxy_instance.set_test != NULL) ? threadsync_set_test : NULL; 202195972f6Sopenharmony_ci snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); 203195972f6Sopenharmony_ci } 204195972f6Sopenharmony_ci 205195972f6Sopenharmony_ci return call_data->retval.err; 206195972f6Sopenharmony_ci} 207195972f6Sopenharmony_ci 208195972f6Sopenharmony_cisnmp_err_t 209195972f6Sopenharmony_cisnmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) 210195972f6Sopenharmony_ci{ 211195972f6Sopenharmony_ci return do_sync(root_oid, root_oid_len, instance, get_instance_synced); 212195972f6Sopenharmony_ci} 213195972f6Sopenharmony_ci 214195972f6Sopenharmony_cisnmp_err_t 215195972f6Sopenharmony_cisnmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) 216195972f6Sopenharmony_ci{ 217195972f6Sopenharmony_ci return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); 218195972f6Sopenharmony_ci} 219195972f6Sopenharmony_ci 220195972f6Sopenharmony_ci/** Initializes thread synchronization instance */ 221195972f6Sopenharmony_civoid snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) 222195972f6Sopenharmony_ci{ 223195972f6Sopenharmony_ci err_t err = sys_mutex_new(&instance->sem_usage_mutex); 224195972f6Sopenharmony_ci LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); 225195972f6Sopenharmony_ci err = sys_sem_new(&instance->sem, 0); 226195972f6Sopenharmony_ci LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ 227195972f6Sopenharmony_ci LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); 228195972f6Sopenharmony_ci instance->sync_fn = sync_fn; 229195972f6Sopenharmony_ci} 230195972f6Sopenharmony_ci 231195972f6Sopenharmony_ci#endif /* LWIP_SNMP */ 232