mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-10-23 08:12:01 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ed7c4fcfc3 | ||
|
3babd1a803 | ||
|
bc3f3b40fe | ||
|
fae09f4562 | ||
|
7c0fe31697 | ||
|
98aef217c6 | ||
|
e03e34f8bb | ||
|
ee6958c9a8 | ||
|
fbcf4a6f6c |
445
.clang-format
445
.clang-format
@@ -64,451 +64,6 @@ DisableFormat: false
|
|||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||||
|
|
||||||
# Taken from:
|
|
||||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
|
||||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
|
||||||
# | sort | uniq
|
|
||||||
ForEachMacros:
|
|
||||||
- 'apei_estatus_for_each_section'
|
|
||||||
- 'ata_for_each_dev'
|
|
||||||
- 'ata_for_each_link'
|
|
||||||
- '__ata_qc_for_each'
|
|
||||||
- 'ata_qc_for_each'
|
|
||||||
- 'ata_qc_for_each_raw'
|
|
||||||
- 'ata_qc_for_each_with_internal'
|
|
||||||
- 'ax25_for_each'
|
|
||||||
- 'ax25_uid_for_each'
|
|
||||||
- '__bio_for_each_bvec'
|
|
||||||
- 'bio_for_each_bvec'
|
|
||||||
- 'bio_for_each_bvec_all'
|
|
||||||
- 'bio_for_each_integrity_vec'
|
|
||||||
- '__bio_for_each_segment'
|
|
||||||
- 'bio_for_each_segment'
|
|
||||||
- 'bio_for_each_segment_all'
|
|
||||||
- 'bio_list_for_each'
|
|
||||||
- 'bip_for_each_vec'
|
|
||||||
- 'bitmap_for_each_clear_region'
|
|
||||||
- 'bitmap_for_each_set_region'
|
|
||||||
- 'blkg_for_each_descendant_post'
|
|
||||||
- 'blkg_for_each_descendant_pre'
|
|
||||||
- 'blk_queue_for_each_rl'
|
|
||||||
- 'bond_for_each_slave'
|
|
||||||
- 'bond_for_each_slave_rcu'
|
|
||||||
- 'bpf_for_each_spilled_reg'
|
|
||||||
- 'btree_for_each_safe128'
|
|
||||||
- 'btree_for_each_safe32'
|
|
||||||
- 'btree_for_each_safe64'
|
|
||||||
- 'btree_for_each_safel'
|
|
||||||
- 'card_for_each_dev'
|
|
||||||
- 'cgroup_taskset_for_each'
|
|
||||||
- 'cgroup_taskset_for_each_leader'
|
|
||||||
- 'cpufreq_for_each_entry'
|
|
||||||
- 'cpufreq_for_each_entry_idx'
|
|
||||||
- 'cpufreq_for_each_valid_entry'
|
|
||||||
- 'cpufreq_for_each_valid_entry_idx'
|
|
||||||
- 'css_for_each_child'
|
|
||||||
- 'css_for_each_descendant_post'
|
|
||||||
- 'css_for_each_descendant_pre'
|
|
||||||
- 'device_for_each_child_node'
|
|
||||||
- 'displayid_iter_for_each'
|
|
||||||
- 'dma_fence_chain_for_each'
|
|
||||||
- 'do_for_each_ftrace_op'
|
|
||||||
- 'drm_atomic_crtc_for_each_plane'
|
|
||||||
- 'drm_atomic_crtc_state_for_each_plane'
|
|
||||||
- 'drm_atomic_crtc_state_for_each_plane_state'
|
|
||||||
- 'drm_atomic_for_each_plane_damage'
|
|
||||||
- 'drm_client_for_each_connector_iter'
|
|
||||||
- 'drm_client_for_each_modeset'
|
|
||||||
- 'drm_connector_for_each_possible_encoder'
|
|
||||||
- 'drm_for_each_bridge_in_chain'
|
|
||||||
- 'drm_for_each_connector_iter'
|
|
||||||
- 'drm_for_each_crtc'
|
|
||||||
- 'drm_for_each_crtc_reverse'
|
|
||||||
- 'drm_for_each_encoder'
|
|
||||||
- 'drm_for_each_encoder_mask'
|
|
||||||
- 'drm_for_each_fb'
|
|
||||||
- 'drm_for_each_legacy_plane'
|
|
||||||
- 'drm_for_each_plane'
|
|
||||||
- 'drm_for_each_plane_mask'
|
|
||||||
- 'drm_for_each_privobj'
|
|
||||||
- 'drm_mm_for_each_hole'
|
|
||||||
- 'drm_mm_for_each_node'
|
|
||||||
- 'drm_mm_for_each_node_in_range'
|
|
||||||
- 'drm_mm_for_each_node_safe'
|
|
||||||
- 'flow_action_for_each'
|
|
||||||
- 'for_each_acpi_dev_match'
|
|
||||||
- 'for_each_active_dev_scope'
|
|
||||||
- 'for_each_active_drhd_unit'
|
|
||||||
- 'for_each_active_iommu'
|
|
||||||
- 'for_each_aggr_pgid'
|
|
||||||
- 'for_each_available_child_of_node'
|
|
||||||
- 'for_each_bio'
|
|
||||||
- 'for_each_board_func_rsrc'
|
|
||||||
- 'for_each_bvec'
|
|
||||||
- 'for_each_card_auxs'
|
|
||||||
- 'for_each_card_auxs_safe'
|
|
||||||
- 'for_each_card_components'
|
|
||||||
- 'for_each_card_dapms'
|
|
||||||
- 'for_each_card_pre_auxs'
|
|
||||||
- 'for_each_card_prelinks'
|
|
||||||
- 'for_each_card_rtds'
|
|
||||||
- 'for_each_card_rtds_safe'
|
|
||||||
- 'for_each_card_widgets'
|
|
||||||
- 'for_each_card_widgets_safe'
|
|
||||||
- 'for_each_cgroup_storage_type'
|
|
||||||
- 'for_each_child_of_node'
|
|
||||||
- 'for_each_clear_bit'
|
|
||||||
- 'for_each_clear_bit_from'
|
|
||||||
- 'for_each_cmsghdr'
|
|
||||||
- 'for_each_compatible_node'
|
|
||||||
- 'for_each_component_dais'
|
|
||||||
- 'for_each_component_dais_safe'
|
|
||||||
- 'for_each_comp_order'
|
|
||||||
- 'for_each_console'
|
|
||||||
- 'for_each_cpu'
|
|
||||||
- 'for_each_cpu_and'
|
|
||||||
- 'for_each_cpu_not'
|
|
||||||
- 'for_each_cpu_wrap'
|
|
||||||
- 'for_each_dapm_widgets'
|
|
||||||
- 'for_each_dev_addr'
|
|
||||||
- 'for_each_dev_scope'
|
|
||||||
- 'for_each_dma_cap_mask'
|
|
||||||
- 'for_each_dpcm_be'
|
|
||||||
- 'for_each_dpcm_be_rollback'
|
|
||||||
- 'for_each_dpcm_be_safe'
|
|
||||||
- 'for_each_dpcm_fe'
|
|
||||||
- 'for_each_drhd_unit'
|
|
||||||
- 'for_each_dss_dev'
|
|
||||||
- 'for_each_dtpm_table'
|
|
||||||
- 'for_each_efi_memory_desc'
|
|
||||||
- 'for_each_efi_memory_desc_in_map'
|
|
||||||
- 'for_each_element'
|
|
||||||
- 'for_each_element_extid'
|
|
||||||
- 'for_each_element_id'
|
|
||||||
- 'for_each_endpoint_of_node'
|
|
||||||
- 'for_each_evictable_lru'
|
|
||||||
- 'for_each_fib6_node_rt_rcu'
|
|
||||||
- 'for_each_fib6_walker_rt'
|
|
||||||
- 'for_each_free_mem_pfn_range_in_zone'
|
|
||||||
- 'for_each_free_mem_pfn_range_in_zone_from'
|
|
||||||
- 'for_each_free_mem_range'
|
|
||||||
- 'for_each_free_mem_range_reverse'
|
|
||||||
- 'for_each_func_rsrc'
|
|
||||||
- 'for_each_hstate'
|
|
||||||
- 'for_each_if'
|
|
||||||
- 'for_each_iommu'
|
|
||||||
- 'for_each_ip_tunnel_rcu'
|
|
||||||
- 'for_each_irq_nr'
|
|
||||||
- 'for_each_link_codecs'
|
|
||||||
- 'for_each_link_cpus'
|
|
||||||
- 'for_each_link_platforms'
|
|
||||||
- 'for_each_lru'
|
|
||||||
- 'for_each_matching_node'
|
|
||||||
- 'for_each_matching_node_and_match'
|
|
||||||
- 'for_each_member'
|
|
||||||
- 'for_each_memcg_cache_index'
|
|
||||||
- 'for_each_mem_pfn_range'
|
|
||||||
- '__for_each_mem_range'
|
|
||||||
- 'for_each_mem_range'
|
|
||||||
- '__for_each_mem_range_rev'
|
|
||||||
- 'for_each_mem_range_rev'
|
|
||||||
- 'for_each_mem_region'
|
|
||||||
- 'for_each_migratetype_order'
|
|
||||||
- 'for_each_msi_entry'
|
|
||||||
- 'for_each_msi_entry_safe'
|
|
||||||
- 'for_each_msi_vector'
|
|
||||||
- 'for_each_net'
|
|
||||||
- 'for_each_net_continue_reverse'
|
|
||||||
- 'for_each_netdev'
|
|
||||||
- 'for_each_netdev_continue'
|
|
||||||
- 'for_each_netdev_continue_rcu'
|
|
||||||
- 'for_each_netdev_continue_reverse'
|
|
||||||
- 'for_each_netdev_feature'
|
|
||||||
- 'for_each_netdev_in_bond_rcu'
|
|
||||||
- 'for_each_netdev_rcu'
|
|
||||||
- 'for_each_netdev_reverse'
|
|
||||||
- 'for_each_netdev_safe'
|
|
||||||
- 'for_each_net_rcu'
|
|
||||||
- 'for_each_new_connector_in_state'
|
|
||||||
- 'for_each_new_crtc_in_state'
|
|
||||||
- 'for_each_new_mst_mgr_in_state'
|
|
||||||
- 'for_each_new_plane_in_state'
|
|
||||||
- 'for_each_new_private_obj_in_state'
|
|
||||||
- 'for_each_node'
|
|
||||||
- 'for_each_node_by_name'
|
|
||||||
- 'for_each_node_by_type'
|
|
||||||
- 'for_each_node_mask'
|
|
||||||
- 'for_each_node_state'
|
|
||||||
- 'for_each_node_with_cpus'
|
|
||||||
- 'for_each_node_with_property'
|
|
||||||
- 'for_each_nonreserved_multicast_dest_pgid'
|
|
||||||
- 'for_each_of_allnodes'
|
|
||||||
- 'for_each_of_allnodes_from'
|
|
||||||
- 'for_each_of_cpu_node'
|
|
||||||
- 'for_each_of_pci_range'
|
|
||||||
- 'for_each_old_connector_in_state'
|
|
||||||
- 'for_each_old_crtc_in_state'
|
|
||||||
- 'for_each_old_mst_mgr_in_state'
|
|
||||||
- 'for_each_oldnew_connector_in_state'
|
|
||||||
- 'for_each_oldnew_crtc_in_state'
|
|
||||||
- 'for_each_oldnew_mst_mgr_in_state'
|
|
||||||
- 'for_each_oldnew_plane_in_state'
|
|
||||||
- 'for_each_oldnew_plane_in_state_reverse'
|
|
||||||
- 'for_each_oldnew_private_obj_in_state'
|
|
||||||
- 'for_each_old_plane_in_state'
|
|
||||||
- 'for_each_old_private_obj_in_state'
|
|
||||||
- 'for_each_online_cpu'
|
|
||||||
- 'for_each_online_node'
|
|
||||||
- 'for_each_online_pgdat'
|
|
||||||
- 'for_each_pci_bridge'
|
|
||||||
- 'for_each_pci_dev'
|
|
||||||
- 'for_each_pci_msi_entry'
|
|
||||||
- 'for_each_pcm_streams'
|
|
||||||
- 'for_each_physmem_range'
|
|
||||||
- 'for_each_populated_zone'
|
|
||||||
- 'for_each_possible_cpu'
|
|
||||||
- 'for_each_present_cpu'
|
|
||||||
- 'for_each_prime_number'
|
|
||||||
- 'for_each_prime_number_from'
|
|
||||||
- 'for_each_process'
|
|
||||||
- 'for_each_process_thread'
|
|
||||||
- 'for_each_prop_codec_conf'
|
|
||||||
- 'for_each_prop_dai_codec'
|
|
||||||
- 'for_each_prop_dai_cpu'
|
|
||||||
- 'for_each_prop_dlc_codecs'
|
|
||||||
- 'for_each_prop_dlc_cpus'
|
|
||||||
- 'for_each_prop_dlc_platforms'
|
|
||||||
- 'for_each_property_of_node'
|
|
||||||
- 'for_each_registered_fb'
|
|
||||||
- 'for_each_requested_gpio'
|
|
||||||
- 'for_each_requested_gpio_in_range'
|
|
||||||
- 'for_each_reserved_mem_range'
|
|
||||||
- 'for_each_reserved_mem_region'
|
|
||||||
- 'for_each_rtd_codec_dais'
|
|
||||||
- 'for_each_rtd_components'
|
|
||||||
- 'for_each_rtd_cpu_dais'
|
|
||||||
- 'for_each_rtd_dais'
|
|
||||||
- 'for_each_set_bit'
|
|
||||||
- 'for_each_set_bit_from'
|
|
||||||
- 'for_each_set_clump8'
|
|
||||||
- 'for_each_sg'
|
|
||||||
- 'for_each_sg_dma_page'
|
|
||||||
- 'for_each_sg_page'
|
|
||||||
- 'for_each_sgtable_dma_page'
|
|
||||||
- 'for_each_sgtable_dma_sg'
|
|
||||||
- 'for_each_sgtable_page'
|
|
||||||
- 'for_each_sgtable_sg'
|
|
||||||
- 'for_each_sibling_event'
|
|
||||||
- 'for_each_subelement'
|
|
||||||
- 'for_each_subelement_extid'
|
|
||||||
- 'for_each_subelement_id'
|
|
||||||
- '__for_each_thread'
|
|
||||||
- 'for_each_thread'
|
|
||||||
- 'for_each_unicast_dest_pgid'
|
|
||||||
- 'for_each_vsi'
|
|
||||||
- 'for_each_wakeup_source'
|
|
||||||
- 'for_each_zone'
|
|
||||||
- 'for_each_zone_zonelist'
|
|
||||||
- 'for_each_zone_zonelist_nodemask'
|
|
||||||
- 'fwnode_for_each_available_child_node'
|
|
||||||
- 'fwnode_for_each_child_node'
|
|
||||||
- 'fwnode_graph_for_each_endpoint'
|
|
||||||
- 'gadget_for_each_ep'
|
|
||||||
- 'genradix_for_each'
|
|
||||||
- 'genradix_for_each_from'
|
|
||||||
- 'hash_for_each'
|
|
||||||
- 'hash_for_each_possible'
|
|
||||||
- 'hash_for_each_possible_rcu'
|
|
||||||
- 'hash_for_each_possible_rcu_notrace'
|
|
||||||
- 'hash_for_each_possible_safe'
|
|
||||||
- 'hash_for_each_rcu'
|
|
||||||
- 'hash_for_each_safe'
|
|
||||||
- 'hctx_for_each_ctx'
|
|
||||||
- 'hlist_bl_for_each_entry'
|
|
||||||
- 'hlist_bl_for_each_entry_rcu'
|
|
||||||
- 'hlist_bl_for_each_entry_safe'
|
|
||||||
- 'hlist_for_each'
|
|
||||||
- 'hlist_for_each_entry'
|
|
||||||
- 'hlist_for_each_entry_continue'
|
|
||||||
- 'hlist_for_each_entry_continue_rcu'
|
|
||||||
- 'hlist_for_each_entry_continue_rcu_bh'
|
|
||||||
- 'hlist_for_each_entry_from'
|
|
||||||
- 'hlist_for_each_entry_from_rcu'
|
|
||||||
- 'hlist_for_each_entry_rcu'
|
|
||||||
- 'hlist_for_each_entry_rcu_bh'
|
|
||||||
- 'hlist_for_each_entry_rcu_notrace'
|
|
||||||
- 'hlist_for_each_entry_safe'
|
|
||||||
- 'hlist_for_each_entry_srcu'
|
|
||||||
- '__hlist_for_each_rcu'
|
|
||||||
- 'hlist_for_each_safe'
|
|
||||||
- 'hlist_nulls_for_each_entry'
|
|
||||||
- 'hlist_nulls_for_each_entry_from'
|
|
||||||
- 'hlist_nulls_for_each_entry_rcu'
|
|
||||||
- 'hlist_nulls_for_each_entry_safe'
|
|
||||||
- 'i3c_bus_for_each_i2cdev'
|
|
||||||
- 'i3c_bus_for_each_i3cdev'
|
|
||||||
- 'ide_host_for_each_port'
|
|
||||||
- 'ide_port_for_each_dev'
|
|
||||||
- 'ide_port_for_each_present_dev'
|
|
||||||
- 'idr_for_each_entry'
|
|
||||||
- 'idr_for_each_entry_continue'
|
|
||||||
- 'idr_for_each_entry_continue_ul'
|
|
||||||
- 'idr_for_each_entry_ul'
|
|
||||||
- 'in_dev_for_each_ifa_rcu'
|
|
||||||
- 'in_dev_for_each_ifa_rtnl'
|
|
||||||
- 'inet_bind_bucket_for_each'
|
|
||||||
- 'inet_lhash2_for_each_icsk_rcu'
|
|
||||||
- 'key_for_each'
|
|
||||||
- 'key_for_each_safe'
|
|
||||||
- 'klp_for_each_func'
|
|
||||||
- 'klp_for_each_func_safe'
|
|
||||||
- 'klp_for_each_func_static'
|
|
||||||
- 'klp_for_each_object'
|
|
||||||
- 'klp_for_each_object_safe'
|
|
||||||
- 'klp_for_each_object_static'
|
|
||||||
- 'kunit_suite_for_each_test_case'
|
|
||||||
- 'kvm_for_each_memslot'
|
|
||||||
- 'kvm_for_each_vcpu'
|
|
||||||
- 'list_for_each'
|
|
||||||
- 'list_for_each_codec'
|
|
||||||
- 'list_for_each_codec_safe'
|
|
||||||
- 'list_for_each_continue'
|
|
||||||
- 'list_for_each_entry'
|
|
||||||
- 'list_for_each_entry_continue'
|
|
||||||
- 'list_for_each_entry_continue_rcu'
|
|
||||||
- 'list_for_each_entry_continue_reverse'
|
|
||||||
- 'list_for_each_entry_from'
|
|
||||||
- 'list_for_each_entry_from_rcu'
|
|
||||||
- 'list_for_each_entry_from_reverse'
|
|
||||||
- 'list_for_each_entry_lockless'
|
|
||||||
- 'list_for_each_entry_rcu'
|
|
||||||
- 'list_for_each_entry_reverse'
|
|
||||||
- 'list_for_each_entry_safe'
|
|
||||||
- 'list_for_each_entry_safe_continue'
|
|
||||||
- 'list_for_each_entry_safe_from'
|
|
||||||
- 'list_for_each_entry_safe_reverse'
|
|
||||||
- 'list_for_each_entry_srcu'
|
|
||||||
- 'list_for_each_prev'
|
|
||||||
- 'list_for_each_prev_safe'
|
|
||||||
- 'list_for_each_safe'
|
|
||||||
- 'llist_for_each'
|
|
||||||
- 'llist_for_each_entry'
|
|
||||||
- 'llist_for_each_entry_safe'
|
|
||||||
- 'llist_for_each_safe'
|
|
||||||
- 'mci_for_each_dimm'
|
|
||||||
- 'media_device_for_each_entity'
|
|
||||||
- 'media_device_for_each_intf'
|
|
||||||
- 'media_device_for_each_link'
|
|
||||||
- 'media_device_for_each_pad'
|
|
||||||
- 'nanddev_io_for_each_page'
|
|
||||||
- 'netdev_for_each_lower_dev'
|
|
||||||
- 'netdev_for_each_lower_private'
|
|
||||||
- 'netdev_for_each_lower_private_rcu'
|
|
||||||
- 'netdev_for_each_mc_addr'
|
|
||||||
- 'netdev_for_each_uc_addr'
|
|
||||||
- 'netdev_for_each_upper_dev_rcu'
|
|
||||||
- 'netdev_hw_addr_list_for_each'
|
|
||||||
- 'nft_rule_for_each_expr'
|
|
||||||
- 'nla_for_each_attr'
|
|
||||||
- 'nla_for_each_nested'
|
|
||||||
- 'nlmsg_for_each_attr'
|
|
||||||
- 'nlmsg_for_each_msg'
|
|
||||||
- 'nr_neigh_for_each'
|
|
||||||
- 'nr_neigh_for_each_safe'
|
|
||||||
- 'nr_node_for_each'
|
|
||||||
- 'nr_node_for_each_safe'
|
|
||||||
- 'of_for_each_phandle'
|
|
||||||
- 'of_property_for_each_string'
|
|
||||||
- 'of_property_for_each_u32'
|
|
||||||
- 'pci_bus_for_each_resource'
|
|
||||||
- 'pcl_for_each_chunk'
|
|
||||||
- 'pcl_for_each_segment'
|
|
||||||
- 'pcm_for_each_format'
|
|
||||||
- 'ping_portaddr_for_each_entry'
|
|
||||||
- 'plist_for_each'
|
|
||||||
- 'plist_for_each_continue'
|
|
||||||
- 'plist_for_each_entry'
|
|
||||||
- 'plist_for_each_entry_continue'
|
|
||||||
- 'plist_for_each_entry_safe'
|
|
||||||
- 'plist_for_each_safe'
|
|
||||||
- 'pnp_for_each_card'
|
|
||||||
- 'pnp_for_each_dev'
|
|
||||||
- 'protocol_for_each_card'
|
|
||||||
- 'protocol_for_each_dev'
|
|
||||||
- 'queue_for_each_hw_ctx'
|
|
||||||
- 'radix_tree_for_each_slot'
|
|
||||||
- 'radix_tree_for_each_tagged'
|
|
||||||
- 'rb_for_each'
|
|
||||||
- 'rbtree_postorder_for_each_entry_safe'
|
|
||||||
- 'rdma_for_each_block'
|
|
||||||
- 'rdma_for_each_port'
|
|
||||||
- 'rdma_umem_for_each_dma_block'
|
|
||||||
- 'resource_list_for_each_entry'
|
|
||||||
- 'resource_list_for_each_entry_safe'
|
|
||||||
- 'rhl_for_each_entry_rcu'
|
|
||||||
- 'rhl_for_each_rcu'
|
|
||||||
- 'rht_for_each'
|
|
||||||
- 'rht_for_each_entry'
|
|
||||||
- 'rht_for_each_entry_from'
|
|
||||||
- 'rht_for_each_entry_rcu'
|
|
||||||
- 'rht_for_each_entry_rcu_from'
|
|
||||||
- 'rht_for_each_entry_safe'
|
|
||||||
- 'rht_for_each_from'
|
|
||||||
- 'rht_for_each_rcu'
|
|
||||||
- 'rht_for_each_rcu_from'
|
|
||||||
- '__rq_for_each_bio'
|
|
||||||
- 'rq_for_each_bvec'
|
|
||||||
- 'rq_for_each_segment'
|
|
||||||
- 'scsi_for_each_prot_sg'
|
|
||||||
- 'scsi_for_each_sg'
|
|
||||||
- 'sctp_for_each_hentry'
|
|
||||||
- 'sctp_skb_for_each'
|
|
||||||
- 'shdma_for_each_chan'
|
|
||||||
- '__shost_for_each_device'
|
|
||||||
- 'shost_for_each_device'
|
|
||||||
- 'sk_for_each'
|
|
||||||
- 'sk_for_each_bound'
|
|
||||||
- 'sk_for_each_entry_offset_rcu'
|
|
||||||
- 'sk_for_each_from'
|
|
||||||
- 'sk_for_each_rcu'
|
|
||||||
- 'sk_for_each_safe'
|
|
||||||
- 'sk_nulls_for_each'
|
|
||||||
- 'sk_nulls_for_each_from'
|
|
||||||
- 'sk_nulls_for_each_rcu'
|
|
||||||
- 'snd_array_for_each'
|
|
||||||
- 'snd_pcm_group_for_each_entry'
|
|
||||||
- 'snd_soc_dapm_widget_for_each_path'
|
|
||||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
|
||||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
|
||||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
|
||||||
- 'tb_property_for_each'
|
|
||||||
- 'tcf_exts_for_each_action'
|
|
||||||
- 'udp_portaddr_for_each_entry'
|
|
||||||
- 'udp_portaddr_for_each_entry_rcu'
|
|
||||||
- 'usb_hub_for_each_child'
|
|
||||||
- 'v4l2_device_for_each_subdev'
|
|
||||||
- 'v4l2_m2m_for_each_dst_buf'
|
|
||||||
- 'v4l2_m2m_for_each_dst_buf_safe'
|
|
||||||
- 'v4l2_m2m_for_each_src_buf'
|
|
||||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
|
||||||
- 'virtio_device_for_each_vq'
|
|
||||||
- 'while_for_each_ftrace_op'
|
|
||||||
- 'xa_for_each'
|
|
||||||
- 'xa_for_each_marked'
|
|
||||||
- 'xa_for_each_range'
|
|
||||||
- 'xa_for_each_start'
|
|
||||||
- 'xas_for_each'
|
|
||||||
- 'xas_for_each_conflict'
|
|
||||||
- 'xas_for_each_marked'
|
|
||||||
- 'xbc_array_for_each_value'
|
|
||||||
- 'xbc_for_each_key_value'
|
|
||||||
- 'xbc_node_for_each_array_value'
|
|
||||||
- 'xbc_node_for_each_child'
|
|
||||||
- 'xbc_node_for_each_key_value'
|
|
||||||
- 'zorro_for_each_dev'
|
|
||||||
- 'for_each_line'
|
|
||||||
- 'for_each_non_empty_line'
|
|
||||||
|
|
||||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '.*'
|
- Regex: '.*'
|
||||||
|
@@ -15,10 +15,6 @@
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
*/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@@ -91,6 +91,11 @@ the IP related aspects is nearly identical to the configuration of the virtual
|
|||||||
trunk. However, it is important that the user assigns one of the E1 line numbers
|
trunk. However, it is important that the user assigns one of the E1 line numbers
|
||||||
that were configured under the e1_input node.
|
that were configured under the e1_input node.
|
||||||
|
|
||||||
|
NOTE: The endpoint name that is used on MGCP level will include the trunk number,
|
||||||
|
not the E1 line number. For simplicity (and compatibility with OsmoBSC) it is
|
||||||
|
recommended to use equal numbers for trunk and E1 line. However, if required any
|
||||||
|
E1 line can be mapped flexible on any trunk as long as the mapping is bijective.
|
||||||
|
|
||||||
.Example: A typical configuration with one E1 trunk
|
.Example: A typical configuration with one E1 trunk
|
||||||
----
|
----
|
||||||
e1_input
|
e1_input
|
||||||
|
@@ -17,3 +17,4 @@ int mgcp_codec_decide(struct mgcp_conn_rtp *conn);
|
|||||||
int mgcp_codec_pt_translate(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst, int payload_type);
|
int mgcp_codec_pt_translate(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst, int payload_type);
|
||||||
const struct mgcp_rtp_codec *mgcp_codec_pt_find_by_subtype_name(struct mgcp_conn_rtp *conn,
|
const struct mgcp_rtp_codec *mgcp_codec_pt_find_by_subtype_name(struct mgcp_conn_rtp *conn,
|
||||||
const char *subtype_name, unsigned int match_nr);
|
const char *subtype_name, unsigned int match_nr);
|
||||||
|
bool mgcp_codec_amr_is_octet_aligned(const struct mgcp_rtp_codec *codec);
|
||||||
|
52
include/osmocom/mgcp/mgcp_threads_queue.h
Normal file
52
include/osmocom/mgcp/mgcp_threads_queue.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* Author: Eric Wild
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct spsc {
|
||||||
|
atomic_uint readptr;
|
||||||
|
atomic_uint writeptr;
|
||||||
|
|
||||||
|
int efd_r, efd_w; /* eventfds used to block/notify readers/writers */
|
||||||
|
|
||||||
|
int count;
|
||||||
|
int size_per_buf;
|
||||||
|
|
||||||
|
void *buf; /* buffer size count*size_per_buf */
|
||||||
|
uintptr_t data[0]; /* count sized array of pointers to size_per_buf chunks in buf array*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qchan {
|
||||||
|
struct spsc *a;
|
||||||
|
struct spsc *b;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool spsc_push(struct spsc *q, void *elem);
|
||||||
|
bool spsc_pop(struct spsc *q, void *elem);
|
||||||
|
ssize_t spsc_prep_pop(struct spsc *q);
|
||||||
|
int spsc_get_a_rdfd(struct qchan *q);
|
||||||
|
|
||||||
|
struct qchan spsc_chan_init(void *talloc_ctx, unsigned int count, unsigned int size_per_buf);
|
||||||
|
struct qchan spsc_chan_init_ex(void *talloc_ctx, unsigned int count, unsigned int size_per_buf, bool blockr_a,
|
||||||
|
bool blockw_a, bool blockr_b, bool blockw_b);
|
||||||
|
void spsc_chan_close(struct qchan *q);
|
@@ -14,10 +14,6 @@
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline int val_seg(int val)
|
static inline int val_seg(int val)
|
||||||
|
@@ -355,7 +355,7 @@ int mgcp_codec_decide(struct mgcp_conn_rtp *conn)
|
|||||||
*
|
*
|
||||||
* https://tools.ietf.org/html/rfc4867
|
* https://tools.ietf.org/html/rfc4867
|
||||||
*/
|
*/
|
||||||
static bool amr_is_octet_aligned(const struct mgcp_rtp_codec *codec)
|
bool mgcp_codec_amr_is_octet_aligned(const struct mgcp_rtp_codec *codec)
|
||||||
{
|
{
|
||||||
if (!codec->param_present)
|
if (!codec->param_present)
|
||||||
return false;
|
return false;
|
||||||
@@ -378,10 +378,10 @@ static bool codecs_same(struct mgcp_rtp_codec *codec_a, struct mgcp_rtp_codec *c
|
|||||||
return false;
|
return false;
|
||||||
if (strcmp(codec_a->subtype_name, codec_b->subtype_name))
|
if (strcmp(codec_a->subtype_name, codec_b->subtype_name))
|
||||||
return false;
|
return false;
|
||||||
if (!strcmp(codec_a->subtype_name, "AMR")) {
|
|
||||||
if (amr_is_octet_aligned(codec_a) != amr_is_octet_aligned(codec_b))
|
/* Note: AMR allows to set the RTP payload format to octet-aligned or bandwith-efficient (octet-aligned=0)
|
||||||
return false;
|
* via SDP. This difference concerns payload format only, but not the actual codec. It is not a difference
|
||||||
}
|
* within the meaning of this function. */
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -325,6 +325,11 @@ void mgcp_conn_free_oldest(struct mgcp_endpoint *endp)
|
|||||||
|
|
||||||
/*! free all connections at once.
|
/*! free all connections at once.
|
||||||
* \param[in] endp associated endpoint */
|
* \param[in] endp associated endpoint */
|
||||||
|
#if defined(__has_attribute)
|
||||||
|
#if __has_attribute(no_sanitize)
|
||||||
|
__attribute__((no_sanitize("undefined"))) /* ubsan detects a misaligned load */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
void mgcp_conn_free_all(struct mgcp_endpoint *endp)
|
void mgcp_conn_free_all(struct mgcp_endpoint *endp)
|
||||||
{
|
{
|
||||||
struct mgcp_conn *conn;
|
struct mgcp_conn *conn;
|
||||||
|
@@ -97,10 +97,6 @@ struct mgcp_request {
|
|||||||
/* function pointer to the request handler */
|
/* function pointer to the request handler */
|
||||||
struct msgb *(*handle_request)(struct mgcp_request_data *data);
|
struct msgb *(*handle_request)(struct mgcp_request_data *data);
|
||||||
|
|
||||||
/* true if the request requires an endpoint, false if only a trunk
|
|
||||||
* is sufficient. (corner cases, e.g. wildcarded DLCX) */
|
|
||||||
bool require_endp;
|
|
||||||
|
|
||||||
/* a human readable name that describes the request */
|
/* a human readable name that describes the request */
|
||||||
char *debug_name;
|
char *debug_name;
|
||||||
};
|
};
|
||||||
@@ -112,32 +108,34 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *data);
|
|||||||
static struct msgb *handle_rsip(struct mgcp_request_data *data);
|
static struct msgb *handle_rsip(struct mgcp_request_data *data);
|
||||||
static struct msgb *handle_noti_req(struct mgcp_request_data *data);
|
static struct msgb *handle_noti_req(struct mgcp_request_data *data);
|
||||||
static const struct mgcp_request mgcp_requests[] = {
|
static const struct mgcp_request mgcp_requests[] = {
|
||||||
{ .name = "AUEP",
|
{ .name = "AUEP", .handle_request = handle_audit_endpoint, .debug_name = "AuditEndpoint" },
|
||||||
.handle_request = handle_audit_endpoint,
|
{
|
||||||
.debug_name = "AuditEndpoint",
|
.name = "CRCX",
|
||||||
.require_endp = true },
|
.handle_request = handle_create_con,
|
||||||
{ .name = "CRCX",
|
.debug_name = "CreateConnection",
|
||||||
.handle_request = handle_create_con,
|
},
|
||||||
.debug_name = "CreateConnection",
|
{
|
||||||
.require_endp = true },
|
.name = "DLCX",
|
||||||
{ .name = "DLCX",
|
.handle_request = handle_delete_con,
|
||||||
.handle_request = handle_delete_con,
|
.debug_name = "DeleteConnection",
|
||||||
.debug_name = "DeleteConnection",
|
},
|
||||||
.require_endp = false },
|
{
|
||||||
{ .name = "MDCX",
|
.name = "MDCX",
|
||||||
.handle_request = handle_modify_con,
|
.handle_request = handle_modify_con,
|
||||||
.debug_name = "ModifiyConnection",
|
.debug_name = "ModifiyConnection",
|
||||||
.require_endp = true },
|
},
|
||||||
{ .name = "RQNT",
|
{
|
||||||
.handle_request = handle_noti_req,
|
.name = "RQNT",
|
||||||
.debug_name = "NotificationRequest",
|
.handle_request = handle_noti_req,
|
||||||
.require_endp = true },
|
.debug_name = "NotificationRequest",
|
||||||
|
},
|
||||||
|
|
||||||
/* SPEC extension */
|
/* SPEC extension */
|
||||||
{ .name = "RSIP",
|
{
|
||||||
.handle_request = handle_rsip,
|
.name = "RSIP",
|
||||||
.debug_name = "ReSetInProgress",
|
.handle_request = handle_rsip,
|
||||||
.require_endp = true },
|
.debug_name = "ReSetInProgress",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initalize transcoder */
|
/* Initalize transcoder */
|
||||||
@@ -173,12 +171,15 @@ static int setup_rtp_processing(struct mgcp_endpoint *endp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function to allocate some memory for responses and retransmissions */
|
/* Helper function to allocate some memory for responses and retransmissions */
|
||||||
static struct msgb *mgcp_msgb_alloc(void)
|
static struct msgb *mgcp_msgb_alloc(void *ctx)
|
||||||
{
|
{
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
|
msg = msgb_alloc_headroom_c(ctx, 4096, 128, "MGCP msg");
|
||||||
if (!msg)
|
|
||||||
|
if (!msg) {
|
||||||
LOGP(DLMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
|
LOGP(DLMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
@@ -186,7 +187,7 @@ static struct msgb *mgcp_msgb_alloc(void)
|
|||||||
/* Helper function for do_retransmission() and create_resp() */
|
/* Helper function for do_retransmission() and create_resp() */
|
||||||
static struct msgb *create_retransmission_response(const struct mgcp_endpoint *endp)
|
static struct msgb *create_retransmission_response(const struct mgcp_endpoint *endp)
|
||||||
{
|
{
|
||||||
struct msgb *msg = mgcp_msgb_alloc();
|
struct msgb *msg = mgcp_msgb_alloc(endp->trunk);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -196,15 +197,14 @@ static struct msgb *create_retransmission_response(const struct mgcp_endpoint *e
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct msgb *create_resp(struct mgcp_endpoint *endp, int code,
|
static struct msgb *create_resp(void *msgctx, struct mgcp_endpoint *endp, int code, const char *txt, const char *msg,
|
||||||
const char *txt, const char *msg,
|
const char *trans, const char *param, const char *sdp)
|
||||||
const char *trans, const char *param,
|
|
||||||
const char *sdp)
|
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
struct msgb *res;
|
struct msgb *res;
|
||||||
|
|
||||||
res = mgcp_msgb_alloc();
|
OSMO_ASSERT(msgctx != 0);
|
||||||
|
res = mgcp_msgb_alloc(msgctx);
|
||||||
if (!res)
|
if (!res)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -236,26 +236,22 @@ static struct msgb *create_resp(struct mgcp_endpoint *endp, int code,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct msgb *create_ok_resp_with_param(struct mgcp_endpoint *endp,
|
static struct msgb *create_ok_resp_with_param(void *msgctx, struct mgcp_endpoint *endp, int code, const char *msg,
|
||||||
int code, const char *msg,
|
const char *trans, const char *param)
|
||||||
const char *trans,
|
|
||||||
const char *param)
|
|
||||||
{
|
{
|
||||||
return create_resp(endp, code, " OK", msg, trans, param, NULL);
|
return create_resp(msgctx, endp, code, " OK", msg, trans, param, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct msgb *create_ok_response(struct mgcp_endpoint *endp,
|
static struct msgb *create_ok_response(void *msgctx, struct mgcp_endpoint *endp, int code, const char *msg,
|
||||||
int code, const char *msg,
|
|
||||||
const char *trans)
|
const char *trans)
|
||||||
{
|
{
|
||||||
return create_ok_resp_with_param(endp, code, msg, trans, NULL);
|
return create_ok_resp_with_param(msgctx, endp, code, msg, trans, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct msgb *create_err_response(struct mgcp_endpoint *endp,
|
static struct msgb *create_err_response(void *msgctx, struct mgcp_endpoint *endp, int code, const char *msg,
|
||||||
int code, const char *msg,
|
|
||||||
const char *trans)
|
const char *trans)
|
||||||
{
|
{
|
||||||
return create_resp(endp, code, " FAIL", msg, trans, NULL, NULL);
|
return create_resp(msgctx, endp, code, " FAIL", msg, trans, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Format MGCP response string (with SDP attached) */
|
/* Format MGCP response string (with SDP attached) */
|
||||||
@@ -278,7 +274,7 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
|||||||
int rc;
|
int rc;
|
||||||
struct msgb *result;
|
struct msgb *result;
|
||||||
|
|
||||||
sdp = msgb_alloc_headroom(4096, 128, "sdp record");
|
sdp = msgb_alloc_headroom_c(endp->trunk, 4096, 128, "sdp record");
|
||||||
if (!sdp)
|
if (!sdp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -309,7 +305,7 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
|||||||
rc = mgcp_write_response_sdp(endp, conn, sdp, addr);
|
rc = mgcp_write_response_sdp(endp, conn, sdp, addr);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto error;
|
goto error;
|
||||||
result = create_resp(endp, 200, " OK", msg, trans_id, NULL, (char*) sdp->data);
|
result = create_resp(endp->trunk, endp, 200, " OK", msg, trans_id, NULL, (char *)sdp->data);
|
||||||
msgb_free(sdp);
|
msgb_free(sdp);
|
||||||
return result;
|
return result;
|
||||||
error:
|
error:
|
||||||
@@ -376,7 +372,7 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
|
|||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
LOGP(DLMGCP, LOGL_ERROR, "%s: failed to parse MCGP message\n", rq.name);
|
LOGP(DLMGCP, LOGL_ERROR, "%s: failed to parse MCGP message\n", rq.name);
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_FAIL_MSG_PARSE));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_FAIL_MSG_PARSE));
|
||||||
return create_err_response(NULL, -rc, rq.name, "000000");
|
return create_err_response(cfg, NULL, -rc, rq.name, "000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate endpoint and trunk, if no endpoint can be located try at least to identify the trunk. */
|
/* Locate endpoint and trunk, if no endpoint can be located try at least to identify the trunk. */
|
||||||
@@ -397,7 +393,7 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
|
|||||||
if (!rq.trunk) {
|
if (!rq.trunk) {
|
||||||
LOGP(DLMGCP, LOGL_ERROR, "%s: failed to identify trunk for endpoint \"%s\" -- abort\n",
|
LOGP(DLMGCP, LOGL_ERROR, "%s: failed to identify trunk for endpoint \"%s\" -- abort\n",
|
||||||
rq.name, pdata.epname);
|
rq.name, pdata.epname);
|
||||||
return create_err_response(NULL, -rq.mgcp_cause, rq.name, pdata.trans);
|
return create_err_response(cfg, NULL, -rq.mgcp_cause, rq.name, pdata.trans);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* If the endpoint name suggests that the request refers to a specific endpoint, then the
|
/* If the endpoint name suggests that the request refers to a specific endpoint, then the
|
||||||
@@ -405,7 +401,7 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
|
|||||||
LOGP(DLMGCP, LOGL_NOTICE,
|
LOGP(DLMGCP, LOGL_NOTICE,
|
||||||
"%s: cannot find endpoint \"%s\", cause=%d -- abort\n", rq.name,
|
"%s: cannot find endpoint \"%s\", cause=%d -- abort\n", rq.name,
|
||||||
pdata.epname, -rq.mgcp_cause);
|
pdata.epname, -rq.mgcp_cause);
|
||||||
return create_err_response(NULL, -rq.mgcp_cause, rq.name, pdata.trans);
|
return create_err_response(cfg, NULL, -rq.mgcp_cause, rq.name, pdata.trans);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
osmo_strlcpy(debug_last_endpoint_name, rq.endp->name, sizeof(debug_last_endpoint_name));
|
osmo_strlcpy(debug_last_endpoint_name, rq.endp->name, sizeof(debug_last_endpoint_name));
|
||||||
@@ -422,15 +418,6 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
|
|||||||
/* Find an appropriate handler for the current request and execute it */
|
/* Find an appropriate handler for the current request and execute it */
|
||||||
for (i = 0; i < ARRAY_SIZE(mgcp_requests); i++) {
|
for (i = 0; i < ARRAY_SIZE(mgcp_requests); i++) {
|
||||||
if (strcmp(mgcp_requests[i].name, rq.name) == 0) {
|
if (strcmp(mgcp_requests[i].name, rq.name) == 0) {
|
||||||
/* Check if the request requires and endpoint, if yes, check if we have it, otherwise don't
|
|
||||||
* execute the request handler. */
|
|
||||||
if (mgcp_requests[i].require_endp && !rq.endp) {
|
|
||||||
LOGP(DLMGCP, LOGL_ERROR,
|
|
||||||
"%s: the request handler \"%s\" requires an endpoint resource for \"%s\", which is not available -- abort\n",
|
|
||||||
rq.name, mgcp_requests[i].debug_name, pdata.epname);
|
|
||||||
return create_err_response(NULL, -rq.mgcp_cause, rq.name, pdata.trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute request handler */
|
/* Execute request handler */
|
||||||
if (rq.endp)
|
if (rq.endp)
|
||||||
LOGP(DLMGCP, LOGL_INFO,
|
LOGP(DLMGCP, LOGL_INFO,
|
||||||
@@ -461,7 +448,12 @@ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
|
|||||||
static struct msgb *handle_audit_endpoint(struct mgcp_request_data *rq)
|
static struct msgb *handle_audit_endpoint(struct mgcp_request_data *rq)
|
||||||
{
|
{
|
||||||
LOGPENDP(rq->endp, DLMGCP, LOGL_NOTICE, "AUEP: auditing endpoint ...\n");
|
LOGPENDP(rq->endp, DLMGCP, LOGL_NOTICE, "AUEP: auditing endpoint ...\n");
|
||||||
return create_ok_response(rq->endp, 200, "AUEP", rq->pdata->trans);
|
if (!rq->endp || !mgcp_endp_avail(rq->endp)) {
|
||||||
|
LOGPENDP(rq->endp, DLMGCP, LOGL_ERROR, "AUEP: selected endpoint not available!\n");
|
||||||
|
return create_err_response(rq->trunk, NULL, 501, "AUEP", rq->pdata->trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
return create_ok_response(rq->trunk, rq->endp, 200, "AUEP", rq->pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to find a free port by attempting to bind on it. Also handle the
|
/* Try to find a free port by attempting to bind on it. Also handle the
|
||||||
@@ -855,11 +847,18 @@ static struct msgb *handle_create_con(struct mgcp_request_data *rq)
|
|||||||
|
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");
|
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");
|
||||||
|
|
||||||
|
/* we must have a free ep */
|
||||||
|
if (!endp) {
|
||||||
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL));
|
||||||
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: no free endpoints available!\n");
|
||||||
|
return create_err_response(rq->trunk, NULL, 403, "CRCX", pdata->trans);
|
||||||
|
}
|
||||||
|
|
||||||
if (!mgcp_endp_avail(endp)) {
|
if (!mgcp_endp_avail(endp)) {
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL));
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"CRCX: selected endpoint not available!\n");
|
"CRCX: selected endpoint not available!\n");
|
||||||
return create_err_response(NULL, 501, "CRCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 501, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse CallID C: and LocalParameters L: */
|
/* parse CallID C: and LocalParameters L: */
|
||||||
@@ -879,7 +878,7 @@ static struct msgb *handle_create_con(struct mgcp_request_data *rq)
|
|||||||
* together with a CRCX, the MGW will assign the
|
* together with a CRCX, the MGW will assign the
|
||||||
* connection identifier by itself on CRCX */
|
* connection identifier by itself on CRCX */
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION));
|
||||||
return create_err_response(NULL, 523, "CRCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 523, "CRCX", pdata->trans);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
mode = (const char *)line + 3;
|
mode = (const char *)line + 3;
|
||||||
@@ -905,7 +904,7 @@ static struct msgb *handle_create_con(struct mgcp_request_data *rq)
|
|||||||
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
|
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
|
||||||
"CRCX: unhandled option: '%c'/%d\n", *line, *line);
|
"CRCX: unhandled option: '%c'/%d\n", *line, *line);
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNHANDLED_PARAM));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNHANDLED_PARAM));
|
||||||
return create_err_response(NULL, 539, "CRCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 539, "CRCX", pdata->trans);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -916,14 +915,14 @@ mgcp_header_done:
|
|||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"CRCX: insufficient parameters, missing callid\n");
|
"CRCX: insufficient parameters, missing callid\n");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_MISSING_CALLID));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_MISSING_CALLID));
|
||||||
return create_err_response(endp, 516, "CRCX", pdata->trans);
|
return create_err_response(endp, endp, 516, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"CRCX: insufficient parameters, missing mode\n");
|
"CRCX: insufficient parameters, missing mode\n");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_MODE));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_MODE));
|
||||||
return create_err_response(endp, 517, "CRCX", pdata->trans);
|
return create_err_response(endp, endp, 517, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we are able to accept the creation of another connection */
|
/* Check if we are able to accept the creation of another connection */
|
||||||
@@ -940,7 +939,7 @@ mgcp_header_done:
|
|||||||
/* There is no more room for a connection, leave
|
/* There is no more room for a connection, leave
|
||||||
* everything as it is and return with an error */
|
* everything as it is and return with an error */
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_LIMIT_EXCEEDED));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_LIMIT_EXCEEDED));
|
||||||
return create_err_response(endp, 540, "CRCX", pdata->trans);
|
return create_err_response(endp, endp, 540, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -958,7 +957,7 @@ mgcp_header_done:
|
|||||||
/* This is not our call, leave everything as it is and
|
/* This is not our call, leave everything as it is and
|
||||||
* return with an error. */
|
* return with an error. */
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNKNOWN_CALLID));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNKNOWN_CALLID));
|
||||||
return create_err_response(endp, 400, "CRCX", pdata->trans);
|
return create_err_response(endp, endp, 400, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -969,7 +968,7 @@ mgcp_header_done:
|
|||||||
rc = mgcp_endp_claim(endp, callid);
|
rc = mgcp_endp_claim(endp, callid);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_CLAIM));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_CLAIM));
|
||||||
return create_err_response(endp, 502, "CRCX", pdata->trans);
|
return create_err_response(endp, endp, 502, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1088,7 +1087,7 @@ error2:
|
|||||||
mgcp_endp_release(endp);
|
mgcp_endp_release(endp);
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
|
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
|
||||||
"CRCX: unable to create connection\n");
|
"CRCX: unable to create connection\n");
|
||||||
return create_err_response(endp, error_code, "CRCX", pdata->trans);
|
return create_err_response(endp, endp, error_code, "CRCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MDCX command handler, processes the received command */
|
/* MDCX command handler, processes the received command */
|
||||||
@@ -1112,26 +1111,24 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *rq)
|
|||||||
|
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");
|
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");
|
||||||
|
|
||||||
if (!mgcp_endp_avail(endp)) {
|
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_AVAIL));
|
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
|
||||||
"MDCX: selected endpoint not available!\n");
|
|
||||||
return create_err_response(NULL, 501, "MDCX", pdata->trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prohibit wildcarded requests */
|
/* Prohibit wildcarded requests */
|
||||||
if (rq->wildcarded) {
|
if (rq->wildcarded) {
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"MDCX: wildcarded endpoint names not supported.\n");
|
"MDCX: wildcarded endpoint names not supported.\n");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_WILDCARD));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_WILDCARD));
|
||||||
return create_err_response(endp, 507, "MDCX", pdata->trans);
|
return create_err_response(rq->trunk, endp, 507, "MDCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!endp || !mgcp_endp_avail(endp)) {
|
||||||
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_AVAIL));
|
||||||
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR, "MDCX: selected endpoint not available!\n");
|
||||||
|
return create_err_response(rq->trunk, NULL, 501, "MDCX", pdata->trans);
|
||||||
|
}
|
||||||
if (llist_count(&endp->conns) <= 0) {
|
if (llist_count(&endp->conns) <= 0) {
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"MDCX: endpoint is not holding a connection.\n");
|
"MDCX: endpoint is not holding a connection.\n");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONN));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONN));
|
||||||
return create_err_response(endp, 400, "MDCX", pdata->trans);
|
return create_err_response(endp, endp, 400, "MDCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_line(line, pdata->save) {
|
for_each_line(line, pdata->save) {
|
||||||
@@ -1181,7 +1178,7 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *rq)
|
|||||||
"MDCX: Unhandled MGCP option: '%c'/%d\n",
|
"MDCX: Unhandled MGCP option: '%c'/%d\n",
|
||||||
line[0], line[0]);
|
line[0], line[0]);
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_UNHANDLED_PARAM));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_UNHANDLED_PARAM));
|
||||||
return create_err_response(NULL, 539, "MDCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 539, "MDCX", pdata->trans);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1191,13 +1188,13 @@ mgcp_header_done:
|
|||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"MDCX: insufficient parameters, missing ci (connectionIdentifier)\n");
|
"MDCX: insufficient parameters, missing ci (connectionIdentifier)\n");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONNID));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONNID));
|
||||||
return create_err_response(endp, 515, "MDCX", pdata->trans);
|
return create_err_response(endp, endp, 515, "MDCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = mgcp_conn_get_rtp(endp, conn_id);
|
conn = mgcp_conn_get_rtp(endp, conn_id);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_CONN_NOT_FOUND));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_CONN_NOT_FOUND));
|
||||||
return create_err_response(endp, 400, "MDCX", pdata->trans);
|
return create_err_response(endp, endp, 400, "MDCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
mgcp_conn_watchdog_kick(conn->conn);
|
mgcp_conn_watchdog_kick(conn->conn);
|
||||||
@@ -1304,7 +1301,7 @@ mgcp_header_done:
|
|||||||
mgcp_endp_update(endp);
|
mgcp_endp_update(endp);
|
||||||
return create_response_with_sdp(endp, conn, "MDCX", pdata->trans, false, false);
|
return create_response_with_sdp(endp, conn, "MDCX", pdata->trans, false, false);
|
||||||
error3:
|
error3:
|
||||||
return create_err_response(endp, error_code, "MDCX", pdata->trans);
|
return create_err_response(endp, endp, error_code, "MDCX", pdata->trans);
|
||||||
|
|
||||||
out_silent:
|
out_silent:
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_DEBUG, "MDCX: silent exit\n");
|
LOGPENDP(endp, DLMGCP, LOGL_DEBUG, "MDCX: silent exit\n");
|
||||||
@@ -1335,14 +1332,27 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
|
|||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_AVAIL));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_AVAIL));
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"DLCX: selected endpoint not available!\n");
|
"DLCX: selected endpoint not available!\n");
|
||||||
return create_err_response(NULL, 501, "DLCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 501, "DLCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endp && !rq->wildcarded && llist_empty(&endp->conns)) {
|
if (endp && !rq->wildcarded && llist_empty(&endp->conns)) {
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
|
||||||
"DLCX: endpoint is not holding a connection.\n");
|
"DLCX: endpoint is not holding a connection.\n");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_NO_CONN));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_NO_CONN));
|
||||||
return create_err_response(endp, 515, "DLCX", pdata->trans);
|
return create_err_response(endp, endp, 515, "DLCX", pdata->trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle wildcarded DLCX that refers to the whole trunk. This means
|
||||||
|
* that we walk over all endpoints on the trunk in order to drop all
|
||||||
|
* connections on the trunk. (see also RFC3435 Annex F.7) */
|
||||||
|
if (rq->wildcarded) {
|
||||||
|
int num_conns = 0;
|
||||||
|
for (i = 0; i < trunk->number_endpoints; i++) {
|
||||||
|
num_conns += llist_count(&trunk->endpoints[i]->conns);
|
||||||
|
mgcp_endp_release(trunk->endpoints[i]);
|
||||||
|
}
|
||||||
|
rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns);
|
||||||
|
return create_ok_response(trunk, NULL, 200, "DLCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_line(line, pdata->save) {
|
for_each_line(line, pdata->save) {
|
||||||
@@ -1357,7 +1367,7 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
|
|||||||
LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
|
LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
|
||||||
"cannot handle requests with call-id (C) without endpoint -- abort!");
|
"cannot handle requests with call-id (C) without endpoint -- abort!");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
|
||||||
return create_err_response(NULL, 539, "DLCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mgcp_verify_call_id(endp, line + 3) != 0) {
|
if (mgcp_verify_call_id(endp, line + 3) != 0) {
|
||||||
@@ -1373,7 +1383,7 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
|
|||||||
LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
|
LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
|
||||||
"cannot handle requests with conn-id (I) without endpoint -- abort!");
|
"cannot handle requests with conn-id (I) without endpoint -- abort!");
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
|
||||||
return create_err_response(NULL, 539, "DLCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
conn_id = (const char *)line + 3;
|
conn_id = (const char *)line + 3;
|
||||||
@@ -1389,24 +1399,11 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
|
|||||||
LOGPEPTR(endp, trunk, DLMGCP, LOGL_NOTICE, "DLCX: Unhandled MGCP option: '%c'/%d\n",
|
LOGPEPTR(endp, trunk, DLMGCP, LOGL_NOTICE, "DLCX: Unhandled MGCP option: '%c'/%d\n",
|
||||||
line[0], line[0]);
|
line[0], line[0]);
|
||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
|
||||||
return create_err_response(NULL, 539, "DLCX", pdata->trans);
|
return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle wildcarded DLCX that refers to the whole trunk. This means
|
|
||||||
* that we walk over all endpoints on the trunk in order to drop all
|
|
||||||
* connections on the trunk. (see also RFC3435 Annex F.7) */
|
|
||||||
if (rq->wildcarded) {
|
|
||||||
int num_conns = 0;
|
|
||||||
for (i = 0; i < trunk->number_endpoints; i++) {
|
|
||||||
num_conns += llist_count(&trunk->endpoints[i]->conns);
|
|
||||||
mgcp_endp_release(trunk->endpoints[i]);
|
|
||||||
}
|
|
||||||
rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns);
|
|
||||||
return create_ok_response(NULL, 200, "DLCX", pdata->trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The logic does not permit to go past this point without having the
|
/* The logic does not permit to go past this point without having the
|
||||||
* the endp pointer populated. */
|
* the endp pointer populated. */
|
||||||
OSMO_ASSERT(endp);
|
OSMO_ASSERT(endp);
|
||||||
@@ -1429,7 +1426,7 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
|
|||||||
/* Note: In this case we do not return any statistics,
|
/* Note: In this case we do not return any statistics,
|
||||||
* as we assume that the client is not interested in
|
* as we assume that the client is not interested in
|
||||||
* this case. */
|
* this case. */
|
||||||
return create_ok_response(endp, 200, "DLCX", pdata->trans);
|
return create_ok_response(endp, endp, 200, "DLCX", pdata->trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the connection */
|
/* Find the connection */
|
||||||
@@ -1458,10 +1455,10 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
|
|||||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS));
|
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS));
|
||||||
if (silent)
|
if (silent)
|
||||||
goto out_silent;
|
goto out_silent;
|
||||||
return create_ok_resp_with_param(endp, 250, "DLCX", pdata->trans, stats);
|
return create_ok_resp_with_param(endp, endp, 250, "DLCX", pdata->trans, stats);
|
||||||
|
|
||||||
error3:
|
error3:
|
||||||
return create_err_response(endp, error_code, "DLCX", pdata->trans);
|
return create_err_response(endp, endp, error_code, "DLCX", pdata->trans);
|
||||||
|
|
||||||
out_silent:
|
out_silent:
|
||||||
LOGPENDP(endp, DLMGCP, LOGL_DEBUG, "DLCX: silent exit\n");
|
LOGPENDP(endp, DLMGCP, LOGL_DEBUG, "DLCX: silent exit\n");
|
||||||
@@ -1516,14 +1513,13 @@ static struct msgb *handle_noti_req(struct mgcp_request_data *rq)
|
|||||||
|
|
||||||
/* we didn't see a signal request with a tone */
|
/* we didn't see a signal request with a tone */
|
||||||
if (tone == CHAR_MAX)
|
if (tone == CHAR_MAX)
|
||||||
return create_ok_response(rq->endp, 200, "RQNT", rq->pdata->trans);
|
return create_ok_response(rq->endp, rq->endp, 200, "RQNT", rq->pdata->trans);
|
||||||
|
|
||||||
if (rq->pdata->cfg->rqnt_cb)
|
if (rq->pdata->cfg->rqnt_cb)
|
||||||
res = rq->pdata->cfg->rqnt_cb(rq->endp, tone);
|
res = rq->pdata->cfg->rqnt_cb(rq->endp, tone);
|
||||||
|
|
||||||
return res == 0 ?
|
return res == 0 ? create_ok_response(rq->endp, rq->endp, 200, "RQNT", rq->pdata->trans) :
|
||||||
create_ok_response(rq->endp, 200, "RQNT", rq->pdata->trans) :
|
create_err_response(rq->endp, rq->endp, res, "RQNT", rq->pdata->trans);
|
||||||
create_err_response(rq->endp, res, "RQNT", rq->pdata->trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connection keepalive timer, will take care that dummy packets are send
|
/* Connection keepalive timer, will take care that dummy packets are send
|
||||||
|
207
src/libosmo-mgcp/mgcp_threads_queue.c
Normal file
207
src/libosmo-mgcp/mgcp_threads_queue.c
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* Author: Eric Wild
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <talloc.h>
|
||||||
|
|
||||||
|
#include <osmocom/mgcp/mgcp_threads_queue.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
classic lamport circular lockfree spsc queue:
|
||||||
|
every "side" only writes its own ptr, but may read the other sides ptr
|
||||||
|
|
||||||
|
notify reader using eventfd as soon as element is added, reader then reads until
|
||||||
|
read fails
|
||||||
|
-> reader pops in a loop until FALSE and might get spurious events because it
|
||||||
|
read before it was notified, which is fine
|
||||||
|
-> writing pushes *the same data* in a loop until TRUE, blocks
|
||||||
|
|
||||||
|
shutting this down requires
|
||||||
|
1) to stop reading and pushing
|
||||||
|
2) ONE side to take care of the eventfds
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct spsc *spsc_init(void *talloc_ctx, unsigned int count, unsigned int size_per_buf, bool blockr, bool blockw)
|
||||||
|
{
|
||||||
|
struct spsc *q = talloc_zero_size(talloc_ctx, sizeof(struct spsc) + sizeof(uintptr_t) * count);
|
||||||
|
atomic_init(&q->readptr, 0);
|
||||||
|
atomic_init(&q->writeptr, 0);
|
||||||
|
q->efd_r = eventfd(0, blockr ? 0 : EFD_NONBLOCK);
|
||||||
|
q->efd_w = eventfd(1, blockw ? 0 : EFD_NONBLOCK);
|
||||||
|
q->count = count;
|
||||||
|
q->size_per_buf = size_per_buf;
|
||||||
|
q->buf = talloc_zero_size(q, size_per_buf * count);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
q->data[i] = (uintptr_t)q->buf + i * size_per_buf;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spsc_deinit(struct spsc *q)
|
||||||
|
{
|
||||||
|
talloc_free(q->buf);
|
||||||
|
close(q->efd_r);
|
||||||
|
close(q->efd_w);
|
||||||
|
talloc_free(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t spsc_check_r(struct spsc *q)
|
||||||
|
{
|
||||||
|
uint64_t efdr;
|
||||||
|
return read(q->efd_r, &efdr, sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
static ssize_t spsc_check_w(struct spsc *q)
|
||||||
|
{
|
||||||
|
uint64_t efdr;
|
||||||
|
return read(q->efd_w, &efdr, sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
static void spsc_notify_r(struct spsc *q)
|
||||||
|
{
|
||||||
|
uint64_t efdu = 1;
|
||||||
|
write(q->efd_r, &efdu, sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
static void spsc_notify_w(struct spsc *q)
|
||||||
|
{
|
||||||
|
uint64_t efdu = 1;
|
||||||
|
write(q->efd_w, &efdu, sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Adds element to the queue by copying the data.
|
||||||
|
* \param[in] q queue.
|
||||||
|
* \param[in] elem input buffer, must match the originally configured queue buffer size!.
|
||||||
|
* \returns true if queue was not full and element was successfully pushed */
|
||||||
|
bool spsc_push(struct spsc *q, void *elem)
|
||||||
|
{
|
||||||
|
size_t cur_wp, cur_rp;
|
||||||
|
cur_wp = atomic_load_explicit(&q->writeptr, memory_order_relaxed);
|
||||||
|
cur_rp = atomic_load_explicit(&q->readptr, memory_order_acquire);
|
||||||
|
if ((cur_wp + 1) % q->count == cur_rp) {
|
||||||
|
spsc_check_w(q); /* blocks, ensures next (!) call succeeds */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy((void *)q->data[cur_wp], elem, q->size_per_buf);
|
||||||
|
atomic_store_explicit(&q->writeptr, (cur_wp + 1) % q->count, memory_order_release);
|
||||||
|
spsc_notify_r(q); /* fine after release */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Reads the read-fd of the queue, which, depending on settings passed on queue creation, blocks.
|
||||||
|
* This function can be used to deliberately wait for a non-empty queue on the read side.
|
||||||
|
* \param[in] q queue.
|
||||||
|
* \returns result of reading the fd. */
|
||||||
|
ssize_t spsc_prep_pop(struct spsc *q)
|
||||||
|
{
|
||||||
|
return spsc_check_r(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Removes element from the queue by copying the data.
|
||||||
|
* \param[in] q queue.
|
||||||
|
* \param[in] elem output buffer, must match the originally configured queue buffer size!.
|
||||||
|
* \returns true if queue was not empty and element was successfully removed */
|
||||||
|
bool spsc_pop(struct spsc *q, void *elem)
|
||||||
|
{
|
||||||
|
size_t cur_wp, cur_rp;
|
||||||
|
cur_wp = atomic_load_explicit(&q->writeptr, memory_order_acquire);
|
||||||
|
cur_rp = atomic_load_explicit(&q->readptr, memory_order_relaxed);
|
||||||
|
|
||||||
|
if (cur_wp == cur_rp) /* blocks via prep_pop */
|
||||||
|
return false;
|
||||||
|
memcpy(elem, (void *)q->data[cur_rp], q->size_per_buf);
|
||||||
|
atomic_store_explicit(&q->readptr, (cur_rp + 1) % q->count, memory_order_release);
|
||||||
|
spsc_notify_w(q);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Creates a bidirectional queue channel that consists of two queues, one in each direction,
|
||||||
|
* commonly referred to as a and b side.
|
||||||
|
* \param[in] talloc_ctx allocation context.
|
||||||
|
* \param[in] count number of buffers per queue.
|
||||||
|
* \param[in] size_per_buf size of buffers per queue.
|
||||||
|
* \param[in] blockr_a should reading the a-side read fd block?.
|
||||||
|
* \param[in] blockw_a should reading the a-side write fd block?.
|
||||||
|
* \param[in] blockr_b should reading the b-side read fd block?.
|
||||||
|
* \param[in] blockw_b should reading the b-side write fd block?.
|
||||||
|
* \returns queue channel */
|
||||||
|
struct qchan spsc_chan_init_ex(void *talloc_ctx, unsigned int count, unsigned int size_per_buf, bool blockr_a,
|
||||||
|
bool blockw_a, bool blockr_b, bool blockw_b)
|
||||||
|
{
|
||||||
|
struct qchan q;
|
||||||
|
q.a = spsc_init(talloc_ctx, count, size_per_buf, blockr_a, blockw_a);
|
||||||
|
q.b = spsc_init(talloc_ctx, count, size_per_buf, blockr_b, blockw_b);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Creates a bidirectional queue channel that consists of two queues, one in each direction,
|
||||||
|
* commonly referred to as a and b side.
|
||||||
|
* \param[in] talloc_ctx allocation context.
|
||||||
|
* \param[in] count number of buffers per queue.
|
||||||
|
* \param[in] size_per_buf size of buffers per queue.
|
||||||
|
* \returns queue channel */
|
||||||
|
struct qchan spsc_chan_init(void *talloc_ctx, unsigned int count, unsigned int size_per_buf)
|
||||||
|
{
|
||||||
|
return spsc_chan_init_ex(talloc_ctx, count, size_per_buf, false, true, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Closes a bidirectional queue channel.
|
||||||
|
* \param[in] q queue */
|
||||||
|
void spsc_chan_close(struct qchan *q)
|
||||||
|
{
|
||||||
|
spsc_deinit(q->a);
|
||||||
|
spsc_deinit(q->b);
|
||||||
|
free(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Gets queue channel read/write fd for a/b side according to function name.
|
||||||
|
* \param[in] q queue channel.
|
||||||
|
* \returns fd */
|
||||||
|
int spsc_get_a_rdfd(struct qchan *q)
|
||||||
|
{
|
||||||
|
return q->a->efd_r;
|
||||||
|
}
|
||||||
|
/*! Gets queue channel read/write fd for a/b side according to function name.
|
||||||
|
* \param[in] q queue channel.
|
||||||
|
* \returns fd */
|
||||||
|
int spsc_get_b_rdfd(struct qchan *q)
|
||||||
|
{
|
||||||
|
return q->b->efd_r;
|
||||||
|
}
|
||||||
|
/*! Gets queue channel read/write fd for a/b side according to function name.
|
||||||
|
* \param[in] q queue channel.
|
||||||
|
* \returns fd */
|
||||||
|
int spsc_get_a_wrfd(struct qchan *q)
|
||||||
|
{
|
||||||
|
return q->a->efd_w;
|
||||||
|
}
|
||||||
|
/*! Gets queue channel read/write fd for a/b side according to function name.
|
||||||
|
* \param[in] q queue channel.
|
||||||
|
* \returns fd */
|
||||||
|
int spsc_get_b_wrfd(struct qchan *q)
|
||||||
|
{
|
||||||
|
return q->b->efd_w;
|
||||||
|
}
|
@@ -1896,16 +1896,13 @@ static const struct testcase_mgcp_codec_pt_translate test_mgcp_codec_pt_translat
|
|||||||
.codecs = {
|
.codecs = {
|
||||||
{
|
{
|
||||||
{ 111, "AMR/8000", &amr_param_octet_aligned_true, },
|
{ 111, "AMR/8000", &amr_param_octet_aligned_true, },
|
||||||
{ 112, "AMR/8000", &amr_param_octet_aligned_false, },
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ 122, "AMR/8000", &amr_param_octet_aligned_false, },
|
{ 122, "AMR/8000", &amr_param_octet_aligned_false, },
|
||||||
{ 121, "AMR/8000", &amr_param_octet_aligned_true, },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.expect = {
|
.expect = {
|
||||||
{ .payload_type_map = {111, 121}, },
|
{ .payload_type_map = {111, 122}, },
|
||||||
{ .payload_type_map = {112, 122} },
|
|
||||||
{ .end = true },
|
{ .end = true },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1914,15 +1911,13 @@ static const struct testcase_mgcp_codec_pt_translate test_mgcp_codec_pt_translat
|
|||||||
.codecs = {
|
.codecs = {
|
||||||
{
|
{
|
||||||
{ 111, "AMR/8000", &amr_param_octet_aligned_true, },
|
{ 111, "AMR/8000", &amr_param_octet_aligned_true, },
|
||||||
{ 112, "AMR/8000", &amr_param_octet_aligned_false, },
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ 122, "AMR/8000", &amr_param_octet_aligned_unset, },
|
{ 122, "AMR/8000", &amr_param_octet_aligned_unset, },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.expect = {
|
.expect = {
|
||||||
{ .payload_type_map = {111, -EINVAL}, },
|
{ .payload_type_map = {111, 122}, },
|
||||||
{ .payload_type_map = {112, 122} },
|
|
||||||
{ .end = true },
|
{ .end = true },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1931,15 +1926,13 @@ static const struct testcase_mgcp_codec_pt_translate test_mgcp_codec_pt_translat
|
|||||||
.codecs = {
|
.codecs = {
|
||||||
{
|
{
|
||||||
{ 111, "AMR/8000", &amr_param_octet_aligned_true, },
|
{ 111, "AMR/8000", &amr_param_octet_aligned_true, },
|
||||||
{ 112, "AMR/8000", &amr_param_octet_aligned_false, },
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ 122, "AMR/8000", NULL, },
|
{ 122, "AMR/8000", NULL, },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.expect = {
|
.expect = {
|
||||||
{ .payload_type_map = {111, -EINVAL}, },
|
{ .payload_type_map = {111, 122}, },
|
||||||
{ .payload_type_map = {112, 122} },
|
|
||||||
{ .end = true },
|
{ .end = true },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -1347,32 +1347,24 @@ Testing mgcp_codec_pt_translate()
|
|||||||
- mgcp_codec_pt_translate(conn0, conn1, 112) -> -22
|
- mgcp_codec_pt_translate(conn0, conn1, 112) -> -22
|
||||||
- mgcp_codec_pt_translate(conn0, conn1, 0) -> -22
|
- mgcp_codec_pt_translate(conn0, conn1, 0) -> -22
|
||||||
- mgcp_codec_pt_translate(conn0, conn1, 111) -> -22
|
- mgcp_codec_pt_translate(conn0, conn1, 111) -> -22
|
||||||
#4: conn1 has no codecs
|
|
||||||
#4: conn1 has no codecs
|
#4: conn1 has no codecs
|
||||||
- add codecs on conn0:
|
- add codecs on conn0:
|
||||||
1: 0 PCMU/8000/1 -> rc=0
|
0: 112 AMR/8000/1 octet-aligned=1 -> rc=0
|
||||||
2: 111 GSM-HR-08/8000/1 -> rc=0
|
1: 0 PCMU/8000/1 -> rc=0
|
||||||
- add codecs on conn1:
|
|
||||||
(none)
|
|
||||||
- mgcp_codec_pt_translate(conn0, conn1, 112) -> -22
|
|
||||||
2: 111 GSM-HR-08/8000/1 -> rc=0
|
2: 111 GSM-HR-08/8000/1 -> rc=0
|
||||||
- add codecs on conn1:
|
- add codecs on conn1:
|
||||||
(none)
|
(none)
|
||||||
- add codecs on conn0:
|
|
||||||
- mgcp_codec_pt_translate(conn0, conn1, 112) -> -22
|
- mgcp_codec_pt_translate(conn0, conn1, 112) -> -22
|
||||||
- mgcp_codec_pt_translate(conn0, conn1, 0) -> -22
|
- mgcp_codec_pt_translate(conn0, conn1, 0) -> -22
|
||||||
- add codecs on conn1:
|
- mgcp_codec_pt_translate(conn0, conn1, 111) -> -22
|
||||||
0: 122 AMR/8000 octet-aligned=0 -> rc=0
|
#5: test AMR with differing octet-aligned settings
|
||||||
1: 121 AMR/8000 octet-aligned=1 -> rc=0
|
|
||||||
- add codecs on conn0:
|
- add codecs on conn0:
|
||||||
0: 111 AMR/8000 octet-aligned=1 -> rc=0
|
0: 111 AMR/8000 octet-aligned=1 -> rc=0
|
||||||
- add codecs on conn1:
|
- add codecs on conn1:
|
||||||
- mgcp_codec_pt_translate(conn1, conn0, 122) -> 112
|
|
||||||
0: 122 AMR/8000 octet-aligned=0 -> rc=0
|
0: 122 AMR/8000 octet-aligned=0 -> rc=0
|
||||||
- mgcp_codec_pt_translate(conn0, conn1, 111) -> 122
|
- mgcp_codec_pt_translate(conn0, conn1, 111) -> 122
|
||||||
0: 111 AMR/8000 octet-aligned=1 -> rc=0
|
- mgcp_codec_pt_translate(conn1, conn0, 122) -> 111
|
||||||
1: 112 AMR/8000 octet-aligned=0 -> rc=0
|
#6: test AMR with missing octet-aligned settings (defaults to 0)
|
||||||
- add codecs on conn1:
|
|
||||||
- add codecs on conn0:
|
- add codecs on conn0:
|
||||||
0: 111 AMR/8000 octet-aligned=1 -> rc=0
|
0: 111 AMR/8000 octet-aligned=1 -> rc=0
|
||||||
- add codecs on conn1:
|
- add codecs on conn1:
|
||||||
|
Reference in New Issue
Block a user