/** * Shrink a pbuf chain to a desired length. * * @param p pbuf to shrink. * @param new_len desired new length of pbuf chain * * Depending on the desired length, the first few pbufs in a chain might * be skipped and left unchanged. The new last pbuf in the chain will be * resized, and any remaining pbufs will be freed. * * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. * @note May not be called on a packet queue. * * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). */ void pbuf_realloc(struct pbuf *p, u16_t new_len) { struct pbuf *q; u16_t rem_len; /* remaining length */ s32_t grow; LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || p->type == PBUF_ROM || p->type == PBUF_RAM || p->type == PBUF_REF); /* desired length larger than current length? */ if (new_len >= p->tot_len) { /* enlarging not yet supported */ return; } /* the pbuf chain grows by (new_len - p->tot_len) bytes * (which may be negative in case of shrinking) */ grow = new_len - p->tot_len; /* first, step over any pbufs that should remain in the chain */ rem_len = new_len; q = p; /* should this pbuf be kept? */ while (rem_len > q->len) { /* decrease remaining length by pbuf length */ rem_len -= q->len; /* decrease total length indicator */ LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); q->tot_len += (u16_t)grow; /* proceed to next pbuf in chain */ q = q->next; LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); } /* we have now reached the new last pbuf (in q) */ /* rem_len == desired length for pbuf q */ /* shrink allocated memory for PBUF_RAM */ /* (other types merely adjust their length fields */ if ((q->type == PBUF_RAM) && (rem_len != q->len)) { /* reallocate and adjust the length of the pbuf that will be split */ q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); } /* adjust length fields for new last pbuf */ q->len = rem_len; q->tot_len = q->len; /* any remaining pbufs in chain? */ if (q->next != NULL) { /* free remaining pbufs in chain */ pbuf_free(q->next); } /* q is last packet in chain */ q->next = NULL; }
/** * @ingroup pbuf * Shrink a pbuf chain to a desired length. * * @param p pbuf to shrink. * @param new_len desired new length of pbuf chain * * Depending on the desired length, the first few pbufs in a chain might * be skipped and left unchanged. The new last pbuf in the chain will be * resized, and any remaining pbufs will be freed. * * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. * @note May not be called on a packet queue. * * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). */ void pbuf_realloc(struct pbuf *p, u16_t new_len) { struct pbuf *q; u16_t rem_len; /* remaining length */ u16_t shrink; LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); /* desired length larger than current length? */ if (new_len >= p->tot_len) { /* enlarging not yet supported */ return; } /* the pbuf chain grows by (new_len - p->tot_len) bytes * (which may be negative in case of shrinking) */ shrink = (u16_t)(p->tot_len - new_len); /* first, step over any pbufs that should remain in the chain */ rem_len = new_len; q = p; /* should this pbuf be kept? */ while (rem_len > q->len) { /* decrease remaining length by pbuf length */ rem_len = (u16_t)(rem_len - q->len); /* decrease total length indicator */ q->tot_len = (u16_t)(q->tot_len - shrink); /* proceed to next pbuf in chain */ q = q->next; LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); } /* we have now reached the new last pbuf (in q) */ /* rem_len == desired length for pbuf q */ /* shrink allocated memory for PBUF_RAM */ /* (other types merely adjust their length fields */ if (pbuf_match_allocsrc(q, PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) && (rem_len != q->len) #if LWIP_SUPPORT_CUSTOM_PBUF && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) #endif /* LWIP_SUPPORT_CUSTOM_PBUF */ ) { /* reallocate and adjust the length of the pbuf that will be split */ q = (struct pbuf *)mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len)); LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); } /* adjust length fields for new last pbuf */ q->len = rem_len; q->tot_len = q->len; /* any remaining pbufs in chain? */ if (q->next != NULL) { /* free remaining pbufs in chain */ pbuf_free(q->next); } /* q is last packet in chain */ q->next = NULL; }
/****************************************************************************** * FunctionName : syslog_compose * Description : compose a syslog_entry_t from va_args * Parameters : va_args * Returns : the malloced syslog_entry_t ******************************************************************************/ static syslog_entry_t* ICACHE_FLASH_ATTR syslog_compose(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...) { syslog_entry_t *se = os_zalloc(sizeof (syslog_entry_t) + 1024); // allow up to 1k datagram char *p = se->datagram; uint32_t tick = WDEV_NOW(); // 0 ... 4294.967295s // The Priority value is calculated by first multiplying the Facility // number by 8 and then adding the numerical value of the Severity. p += os_sprintf(p, "<%d> ", facility * 8 + severity); // strftime doesn't work as expected - or adds 8k overhead. // so let's do poor man conversion - format is fixed anyway if (flashConfig.syslog_showdate == 0) p += os_sprintf(p, "- "); else { time_t now = NULL; struct tm *tp = NULL; // create timestamp: FULL-DATE "T" PARTIAL-TIME "Z": 'YYYY-mm-ddTHH:MM:SSZ ' // as long as realtime_stamp is 0 we use tick div 10⁶ as date now = (realtime_stamp == 0) ? (tick / 1000000) : realtime_stamp; tp = gmtime(&now); p += os_sprintf(p, "%4d-%02d-%02dT%02d:%02d:%02dZ ", tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); } // add HOSTNAME APP-NAME PROCID MSGID if (flashConfig.syslog_showtick) p += os_sprintf(p, "%s %s %lu.%06lu %lu ", flashConfig.hostname, tag, tick / 1000000, tick % 1000000, syslog_msgid++); else p += os_sprintf(p, "%s %s - %lu ", flashConfig.hostname, tag, syslog_msgid++); // append syslog message va_list arglist; va_start(arglist, fmt); p += ets_vsprintf(p, fmt, arglist ); va_end(arglist); se->datagram_len = p - se->datagram; se = mem_trim(se, sizeof(syslog_entry_t) + se->datagram_len + 1); return se; }
int event_expire(conf_t *conf, zone_t *zone) { assert(zone); zone_contents_t *expired = zone_switch_contents(zone, NULL); synchronize_rcu(); /* Expire zonefile information. */ zone->zonefile_mtime = 0; zone->zonefile_serial = 0; zone->flags |= ZONE_EXPIRED; zone_contents_deep_free(&expired); log_zone_info(zone->name, "zone expired"); /* Trim extra heap. */ mem_trim(); return KNOT_EOK; }
int event_update(conf_t *conf, zone_t *zone) { assert(zone); /* Process update list - forward if zone has master, or execute. */ updates_execute(conf, zone); /* Trim extra heap. */ mem_trim(); /* Replan event if next update waiting. */ pthread_mutex_lock(&zone->ddns_lock); const bool empty = EMPTY_LIST(zone->ddns_queue); pthread_mutex_unlock(&zone->ddns_lock); if (!empty) { zone_events_schedule(zone, ZONE_EVENT_UPDATE, ZONE_EVENT_NOW); } return KNOT_EOK; }
int event_xfer(conf_t *conf, zone_t *zone) { assert(zone); /* Ignore if not slave zone. */ if (!zone_is_slave(conf, zone)) { return KNOT_EOK; } struct transfer_data data = { 0 }; const char *err_str = ""; /* Determine transfer type. */ bool is_bootstrap = zone_contents_is_empty(zone->contents); if (is_bootstrap || zone->flags & ZONE_FORCE_AXFR) { data.pkt_type = KNOT_QUERY_AXFR; err_str = "AXFR, incoming"; } else { data.pkt_type = KNOT_QUERY_IXFR; err_str = "IXFR, incoming"; } /* Execute zone transfer. */ int ret = zone_master_try(conf, zone, try_xfer, &data, err_str); zone_clear_preferred_master(zone); if (ret != KNOT_EOK) { log_zone_error(zone->name, "%s, failed (%s)", err_str, knot_strerror(ret)); if (is_bootstrap) { zone->bootstrap_retry = bootstrap_next(zone->bootstrap_retry); zone_events_schedule(zone, ZONE_EVENT_XFER, zone->bootstrap_retry); } else { const knot_rdataset_t *soa = zone_soa(zone); zone_events_schedule(zone, ZONE_EVENT_XFER, knot_soa_retry(soa)); start_expire_timer(conf, zone, soa); } return KNOT_EOK; } assert(!zone_contents_is_empty(zone->contents)); const knot_rdataset_t *soa = zone_soa(zone); /* Rechedule events. */ zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_refresh(soa)); zone_events_schedule(zone, ZONE_EVENT_NOTIFY, ZONE_EVENT_NOW); zone_events_cancel(zone, ZONE_EVENT_EXPIRE); conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name); int64_t sync_timeout = conf_int(&val); if (sync_timeout == 0) { zone_events_schedule(zone, ZONE_EVENT_FLUSH, ZONE_EVENT_NOW); } else if (sync_timeout > 0 && !zone_events_is_scheduled(zone, ZONE_EVENT_FLUSH)) { zone_events_schedule(zone, ZONE_EVENT_FLUSH, sync_timeout); } /* Transfer cleanup. */ zone->bootstrap_retry = ZONE_EVENT_NOW; zone->flags &= ~ZONE_FORCE_AXFR; /* Trim extra heap. */ if (!is_bootstrap) { mem_trim(); } return KNOT_EOK; }