void tags_cache_init (struct tags_cache *c, const size_t max_size) { int i, rc; assert (c != NULL); c->db_env = NULL; c->db = NULL; for (i = 0; i < CLIENTS_MAX; i++) request_queue_init (&c->queues[i]); c->max_items = max_size; c->stop_reader_thread = 0; pthread_mutex_init (&c->mutex, NULL); rc = pthread_cond_init (&c->request_cond, NULL); if (rc != 0) fatal ("Can't create request_cond: %s", strerror (rc)); rc = pthread_create (&c->reader_thread, NULL, reader_thread, c); if (rc != 0) fatal ("Can't create tags cache thread: %s", strerror (rc)); }
int main(int argc, char **argv) { int fd, i, j, k; int c; int foreground=0; int active_slave=0; int log_options; char config_file_name[PATH_MAX] = RENDERD_CONFIG; while (1) { int option_index = 0; static struct option long_options[] = { {"config", 1, 0, 'c'}, {"foreground", 1, 0, 'f'}, {"slave", 1, 0, 's'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "hfc:", long_options, &option_index); if (c == -1) break; switch (c) { case 'f': foreground=1; break; case 'c': strncpy(config_file_name, optarg, PATH_MAX-1); config_file_name[PATH_MAX-1] = 0; break; case 's': if (sscanf(optarg, "%i", &active_slave) != 1) { fprintf(stderr, "--slave needs to be nummeric (%s)\n", optarg); active_slave = 0; } break; case 'h': fprintf(stderr, "Usage: renderd [OPTION] ...\n"); fprintf(stderr, "Mapnik rendering daemon\n"); fprintf(stderr, " -f, --foreground run in foreground\n"); fprintf(stderr, " -h, --help display this help and exit\n"); fprintf(stderr, " -c, --config=CONFIG set location of config file (default /etc/renderd.conf)\n"); fprintf(stderr, " -s, --slave=CONFIG_NR set which render slave this is (default 0)\n"); exit(0); default: fprintf(stderr, "unknown config option '%c'\n", c); exit(1); } } log_options = LOG_PID; #ifdef LOG_PERROR if (foreground) log_options |= LOG_PERROR; #endif openlog("renderd", log_options, LOG_DAEMON); syslog(LOG_INFO, "Rendering daemon started"); render_request_queue = request_queue_init(); if (render_request_queue == NULL ) { syslog(LOG_ERR, "Failed to initialise request queue"); exit(1); } syslog(LOG_ERR, "Initiating reqyest_queue"); xmlconfigitem maps[XMLCONFIGS_MAX]; bzero(maps, sizeof(xmlconfigitem) * XMLCONFIGS_MAX); renderd_config config_slaves[MAX_SLAVES]; bzero(config_slaves, sizeof(renderd_config) * MAX_SLAVES); bzero(&config, sizeof(renderd_config)); dictionary *ini = iniparser_load(config_file_name); if (! ini) { exit(1); } noSlaveRenders = 0; int iconf = -1; char buffer[PATH_MAX]; for (int section=0; section < iniparser_getnsec(ini); section++) { char *name = iniparser_getsecname(ini, section); syslog(LOG_INFO, "Parsing section %s\n", name); if (strncmp(name, "renderd", 7) && strcmp(name, "mapnik")) { if (config.tile_dir == NULL) { fprintf(stderr, "No valid (active) renderd config section available\n"); exit(7); } /* this is a map section */ iconf++; if (iconf >= XMLCONFIGS_MAX) { fprintf(stderr, "Config: more than %d configurations found\n", XMLCONFIGS_MAX); exit(7); } if (strlen(name) >= (XMLCONFIG_MAX - 1)) { fprintf(stderr, "XML name too long: %s\n", name); exit(7); } strcpy(maps[iconf].xmlname, name); sprintf(buffer, "%s:uri", name); char *ini_uri = iniparser_getstring(ini, buffer, (char *)""); if (strlen(ini_uri) >= (PATH_MAX - 1)) { fprintf(stderr, "URI too long: %s\n", ini_uri); exit(7); } strcpy(maps[iconf].xmluri, ini_uri); sprintf(buffer, "%s:xml", name); char *ini_xmlpath = iniparser_getstring(ini, buffer, (char *)""); if (strlen(ini_xmlpath) >= (PATH_MAX - 1)){ fprintf(stderr, "XML path too long: %s\n", ini_xmlpath); exit(7); } strcpy(maps[iconf].xmlfile, ini_xmlpath); sprintf(buffer, "%s:host", name); char *ini_hostname = iniparser_getstring(ini, buffer, (char *) ""); if (strlen(ini_hostname) >= (PATH_MAX - 1)) { fprintf(stderr, "Host name too long: %s\n", ini_hostname); exit(7); } strcpy(maps[iconf].host, ini_hostname); sprintf(buffer, "%s:htcphost", name); char *ini_htcpip = iniparser_getstring(ini, buffer, (char *) ""); if (strlen(ini_htcpip) >= (PATH_MAX - 1)) { fprintf(stderr, "HTCP host name too long: %s\n", ini_htcpip); exit(7); } strcpy(maps[iconf].htcpip, ini_htcpip); sprintf(buffer, "%s:tilesize", name); char *ini_tilesize = iniparser_getstring(ini, buffer, (char *) "256"); maps[iconf].tile_px_size = atoi(ini_tilesize); if (maps[iconf].tile_px_size < 1) { fprintf(stderr, "Tile size is invalid: %s\n", ini_tilesize); exit(7); } sprintf(buffer, "%s:tiledir", name); char *ini_tiledir = iniparser_getstring(ini, buffer, (char *) config.tile_dir); if (strlen(ini_tiledir) >= (PATH_MAX - 1)) { fprintf(stderr, "Tiledir too long: %s\n", ini_tiledir); exit(7); } strcpy(maps[iconf].tile_dir, ini_tiledir); sprintf(buffer, "%s:maxzoom", name); char *ini_maxzoom = iniparser_getstring(ini, buffer, "18"); maps[iconf].max_zoom = atoi(ini_maxzoom); if (maps[iconf].max_zoom > MAX_ZOOM) { fprintf(stderr, "Specified max zoom (%i) is to large. Renderd currently only supports up to zoom level %i\n", maps[iconf].max_zoom, MAX_ZOOM); exit(7); } sprintf(buffer, "%s:minzoom", name); char *ini_minzoom = iniparser_getstring(ini, buffer, "0"); maps[iconf].min_zoom = atoi(ini_minzoom); if (maps[iconf].min_zoom < 0) { fprintf(stderr, "Specified min zoom (%i) is to small. Minimum zoom level has to be greater or equal to 0\n", maps[iconf].min_zoom); exit(7); } if (maps[iconf].min_zoom > maps[iconf].max_zoom) { fprintf(stderr, "Specified min zoom (%i) is larger than max zoom (%i).\n", maps[iconf].min_zoom, maps[iconf].max_zoom); exit(7); } sprintf(buffer, "%s:parameterize_style", name); char *ini_parameterize = iniparser_getstring(ini, buffer, ""); if (strlen(ini_parameterize) >= (PATH_MAX - 1)) { fprintf(stderr, "Parameterize_style too long: %s\n", ini_parameterize); exit(7); } strcpy(maps[iconf].parameterization, ini_parameterize); /* Pass this information into the rendering threads, * as it is needed to configure mapniks number of connections */ maps[iconf].num_threads = config.num_threads; } else if (strncmp(name, "renderd", 7) == 0) { int render_sec = 0; if (sscanf(name, "renderd%i", &render_sec) != 1) { render_sec = 0; } syslog(LOG_INFO, "Parsing render section %i\n", render_sec); if (render_sec >= MAX_SLAVES) { syslog(LOG_ERR, "Can't handle more than %i render sections\n", MAX_SLAVES); exit(7); } sprintf(buffer, "%s:socketname", name); config_slaves[render_sec].socketname = iniparser_getstring(ini, buffer, (char *) RENDER_SOCKET); sprintf(buffer, "%s:iphostname", name); config_slaves[render_sec].iphostname = iniparser_getstring(ini, buffer, ""); sprintf(buffer, "%s:ipport", name); config_slaves[render_sec].ipport = iniparser_getint(ini, buffer, 0); sprintf(buffer, "%s:num_threads", name); config_slaves[render_sec].num_threads = iniparser_getint(ini, buffer, NUM_THREADS); sprintf(buffer, "%s:tile_dir", name); config_slaves[render_sec].tile_dir = iniparser_getstring(ini, buffer, (char *) HASH_PATH); sprintf(buffer, "%s:stats_file", name); config_slaves[render_sec].stats_filename = iniparser_getstring(ini, buffer, NULL); if (render_sec == active_slave) { config.socketname = config_slaves[render_sec].socketname; config.iphostname = config_slaves[render_sec].iphostname; config.ipport = config_slaves[render_sec].ipport; config.num_threads = config_slaves[render_sec].num_threads; config.tile_dir = config_slaves[render_sec].tile_dir; config.stats_filename = config_slaves[render_sec].stats_filename; config.mapnik_plugins_dir = iniparser_getstring(ini, "mapnik:plugins_dir", (char *) MAPNIK_PLUGINS); config.mapnik_font_dir = iniparser_getstring(ini, "mapnik:font_dir", (char *) FONT_DIR); config.mapnik_font_dir_recurse = iniparser_getboolean(ini, "mapnik:font_dir_recurse", FONT_RECURSE); } else { noSlaveRenders += config_slaves[render_sec].num_threads; } } } if (config.ipport > 0) { syslog(LOG_INFO, "config renderd: ip socket=%s:%i\n", config.iphostname, config.ipport); } else { syslog(LOG_INFO, "config renderd: unix socketname=%s\n", config.socketname); } syslog(LOG_INFO, "config renderd: num_threads=%d\n", config.num_threads); if (active_slave == 0) { syslog(LOG_INFO, "config renderd: num_slaves=%d\n", noSlaveRenders); } syslog(LOG_INFO, "config renderd: tile_dir=%s\n", config.tile_dir); syslog(LOG_INFO, "config renderd: stats_file=%s\n", config.stats_filename); syslog(LOG_INFO, "config mapnik: plugins_dir=%s\n", config.mapnik_plugins_dir); syslog(LOG_INFO, "config mapnik: font_dir=%s\n", config.mapnik_font_dir); syslog(LOG_INFO, "config mapnik: font_dir_recurse=%d\n", config.mapnik_font_dir_recurse); for (i = 0; i < MAX_SLAVES; i++) { if (config_slaves[i].num_threads == 0) { continue; } if (i == active_slave) { syslog(LOG_INFO, "config renderd(%i): Active\n", i); } if (config_slaves[i].ipport > 0) { syslog(LOG_INFO, "config renderd(%i): ip socket=%s:%i\n", i, config_slaves[i].iphostname, config_slaves[i].ipport); } else { syslog(LOG_INFO, "config renderd(%i): unix socketname=%s\n", i, config_slaves[i].socketname); } syslog(LOG_INFO, "config renderd(%i): num_threads=%d\n", i, config_slaves[i].num_threads); syslog(LOG_INFO, "config renderd(%i): tile_dir=%s\n", i, config_slaves[i].tile_dir); syslog(LOG_INFO, "config renderd(%i): stats_file=%s\n", i, config_slaves[i].stats_filename); } for(iconf = 0; iconf < XMLCONFIGS_MAX; ++iconf) { if (maps[iconf].xmlname[0] != 0) { syslog(LOG_INFO, "config map %d: name(%s) file(%s) uri(%s) htcp(%s) host(%s)", iconf, maps[iconf].xmlname, maps[iconf].xmlfile, maps[iconf].xmluri, maps[iconf].htcpip, maps[iconf].host); } } fd = server_socket_init(&config); #if 0 if (fcntl(fd, F_SETFD, O_RDWR | O_NONBLOCK) < 0) { fprintf(stderr, "setting socket non-block failed\n"); close(fd); exit(5); } #endif //sigPipeAction.sa_handler = pipe_handler; sigPipeAction.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sigPipeAction, NULL) < 0) { fprintf(stderr, "failed to register signal handler\n"); close(fd); exit(6); } render_init(config.mapnik_plugins_dir, config.mapnik_font_dir, config.mapnik_font_dir_recurse); /* unless the command line said to run in foreground mode, fork and detach from terminal */ if (foreground) { fprintf(stderr, "Running in foreground mode...\n"); } else { if (daemon(0, 0) != 0) { fprintf(stderr, "can't daemonize: %s\n", strerror(errno)); } /* write pid file */ FILE *pidfile = fopen(PIDFILE, "w"); if (pidfile) { (void) fprintf(pidfile, "%d\n", getpid()); (void) fclose(pidfile); } } if (config.stats_filename != NULL) { if (pthread_create(&stats_thread, NULL, stats_writeout_thread, NULL)) { syslog(LOG_WARNING, "Could not create stats writeout thread"); } } else { syslog(LOG_INFO, "No stats file specified in config. Stats reporting disabled"); } render_threads = (pthread_t *) malloc(sizeof(pthread_t) * config.num_threads); for(i=0; i<config.num_threads; i++) { if (pthread_create(&render_threads[i], NULL, render_thread, (void *)maps)) { fprintf(stderr, "error spawning render thread\n"); close(fd); exit(7); } } if (active_slave == 0) { //Only the master renderd opens connections to its slaves k = 0; slave_threads = (pthread_t *) malloc(sizeof(pthread_t) * noSlaveRenders); for (i = 1; i < MAX_SLAVES; i++) { for (j = 0; j < config_slaves[i].num_threads; j++) { if (pthread_create(&slave_threads[k++], NULL, slave_thread, (void *) &config_slaves[i])) { fprintf(stderr, "error spawning render thread\n"); close(fd); exit(7); } } } } process_loop(fd); unlink(config.socketname); close(fd); return 0; }
int main ( void ) { uint8_t aes_key_nr; uint8_t loop = 0; uint8_t loop2 = 0; uint8_t data[22]; sbi(LED_DDR, LED_PIN); // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); request_queue_init(); // read packetcounter, increase by cycle and write back packetcounter = eeprom_read_dword((uint32_t*)EEPROM_POS_PACKET_COUNTER) + PACKET_COUNTER_WRITE_CYCLE; eeprom_write_dword((uint32_t*)0, packetcounter); uart_init(true); UART_PUTS ("\r\n"); UART_PUTS ("Open Home Control Base Station V1.0\r\n"); UART_PUTS ("(c) 2012 Uwe Freese, www.open-home-control.com\r\n"); UART_PUTF ("Packet counter: %lu\r\n", packetcounter); UART_PUTS ("Waiting for incoming data. Press h for help.\r\n"); rfm12_init(); sei(); // ENCODE TEST /* uint8_t testlen = 64; eeprom_read_block (aes_key, (uint8_t *)EEPROM_POS_AES_KEY, 32); UART_PUTS("Using AES key "); printbytearray((uint8_t *)aes_key, 32); UART_PUTS("Before encryption: "); printbytearray(bufx, testlen); unsigned long crc = crc32(bufx, testlen); UART_PUTF("CRC32 is %lx (added as last 4 bytes)\r\n", crc); UART_PUTS("1\r\n"); crc = crc32(bufx, testlen - 4); UART_PUTS("2\r\n"); setBuf32(testlen - 4, crc); UART_PUTS("Before encryption (CRC added): "); printbytearray(bufx, testlen); UART_PUTS("1\r\n"); uint8_t aes_byte_count = aes256_encrypt_cbc(bufx, testlen); UART_PUTS("2\r\n"); UART_PUTS("After encryption: "); printbytearray(bufx, aes_byte_count); UART_PUTF("String len = %u\r\n", aes_byte_count); UART_PUTS("1\r\n"); aes256_decrypt_cbc(bufx, aes_byte_count); UART_PUTS("2\r\n"); UART_PUTS("After decryption: "); printbytearray(bufx, testlen); crc = getBuf32(testlen - 4); UART_PUTF("CRC32 is %lx (last 4 bytes from decrypted message)\r\n", crc); printbytearray(bufx, testlen); UART_PUTS("After decryption (CRC removed): "); printbytearray(bufx, testlen); UART_PUTF("String len = %u\r\n", testlen); while(1); */ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); printbytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { uint32_t assumed_crc; uint32_t actual_crc; for(aes_key_nr = 0; aes_key_nr < AES_KEY_EEPROM_COUNT ; aes_key_nr++) { //strncpy((char *)bufx, (char *)rfm12_rx_buffer(), len); memcpy(bufx, rfm12_rx_buffer(), len); /*if (aes_key_nr == 0) { UART_PUTS("Before decryption: "); printbytearray(bufx, len); }*/ eeprom_read_block (aes_key, (uint8_t *)(EEPROM_POS_AES_KEY + aes_key_nr * 32), 32); //UART_PUTS("Trying AES key "); //printbytearray((uint8_t *)aes_key, 32); aes256_decrypt_cbc(bufx, len); //UART_PUTS("Decrypted bytes: "); //printbytearray(bufx, len); assumed_crc = getBuf32(len - 4); actual_crc = crc32(bufx, len - 4); //UART_PUTF("Received CRC32 would be %lx\r\n", assumed_crc); //UART_PUTF("Re-calculated CRC32 is %lx\r\n", actual_crc); if (assumed_crc == actual_crc) { //UART_PUTS("CRC correct, AES key found!\r\n"); UART_PUTF("Received (AES key %u): ", aes_key_nr); printbytearray(bufx, len - 4); decode_data(len - 4); break; } } if (assumed_crc != actual_crc) { UART_PUTS("Received garbage (CRC wrong after decryption).\r\n"); } UART_PUTS("\r\n"); } //uart_hexdump((char *)bufcontents, rfm12_rx_len()); //UART_PUTS("\r\n"); // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } // send data, if waiting in send buffer if (send_data_avail) { uint8_t i; uint8_t data_len_raw = strlen(sendbuf) / 2 - 2; // round data length to 6 + 16 bytes (including padding bytes) uint8_t data_len = (((data_len_raw + 9) / 16) + 1) * 16 - 10; // set aes key nr aes_key_nr = hex_to_uint8((uint8_t *)sendbuf, 0); //UART_PUTF("AES KEY = %u\r\n", aes_key_nr); // set command id uint8_t command_id = hex_to_uint8((uint8_t *)sendbuf, 2); // set data for (i = 0; i < data_len_raw; i++) { data[i] = hex_to_uint8((uint8_t *)sendbuf, 4 + 2 * i); } // set padding bytes for (i = data_len_raw; i < data_len; i++) { data[i] = 0; } // send status packet immediately (command IDs are less than 128) if (command_id < 128) { // set command id bufx[5] = command_id; // set data memcpy(bufx + 6, data, data_len); send_packet(aes_key_nr, data_len); } else // enqueue request (don't send immediately) { if (queue_request(data[0], command_id, aes_key_nr, data + 1)) { UART_PUTS("Adding request to queue.\r\n"); } else { UART_PUTS("Warning! Request queue full. Packet will not be sent.\r\n"); } print_request_queue(); } // clear send text buffer send_data_avail = false; rfm12_tick(); led_blink(200, 0, 1); } // flash LED every second to show the device is alive if (loop == 50) { led_blink(10, 10, 1); loop = 0; if (set_repeat_request(packetcounter + 1)) // if request to repeat was found in queue { UART_PUTS("Repeating request.\r\n"); send_packet(0, 6); print_request_queue(); } // Auto-send something for debugging purposes... if (loop2 == 50) { //strcpy(sendbuf, "008c0001003d"); //send_data_avail = true; loop2 = 0; } else { loop2++; } } else { _delay_ms(20); } rfm12_tick(); loop++; process_rxbuf(); if (uart_timeout > 0) { uart_timeout--; if (uart_timeout == 0) { UART_PUTS("*** UART user timeout. Input was ignored. ***\r\n"); } } } // never called // aes256_done(&aes_ctx); }
int main(void) { uint8_t aes_key_nr; uint8_t loop = 0; uint8_t loop2 = 0; // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); util_init(); check_eeprom_compatibility(DEVICETYPE_BASESTATION); request_queue_init(); // read packetcounter, increase by cycle and write back packetcounter = e2p_generic_get_packetcounter() + PACKET_COUNTER_WRITE_CYCLE; e2p_generic_set_packetcounter(packetcounter); // read device specific config aes_key_count = e2p_basestation_get_aeskeycount(); device_id = e2p_generic_get_deviceid(); uart_init(); UART_PUTS("\r\n"); UART_PUTF4("smarthomatic Base Station v%u.%u.%u (%08lx)\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_HASH); UART_PUTS("(c) 2012..2014 Uwe Freese, www.smarthomatic.org\r\n"); UART_PUTF("Device ID: %u\r\n", device_id); UART_PUTF("Packet counter: %lu\r\n", packetcounter); UART_PUTF("AES key count: %u\r\n", aes_key_count); UART_PUTS("Waiting for incoming data. Press h for help.\r\n\r\n"); led_blink(500, 500, 3); rfm12_init(); sei(); // ENCODE TEST (Move to unit test some day...) /* uint8_t testlen = 32; uint8_t aes_key_num = 0; memset(&bufx[0], 0, sizeof(bufx)); bufx[0] = 0xff; bufx[1] = 0xb0; bufx[2] = 0xa0; bufx[3] = 0x3f; bufx[4] = 0x01; bufx[5] = 0x70; bufx[6] = 0x00; bufx[7] = 0x0c; bufx[8] = 0xa8; bufx[9] = 0x00; bufx[10] = 0x20; bufx[20] = 0x20; eeprom_read_block (aes_key, (uint8_t *)(EEPROM_AESKEYS_BYTE + aes_key_num * 32), 32); UART_PUTS("Using AES key "); print_bytearray((uint8_t *)aes_key, 32); UART_PUTS("Before encryption: "); print_bytearray(bufx, testlen); uint8_t aes_byte_count = aes256_encrypt_cbc(bufx, testlen); UART_PUTF("byte count = %u\r\n", aes_byte_count); UART_PUTS("After encryption: "); print_bytearray(bufx, aes_byte_count); aes256_decrypt_cbc(bufx, aes_byte_count); UART_PUTS("After decryption: "); print_bytearray(bufx, testlen); while(1); */ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); print_bytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { bool crcok = false; for (aes_key_nr = 0; aes_key_nr < aes_key_count ; aes_key_nr++) { memcpy(bufx, rfm12_rx_buffer(), len); /*if (aes_key_nr == 0) { UART_PUTS("Before decryption: "); print_bytearray(bufx, len); }*/ e2p_basestation_get_aeskey(aes_key_nr, aes_key); //UART_PUTS("Trying AES key 2 "); //print_bytearray((uint8_t *)aes_key, 32); aes256_decrypt_cbc(bufx, len); //UART_PUTS("Decrypted bytes: "); //print_bytearray(bufx, len); crcok = pkg_header_check_crc32(len); if (crcok) { //UART_PUTS("CRC correct, AES key found!\r\n"); UART_PUTF("Received (AES key %u): ", aes_key_nr); print_bytearray(bufx, len); decode_data(len); break; } } if (!crcok) { UART_PUTS("Received garbage (CRC wrong after decryption): "); memcpy(bufx, rfm12_rx_buffer(), len); print_bytearray(bufx, len); } UART_PUTS("\r\n"); } //uart_hexdump((char *)bufcontents, rfm12_rx_len()); //UART_PUTS("\r\n"); // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } // send data, if waiting in send buffer if (send_data_avail) { uint8_t i; // set AES key nr aes_key_nr = hex_to_uint8((uint8_t *)cmdbuf, 1); //UART_PUTF("AES KEY = %u\r\n", aes_key_nr); // init packet buffer memset(&bufx[0], 0, sizeof(bufx)); // set message type uint8_t message_type = hex_to_uint8((uint8_t *)cmdbuf, 3); pkg_header_set_messagetype(message_type); pkg_header_adjust_offset(); //UART_PUTF("MessageType = %u\r\n", message_type); uint8_t string_offset_data = 0; /* UART_PUTS("sKK00RRRRGGMM.............Get\r\n"); UART_PUTS("sKK01RRRRGGMMDD...........Set\r\n"); UART_PUTS("sKK02RRRRGGMMDD...........SetGet\r\n"); UART_PUTS("sKK08GGMMDD...............Status\r\n"); UART_PUTS("sKK09SSSSPPPPPPEE.........Ack\r\n"); UART_PUTS("sKK0ASSSSPPPPPPEEGGMMDD...AckStatus\r\n"); */ // set header extension fields to the values given as hex string in the user input switch (message_type) { case MESSAGETYPE_GET: case MESSAGETYPE_SET: case MESSAGETYPE_SETGET: pkg_headerext_common_set_receiverid(hex_to_uint16((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 9)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 11)); string_offset_data = 12; break; case MESSAGETYPE_STATUS: pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 7)); string_offset_data = 8; break; case MESSAGETYPE_ACK: pkg_headerext_common_set_acksenderid(hex_to_uint16((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_ackpacketcounter(hex_to_uint24((uint8_t *)cmdbuf, 9)); pkg_headerext_common_set_error(hex_to_uint8((uint8_t *)cmdbuf, 15)); // fallthrough! case MESSAGETYPE_ACKSTATUS: pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 17)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 19)); string_offset_data = 20; break; } uint8_t data_len_raw = 0; // copy message data, which exists in all packets except in Get and Ack packets if ((message_type != MESSAGETYPE_GET) && (message_type != MESSAGETYPE_ACK)) { uint8_t data_len_raw = (strlen(cmdbuf) - 1 - string_offset_data) / 2; //UART_PUTF("Data bytes = %u\r\n", data_len_raw); uint8_t start = __HEADEROFFSETBITS / 8; uint8_t shift = __HEADEROFFSETBITS % 8; // copy message data, using __HEADEROFFSETBITS value and string_offset_data for (i = 0; i < data_len_raw; i++) { uint8_t val = hex_to_uint8((uint8_t *)cmdbuf, string_offset_data + 2 * i + 1); array_write_UIntValue(start + i, shift, 8, val, bufx); } } // round packet length to x * 16 bytes uint8_t packet_len = ((uint16_t)__HEADEROFFSETBITS + (uint16_t)data_len_raw * 8) / 8; packet_len = ((packet_len - 1) / 16 + 1) * 16; // send packet which doesn't require an acknowledge immediately if ((message_type != MESSAGETYPE_GET) && (message_type != MESSAGETYPE_SET) && (message_type != MESSAGETYPE_SETGET)) { send_packet(aes_key_nr, packet_len); } else // enqueue request (don't send immediately) { // header size = 9 bytes! if (queue_request(pkg_headerext_common_get_receiverid(), message_type, aes_key_nr, bufx + 9, packet_len - 9)) { UART_PUTF("Request added to queue (%u bytes packet).\r\n", packet_len); } else { UART_PUTS("Warning! Request queue full. Packet will not be sent.\r\n"); } print_request_queue(); } // clear cmdbuf to receive more input from UART send_data_avail = false; rfm12_tick(); led_blink(200, 0, 1); } // flash LED every second to show the device is alive if (loop == 50) { led_blink(10, 10, 1); loop = 0; request_t* request = find_request_to_repeat(packetcounter + 1); if (request != 0) // if request to repeat was found in queue { UART_PUTS("Repeating request.\r\n"); send_packet((*request).aes_key, (*request).data_bytes + 9); // header size = 9 bytes! print_request_queue(); } // Auto-send something for debugging purposes... if (loop2 == 50) { //strcpy(cmdbuf, "s000102828300"); //send_data_avail = true; loop2 = 0; } else { loop2++; } } else { _delay_ms(20); } rfm12_tick(); loop++; process_rxbuf(); if (uart_timeout > 0) { uart_timeout--; if (uart_timeout == 0) { UART_PUTS("*** UART user timeout. Input was ignored. ***\r\n"); } } } // never called // aes256_done(&aes_ctx); }
} } void *fetch_thread(void * arg) { struct request_queue * queue = (struct request_queue *)arg; struct item * item; enum protoCmd res; for (int i = 0; i < NO_QUEUE_REQUESTS; i++) { item = request_queue_fetch_request(queue); } } TEST_CASE( "renderd/queueing", "request queueing") { SECTION("renderd/queueing/initialisation", "test the initialisation of the request queue") { request_queue * queue = request_queue_init(); REQUIRE( queue != NULL ); request_queue_close(queue); } SECTION("renderd/queueing/simple request add", "test the addition of a single request") { request_queue * queue = request_queue_init(); struct item * item = init_render_request(cmdRender); enum protoCmd res = request_queue_add_request(queue, item); REQUIRE ( res == cmdIgnore ); request_queue_close(queue); } SECTION("renderd/queueing/simple request add priority", "test the addition of requests with different priorities") {