### VTY CLI Setup and Command Definition in C Source: https://context7.com/osmocom/libosmocore/llms.txt This C code demonstrates how to set up the VTY framework, define custom configuration nodes, and register commands for interacting with application settings. It includes examples for setting server IP, port, and maximum connections, as well as showing the current configuration. Dependencies include osmocom/vty headers and osmocom/core/application.h. ```c #include #include #include #include /* Custom configuration structure */ struct app_config { char *server_ip; int server_port; int max_connections; }; static struct app_config g_config = { .server_ip = "127.0.0.1", .server_port = 5000, .max_connections = 100, }; /* Define custom VTY node */ enum app_vty_node { APP_NODE = _LAST_OSMOVTY_NODE, }; /* VTY application info */ static struct vty_app_info vty_info = { .name = "MyApp", .version = "1.0.0", .copyright = "(C) 2024 Example Corp", }; /* Command: enter application config node */ DEFUN(cfg_app, cfg_app_cmd, "app", "Enter application configuration\n") { vty->node = APP_NODE; return CMD_SUCCESS; } /* Command: set server address */ DEFUN(cfg_app_server, cfg_app_server_cmd, "server IP PORT", "Configure server connection\n" "Server IP address\n" "Server port number\n") { g_config.server_ip = talloc_strdup(tall_vty_ctx, argv[0]); g_config.server_port = atoi(argv[1]); vty_out(vty, "Server configured: %s:%d%s", g_config.server_ip, g_config.server_port, VTY_NEWLINE); return CMD_SUCCESS; } /* Command: set max connections */ DEFUN(cfg_app_max_conn, cfg_app_max_conn_cmd, "max-connections <1-1000>", "Set maximum number of connections\n" "Number of connections\n") { g_config.max_connections = atoi(argv[0]); return CMD_SUCCESS; } /* Command: show current configuration */ DEFUN(show_app_config, show_app_config_cmd, "show app config", SHOW_STR "Application\n" "Current configuration\n") { vty_out(vty, "Application Configuration:%s", VTY_NEWLINE); vty_out(vty, " Server: %s:%d%s", g_config.server_ip, g_config.server_port, VTY_NEWLINE); vty_out(vty, " Max connections: %d%s", g_config.max_connections, VTY_NEWLINE); return CMD_SUCCESS; } /* Node configuration write callback */ static int config_write_app(struct vty *vty) { vty_out(vty, "app%s", VTY_NEWLINE); vty_out(vty, " server %s %d%s", g_config.server_ip, g_config.server_port, VTY_NEWLINE); vty_out(vty, " max-connections %d%s", g_config.max_connections, VTY_NEWLINE); return CMD_SUCCESS; } /* Define the command node */ static struct cmd_node app_node = { .node = APP_NODE, .prompt = "%s(config-app)# ", .vtysh = 1, }; int main(int argc, char **argv) { void *tall_ctx = talloc_named_const(NULL, 0, "vty_example"); /* Initialize VTY */ vty_info.tall_ctx = tall_ctx; vty_init(&vty_info); /* Install custom node */ install_node(&app_node, config_write_app); /* Install commands in CONFIG_NODE */ install_element(CONFIG_NODE, &cfg_app_cmd); /* Install commands in APP_NODE */ install_element(APP_NODE, &cfg_app_server_cmd); install_element(APP_NODE, &cfg_app_max_conn_cmd); /* Install show command in VIEW and ENABLE nodes */ install_element_ve(&show_app_config_cmd); /* Read configuration file */ vty_read_config_file("app.cfg", NULL); /* Start telnet VTY interface */ int rc = telnet_init_default(tall_ctx, NULL, 4240); if (rc < 0) { fprintf(stderr, "Failed to start VTY telnet interface\n"); return 1; } printf("VTY listening on port 4240\n"); printf("Connect with: telnet localhost 4240\n"); /* Run main loop */ while (1) { osmo_select_main(0); } return 0; } ``` -------------------------------- ### Implement Control Interface Commands (C) Source: https://context7.com/osmocom/libosmocore/llms.txt This C code snippet demonstrates how to define and implement read-only and read-write control variables using the libosmocore Control Interface API. It includes examples for getting and setting variables like 'uptime' and 'debug-level', along with validation for input values. ```c #include #include /* Define a read-only control variable */ CTRL_CMD_DEFINE_RO(uptime, "uptime"); static int get_uptime(struct ctrl_cmd *cmd, void *data) { static time_t start_time = 0; if (!start_time) start_time = time(NULL); time_t uptime = time(NULL) - start_time; cmd->reply = talloc_asprintf(cmd, "%ld", uptime); return CTRL_CMD_REPLY; } /* Define a read-write control variable */ CTRL_CMD_DEFINE(debug_level, "debug-level"); static int debug_level = 0; static int get_debug_level(struct ctrl_cmd *cmd, void *data) { cmd->reply = talloc_asprintf(cmd, "%d", debug_level); return CTRL_CMD_REPLY; } static int set_debug_level(struct ctrl_cmd *cmd, void *data) { debug_level = atoi(cmd->value); cmd->reply = talloc_asprintf(cmd, "Debug level set to %d", debug_level); return CTRL_CMD_REPLY; } static int verify_debug_level(struct ctrl_cmd *cmd, const char *value, void *data) { int level = atoi(value); if (level < 0 || level > 10) { cmd->reply = "Debug level must be 0-10"; return -1; } return 0; } /* Define a range-limited integer variable using helper macro */ static struct { int max_connections; } config = { .max_connections = 100 }; CTRL_CMD_DEFINE_RANGE(max_conns, "max-connections", typeof(config), max_connections, 1, 1000); int ctrl_interface_setup(void *ctx) { /* Create control interface handle */ struct ctrl_handle *ctrl = ctrl_interface_setup(NULL, 4249, ctx); if (!ctrl) { fprintf(stderr, "Failed to create control interface\n"); return -1; } /* Install control commands */ ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_uptime); ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_debug_level); ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_max_conns); printf("Control interface listening on port 4249\n"); printf("Test with: echo 'GET 1 uptime' | nc localhost 4249\n"); printf(" echo 'SET 2 debug-level 5' | nc localhost 4249\n"); return 0; } ``` -------------------------------- ### Setup Multicast Receiver - C Source: https://context7.com/osmocom/libosmocore/llms.txt Initializes a UDP socket, binds it to a port, and subscribes to a multicast group. It also configures the socket to disable loopback for multicast messages. Returns the socket file descriptor or -1 on error. ```c #include /* Join multicast group */ int setup_multicast_receiver(const char *mcast_addr, uint16_t port) { int fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, port, OSMO_SOCK_F_BIND | OSMO_SOCK_F_UDP_REUSEADDR | OSMO_SOCK_F_NO_MCAST_ALL); if (fd < 0) return -1; osmo_sock_mcast_subscribe(fd, mcast_addr); osmo_sock_mcast_loop_set(fd, false); /* Don't receive own packets */ return fd; } ``` -------------------------------- ### C: Finite State Machine (FSM) Implementation Source: https://context7.com/osmocom/libosmocore/llms.txt Implements a connection-oriented finite state machine using the libosmocore FSM framework. It defines states (IDLE, CONNECTING, CONNECTED, DISCONNECTING), events (CONNECT_REQ, CONNECT_ACK, etc.), and corresponding action handlers for state transitions. Includes timer callbacks for handling timeouts and a main function demonstrating FSM setup and event dispatching. ```c #include #include /* FSM states */ enum conn_fsm_state { ST_IDLE, ST_CONNECTING, ST_CONNECTED, ST_DISCONNECTING, }; /* FSM events */ enum conn_fsm_event { EV_CONNECT_REQ, EV_CONNECT_ACK, EV_CONNECT_NACK, EV_DISCONNECT_REQ, EV_DISCONNECT_COMPLETE, EV_TIMEOUT, }; static const struct value_string conn_fsm_event_names[] = { OSMO_VALUE_STRING(EV_CONNECT_REQ), OSMO_VALUE_STRING(EV_CONNECT_ACK), OSMO_VALUE_STRING(EV_CONNECT_NACK), OSMO_VALUE_STRING(EV_DISCONNECT_REQ), OSMO_VALUE_STRING(EV_DISCONNECT_COMPLETE), { 0, NULL } }; /* State action handlers */ static void st_idle_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { case EV_CONNECT_REQ: LOGPFSML(fi, LOGL_INFO, "Initiating connection\n"); osmo_fsm_inst_state_chg(fi, ST_CONNECTING, 5, 1); /* 5s timeout, T1 */ break; default: LOGPFSML(fi, LOGL_ERROR, "Unexpected event %s\n", osmo_fsm_event_name(fi->fsm, event)); } } static void st_connecting_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { case EV_CONNECT_ACK: LOGPFSML(fi, LOGL_NOTICE, "Connection established\n"); osmo_fsm_inst_state_chg(fi, ST_CONNECTED, 0, 0); break; case EV_CONNECT_NACK: LOGPFSML(fi, LOGL_ERROR, "Connection rejected\n"); osmo_fsm_inst_state_chg(fi, ST_IDLE, 0, 0); break; } } static void st_connected_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) { if (event == EV_DISCONNECT_REQ) { LOGPFSML(fi, LOGL_INFO, "Disconnecting\n"); osmo_fsm_inst_state_chg(fi, ST_DISCONNECTING, 3, 2); } } /* Timer callback - called when state timeout expires */ static int conn_fsm_timer_cb(struct osmo_fsm_inst *fi) { LOGPFSML(fi, LOGL_ERROR, "Timeout T%d in state %s\n", fi->T, osmo_fsm_inst_state_name(fi)); switch (fi->state) { case ST_CONNECTING: osmo_fsm_inst_state_chg(fi, ST_IDLE, 0, 0); break; case ST_DISCONNECTING: osmo_fsm_inst_state_chg(fi, ST_IDLE, 0, 0); break; } return 0; /* Return 1 to terminate FSM */ } /* FSM state definitions */ static const struct osmo_fsm_state conn_fsm_states[] = { [ST_IDLE] = { .name = "IDLE", .in_event_mask = (1 << EV_CONNECT_REQ), .out_state_mask = (1 << ST_CONNECTING), .action = st_idle_action, }, [ST_CONNECTING] = { .name = "CONNECTING", .in_event_mask = (1 << EV_CONNECT_ACK) | (1 << EV_CONNECT_NACK), .out_state_mask = (1 << ST_CONNECTED) | (1 << ST_IDLE), .action = st_connecting_action, }, [ST_CONNECTED] = { .name = "CONNECTED", .in_event_mask = (1 << EV_DISCONNECT_REQ), .out_state_mask = (1 << ST_DISCONNECTING), .action = st_connected_action, }, [ST_DISCONNECTING] = { .name = "DISCONNECTING", .in_event_mask = (1 << EV_DISCONNECT_COMPLETE), .out_state_mask = (1 << ST_IDLE), }, }; /* FSM definition */ static struct osmo_fsm conn_fsm = { .name = "CONNECTION", .states = conn_fsm_states, .num_states = ARRAY_SIZE(conn_fsm_states), .event_names = conn_fsm_event_names, .log_subsys = DLGLOBAL, .timer_cb = conn_fsm_timer_cb, }; int main(void) { void *ctx = talloc_named_const(NULL, 0, "fsm_example"); /* Register FSM with the framework */ OSMO_ASSERT(osmo_fsm_register(&conn_fsm) == 0); /* Create FSM instance */ struct osmo_fsm_inst *fi = osmo_fsm_inst_alloc(&conn_fsm, ctx, NULL, LOGL_DEBUG, "conn-1"); OSMO_ASSERT(fi); /* Dispatch events to FSM */ osmo_fsm_inst_dispatch(fi, EV_CONNECT_REQ, NULL); osmo_fsm_inst_dispatch(fi, EV_CONNECT_ACK, NULL); osmo_fsm_inst_dispatch(fi, EV_DISCONNECT_REQ, NULL); /* Terminate FSM */ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); talloc_free(ctx); return 0; } ``` -------------------------------- ### Create TCP Server Socket - C Source: https://context7.com/osmocom/libosmocore/llms.txt Initializes and binds a TCP server socket to a specified IP address and port. It then starts listening for incoming connections. Returns a file descriptor on success or -1 on failure. ```c #include #include #include /* Create a TCP server */ int create_tcp_server(const char *bind_ip, uint16_t port) { int fd = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, bind_ip, port, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); if (fd < 0) return -1; listen(fd, 10); return fd; } ``` -------------------------------- ### Mobile Station Power Control Example Source: https://context7.com/osmocom/libosmocore/llms.txt Demonstrates functions related to mobile station power control in GSM. This includes converting between MS power classes and dBm, converting dBm to power control levels, and converting between RXLEV values and dBm. ```c #include #include /* Mobile station power control */ void power_control_example(void) { enum gsm_band band = GSM_BAND_900; /* Get MS power class in dBm */ int dbm = ms_class_gmsk_dbm(band, 4); /* Class 4 */ printf("MS class 4 on %s: %d dBm\n", gsm_band_name(band), dbm); /* Convert dBm to power control level */ uint8_t pwr_lvl = ms_pwr_ctl_lvl(band, 33); /* 33 dBm */ printf("33 dBm on %s = power level %u\n", gsm_band_name(band), pwr_lvl); /* Convert power level back to dBm */ int pwr_dbm = ms_pwr_dbm(band, pwr_lvl); printf("Power level %u on %s = %d dBm\n", pwr_lvl, gsm_band_name(band), pwr_dbm); /* RXLEV <-> dBm conversion */ uint8_t rxlev = 45; int rx_dbm = rxlev2dbm(rxlev); printf("RXLEV %u = %d dBm\n", rxlev, rx_dbm); uint8_t rxlev_back = dbm2rxlev(-75); printf("-75 dBm = RXLEV %u\n", rxlev_back); } ``` -------------------------------- ### GSM 7-bit SMS Encoding/Decoding Example Source: https://context7.com/osmocom/libosmocore/llms.txt Demonstrates the encoding of a string into GSM 7-bit format and decoding it back. It utilizes functions like gsm_7bit_encode_n and gsm_7bit_decode_n. Input is a string, and output is encoded bytes and decoded string. ```c #include #include /* GSM 7-bit SMS encoding/decoding */ void sms_encoding_example(void) { const char *text = "Hello GSM World!"; uint8_t encoded[256]; char decoded[256]; int octets_written; /* Encode text to GSM 7-bit */ int septets = gsm_7bit_encode_n(encoded, sizeof(encoded), text, &octets_written); printf("Encoded '%s': %d septets, %d octets\n", text, septets, octets_written); /* Decode GSM 7-bit back to text */ int chars = gsm_7bit_decode_n(decoded, sizeof(decoded), encoded, septets); printf("Decoded: '%s' (%d chars)\n", decoded, chars); } ``` -------------------------------- ### ARFCN and Frequency Conversion Example Source: https://context7.com/osmocom/libosmocore/llms.txt Provides examples for converting between Absolute Radio Frequency Channel Numbers (ARFCN) and GSM band frequencies. It includes functions to determine the GSM band from an ARFCN and to convert between ARFCN and frequency in units of 100kHz. ```c #include #include /* ARFCN and frequency conversion */ void frequency_example(void) { uint16_t arfcn = 100; /* GSM 900 channel */ /* Get band from ARFCN */ enum gsm_band band; if (gsm_arfcn2band_rc(arfcn, &band) == 0) { printf("ARFCN %u is in %s band\n", arfcn, gsm_band_name(band)); } /* Convert ARFCN to frequency (in units of 100kHz) */ uint16_t dl_freq = gsm_arfcn2freq10(arfcn, 0); /* Downlink */ uint16_t ul_freq = gsm_arfcn2freq10(arfcn, 1); /* Uplink */ printf("ARFCN %u: DL=%u.%u MHz, UL=%u.%u MHz\n", arfcn, dl_freq/10, dl_freq%10, ul_freq/10, ul_freq%10); /* Convert frequency back to ARFCN */ uint16_t arfcn_from_freq = gsm_freq102arfcn(dl_freq, 0); printf("Frequency %u.%u MHz -> ARFCN %u\n", dl_freq/10, dl_freq%10, arfcn_from_freq); } ``` -------------------------------- ### GSM Frame Number and Time Conversion Example Source: https://context7.com/osmocom/libosmocore/llms.txt Illustrates the conversion between GSM frame numbers (FN) and the GSM time structure. It includes functions to convert FN to a structured GSM time (gt) and back, as well as to obtain a human-readable string representation of the GSM time. ```c #include #include /* GSM frame number and time conversion */ void gsm_time_example(void) { uint32_t fn = 1234567; /* GSM frame number */ struct gsm_time gt; /* Convert FN to GSM time structure */ gsm_fn2gsmtime(>, fn); printf("FN %u = T1=%u T2=%u T3=%u TC=%u\n", fn, gt.t1, gt.t2, gt.t3, gt.tc); /* Convert back to frame number */ uint32_t fn_back = gsm_gsmtime2fn(>); printf("GSM time -> FN %u\n", fn_back); /* Get human-readable GSM time string */ char *time_str = osmo_dump_gsmtime(>); printf("GSM time: %s\n", time_str); } ``` -------------------------------- ### AMR Codec RTP Payload Handling in C Source: https://context7.com/osmocom/libosmocore/llms.txt Provides an example of encoding and decoding AMR RTP payloads according to RFC 4867. It covers setting codec mode requests and frame types, and interpreting the decoded frame information. ```c #include #include /* AMR codec RTP payload handling */ void amr_codec_example(void) { uint8_t rtp_payload[32]; /* Encode AMR RTP header (RFC 4867) */ uint8_t cmr = 7; /* Codec Mode Request: AMR 12.2 */ enum osmo_amr_type ft = AMR_12_2; /* Frame Type: 12.2 kbps */ enum osmo_amr_quality quality = AMR_GOOD; int header_len = osmo_amr_rtp_enc(rtp_payload, cmr, ft, quality); printf("AMR RTP header length: %d bytes\n", header_len); /* Decode AMR RTP payload */ uint8_t dec_cmr; int8_t dec_cmi; enum osmo_amr_type dec_ft; enum osmo_amr_quality dec_quality; int8_t sti; int rc = osmo_amr_rtp_dec(rtp_payload, header_len + 31, &dec_cmr, &dec_cmi, &dec_ft, &dec_quality, &sti); if (rc >= 0) { printf("AMR: CMR=%u, FT=%s, Quality=%s\n", dec_cmr, osmo_amr_type_name(dec_ft), dec_quality == AMR_GOOD ? "GOOD" : "BAD"); if (osmo_amr_is_speech(dec_ft)) { printf("Frame contains speech data\n"); printf("Bit length: %u bits\n", gsm690_bitlength[dec_ft]); } } } ``` -------------------------------- ### Implement Event-Driven I/O with Select Loop Source: https://context7.com/osmocom/libosmocore/llms.txt Demonstrates how to create a TCP server using osmo_sock_init and manage file descriptors with the osmo_select loop. It includes a callback function to handle read/write events and shows how to register and enable file descriptors. ```c #include #include #include #include static int socket_cb(struct osmo_fd *ofd, unsigned int what) { char buf[1024]; if (what & OSMO_FD_READ) { int rc = read(ofd->fd, buf, sizeof(buf) - 1); if (rc <= 0) { if (rc == 0) printf("Connection closed\n"); else printf("Read error: %s\n", strerror(errno)); osmo_fd_unregister(ofd); close(ofd->fd); return -1; } buf[rc] = '\0'; printf("Received: %s\n", buf); } if (what & OSMO_FD_WRITE) { const char *response = "ACK\n"; write(ofd->fd, response, strlen(response)); osmo_fd_write_disable(ofd); } return 0; } int main(void) { struct osmo_fd server_ofd; int fd = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, "127.0.0.1", 4242, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); if (fd < 0) return 1; osmo_fd_setup(&server_ofd, fd, OSMO_FD_READ, socket_cb, NULL, 0); if (osmo_fd_register(&server_ofd) < 0) { close(fd); return 1; } osmo_fd_read_enable(&server_ofd); osmo_fd_write_disable(&server_ofd); while (!osmo_select_shutdown_requested()) { osmo_select_main(0); } osmo_fd_close(&server_ofd); return 0; } ``` -------------------------------- ### Configure Hierarchical Logging Framework Source: https://context7.com/osmocom/libosmocore/llms.txt Shows how to define logging subsystems and categories, initialize the logging system, and add multiple targets like stderr and files. It demonstrates the use of LOGP and DEBUGP macros for categorized application diagnostics. ```c #include #include enum log_subsys { DAPP, DPROTOCOL, DNET }; static const struct log_info_cat app_log_categories[] = { [DAPP] = { .name = "DAPP", .description = "Application", .color = OSMO_LOGCOLOR_GREEN, .enabled = 1, .loglevel = LOGL_DEBUG }, [DPROTOCOL] = { .name = "DPROTOCOL", .description = "Protocol handling", .color = OSMO_LOGCOLOR_BLUE, .enabled = 1, .loglevel = LOGL_INFO }, [DNET] = { .name = "DNET", .description = "Network layer", .color = OSMO_LOGCOLOR_CYAN, .enabled = 1, .loglevel = LOGL_NOTICE }, }; static struct log_info app_log_info = { .cat = app_log_categories, .num_cat = ARRAY_SIZE(app_log_categories) }; int main(int argc, char **argv) { void *tall_ctx = talloc_named_const(NULL, 0, "logging_example"); osmo_init_logging2(tall_ctx, &app_log_info); struct log_target *stderr_target = log_target_create_stderr(); log_add_target(stderr_target); log_set_use_color(stderr_target, 1); log_set_log_level(stderr_target, LOGL_DEBUG); struct log_target *file_target = log_target_create_file("app.log"); if (file_target) log_add_target(file_target); LOGP(DAPP, LOGL_DEBUG, "Debug message: initializing\n"); LOGP(DNET, LOGL_ERROR, "Connection failed to %s:%d\n", "192.168.1.1", 5000); log_fini(); talloc_free(tall_ctx); return 0; } ``` -------------------------------- ### Create Unix Domain Socket Server - C Source: https://context7.com/osmocom/libosmocore/llms.txt Initializes a Unix domain stream socket and binds it to a specified file path. This allows for inter-process communication on the same host. ```c #include /* Create Unix domain socket */ int create_unix_server(const char *path) { return osmo_sock_unix_init(SOCK_STREAM, 0, path, OSMO_SOCK_F_BIND); } ``` -------------------------------- ### Create TCP Client Socket - C Source: https://context7.com/osmocom/libosmocore/llms.txt Initializes and connects a TCP client socket. It sets DSCP and priority options for the socket. Returns a file descriptor on success or -1 on failure. ```c #include #include #include /* Create a TCP client connection */ int create_tcp_client(const char *host, uint16_t port) { int fd = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, host, port, OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_NONBLOCK); if (fd < 0) return -1; /* Set socket options */ osmo_sock_set_dscp(fd, 46); /* EF for voice traffic */ osmo_sock_set_priority(fd, 6); return fd; } ``` -------------------------------- ### GSM Full Rate (FR) Codec Handling in C Source: https://context7.com/osmocom/libosmocore/llms.txt Demonstrates how to handle GSM Full Rate (FR) frames, including checking for SID frames and classifying them. It also shows how to use a silence frame for comfort noise. ```c #include #include /* GSM Full Rate (FR) codec handling */ void fr_codec_example(void) { /* GSM FR frame is 33 bytes (260 bits + 4 bit signature) */ uint8_t fr_frame[GSM_FR_BYTES]; /* Check if frame is a SID (Silence Insertion Descriptor) */ if (osmo_fr_check_sid(fr_frame, sizeof(fr_frame))) { printf("Frame is a valid SID frame\n"); } /* Classify SID frame */ enum osmo_gsm631_sid_class sid_class = osmo_fr_sid_classify(fr_frame); switch (sid_class) { case OSMO_GSM631_SID_CLASS_SPEECH: printf("Speech frame\n"); break; case OSMO_GSM631_SID_CLASS_VALID: printf("Valid SID frame\n"); break; case OSMO_GSM631_SID_CLASS_INVALID: printf("Invalid SID frame\n"); break; } /* Use silence frame for comfort noise */ printf("FR silence frame: %s\n", osmo_hexdump(osmo_gsm611_silence_frame, GSM_FR_BYTES)); } ``` -------------------------------- ### Message Buffer API (msgb) Source: https://context7.com/osmocom/libosmocore/llms.txt Demonstrates the usage of the msgb API for allocating, manipulating, and managing message buffers, including prepending and appending headers, and copying buffers. ```APIDOC ## Message Buffer API (msgb) ### Description The message buffer (msgb) API provides a flexible buffer structure for network protocol data handling, supporting layered protocol headers (L1-L4) with efficient memory management. It allows prepending headers (push), appending data (put), and removing data from either end. ### Method N/A (C library functions) ### Endpoint N/A (C library functions) ### Parameters N/A (C library functions) ### Request Example ```c #include #include /* Initialize msgb talloc context */ void *tall_ctx = talloc_named_const(NULL, 0, "msgb_example"); msgb_talloc_ctx_init(tall_ctx, 0); /* Allocate a message buffer with headroom for protocol headers */ struct msgb *msg = msgb_alloc_headroom(256, 64, "my_packet"); if (!msg) { fprintf(stderr, "Failed to allocate msgb\n"); return -1; } /* Add Layer 3 payload data at the tail */ uint8_t *data = msgb_put(msg, 10); memset(data, 0xAB, 10); msg->l3h = data; /* Mark L3 header position */ /* Prepend Layer 2 header */ uint8_t *l2h = msgb_push(msg, 4); l2h[0] = 0x01; /* Protocol discriminator */ l2h[1] = 0x02; /* Transaction ID */ l2h[2] = 0x03; /* Message type */ l2h[3] = msgb_l3len(msg); /* L3 length */ msg->l2h = l2h; /* Access message data */ printf("Total length: %u bytes\n", msgb_length(msg)); printf("L2 length: %u bytes\n", msgb_l2len(msg)); printf("L3 length: %u bytes\n", msgb_l3len(msg)); printf("Headroom: %d, Tailroom: %d\n", msgb_headroom(msg), msgb_tailroom(msg)); /* Remove data from front (e.g., after processing L2) */ msgb_pull(msg, 4); /* Copy message buffer */ struct msgb *copy = msgb_copy(msg, "msg_copy"); /* Enqueue/dequeue for message queues */ struct llist_head queue; INIT_LLIST_HEAD(&queue); msgb_enqueue(&queue, msg); struct msgb *dequeued = msgb_dequeue(&queue); /* Clean up */ msgb_free(copy); msgb_free(dequeued); ``` ### Response N/A (C library functions) ### Response Example N/A (C library functions) ``` -------------------------------- ### Timer API Source: https://context7.com/osmocom/libosmocore/llms.txt Illustrates the use of the Timer API for scheduling callbacks with millisecond precision, integrating with the select loop, and managing timer states. ```APIDOC ## Timer API ### Description The timer API provides millisecond-precision timers integrated with the select loop for scheduling callbacks. Timers are managed in a red-black tree for efficient nearest-timer lookups. ### Method N/A (C library functions) ### Endpoint N/A (C library functions) ### Parameters N/A (C library functions) ### Request Example ```c #include #include static int retry_count = 0; /* Timer callback function */ static void timeout_handler(void *data) { const char *name = (const char *)data; printf("Timer '%s' fired! Retry count: %d\n", name, ++retry_count); if (retry_count < 3) { /* Reschedule the timer */ struct osmo_timer_list *timer = (struct osmo_timer_list *) ((char *)data - offsetof(struct osmo_timer_list, data)); osmo_timer_schedule(timer, 2, 500000); /* 2.5 seconds */ } } int main(void) { struct osmo_timer_list my_timer; /* Setup and schedule timer */ osmo_timer_setup(&my_timer, timeout_handler, "retry_timer"); osmo_timer_schedule(&my_timer, 1, 0); /* Fire in 1 second */ /* Check if timer is pending */ if (osmo_timer_pending(&my_timer)) { printf("Timer is scheduled\n"); } /* Get remaining time */ struct timeval now, remaining; osmo_gettimeofday(&now, NULL); if (osmo_timer_remaining(&my_timer, &now, &remaining) == 0) { printf("Time remaining: %ld.%06ld seconds\n", remaining.tv_sec, remaining.tv_usec); } /* Main select loop - processes timers and file descriptors */ while (retry_count < 3) { osmo_select_main(0); /* 0 = blocking wait */ } /* Cancel timer if needed */ osmo_timer_del(&my_timer); return 0; } ``` ### Response N/A (C library functions) ### Response Example N/A (C library functions) ``` -------------------------------- ### Create UDP Socket - C Source: https://context7.com/osmocom/libosmocore/llms.txt Initializes a UDP socket that is both bound to a local address and port, and connected to a remote address and port. This is useful for sending and receiving UDP packets to/from a specific peer. ```c #include /* Create a bound+connected UDP socket */ int create_udp_socket(const char *local_ip, uint16_t local_port, const char *remote_ip, uint16_t remote_port) { return osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, local_ip, local_port, remote_ip, remote_port, OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT); } ``` -------------------------------- ### Generate GSM/UMTS Authentication Vectors (C) Source: https://context7.com/osmocom/libosmocore/llms.txt This C code snippet demonstrates how to generate authentication vectors using the libosmocore Authentication API. It covers setting up subscriber data, including keys and constants, and generating vectors for algorithms like Milenage. It also shows how to check for algorithm support. ```c #include #include /* Generate authentication vectors */ void auth_example(void) { /* Subscriber authentication data (from HLR/HSS) */ struct osmo_sub_auth_data2 aud = { .type = OSMO_AUTH_TYPE_UMTS, .algo = OSMO_AUTH_ALG_MILENAGE, }; /* Set subscriber key K (128-bit) */ uint8_t k[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; memcpy(aud.u.umts.k, k, 16); aud.u.umts.k_len = 16; /* Set OPc (operator-specific constant) */ uint8_t opc[16] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; memcpy(aud.u.umts.opc, opc, 16); aud.u.umts.opc_len = 16; aud.u.umts.opc_is_op = 0; /* This is OPc, not OP */ /* Set AMF (Authentication Management Field) */ aud.u.umts.amf[0] = 0x80; aud.u.umts.amf[1] = 0x00; /* Set sequence number */ aud.u.umts.sqn = 0x000000000001ULL; aud.u.umts.ind_bitlen = 5; /* Random challenge from network */ uint8_t rand[16] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}; /* Generate authentication vector */ struct osmo_auth_vector vec; memset(&vec, 0, sizeof(vec)); int rc = osmo_auth_gen_vec2(&vec, &aud, rand); if (rc < 0) { fprintf(stderr, "Authentication vector generation failed\n"); return; } /* Print authentication vector components */ printf("RAND: %s\n", osmo_hexdump(vec.rand, 16)); printf("AUTN: %s\n", osmo_hexdump(vec.autn, 16)); printf("CK: %s\n", osmo_hexdump(vec.ck, 16)); printf("IK: %s\n", osmo_hexdump(vec.ik, 16)); printf("RES: %s (len=%u)\n", osmo_hexdump(vec.res, vec.res_len), vec.res_len); printf("Kc: %s\n", osmo_hexdump(vec.kc, 8)); printf("SRES: %s\n", osmo_hexdump(vec.sres, 4)); /* Check algorithm support */ if (osmo_auth_supported(OSMO_AUTH_ALG_MILENAGE)) printf("Milenage algorithm is supported\n"); if (osmo_auth_supported(OSMO_AUTH_ALG_COMP128v1)) printf("COMP128v1 algorithm is supported\n"); } ``` -------------------------------- ### FSM Framework API Source: https://context7.com/osmocom/libosmocore/llms.txt Core functions for registering, allocating, dispatching events, and terminating FSM instances. ```APIDOC ## FSM Management API ### Description Functions to manage the lifecycle and event dispatching of Finite State Machines within the Osmocom framework. ### Methods - **osmo_fsm_register**: Registers an FSM definition with the framework. - **osmo_fsm_inst_alloc**: Allocates a new instance of a registered FSM. - **osmo_fsm_inst_dispatch**: Sends an event to an FSM instance to trigger state transitions. - **osmo_fsm_inst_state_chg**: Changes the current state of an FSM instance, optionally setting a timeout. - **osmo_fsm_inst_term**: Terminates an FSM instance. ### Usage Example ```c /* Register FSM */ osmo_fsm_register(&conn_fsm); /* Allocate Instance */ struct osmo_fsm_inst *fi = osmo_fsm_inst_alloc(&conn_fsm, ctx, NULL, LOGL_DEBUG, "conn-1"); /* Dispatch Event */ osmo_fsm_inst_dispatch(fi, EV_CONNECT_REQ, NULL); /* Terminate */ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); ``` ``` -------------------------------- ### Schedule Asynchronous Tasks with Timer API Source: https://context7.com/osmocom/libosmocore/llms.txt The Timer API allows for millisecond-precision scheduling of callbacks integrated with the main select loop. It uses a red-black tree for efficient management of multiple timers. ```c #include #include static int retry_count = 0; /* Timer callback function */ static void timeout_handler(void *data) { const char *name = (const char *)data; printf("Timer '%s' fired! Retry count: %d\n", name, ++retry_count); if (retry_count < 3) { /* Reschedule the timer */ struct osmo_timer_list *timer = (struct osmo_timer_list *) ((char *)data - offsetof(struct osmo_timer_list, data)); osmo_timer_schedule(timer, 2, 500000); /* 2.5 seconds */ } } int main(void) { struct osmo_timer_list my_timer; /* Setup and schedule timer */ osmo_timer_setup(&my_timer, timeout_handler, "retry_timer"); osmo_timer_schedule(&my_timer, 1, 0); /* Fire in 1 second */ /* Check if timer is pending */ if (osmo_timer_pending(&my_timer)) { printf("Timer is scheduled\n"); } /* Get remaining time */ struct timeval now, remaining; osmo_gettimeofday(&now, NULL); if (osmo_timer_remaining(&my_timer, &now, &remaining) == 0) { printf("Time remaining: %ld.%06ld seconds\n", remaining.tv_sec, remaining.tv_usec); } /* Main select loop - processes timers and file descriptors */ while (retry_count < 3) { osmo_select_main(0); /* 0 = blocking wait */ } /* Cancel timer if needed */ osmo_timer_del(&my_timer); return 0; } ``` -------------------------------- ### Print Socket Information - C Source: https://context7.com/osmocom/libosmocore/llms.txt Retrieves and prints the local and remote IP addresses and ports associated with a given socket file descriptor. It also prints a formatted string representing the socket's connection. ```c #include #include /* Get socket name information */ void print_socket_info(int fd) { char local_ip[64], remote_ip[64]; char local_port[16], remote_port[16]; osmo_sock_get_local_ip(fd, local_ip, sizeof(local_ip)); osmo_sock_get_local_ip_port(fd, local_port, sizeof(local_port)); osmo_sock_get_remote_ip(fd, remote_ip, sizeof(remote_ip)); osmo_sock_get_remote_ip_port(fd, remote_port, sizeof(remote_port)); printf("Socket: %s:%s <-> %s:%s\n", local_ip, local_port, remote_ip, remote_port); /* Get formatted socket name */ const char *name = osmo_sock_get_name2(fd); printf("Socket name: %s\n", name); } ``` -------------------------------- ### Manage Protocol Data with msgb API Source: https://context7.com/osmocom/libosmocore/llms.txt The msgb API provides a flexible buffer structure for handling network protocol data. It supports efficient memory management, layered header manipulation, and queueing operations. ```c #include #include /* Initialize msgb talloc context */ void *tall_ctx = talloc_named_const(NULL, 0, "msgb_example"); msgb_talloc_ctx_init(tall_ctx, 0); /* Allocate a message buffer with headroom for protocol headers */ struct msgb *msg = msgb_alloc_headroom(256, 64, "my_packet"); if (!msg) { fprintf(stderr, "Failed to allocate msgb\n"); return -1; } /* Add Layer 3 payload data at the tail */ uint8_t *data = msgb_put(msg, 10); memset(data, 0xAB, 10); msg->l3h = data; /* Mark L3 header position */ /* Prepend Layer 2 header */ uint8_t *l2h = msgb_push(msg, 4); l2h[0] = 0x01; /* Protocol discriminator */ l2h[1] = 0x02; /* Transaction ID */ l2h[2] = 0x03; /* Message type */ l2h[3] = msgb_l3len(msg); /* L3 length */ msg->l2h = l2h; /* Access message data */ printf("Total length: %u bytes\n", msgb_length(msg)); printf("L2 length: %u bytes\n", msgb_l2len(msg)); printf("L3 length: %u bytes\n", msgb_l3len(msg)); printf("Headroom: %d, Tailroom: %d\n", msgb_headroom(msg), msgb_tailroom(msg)); /* Remove data from front (e.g., after processing L2) */ msgb_pull(msg, 4); /* Copy message buffer */ struct msgb *copy = msgb_copy(msg, "msg_copy"); /* Enqueue/dequeue for message queues */ struct llist_head queue; INIT_LLIST_HEAD(&queue); msgb_enqueue(&queue, msg); struct msgb *dequeued = msgb_dequeue(&queue); /* Clean up */ msgb_free(copy); msgb_free(dequeued); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.