void mac_node_set_address(node_t *node, const char *address) { rs_assert(node != NULL); rs_assert(address != NULL); if (node->mac_info->address != NULL) free(node->mac_info->address); node->mac_info->address = strdup(address); }
bool mac_node_receive(node_t *node, node_t *incoming_node, mac_pdu_t *pdu) { rs_assert(pdu!= NULL); rs_assert(node != NULL); bool all_ok = event_execute(mac_event_pdu_receive, node, incoming_node, pdu); mac_pdu_destroy(pdu); return all_ok; }
void mac_node_init(node_t *node, char *address) { rs_assert(node!= NULL); rs_assert(address != NULL); node->mac_info = malloc(sizeof(mac_node_info_t)); node->mac_info->address = strdup(address); node->mac_info->busy = FALSE; node->mac_info->error = FALSE; }
mac_pdu_t *mac_pdu_create(char *src_address, char *dst_address) { rs_assert(src_address != NULL); rs_assert(dst_address != NULL); mac_pdu_t *pdu = malloc(sizeof(mac_pdu_t)); pdu->src_address = strdup(src_address); pdu->dst_address = strdup(dst_address); pdu->type = -1; pdu->sdu = NULL; return pdu; }
int main(int argc, char** argv) { if (argc != 2) return 1; RSRegion* reg = rs_region_open(argv[1], false); rs_assert(reg); int x = 0, z = 0; for (z = 0; z < 32; z++) { for (x = 0; x < 32; x++) { if (rs_region_contains_chunk(reg, x, z)) { const char* comp = get_compression_string(rs_region_get_chunk_compression(reg, x, z)); printf("(%i, %i) [%i] %i bytes (%s)\n", x, z, rs_region_get_chunk_timestamp(reg, x, z), rs_region_get_chunk_length(reg, x, z), comp); } } } rs_region_close(reg); return 0; }
void mac_pdu_set_sdu(mac_pdu_t *pdu, uint16 type, void *sdu) { rs_assert(pdu != NULL); pdu->type = type; pdu->sdu = sdu; }
void mac_node_done(node_t *node) { rs_assert(node != NULL); if (node->mac_info != NULL) { if (node->mac_info->address != NULL) free(node->mac_info->address); free(node->mac_info); node->mac_info = NULL; } }
void rs_region_close(RSRegion* self) { rs_return_if_fail(self); if (self->write && self->cached_writes) rs_region_flush(self); rs_assert(self->cached_writes == NULL); rs_free(self->path); if (self->map) munmap(self->map, self->fsize); close(self->fd); rs_free(self); }
void _rs_error_log(bool error, const char* filename, unsigned int line, const char* func, const char* str, ...) { va_list ap; va_start(ap, str); rs_assert(filename != NULL); rs_assert(func != NULL); rs_assert(str != NULL); if (error) printf("ERROR: "); else printf("CRITICAL: "); printf("%s:%i (%s) ", filename, line, func); vprintf(str, ap); printf("\n"); va_end(ap); if (error) exit(1); }
int main(int argc, char** argv) { if (argc != 3) { fprintf(stderr, "usage: %s [input] [output]\n", argv[0]); return 1; } RSRegion* reg = rs_region_open(argv[1], false); RSRegion* out = rs_region_open(argv[2], true); rs_assert(reg); rs_assert(out); int x = 0, z = 0; for (z = 0; z < 32; z++) { for (x = 0; x < 32; x++) { if (INSIDE_EXMAPLE(x, z) && rs_region_contains_chunk(reg, x, z)) { void* data = rs_region_get_chunk_data(reg, x, z); uint32_t len = rs_region_get_chunk_length(reg, x, z); RSCompressionType comp = rs_region_get_chunk_compression(reg, x, z); uint32_t timestamp = rs_region_get_chunk_timestamp(reg, x, z); rs_region_set_chunk_data_full(out, x, z, data, len, comp, timestamp); } } } rs_region_flush(out); rs_region_close(out); rs_region_close(reg); return 0; }
bool mac_node_send(node_t *node, node_t *outgoing_node, uint16 type, void *sdu) { rs_assert(node != NULL); mac_pdu_t *mac_pdu = mac_pdu_create(node->mac_info->address, outgoing_node != NULL ? outgoing_node->mac_info->address : ""); mac_pdu_set_sdu(mac_pdu, type, sdu); if (!event_execute(mac_event_pdu_send, node, outgoing_node, mac_pdu)) { mac_pdu->sdu = NULL; mac_pdu_destroy(mac_pdu); return FALSE; } return TRUE; }
void rs_region_set_chunk_data_full(RSRegion* self, uint8_t x, uint8_t z, void* data, uint32_t len, RSCompressionType enc, uint32_t timestamp) { rs_return_if_fail(self); rs_return_if_fail(x < 32 && z < 32); rs_return_if_fail(self->write); /* first, check if there's a cached write already, and clear it if * needed */ RSList* cell = self->cached_writes; for (; cell != NULL; cell = cell->next) { struct ChunkWrite* write = cell->data; rs_assert(write); if (write->x == x && write->z == z) break; } if (cell) { struct ChunkWrite* write = cell->data; rs_free(write->data); rs_free(write); self->cached_writes = rs_list_remove(self->cached_writes, cell); } if (enc == RS_AUTO_COMPRESSION) enc = rs_get_compression_type(data, len); /* copy the data */ void* data_copy = memcpy(rs_malloc(len), data, len); /* now, create a new write struct */ struct ChunkWrite* job = rs_new0(struct ChunkWrite, 1); job->x = x; job->z = z; job->data = data_copy; job->length = len; job->encoding = enc; job->timestamp = timestamp; self->cached_writes = rs_list_push(self->cached_writes, job); }
mac_pdu_t *mac_pdu_duplicate(mac_pdu_t *pdu) { rs_assert(pdu != NULL); mac_pdu_t *new_pdu = malloc(sizeof(mac_pdu_t)); new_pdu->src_address = strdup(pdu->src_address); new_pdu->dst_address = strdup(pdu->dst_address); new_pdu->type = pdu->type; switch (pdu->type) { case MAC_TYPE_IP: new_pdu->sdu = ip_pdu_duplicate(pdu->sdu); break; } return new_pdu; }
void mac_pdu_destroy(mac_pdu_t *pdu) { rs_assert(pdu != NULL); if (pdu->dst_address != NULL) free(pdu->dst_address); if (pdu->src_address != NULL) free(pdu->src_address); if (pdu->sdu != NULL) { switch (pdu->type) { case MAC_TYPE_IP : ip_pdu_destroy(pdu->sdu); break; } } free(pdu); }
/* writes are cached until this is called */ void rs_region_flush(RSRegion* self) { rs_return_if_fail(self); RSList* cell; if (self->write && self->cached_writes) { /* check to see if this is a brand-new file */ if (self->map == NULL) { /* it is! so we have to write everything */ /* first, figure out how big the file needs to be */ uint32_t final_size = 0; cell = self->cached_writes; for (; cell != NULL; cell = cell->next) { struct ChunkWrite* write = cell->data; rs_assert(write); /* be sure to account for extra size/compression info */ final_size += write->length + 4 + 1; /* force size to be on sector boundaries */ if (final_size % 4096 > 0) final_size += (4096 - final_size % 4096); } /* add on 4096 * 2 to account for location/timestamp headers */ final_size += 4096 * 2; rs_assert(final_size % 4096 == 0); /* resize the file, and remap */ if (ftruncate(self->fd, final_size) < 0) { rs_error("file resize failed"); /* FIXME */ } self->fsize = final_size; self->map = mmap(NULL, final_size, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd, 0); if (self->map == MAP_FAILED) { rs_error("remap failed"); /* FIXME */ } self->locations = (struct ChunkLocation*)(self->map); self->timestamps = (uint32_t*)(self->map + 4096); /* zero out the headers */ memset(self->map, 0, 4096 * 2); /* now, we can iterate through the writes and copy them in */ uint32_t cur_sector = 2; for (cell = self->cached_writes; cell != NULL; cell = cell->next) { struct ChunkWrite* write = cell->data; rs_assert(write); unsigned int i = write->x + write->z*32; /* handle chunk clears */ if (write->length == 0) { self->locations[i].offset = 0; self->locations[i].sector_count = 0; self->timestamps[i] = 0; continue; } uint8_t sector_count = (write->length + 4 + 1) / 4096; if ((write->length + 4 + 1) % 4096 > 0) sector_count++; self->locations[i].offset = rs_endian_uint24(cur_sector); self->locations[i].sector_count = sector_count; self->timestamps[i] = rs_endian_uint32(write->timestamp); /* convert compression types */ uint8_t enc = 0; switch (write->encoding) { case RS_GZIP: enc = 1; break; case RS_ZLIB: enc = 2; break; default: rs_return_if_reached(); /* unhandled compression type */ }; /* write the pre-data header (carefully) */ void* dest = _rs_region_get_data(self, write->x, write->z); ((uint32_t*)dest)[0] = rs_endian_uint32(write->length + 1); ((uint8_t*)dest)[4] = enc; /* write out the data */ rs_assert(write->data); memcpy(dest + 4 + 1, write->data, write->length); /* move along */ cur_sector += sector_count; } } else { /* there's already header info in place, we just need to * shuffle things around and update it */ /* for now, this is unsupported */ rs_return_if_reached(); } } /* clear the cached writes */ cell = self->cached_writes; for (; cell != NULL; cell = cell->next) { struct ChunkWrite* write = cell->data; rs_free(write->data); rs_free(write); } rs_list_free(self->cached_writes); self->cached_writes = NULL; /* sync the memory */ if (self->map && msync(self->map, self->fsize, MS_SYNC) < 0) { rs_error("sync failed"); /* FIXME */ } }