/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if PULSE_EVERYWHERE #include "pulse_protocol_impl.h" #include "console/control_protocol.h" #include "console/control_protocol_impl.h" #include "console/pulse.h" #include "console/pulse2_transport_impl.h" #include "console/pulse_control_message_protocol.h" #include "system/passert.h" #include #include #include #include #include static bool s_layer_up = false; // Best Effort transport Control Protocol // ====================================== static void prv_on_this_layer_up(PPPControlProtocol *this) { s_layer_up = true; #define REGISTER_PROTOCOL(N, HANDLER, LAYER_STATE_HANDLER) \ LAYER_STATE_HANDLER(PulseLinkState_Open); #include "console/pulse_protocol_registry.def" #undef REGISTER_PROTOCOL } static void prv_on_this_layer_down(PPPControlProtocol *this) { s_layer_up = false; #define REGISTER_PROTOCOL(N, HANDLER, LAYER_STATE_HANDLER) \ LAYER_STATE_HANDLER(PulseLinkState_Closed); #include "console/pulse_protocol_registry.def" #undef REGISTER_PROTOCOL } static void prv_on_receive_code_reject(PPPControlProtocol *this, LCPPacket *packet) { // TODO } static PPPControlProtocolState s_becp_state = {}; static PPPControlProtocol s_becp_protocol = { .protocol_number = PULSE2_BEST_EFFORT_CONTROL_PROTOCOL, .state = &s_becp_state, .on_this_layer_up = prv_on_this_layer_up, .on_this_layer_down = prv_on_this_layer_down, .on_receive_code_reject = prv_on_receive_code_reject, }; PPPControlProtocol * const PULSE2_BECP = &s_becp_protocol; void pulse2_best_effort_control_on_packet(void *packet, size_t length) { ppp_control_protocol_handle_incoming_packet(PULSE2_BECP, packet, length); } // Best Effort Application Transport protocol // ========================================== typedef struct PACKED BestEffortPacket { net16 protocol; net16 length; char information[]; } BestEffortPacket; static PulseControlMessageProtocol s_best_effort_pcmp = { .send_begin_fn = pulse_best_effort_send_begin, .send_fn = pulse_best_effort_send, }; void pulse2_best_effort_transport_on_packet(void *raw_packet, size_t length) { if (!s_layer_up) { return; } BestEffortPacket *packet = raw_packet; if (length < ntoh16(packet->length)) { // Packet truncated; discard return; } size_t info_length = ntoh16(packet->length) - sizeof(BestEffortPacket); // This variable is read in the macro-expansion below, but linters // have a hard time figuring that out. (void)info_length; switch (ntoh16(packet->protocol)) { case PULSE_CONTROL_MESSAGE_PROTOCOL: pulse_control_message_protocol_on_packet( &s_best_effort_pcmp, packet->information, info_length); break; #define REGISTER_PROTOCOL(N, HANDLER, LAYER_STATE_HANDLER) \ case N: \ HANDLER(packet->information, info_length); \ break; #include "console/pulse_protocol_registry.def" #undef REGISTER_PROTOCOL default: pulse_control_message_protocol_send_port_closed_message( &s_best_effort_pcmp, packet->protocol); break; } } void *pulse_best_effort_send_begin(const uint16_t app_protocol) { PBL_ASSERTN(s_layer_up); BestEffortPacket *packet = pulse_link_send_begin( PULSE2_BEST_EFFORT_TRANSPORT_PROTOCOL); packet->protocol = hton16(app_protocol); return &packet->information; } void pulse_best_effort_send(void *buf, const size_t length) { PBL_ASSERTN(s_layer_up); PBL_ASSERT(length <= pulse_link_max_send_size() - sizeof(BestEffortPacket), "Packet too big to send"); // We're blindly assuming that buf is the same pointer returned by // pulse_best_effort_send_begin. If it isn't, we'll either crash here // when trying to dereference it or we'll hit the assert in // pulse_link_send. BestEffortPacket *packet = (void *)((char *)buf - offsetof(BestEffortPacket, information)); size_t packet_size = length + sizeof(BestEffortPacket); packet->length = hton16(packet_size); pulse_link_send(packet, packet_size); } // Shared events // ============= void pulse2_best_effort_on_link_up(void) { ppp_control_protocol_lower_layer_is_up(PULSE2_BECP); } void pulse2_best_effort_on_link_down(void) { ppp_control_protocol_lower_layer_is_down(PULSE2_BECP); } void pulse2_best_effort_init(void) { ppp_control_protocol_init(PULSE2_BECP); ppp_control_protocol_open(PULSE2_BECP); } #endif