void vrpn_Imager_Stream_Buffer::mainloop(void) { // Required from all servers server_mainloop(); // See if we have a new image description from a logging thread. If so, // fill in our values and send a description to any attached clients. const char *channelBuffer = NULL; if (d_shared_state.get_imager_description(d_nRows, d_nCols, d_nDepth, d_nChannels, &channelBuffer)) { int i; const char *bufptr = channelBuffer; for (i = 0; i < d_nChannels; i++) { d_channels[i].unbuffer(&bufptr); } delete[] const_cast<char *>(channelBuffer); send_description(); } // See if we have any messages waiting in the queue from the logging thread. // If we do, get an initial count and then send that many messages to the // client. Don't go looking again this iteration or we may never return -- // the server is quite possibly packing frames faster than we can send them. // Note that the messages in the queue have already been transcoded for our // and sender ID. unsigned count = d_shared_state.get_logger_to_client_queue_size(); if (count) { unsigned i; for (i = 0; i < count; i++) { // Read the next message from the queue. vrpn_HANDLERPARAM p; if (!d_shared_state.retrieve_logger_to_client_message(&p)) { fprintf(stderr, "vrpn_Imager_Stream_Buffer::mainloop(): Could " "not retrieve message from queue\n"); break; } // Decrement the in-buffer frame count whenever we see a begin_frame // message. This will un-block the way for later frames to be // buffered. if (p.type == d_begin_frame_m_id) { d_shared_state.decrement_frames_in_queue(); } // Pack and send the message to the client, then delete the buffer // associated with the message. Send them all reliably. Send them // all using our sender ID. if (d_connection->pack_message(p.payload_len, p.msg_time, p.type, d_sender_id, p.buffer, vrpn_CONNECTION_RELIABLE) != 0) { fprintf(stderr, "vrpn_Imager_Stream_Buffer::mainloop(): Could " "not pack message\n"); break; } delete[] const_cast<char *>(p.buffer); } } }
/** * Decodes and dispatches a received message to its handler. */ ProtocolError Protocol::handle_received_message(Message& message, CoAPMessageType::Enum& message_type) { last_message_millis = callbacks.millis(); pinger.message_received(); uint8_t* queue = message.buf(); message_type = Messages::decodeType(queue, message.length()); token_t token = queue[4]; message_id_t msg_id = CoAP::message_id(queue); ProtocolError error = NO_ERROR; //DEBUG("message type %d", message_type); switch (message_type) { case CoAPMessageType::DESCRIBE: { // 4 bytes header, 1 byte token, 2 bytes location path // 2 bytes optional single character location path for describe flags int descriptor_type = DESCRIBE_ALL; if (message.length()>8) descriptor_type = queue[8]; error = send_description(token, msg_id, descriptor_type); break; } case CoAPMessageType::FUNCTION_CALL: return functions.handle_function_call(token, msg_id, message, channel, descriptor.call_function); case CoAPMessageType::VARIABLE_REQUEST: { char variable_key[13]; variables.decode_variable_request(variable_key, message); return variables.handle_variable_request(variable_key, message, channel, token, msg_id, descriptor.variable_type, descriptor.get_variable); } case CoAPMessageType::SAVE_BEGIN: // fall through case CoAPMessageType::UPDATE_BEGIN: return chunkedTransfer.handle_update_begin(token, message, channel); case CoAPMessageType::CHUNK: return chunkedTransfer.handle_chunk(token, message, channel); case CoAPMessageType::UPDATE_DONE: return chunkedTransfer.handle_update_done(token, message, channel); case CoAPMessageType::EVENT: return subscriptions.handle_event(message, descriptor.call_event_handler, channel); case CoAPMessageType::KEY_CHANGE: return handle_key_change(message); case CoAPMessageType::SIGNAL_START: message.set_length( Messages::coded_ack(message.buf(), token, ChunkReceivedCode::OK, queue[2], queue[3])); callbacks.signal(true, 0, NULL); return channel.send(message); case CoAPMessageType::SIGNAL_STOP: message.set_length( Messages::coded_ack(message.buf(), token, ChunkReceivedCode::OK, queue[2], queue[3])); callbacks.signal(false, 0, NULL); return channel.send(message); case CoAPMessageType::HELLO: if (message.get_type()==CoAPType::CON) send_empty_ack(message, msg_id); descriptor.ota_upgrade_status_sent(); break; case CoAPMessageType::TIME: handle_time_response( queue[6] << 24 | queue[7] << 16 | queue[8] << 8 | queue[9]); break; case CoAPMessageType::PING: message.set_length( Messages::empty_ack(message.buf(), queue[2], queue[3])); error = channel.send(message); break; case CoAPMessageType::EMPTY_ACK: case CoAPMessageType::ERROR: default: ; // drop it on the floor } // all's well return error; }