bool serial_handler_event_send(serial_evt_t* evt) { if (fifo_is_full(&tx_fifo)) { return false; } enable_pin_listener(false); NVIC_DisableIRQ(SPI1_TWI1_IRQn); /* critical section */ serial_data_t raw_data; raw_data.status_byte = 0; memcpy(raw_data.buffer, evt, evt->length + 1); fifo_push(&tx_fifo, &raw_data); if (fifo_is_full(&rx_fifo)) { enable_pin_listener(true); serial_state = SERIAL_STATE_WAIT_FOR_QUEUE; } else if (serial_state == SERIAL_STATE_IDLE) { do_transmit(); } NVIC_EnableIRQ(SPI1_TWI1_IRQn); /* critical section complete */ return true; }
bool serial_handler_command_get(serial_cmd_t* cmd) { /* want to do this without being pre-empted, as there's a potential race condition */ NVIC_DisableIRQ(SPI1_TWI1_IRQn); enable_pin_listener(false); serial_data_t temp; if (fifo_pop(&rx_fifo, &temp) != NRF_SUCCESS) { enable_pin_listener(true); NVIC_EnableIRQ(SPI1_TWI1_IRQn); return false; } if (temp.buffer[SERIAL_LENGTH_POS] > 0) { memcpy(cmd, temp.buffer, temp.buffer[SERIAL_LENGTH_POS] + 1); } /* just made room in the queue */ if (serial_state == SERIAL_STATE_WAIT_FOR_QUEUE) { /* would have race condition here with several irq contexts */ do_transmit(); } else if (serial_state == SERIAL_STATE_IDLE) { /* only want GPIOTE IRQ in IDLE */ enable_pin_listener(true); } NVIC_EnableIRQ(SPI1_TWI1_IRQn); return true; }
/** * We can now transmit a message to NAMESTORE. Do it. * * @param cls the 'struct GNUNET_NAMESTORE_Handle' * @param size number of bytes we can transmit * @param buf where to copy the messages * @return number of bytes copied into buf */ static size_t transmit_message_to_namestore (void *cls, size_t size, void *buf) { struct GNUNET_NAMESTORE_Handle *h = cls; struct PendingMessage *p; size_t ret; char *cbuf; h->th = NULL; if ((size == 0) || (buf == NULL)) { force_reconnect (h); return 0; } ret = 0; cbuf = buf; while ((NULL != (p = h->pending_head)) && (p->size <= size)) { memcpy (&cbuf[ret], &p[1], p->size); ret += p->size; size -= p->size; GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); if (GNUNET_YES == p->is_init) GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_free (p); } do_transmit (h); return ret; }
/** * @brief SPI event handler, from SPI driver */ void spi_event_handler(spi_slave_evt_t evt) { switch (evt.evt_type) { case SPI_SLAVE_BUFFERS_SET_DONE: if (has_pending_tx) { NRF_GPIO->OUTCLR = (1 << PIN_RDYN); } has_pending_tx = false; break; case SPI_SLAVE_XFER_DONE: NRF_GPIO->OUTSET = (1 << PIN_RDYN); nrf_gpio_pin_set(1); nrf_gpio_pin_clear(1); /* handle incoming */ if (rx_buffer.buffer[SERIAL_LENGTH_POS] > 0) { if (fifo_push(&rx_fifo, &rx_buffer) == NRF_SUCCESS) { /* notify ACI handler */ async_event_t async_evt; async_evt.callback.generic = mesh_aci_command_check; async_evt.type = EVENT_TYPE_GENERIC; event_handler_push(&async_evt); } else { APP_ERROR_CHECK(NRF_ERROR_NO_MEM); } } if (fifo_is_empty(&tx_fifo)) { serial_state = SERIAL_STATE_IDLE; prepare_rx(); enable_pin_listener(true); } else if (fifo_is_full(&rx_fifo)) { prepare_rx(); serial_state = SERIAL_STATE_WAIT_FOR_QUEUE; } else { do_transmit(); } break; default: /* no implementation necessary */ break; } }
/** * Get a result for a particular key from the namestore. The processor * will only be called once. * * @param h handle to the namestore * @param zone zone to look up a record from * @param name name to look up * @param record_type desired record type, 0 for all * @param proc function to call on the matching records, or with * NULL (rd_count == 0) if there are no matching records * @param proc_cls closure for proc * @return a handle that can be used to * cancel */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_ShortHashCode *zone, const char *name, uint32_t record_type, GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; size_t msg_size = 0; size_t name_len = 0; uint32_t rid = 0; GNUNET_assert (NULL != h); GNUNET_assert (NULL != zone); GNUNET_assert (NULL != name); name_len = strlen (name) + 1; if ((name_len == 0) || (name_len > 256)) { GNUNET_break (0); return NULL; } rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->proc = proc; qe->proc_cls = proc_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ msg_size = sizeof (struct LookupNameMessage) + name_len; pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); /* create msg here */ struct LookupNameMessage * msg; pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct LookupNameMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->record_type = htonl (record_type); msg->name_len = htonl (name_len); msg->zone = *zone; memcpy (&msg[1], name, name_len); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit(h); return qe; }
/** * Look for an existing PKEY delegation record for a given public key. * Returns at most one result to the processor. * * @param h handle to the namestore * @param zone hash of public key of the zone to look up in, never NULL * @param value_zone hash of the public key of the target zone (value), never NULL * @param proc function to call on the matching records, or with * NULL (rd_count == 0) if there are no matching records * @param proc_cls closure for proc * @return a handle that can be used to * cancel */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_ShortHashCode *zone, const struct GNUNET_CRYPTO_ShortHashCode *value_zone, GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; size_t msg_size = 0; uint32_t rid = 0; GNUNET_assert (NULL != h); GNUNET_assert (NULL != zone); GNUNET_assert (NULL != value_zone); rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->proc = proc; qe->proc_cls = proc_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ msg_size = sizeof (struct ZoneToNameMessage); pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); /* create msg here */ struct ZoneToNameMessage * msg; pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct ZoneToNameMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->zone = *zone; msg->value_zone = *value_zone; char * z_tmp = GNUNET_strdup (GNUNET_short_h2s (zone)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s' in zone `%s'\n", "NAMESTORE_ZONE_TO_NAME", z_tmp, GNUNET_short_h2s (value_zone)); GNUNET_free (z_tmp); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit(h); return qe; }
/** * @brief IRQ handler for treating incoming SPI message. The master will not * start sending before we lower the RDYN pin. */ void GPIOTE_IRQHandler(void) { NRF_GPIO->OUTSET = (1 << 2); if (NRF_GPIOTE->EVENTS_IN[SERIAL_REQN_GPIOTE_CH] && serial_state == SERIAL_STATE_IDLE) { NRF_GPIO->OUTSET = (1 << 3); if (fifo_is_full(&rx_fifo)) { /* wait until the application pops an event off the rx queue */ serial_state = SERIAL_STATE_WAIT_FOR_QUEUE; } else { do_transmit(); } NRF_GPIO->OUTCLR = (1 << 3); } NRF_GPIOTE->EVENTS_IN[SERIAL_REQN_GPIOTE_CH] = 0; NRF_GPIO->OUTCLR = (1 << 2); }
/** * Stops iteration and releases the namestore handle for further calls. * * @param it the iterator */ void GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) { GNUNET_assert (NULL != it); struct PendingMessage *pe; size_t msg_size = 0; struct GNUNET_NAMESTORE_Handle *h = it->h; struct GNUNET_NAMESTORE_ZoneIterator *tmp = it->h->z_head; while (tmp != NULL) { if (tmp == it) break; tmp = tmp->next; } GNUNET_assert (NULL != tmp); /* set msg_size*/ msg_size = sizeof (struct ZoneIterationStopMessage); pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); /* create msg here */ struct ZoneIterationStopMessage * msg; pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct ZoneIterationStopMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (it->op_id); if (GNUNET_YES == it->has_zone) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_STOP", GNUNET_short_h2s(&it->zone)); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for all zones\n", "ZONE_ITERATION_STOP"); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit(h); }
/** * Reconnect to namestore service. * * @param h the handle to the namestore service */ static void reconnect (struct GNUNET_NAMESTORE_Handle *h) { struct PendingMessage *p; struct StartMessage *init; GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("namestore", h->cfg); GNUNET_assert (NULL != h->client); if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init)) { p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct StartMessage)); p->size = sizeof (struct StartMessage); p->is_init = GNUNET_YES; init = (struct StartMessage *) &p[1]; init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START); init->header.size = htons (sizeof (struct StartMessage)); GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p); } do_transmit (h); }
/** * Store an item in the namestore. If the item is already present, * the expiration time is updated to the max of the existing time and * the new time. This API is used when we cache signatures from other * authorities. * * @param h handle to the namestore * @param zone_key public key of the zone * @param name name that is being mapped (at most 255 characters long) * @param freshness when does the corresponding block in the DHT expire (until * when should we never do a DHT lookup for the same name again)? * @param rd_count number of entries in 'rd' array * @param rd array of records with data to store * @param signature signature for all the records in the zone under the given name * @param cont continuation to call when done * @param cont_cls closure for cont * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, const char *name, struct GNUNET_TIME_Absolute freshness, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; /* pointer to elements */ char * rd_tmp; char * name_tmp; size_t msg_size = 0; size_t name_len = 0; size_t rd_ser_len = 0; uint32_t rid = 0; GNUNET_assert (NULL != h); GNUNET_assert (NULL != zone_key); GNUNET_assert (NULL != name); GNUNET_assert (NULL != rd); GNUNET_assert (NULL != signature); name_len = strlen(name) + 1; if (name_len > 256) { GNUNET_break (0); return NULL; } rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd); char rd_ser[rd_ser_len]; GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser); struct RecordPutMessage * msg; msg_size = sizeof (struct RecordPutMessage) + name_len + rd_ser_len; /* create msg here */ pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct RecordPutMessage *) &pe[1]; name_tmp = (char *) &msg[1]; rd_tmp = &name_tmp[name_len]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->signature = *signature; msg->name_len = htons (name_len); msg->expire = GNUNET_TIME_absolute_hton (freshness); msg->rd_len = htons (rd_ser_len); msg->rd_count = htons (rd_count); msg->public_key = *zone_key; memcpy (name_tmp, name, name_len); memcpy (rd_tmp, rd_ser, rd_ser_len); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size); GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit(h); return qe; }
/** * Starts a new zone iteration (used to periodically PUT all of our * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and * GNUNET_NAMESTORE_zone_iteration_stop. "proc" will be called once * immediately, and then again after * "GNUNET_NAMESTORE_zone_iterator_next" is invoked. * * @param h handle to the namestore * @param zone zone to access, NULL for all zones * @param must_have_flags flags that must be set for the record to be returned * @param must_not_have_flags flags that must NOT be set for the record to be returned * @param proc function to call on each name from the zone; it * will be called repeatedly with a value (if available) * and always once at the end with a name of NULL. * @param proc_cls closure for proc * @return an iterator handle to use for iteration */ struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_ShortHashCode *zone, enum GNUNET_NAMESTORE_RecordFlags must_have_flags, enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags, GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls) { struct GNUNET_NAMESTORE_ZoneIterator *it; struct PendingMessage *pe; size_t msg_size = 0; uint32_t rid = 0; GNUNET_assert (NULL != h); rid = get_op_id(h); it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator)); it->h = h; it->proc = proc; it->proc_cls = proc_cls; it->op_id = rid; if (NULL != zone) { it->zone = *zone; it->has_zone = GNUNET_YES; } else { memset (&it->zone, '\0', sizeof (it->zone)); it->has_zone = GNUNET_NO; } GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it); /* set msg_size*/ msg_size = sizeof (struct ZoneIterationStartMessage); pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); /* create msg here */ struct ZoneIterationStartMessage * msg; pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct ZoneIterationStartMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); if (NULL != zone) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_short_h2s(zone)); msg->zone = *zone; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for all zones\n", "ZONE_ITERATION_START"); memset (&msg->zone, '\0', sizeof (msg->zone)); } msg->must_have_flags = ntohs (must_have_flags); msg->must_not_have_flags = ntohs (must_not_have_flags); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit(h); return it; }
/** * Explicitly remove some content from the database. The * "cont"inuation will be called with status "GNUNET_OK" if content * was removed, "GNUNET_NO" if no matching entry was found and * "GNUNET_SYSERR" on all other types of errors. * This API is used by the authority of a zone. * * @param h handle to the namestore * @param pkey private key of the zone * @param name name that is being mapped (at most 255 characters long) * @param rd record data, remove specific record, NULL to remove the name and all records * @param cont continuation to call when done * @param cont_cls closure for cont * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_RsaPrivateKey *pkey, const char *name, const struct GNUNET_NAMESTORE_RecordData *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; char *pkey_tmp; char *rd_tmp; char *name_tmp; size_t rd_ser_len = 0; size_t msg_size = 0; size_t name_len = 0; size_t key_len = 0; uint32_t rid = 0; uint16_t rd_count = 1; GNUNET_assert (NULL != h); rid = get_op_id(h); qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); /* set msg_size*/ struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey); GNUNET_assert (pkey_enc != NULL); key_len = ntohs (pkey_enc->len); if (NULL == rd) rd_count = 0; else rd_count = 1; rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); char rd_ser[rd_ser_len]; GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser); name_len = strlen (name) + 1; struct RecordRemoveMessage * msg; msg_size = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len; /* create msg here */ pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; pe->is_init = GNUNET_NO; msg = (struct RecordRemoveMessage *) &pe[1]; pkey_tmp = (char *) &msg[1]; name_tmp = &pkey_tmp[key_len]; rd_tmp = &name_tmp[name_len]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->name_len = htons (name_len); msg->rd_len = htons (rd_ser_len); msg->rd_count = htons (rd_count); msg->pkey_len = htons (key_len); memcpy (pkey_tmp, pkey_enc, key_len); memcpy (name_tmp, name, name_len); memcpy (rd_tmp, rd_ser, rd_ser_len); GNUNET_free (pkey_enc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size); GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit(h); return qe; }
void SWI1_IRQHandler(void) { do_transmit(NULL); }