trema 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.mono.rant +4107 -0
- data/.rspec +1 -0
- data/.yardopts +4 -0
- data/Doxyfile +1679 -0
- data/GPL2 +339 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +71 -0
- data/README.md +135 -0
- data/Rakefile +140 -0
- data/Rantfile +834 -0
- data/VERSION +1 -0
- data/build.rb +32 -0
- data/cruise.rb +389 -0
- data/features/example.dumper.feature +87 -0
- data/features/example.learning_switch.feature +39 -0
- data/features/example.list_switches.feature +38 -0
- data/features/example.message.echo_reply.feature +26 -0
- data/features/example.message.echo_request.feature +25 -0
- data/features/example.message.features_request.feature +84 -0
- data/features/example.message.hello.feature +25 -0
- data/features/example.message.set_config.feature +27 -0
- data/features/example.multi_learning_switch.feature +135 -0
- data/features/example.packetin_filter_config.feature +91 -0
- data/features/example.repeater_hub.feature +49 -0
- data/features/example.switch_monitor.feature +39 -0
- data/features/packetin_filter.feature +49 -0
- data/features/step_definitions/kill_steps.rb +30 -0
- data/features/step_definitions/log_steps.rb +90 -0
- data/features/step_definitions/misc_steps.rb +64 -0
- data/features/step_definitions/off_steps.rb +30 -0
- data/features/step_definitions/run_steps.rb +91 -0
- data/features/step_definitions/send_packets_steps.rb +42 -0
- data/features/step_definitions/show_stats_steps.rb +43 -0
- data/features/step_definitions/stats_steps.rb +39 -0
- data/features/support/env.rb +75 -0
- data/features/support/hooks.rb +8 -0
- data/features/switch_manager.feature +35 -0
- data/features/trema-config.feature +68 -0
- data/features/trema.dump_flows.feature +25 -0
- data/features/trema.feature +25 -0
- data/features/trema.kill.feature +53 -0
- data/features/trema.killall.feature +30 -0
- data/features/trema.reset_stats.feature +14 -0
- data/features/trema.run.feature +46 -0
- data/features/trema.send_packets.feature +56 -0
- data/features/trema.show_stats.feature +67 -0
- data/features/tutorial.hello_trema.feature +27 -0
- data/features/tutorial.packet_in.feature +47 -0
- data/features/tutorial.switch_info.feature +55 -0
- data/ruby/.gitignore +4 -0
- data/ruby/blocker.rb +78 -0
- data/ruby/extconf.rb +71 -0
- data/ruby/sub-process.rb +291 -0
- data/ruby/trema/action-common.c +60 -0
- data/ruby/trema/action-common.h +42 -0
- data/ruby/trema/action-enqueue.c +161 -0
- data/ruby/trema/action-enqueue.h +40 -0
- data/ruby/trema/action-output.c +169 -0
- data/ruby/trema/action-output.h +42 -0
- data/ruby/trema/action-set-dl-dst.c +131 -0
- data/ruby/trema/action-set-dl-dst.h +44 -0
- data/ruby/trema/action-set-dl-src.c +131 -0
- data/ruby/trema/action-set-dl-src.h +44 -0
- data/ruby/trema/action-set-nw-dst.c +135 -0
- data/ruby/trema/action-set-nw-dst.h +42 -0
- data/ruby/trema/action-set-nw-src.c +140 -0
- data/ruby/trema/action-set-nw-src.h +42 -0
- data/ruby/trema/action-set-nw-tos.c +124 -0
- data/ruby/trema/action-set-nw-tos.h +42 -0
- data/ruby/trema/action-set-tp-dst.c +122 -0
- data/ruby/trema/action-set-tp-dst.h +42 -0
- data/ruby/trema/action-set-tp-src.c +124 -0
- data/ruby/trema/action-set-tp-src.h +42 -0
- data/ruby/trema/action-set-vlan-pcp.c +128 -0
- data/ruby/trema/action-set-vlan-pcp.h +42 -0
- data/ruby/trema/action-set-vlan-vid.c +125 -0
- data/ruby/trema/action-set-vlan-vid.h +42 -0
- data/ruby/trema/action-strip-vlan.c +81 -0
- data/ruby/trema/action-strip-vlan.h +42 -0
- data/ruby/trema/action-vendor.c +121 -0
- data/ruby/trema/action-vendor.h +42 -0
- data/ruby/trema/aggregate-stats-reply.rb +70 -0
- data/ruby/trema/app.rb +112 -0
- data/ruby/trema/barrier-reply.c +99 -0
- data/ruby/trema/barrier-reply.h +46 -0
- data/ruby/trema/barrier-request.c +108 -0
- data/ruby/trema/barrier-request.h +44 -0
- data/ruby/trema/cli.rb +269 -0
- data/ruby/trema/command.rb +40 -0
- data/ruby/trema/command/dump_flows.rb +62 -0
- data/ruby/trema/command/kill.rb +71 -0
- data/ruby/trema/command/killall.rb +56 -0
- data/ruby/trema/command/reset_stats.rb +61 -0
- data/ruby/trema/command/ruby.rb +55 -0
- data/ruby/trema/command/run.rb +120 -0
- data/ruby/trema/command/send_packets.rb +130 -0
- data/ruby/trema/command/shell.rb +61 -0
- data/ruby/trema/command/show_stats.rb +84 -0
- data/ruby/trema/command/usage.rb +61 -0
- data/ruby/trema/command/version.rb +39 -0
- data/ruby/trema/controller.c +595 -0
- data/ruby/trema/controller.h +44 -0
- data/ruby/trema/controller.rb +81 -0
- data/ruby/trema/daemon.rb +167 -0
- data/ruby/trema/dsl.rb +34 -0
- data/ruby/trema/dsl/configuration.rb +153 -0
- data/ruby/trema/dsl/context.rb +71 -0
- data/ruby/trema/dsl/link.rb +41 -0
- data/ruby/trema/dsl/parser.rb +70 -0
- data/ruby/trema/dsl/run.rb +49 -0
- data/ruby/trema/dsl/runner.rb +165 -0
- data/ruby/trema/dsl/stanza.rb +53 -0
- data/ruby/trema/dsl/switch.rb +78 -0
- data/ruby/trema/dsl/syntax-error.rb +33 -0
- data/ruby/trema/dsl/syntax.rb +109 -0
- data/ruby/trema/dsl/vhost.rb +108 -0
- data/ruby/trema/dsl/vswitch.rb +47 -0
- data/ruby/trema/echo-reply.c +107 -0
- data/ruby/trema/echo-reply.h +42 -0
- data/ruby/trema/echo-request.c +140 -0
- data/ruby/trema/echo-request.h +42 -0
- data/ruby/trema/error.c +253 -0
- data/ruby/trema/error.h +44 -0
- data/ruby/trema/exact-match.rb +36 -0
- data/ruby/trema/executables.rb +95 -0
- data/ruby/trema/features-reply.c +238 -0
- data/ruby/trema/features-reply.h +60 -0
- data/ruby/trema/features-request.c +109 -0
- data/ruby/trema/features-request.h +44 -0
- data/ruby/trema/flow-removed.c +275 -0
- data/ruby/trema/flow-removed.h +46 -0
- data/ruby/trema/flow-stats-reply.rb +109 -0
- data/ruby/trema/flow.rb +56 -0
- data/ruby/trema/get-config-reply.c +159 -0
- data/ruby/trema/get-config-reply.h +52 -0
- data/ruby/trema/get-config-request.c +107 -0
- data/ruby/trema/get-config-request.h +44 -0
- data/ruby/trema/hello.c +110 -0
- data/ruby/trema/hello.h +44 -0
- data/ruby/trema/host.rb +257 -0
- data/ruby/trema/ip.rb +101 -0
- data/ruby/trema/link.rb +176 -0
- data/ruby/trema/list-switches-reply.c +46 -0
- data/ruby/trema/list-switches-reply.h +40 -0
- data/ruby/trema/logger.c +162 -0
- data/ruby/trema/logger.h +44 -0
- data/ruby/trema/mac.rb +151 -0
- data/ruby/trema/match.c +594 -0
- data/ruby/trema/match.h +36 -0
- data/ruby/trema/monkey-patch/integer.rb +35 -0
- data/ruby/trema/monkey-patch/integer/base-conversions.rb +36 -0
- data/ruby/trema/monkey-patch/integer/ranges.rb +51 -0
- data/ruby/trema/monkey-patch/module.rb +33 -0
- data/ruby/trema/monkey-patch/module/deprecation.rb +41 -0
- data/ruby/trema/monkey-patch/string.rb +33 -0
- data/ruby/trema/monkey-patch/string/inflectors.rb +54 -0
- data/ruby/trema/network-component.rb +153 -0
- data/ruby/trema/ofctl.rb +62 -0
- data/ruby/trema/open-vswitch.rb +154 -0
- data/ruby/trema/openflow-error.c +191 -0
- data/ruby/trema/openflow-error.h +53 -0
- data/ruby/trema/openflow-switch.rb +88 -0
- data/ruby/trema/ordered-hash.rb +74 -0
- data/ruby/trema/packet-queue.rb +178 -0
- data/ruby/trema/packet_in.c +736 -0
- data/ruby/trema/packet_in.h +46 -0
- data/ruby/trema/packetin-filter.rb +126 -0
- data/ruby/trema/path.rb +135 -0
- data/ruby/trema/phost.rb +69 -0
- data/ruby/trema/port-mod.c +226 -0
- data/ruby/trema/port-mod.h +36 -0
- data/ruby/trema/port-stats-reply.rb +111 -0
- data/ruby/trema/port-status.c +156 -0
- data/ruby/trema/port-status.h +45 -0
- data/ruby/trema/port.c +295 -0
- data/ruby/trema/port.h +47 -0
- data/ruby/trema/process.rb +76 -0
- data/ruby/trema/queue-get-config-reply.c +200 -0
- data/ruby/trema/queue-get-config-reply.h +47 -0
- data/ruby/trema/queue-get-config-request.c +141 -0
- data/ruby/trema/queue-get-config-request.h +44 -0
- data/ruby/trema/queue-stats-reply.rb +78 -0
- data/ruby/trema/set-config.c +171 -0
- data/ruby/trema/set-config.h +44 -0
- data/ruby/trema/shell.rb +39 -0
- data/ruby/trema/shell/down.rb +39 -0
- data/ruby/trema/shell/killall.rb +40 -0
- data/ruby/trema/shell/link.rb +61 -0
- data/ruby/trema/shell/reset_stats.rb +50 -0
- data/ruby/trema/shell/run.rb +67 -0
- data/ruby/trema/shell/send_packets.rb +42 -0
- data/ruby/trema/shell/show_stats.rb +49 -0
- data/ruby/trema/shell/up.rb +43 -0
- data/ruby/trema/shell/vhost.rb +44 -0
- data/ruby/trema/shell/vswitch.rb +49 -0
- data/ruby/trema/stats-helper.rb +65 -0
- data/ruby/trema/stats-reply.c +483 -0
- data/ruby/trema/stats-reply.h +53 -0
- data/ruby/trema/stats-request.c +634 -0
- data/ruby/trema/stats-request.h +42 -0
- data/ruby/trema/switch-daemon.rb +74 -0
- data/ruby/trema/switch-disconnected.c +40 -0
- data/ruby/trema/switch-disconnected.h +38 -0
- data/ruby/trema/switch-manager.rb +121 -0
- data/ruby/trema/switch.rb +37 -0
- data/ruby/trema/table-stats-reply.rb +87 -0
- data/ruby/trema/timers.rb +97 -0
- data/ruby/trema/trema.c +122 -0
- data/ruby/trema/tremashark.rb +39 -0
- data/ruby/trema/util.rb +84 -0
- data/ruby/trema/vendor-request.c +193 -0
- data/ruby/trema/vendor-request.h +44 -0
- data/ruby/trema/vendor-stats-reply.rb +62 -0
- data/ruby/trema/vendor.c +152 -0
- data/ruby/trema/vendor.h +52 -0
- data/ruby/trema/version.rb +30 -0
- data/spec/spec_helper.rb +153 -0
- data/spec/support/openflow-message.rb +94 -0
- data/spec/trema/action-enqueue_spec.rb +100 -0
- data/spec/trema/action-output_spec.rb +116 -0
- data/spec/trema/action-set-dl-dst_spec.rb +95 -0
- data/spec/trema/action-set-dl-src_spec.rb +92 -0
- data/spec/trema/action-set-nw-dst_spec.rb +96 -0
- data/spec/trema/action-set-nw-src_spec.rb +97 -0
- data/spec/trema/action-set-nw-tos_spec.rb +88 -0
- data/spec/trema/action-set-tp-dst_spec.rb +88 -0
- data/spec/trema/action-set-tp-src_spec.rb +88 -0
- data/spec/trema/action-set-vlan-pcp_spec.rb +91 -0
- data/spec/trema/action-set-vlan-vid_spec.rb +91 -0
- data/spec/trema/action-strip-vlan_spec.rb +57 -0
- data/spec/trema/action-vendor_spec.rb +90 -0
- data/spec/trema/app_spec.rb +90 -0
- data/spec/trema/barrier-reply_spec.rb +45 -0
- data/spec/trema/barrier-request_spec.rb +83 -0
- data/spec/trema/cli_spec.rb +160 -0
- data/spec/trema/controller_spec.rb +100 -0
- data/spec/trema/dsl/configuration_spec.rb +122 -0
- data/spec/trema/dsl/link_spec.rb +54 -0
- data/spec/trema/dsl/run_spec.rb +78 -0
- data/spec/trema/dsl/runner_spec.rb +239 -0
- data/spec/trema/dsl/switch_spec.rb +77 -0
- data/spec/trema/dsl/syntax_spec.rb +121 -0
- data/spec/trema/dsl/vhost_spec.rb +148 -0
- data/spec/trema/dsl/vswitch_spec.rb +90 -0
- data/spec/trema/echo-reply_spec.rb +49 -0
- data/spec/trema/echo-request_spec.rb +75 -0
- data/spec/trema/error_spec.rb +142 -0
- data/spec/trema/executables_spec.rb +75 -0
- data/spec/trema/features-reply_spec.rb +57 -0
- data/spec/trema/features-request_spec.rb +66 -0
- data/spec/trema/flow-removed_spec.rb +146 -0
- data/spec/trema/get-config-reply_spec.rb +43 -0
- data/spec/trema/get-config-request_spec.rb +82 -0
- data/spec/trema/hello_spec.rb +49 -0
- data/spec/trema/host_spec.rb +193 -0
- data/spec/trema/link_spec.rb +64 -0
- data/spec/trema/list-switches-reply_spec.rb +48 -0
- data/spec/trema/logger_spec.rb +48 -0
- data/spec/trema/mac_spec.rb +115 -0
- data/spec/trema/match_spec.rb +113 -0
- data/spec/trema/open-vswitch_spec.rb +123 -0
- data/spec/trema/openflow-error_spec.rb +141 -0
- data/spec/trema/openflow-switch_spec.rb +56 -0
- data/spec/trema/packet-in_spec.rb +168 -0
- data/spec/trema/packet-out_spec.rb +128 -0
- data/spec/trema/packetin-filter_spec.rb +41 -0
- data/spec/trema/port-mod_spec.rb +101 -0
- data/spec/trema/port-status_spec.rb +108 -0
- data/spec/trema/port_spec.rb +61 -0
- data/spec/trema/process_spec.rb +71 -0
- data/spec/trema/queue-get-config-reply_spec.rb +66 -0
- data/spec/trema/queue-get-config-request_spec.rb +69 -0
- data/spec/trema/set-config_spec.rb +80 -0
- data/spec/trema/shell/vhost_spec.rb +57 -0
- data/spec/trema/shell/vswitch_spec.rb +89 -0
- data/spec/trema/stats-reply_spec.rb +306 -0
- data/spec/trema/stats-request_spec.rb +151 -0
- data/spec/trema/switch-disconnected_spec.rb +58 -0
- data/spec/trema/switch-manager_spec.rb +43 -0
- data/spec/trema/tremashark_spec.rb +41 -0
- data/spec/trema/util_spec.rb +93 -0
- data/spec/trema/vendor-request_spec.rb +79 -0
- data/src/examples/cbench_switch/README +21 -0
- data/src/examples/cbench_switch/cbench-switch.rb +39 -0
- data/src/examples/cbench_switch/cbench_switch.c +68 -0
- data/src/examples/dumper/dumper.c +370 -0
- data/src/examples/dumper/dumper.conf +7 -0
- data/src/examples/dumper/dumper.rb +196 -0
- data/src/examples/hello_trema/README +13 -0
- data/src/examples/hello_trema/hello_trema.c +51 -0
- data/src/examples/hello_trema/hello_trema.conf +3 -0
- data/src/examples/hello_trema/hello_trema.rb +35 -0
- data/src/examples/learning_switch/README +15 -0
- data/src/examples/learning_switch/fdb.rb +112 -0
- data/src/examples/learning_switch/learning-switch.rb +88 -0
- data/src/examples/learning_switch/learning_switch.c +236 -0
- data/src/examples/learning_switch/learning_switch.conf +18 -0
- data/src/examples/list_switches/README +19 -0
- data/src/examples/list_switches/list-switches.rb +45 -0
- data/src/examples/list_switches/list_switches.c +81 -0
- data/src/examples/list_switches/list_switches.conf +15 -0
- data/src/examples/match_compare/match-compare.conf +30 -0
- data/src/examples/match_compare/match-compare.rb +99 -0
- data/src/examples/multi_learning_switch/README +14 -0
- data/src/examples/multi_learning_switch/multi-learning-switch.rb +96 -0
- data/src/examples/multi_learning_switch/multi_learning_switch.c +296 -0
- data/src/examples/multi_learning_switch/multi_learning_switch.conf +17 -0
- data/src/examples/openflow_message/README +11 -0
- data/src/examples/openflow_message/echo-reply.rb +59 -0
- data/src/examples/openflow_message/echo-request.rb +58 -0
- data/src/examples/openflow_message/echo_reply.c +70 -0
- data/src/examples/openflow_message/echo_request.c +70 -0
- data/src/examples/openflow_message/example.rb +63 -0
- data/src/examples/openflow_message/features-request.rb +97 -0
- data/src/examples/openflow_message/features_request.c +168 -0
- data/src/examples/openflow_message/hello.c +70 -0
- data/src/examples/openflow_message/hello.rb +58 -0
- data/src/examples/openflow_message/set-config.rb +59 -0
- data/src/examples/openflow_message/set_config.c +70 -0
- data/src/examples/packet_in/README +15 -0
- data/src/examples/packet_in/packet_in.c +55 -0
- data/src/examples/packet_in/packet_in.conf +15 -0
- data/src/examples/packet_in/packet_in.rb +34 -0
- data/src/examples/packetin_filter_config/README +12 -0
- data/src/examples/packetin_filter_config/add_filter.c +73 -0
- data/src/examples/packetin_filter_config/delete_filter.c +65 -0
- data/src/examples/packetin_filter_config/delete_filter_strict.c +75 -0
- data/src/examples/packetin_filter_config/dump_filter.c +65 -0
- data/src/examples/packetin_filter_config/dump_filter_strict.c +75 -0
- data/src/examples/packetin_filter_config/packetin_filter_config.c +134 -0
- data/src/examples/packetin_filter_config/packetin_filter_config.conf +7 -0
- data/src/examples/packetin_filter_config/utils.c +102 -0
- data/src/examples/packetin_filter_config/utils.h +42 -0
- data/src/examples/repeater_hub/README +8 -0
- data/src/examples/repeater_hub/repeater-hub.rb +43 -0
- data/src/examples/repeater_hub/repeater-hub_spec.rb +156 -0
- data/src/examples/repeater_hub/repeater_hub.c +83 -0
- data/src/examples/repeater_hub/repeater_hub.conf +28 -0
- data/src/examples/switch_info/README +13 -0
- data/src/examples/switch_info/switch_info.c +80 -0
- data/src/examples/switch_info/switch_info.conf +3 -0
- data/src/examples/switch_info/switch_info.rb +46 -0
- data/src/examples/switch_monitor/switch-monitor.conf +3 -0
- data/src/examples/switch_monitor/switch-monitor.rb +58 -0
- data/src/examples/switch_monitor/switch_monitor.c +154 -0
- data/src/examples/traffic_monitor/counter.c +74 -0
- data/src/examples/traffic_monitor/counter.h +48 -0
- data/src/examples/traffic_monitor/counter.rb +46 -0
- data/src/examples/traffic_monitor/fdb.c +76 -0
- data/src/examples/traffic_monitor/fdb.h +50 -0
- data/src/examples/traffic_monitor/fdb.rb +44 -0
- data/src/examples/traffic_monitor/traffic-monitor.rb +100 -0
- data/src/examples/traffic_monitor/traffic_monitor.c +163 -0
- data/src/examples/traffic_monitor/traffic_monitor.conf +16 -0
- data/src/lib/arp.h +61 -0
- data/src/lib/bool.h +49 -0
- data/src/lib/buffer.c +305 -0
- data/src/lib/buffer.h +56 -0
- data/src/lib/byteorder.c +547 -0
- data/src/lib/byteorder.h +110 -0
- data/src/lib/checks.h +42 -0
- data/src/lib/daemon.c +302 -0
- data/src/lib/daemon.h +42 -0
- data/src/lib/doubly_linked_list.c +281 -0
- data/src/lib/doubly_linked_list.h +88 -0
- data/src/lib/ether.c +48 -0
- data/src/lib/ether.h +94 -0
- data/src/lib/etherip.h +46 -0
- data/src/lib/event_handler.c +389 -0
- data/src/lib/event_handler.h +64 -0
- data/src/lib/hash_table.c +417 -0
- data/src/lib/hash_table.h +138 -0
- data/src/lib/icmp.h +74 -0
- data/src/lib/igmp.h +50 -0
- data/src/lib/ipv4.h +50 -0
- data/src/lib/linked_list.c +199 -0
- data/src/lib/linked_list.h +84 -0
- data/src/lib/log.c +402 -0
- data/src/lib/log.h +78 -0
- data/src/lib/match.h +84 -0
- data/src/lib/match_table.c +608 -0
- data/src/lib/match_table.h +51 -0
- data/src/lib/message_queue.c +143 -0
- data/src/lib/message_queue.h +61 -0
- data/src/lib/messenger.c +1714 -0
- data/src/lib/messenger.h +145 -0
- data/src/lib/openflow_application_interface.c +1673 -0
- data/src/lib/openflow_application_interface.h +329 -0
- data/src/lib/openflow_message.c +4051 -0
- data/src/lib/openflow_message.h +288 -0
- data/src/lib/openflow_service_interface.h +59 -0
- data/src/lib/packet_info.c +230 -0
- data/src/lib/packet_info.h +209 -0
- data/src/lib/packet_parser.c +502 -0
- data/src/lib/packetin_filter_interface.c +294 -0
- data/src/lib/packetin_filter_interface.h +127 -0
- data/src/lib/persistent_storage.c +480 -0
- data/src/lib/persistent_storage.h +46 -0
- data/src/lib/stat.c +213 -0
- data/src/lib/stat.h +44 -0
- data/src/lib/tcp.h +67 -0
- data/src/lib/timer.c +350 -0
- data/src/lib/timer.h +53 -0
- data/src/lib/trema.c +710 -0
- data/src/lib/trema.h +79 -0
- data/src/lib/trema_private.c +177 -0
- data/src/lib/trema_private.h +60 -0
- data/src/lib/trema_wrapper.c +56 -0
- data/src/lib/trema_wrapper.h +64 -0
- data/src/lib/udp.h +43 -0
- data/src/lib/utility.c +515 -0
- data/src/lib/utility.h +67 -0
- data/src/lib/wrapper.c +100 -0
- data/src/lib/wrapper.h +76 -0
- data/src/packetin_filter/README +17 -0
- data/src/packetin_filter/packetin_filter.c +575 -0
- data/src/switch_manager/README +20 -0
- data/src/switch_manager/cookie_table.c +292 -0
- data/src/switch_manager/cookie_table.h +72 -0
- data/src/switch_manager/dpid_table.c +110 -0
- data/src/switch_manager/dpid_table.h +46 -0
- data/src/switch_manager/management_interface.h +44 -0
- data/src/switch_manager/ofpmsg_recv.c +482 -0
- data/src/switch_manager/ofpmsg_recv.h +42 -0
- data/src/switch_manager/ofpmsg_send.c +235 -0
- data/src/switch_manager/ofpmsg_send.h +50 -0
- data/src/switch_manager/secure_channel_listener.c +281 -0
- data/src/switch_manager/secure_channel_listener.h +42 -0
- data/src/switch_manager/secure_channel_receiver.c +126 -0
- data/src/switch_manager/secure_channel_receiver.h +43 -0
- data/src/switch_manager/secure_channel_sender.c +126 -0
- data/src/switch_manager/secure_channel_sender.h +43 -0
- data/src/switch_manager/service_interface.c +181 -0
- data/src/switch_manager/service_interface.h +46 -0
- data/src/switch_manager/switch.c +538 -0
- data/src/switch_manager/switch.h +51 -0
- data/src/switch_manager/switch_manager.c +448 -0
- data/src/switch_manager/switch_manager.h +63 -0
- data/src/switch_manager/switchinfo.h +72 -0
- data/src/switch_manager/xid_table.c +184 -0
- data/src/switch_manager/xid_table.h +56 -0
- data/src/tremashark/README +78 -0
- data/src/tremashark/packet_capture.c +357 -0
- data/src/tremashark/pcap_private.h +47 -0
- data/src/tremashark/pcap_queue.c +197 -0
- data/src/tremashark/pcap_queue.h +58 -0
- data/src/tremashark/plugin/.gitignore +6 -0
- data/src/tremashark/plugin/packet-trema/.gitignore +5 -0
- data/src/tremashark/plugin/packet-trema/Makefile +77 -0
- data/src/tremashark/plugin/packet-trema/Makefile.am +110 -0
- data/src/tremashark/plugin/packet-trema/Makefile.common +31 -0
- data/src/tremashark/plugin/packet-trema/moduleinfo.h +41 -0
- data/src/tremashark/plugin/packet-trema/packet-trema.c +1659 -0
- data/src/tremashark/plugin/packet-trema/plugin.c +31 -0
- data/src/tremashark/plugin/user_dlts +2 -0
- data/src/tremashark/queue.c +168 -0
- data/src/tremashark/queue.h +60 -0
- data/src/tremashark/stdin_relay.c +257 -0
- data/src/tremashark/syslog_relay.c +247 -0
- data/src/tremashark/tremashark.c +556 -0
- data/trema +93 -0
- data/trema-config +61 -0
- data/unittests/buffer_stubs.c +74 -0
- data/unittests/cmockery_trema.c +123 -0
- data/unittests/cmockery_trema.h +96 -0
- data/unittests/lib/buffer_test.c +370 -0
- data/unittests/lib/byteorder_test.c +1717 -0
- data/unittests/lib/daemon_test.c +664 -0
- data/unittests/lib/doubly_linked_list_test.c +346 -0
- data/unittests/lib/ether_test.c +127 -0
- data/unittests/lib/hash_table_test.c +278 -0
- data/unittests/lib/linked_list_test.c +343 -0
- data/unittests/lib/log_test.c +459 -0
- data/unittests/lib/match_table_test.c +1509 -0
- data/unittests/lib/message_queue_test.c +379 -0
- data/unittests/lib/messenger_test.c +438 -0
- data/unittests/lib/openflow_application_interface_test.c +3488 -0
- data/unittests/lib/openflow_message_test.c +7337 -0
- data/unittests/lib/packet_info_test.c +544 -0
- data/unittests/lib/packet_parser_test.c +703 -0
- data/unittests/lib/packetin_filter_interface_test.c +723 -0
- data/unittests/lib/persistent_storage_test.c +802 -0
- data/unittests/lib/stat_test.c +291 -0
- data/unittests/lib/test_packets/arp_rep.cap +0 -0
- data/unittests/lib/test_packets/arp_req.cap +0 -0
- data/unittests/lib/test_packets/icmp_echo_rep.cap +0 -0
- data/unittests/lib/test_packets/icmp_echo_req.cap +0 -0
- data/unittests/lib/test_packets/igmp_query_v2.cap +0 -0
- data/unittests/lib/test_packets/ipx.cap +0 -0
- data/unittests/lib/test_packets/lldp.cap +0 -0
- data/unittests/lib/test_packets/lldp_over_ip.cap +0 -0
- data/unittests/lib/test_packets/tcp.cap +0 -0
- data/unittests/lib/test_packets/tcp_syn.cap +0 -0
- data/unittests/lib/test_packets/udp.cap +0 -0
- data/unittests/lib/test_packets/udp_frag_head.cap +0 -0
- data/unittests/lib/test_packets/udp_frag_next.cap +0 -0
- data/unittests/lib/test_packets/vtag_icmp_echo_rep.cap +0 -0
- data/unittests/lib/test_packets/vtag_icmp_echo_req.cap +0 -0
- data/unittests/lib/timer_test.c +248 -0
- data/unittests/lib/trema_private_test.c +323 -0
- data/unittests/lib/trema_test.c +985 -0
- data/unittests/lib/utility_test.c +628 -0
- data/unittests/lib/wrapper_test.c +201 -0
- data/unittests/packetin_filter/packetin_filter_test.c +477 -0
- data/unittests/switch_manager/switch_manager_test.c +1178 -0
- data/unittests/wrapper_stubs.c +39 -0
- data/vendor/.gitignore +6 -0
- data/vendor/README +30 -0
- data/vendor/cmockery-20110428.tar.gz +0 -0
- data/vendor/oflops-0.03.tar.gz +0 -0
- data/vendor/oflops_no_snmp+1.0.0.patch +340 -0
- data/vendor/openflow-1.0.0.tar.gz +0 -0
- data/vendor/openflow.git.tar.gz +0 -0
- data/vendor/openvswitch-1.2.2.tar.gz +0 -0
- data/vendor/ruby-ifconfig-1.2/COPYING +340 -0
- data/vendor/ruby-ifconfig-1.2/Changelog +16 -0
- data/vendor/ruby-ifconfig-1.2/INSTALL +239 -0
- data/vendor/ruby-ifconfig-1.2/README +38 -0
- data/vendor/ruby-ifconfig-1.2/Rakefile +14 -0
- data/vendor/ruby-ifconfig-1.2/TODO +8 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/darwin.txt +17 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/dragonflybsd.txt +10 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/dragonflybsd_netstat.txt +14 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/freebsd.txt +17 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/freebsd_netstat.txt +24 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/linux.txt +60 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/linux_ethernet.txt +20 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/netbsd.txt +10 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/openbsd.txt +36 -0
- data/vendor/ruby-ifconfig-1.2/ifconfig_examples/sunos.txt +10 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig.rb +71 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/ifconfig.rb +72 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/interface_types.rb +69 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/network_types.rb +3 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/ifconfig.rb +84 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/interface_types.rb +130 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/network_types.rb +49 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/ifconfig.rb +43 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/interface_types.rb +112 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/network_types.rb +55 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/ifconfig.rb +38 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/interface_types.rb +77 -0
- data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/network_types.rb +4 -0
- data/vendor/ruby-ifconfig-1.2/setup.rb +1306 -0
- data/vendor/ruby-ifconfig-1.2/test/test_bsd.rb +35 -0
- data/vendor/ruby-ifconfig-1.2/test/test_darwin.rb +33 -0
- data/vendor/ruby-ifconfig-1.2/test/test_dragonflybsd.rb +35 -0
- data/vendor/ruby-ifconfig-1.2/test/test_helper.rb +4 -0
- data/vendor/ruby-ifconfig-1.2/test/test_linux.rb +31 -0
- data/vendor/ruby-ifconfig-1.2/test/test_netbsd.rb +33 -0
- data/vendor/ruby-ifconfig-1.2/test/test_openbsd.rb +33 -0
- data/vendor/ruby-ifconfig-1.2/test/test_sunos.rb +35 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_darwin.rb +40 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_dragonflybsd.rb +39 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_freebsd.rb +40 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_linux.rb +49 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_netbsd.rb +39 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_openbsd.rb +39 -0
- data/vendor/ruby-ifconfig-1.2/test/unit/tc_sunos.rb +44 -0
- metadata +856 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* OpenFlow flow matching library
|
|
3
|
+
*
|
|
4
|
+
* Author: Kazushi SUGYO
|
|
5
|
+
*
|
|
6
|
+
* Copyright (C) 2008-2012 NEC Corporation
|
|
7
|
+
*
|
|
8
|
+
* This program is free software; you can redistribute it and/or modify
|
|
9
|
+
* it under the terms of the GNU General Public License, version 2, as
|
|
10
|
+
* published by the Free Software Foundation.
|
|
11
|
+
*
|
|
12
|
+
* This program is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
* GNU General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU General Public License along
|
|
18
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
19
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#ifndef MATCH_TABLE_H
|
|
24
|
+
#define MATCH_TABLE_H
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
#include <openflow.h>
|
|
28
|
+
#include "hash_table.h"
|
|
29
|
+
#include "linked_list.h"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
void init_match_table( void );
|
|
33
|
+
void finalize_match_table( void );
|
|
34
|
+
bool insert_match_entry( struct ofp_match match, uint16_t priority, void *data );
|
|
35
|
+
void *lookup_match_strict_entry( struct ofp_match match, uint16_t priority );
|
|
36
|
+
void *lookup_match_entry( struct ofp_match match );
|
|
37
|
+
bool update_match_entry( struct ofp_match match, uint16_t priority, void *data );
|
|
38
|
+
void *delete_match_strict_entry( struct ofp_match match, uint16_t priority );
|
|
39
|
+
void foreach_match_table( void function( struct ofp_match match, uint16_t priority, void *data, void *user_data ), void *user_data );
|
|
40
|
+
void map_match_table( struct ofp_match match, void function( struct ofp_match match, uint16_t priority, void *data, void *user_data ), void *user_data );
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
#endif // MATCH_TABLE_H
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/*
|
|
47
|
+
* Local variables:
|
|
48
|
+
* c-basic-offset: 2
|
|
49
|
+
* indent-tabs-mode: nil
|
|
50
|
+
* End:
|
|
51
|
+
*/
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Author: Yasunobu Chiba
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2008-2012 NEC Corporation
|
|
5
|
+
*
|
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
|
7
|
+
* it under the terms of the GNU General Public License, version 2, as
|
|
8
|
+
* published by the Free Software Foundation.
|
|
9
|
+
*
|
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU General Public License along
|
|
16
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
17
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#include <assert.h>
|
|
22
|
+
#include "wrapper.h"
|
|
23
|
+
#include "message_queue.h"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
message_queue *
|
|
27
|
+
create_message_queue( void ) {
|
|
28
|
+
message_queue *new_queue = xmalloc( sizeof( message_queue ) );
|
|
29
|
+
new_queue->head = xmalloc( sizeof( message_queue_element ) );
|
|
30
|
+
new_queue->head->data = NULL;
|
|
31
|
+
new_queue->head->next = NULL;
|
|
32
|
+
new_queue->divider = new_queue->tail = new_queue->head;
|
|
33
|
+
new_queue->length = 0;
|
|
34
|
+
|
|
35
|
+
return new_queue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
bool
|
|
40
|
+
delete_message_queue( message_queue *queue ) {
|
|
41
|
+
if ( queue == NULL ) {
|
|
42
|
+
die( "queue must not be NULL" );
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
while( queue->head != NULL ) {
|
|
46
|
+
message_queue_element *element = queue->head;
|
|
47
|
+
if ( queue->head->data != NULL ) {
|
|
48
|
+
free_buffer( element->data );
|
|
49
|
+
}
|
|
50
|
+
queue->head = queue->head->next;
|
|
51
|
+
xfree( element );
|
|
52
|
+
}
|
|
53
|
+
xfree( queue );
|
|
54
|
+
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
static void
|
|
60
|
+
collect_garbage( message_queue *queue ) {
|
|
61
|
+
while ( queue->head != queue->divider ) {
|
|
62
|
+
message_queue_element *element = queue->head;
|
|
63
|
+
queue->head = queue->head->next;
|
|
64
|
+
xfree( element );
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
bool
|
|
70
|
+
enqueue_message( message_queue *queue, buffer *message ) {
|
|
71
|
+
if ( queue == NULL ) {
|
|
72
|
+
die( "queues must not be NULL" );
|
|
73
|
+
}
|
|
74
|
+
if ( message == NULL ) {
|
|
75
|
+
die( "message must not be NULL" );
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
message_queue_element *new_tail = xmalloc( sizeof( message_queue_element ) );
|
|
79
|
+
new_tail->data = message;
|
|
80
|
+
new_tail->next = NULL;
|
|
81
|
+
|
|
82
|
+
queue->tail->next = new_tail;
|
|
83
|
+
queue->tail = new_tail;
|
|
84
|
+
queue->length++;
|
|
85
|
+
|
|
86
|
+
collect_garbage( queue );
|
|
87
|
+
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
buffer *
|
|
93
|
+
dequeue_message( message_queue *queue ) {
|
|
94
|
+
if ( queue == NULL ) {
|
|
95
|
+
die( "queue must not be NULL" );
|
|
96
|
+
}
|
|
97
|
+
if ( queue->divider == queue->tail ) {
|
|
98
|
+
return NULL;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
message_queue_element *next = queue->divider->next;
|
|
102
|
+
buffer *message = next->data;
|
|
103
|
+
next->data = NULL; // data must be freed by caller
|
|
104
|
+
queue->divider = next;
|
|
105
|
+
queue->length--;
|
|
106
|
+
|
|
107
|
+
return message;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
buffer *
|
|
112
|
+
peek_message( message_queue *queue ) {
|
|
113
|
+
if ( queue == NULL ) {
|
|
114
|
+
die( "queue must not be NULL" );
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if ( queue->divider == queue->tail ) {
|
|
118
|
+
return NULL;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return queue->divider->next->data;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
void foreach_message_queue( message_queue *queue, void function( buffer *message, void *user_data ), void *user_data ) {
|
|
126
|
+
if ( queue->divider == queue->tail ) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
message_queue_element *element;
|
|
130
|
+
for ( element = queue->divider->next; element != NULL; element = element->next ) {
|
|
131
|
+
buffer *message = element->data;
|
|
132
|
+
assert( message != NULL );
|
|
133
|
+
function( message, user_data );
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/*
|
|
139
|
+
* Local variables:
|
|
140
|
+
* c-basic-offset: 2
|
|
141
|
+
* indent-tabs-mode: nil
|
|
142
|
+
* End:
|
|
143
|
+
*/
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Queue implementation
|
|
3
|
+
*
|
|
4
|
+
* Author: Yasunobu Chiba
|
|
5
|
+
*
|
|
6
|
+
* Copyright (C) 2008-2012 NEC Corporation
|
|
7
|
+
*
|
|
8
|
+
* This program is free software; you can redistribute it and/or modify
|
|
9
|
+
* it under the terms of the GNU General Public License, version 2, as
|
|
10
|
+
* published by the Free Software Foundation.
|
|
11
|
+
*
|
|
12
|
+
* This program is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
* GNU General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU General Public License along
|
|
18
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
19
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#ifndef MESSAGE_QUEUE_H
|
|
24
|
+
#define MESSAGE_QUEUE_H
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
#include "bool.h"
|
|
28
|
+
#include "buffer.h"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
typedef struct message_queue_element {
|
|
32
|
+
buffer *data;
|
|
33
|
+
struct message_queue_element *next;
|
|
34
|
+
} message_queue_element;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
typedef struct {
|
|
38
|
+
message_queue_element *head;
|
|
39
|
+
message_queue_element *divider;
|
|
40
|
+
message_queue_element *tail;
|
|
41
|
+
unsigned int length;
|
|
42
|
+
} message_queue;
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
message_queue *create_message_queue( void );
|
|
46
|
+
bool delete_message_queue( message_queue *queue );
|
|
47
|
+
bool enqueue_message( message_queue *queue, buffer *message );
|
|
48
|
+
buffer *dequeue_message( message_queue *queue );
|
|
49
|
+
buffer *peek_message( message_queue *queue );
|
|
50
|
+
void foreach_message_queue( message_queue *queue, void function( buffer *message, void *user_data ), void *user_data );
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
#endif // MESSAGE_QUEUE_H
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* Local variables:
|
|
58
|
+
* c-basic-offset: 2
|
|
59
|
+
* indent-tabs-mode: nil
|
|
60
|
+
* End:
|
|
61
|
+
*/
|
data/src/lib/messenger.c
ADDED
|
@@ -0,0 +1,1714 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Author: Toshio Koide
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2008-2012 NEC Corporation
|
|
5
|
+
*
|
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
|
7
|
+
* it under the terms of the GNU General Public License, version 2, as
|
|
8
|
+
* published by the Free Software Foundation.
|
|
9
|
+
*
|
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU General Public License along
|
|
16
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
17
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#include <arpa/inet.h>
|
|
22
|
+
#include <assert.h>
|
|
23
|
+
#include <errno.h>
|
|
24
|
+
#include <fcntl.h>
|
|
25
|
+
#include <inttypes.h>
|
|
26
|
+
#include <linux/limits.h>
|
|
27
|
+
#include <linux/sockios.h>
|
|
28
|
+
#include <stdio.h>
|
|
29
|
+
#include <stdlib.h>
|
|
30
|
+
#include <sys/ioctl.h>
|
|
31
|
+
#include <sys/socket.h>
|
|
32
|
+
#include <sys/types.h>
|
|
33
|
+
#include <sys/un.h>
|
|
34
|
+
#include <unistd.h>
|
|
35
|
+
#include "doubly_linked_list.h"
|
|
36
|
+
#include "event_handler.h"
|
|
37
|
+
#include "hash_table.h"
|
|
38
|
+
#include "log.h"
|
|
39
|
+
#include "messenger.h"
|
|
40
|
+
#include "timer.h"
|
|
41
|
+
#include "wrapper.h"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
#ifdef UNIT_TESTING
|
|
45
|
+
|
|
46
|
+
#define static
|
|
47
|
+
|
|
48
|
+
// Redirect socket functions to mock functions in the unit test.
|
|
49
|
+
#ifdef socket
|
|
50
|
+
#undef socket
|
|
51
|
+
#endif
|
|
52
|
+
#define socket mock_socket
|
|
53
|
+
extern int mock_socket( int domain, int type, int protocol );
|
|
54
|
+
|
|
55
|
+
#ifdef bind
|
|
56
|
+
#undef bind
|
|
57
|
+
#endif
|
|
58
|
+
#define bind mock_bind
|
|
59
|
+
extern int mock_bind( int sockfd, const struct sockaddr *addr, socklen_t addrlen );
|
|
60
|
+
|
|
61
|
+
#ifdef listen
|
|
62
|
+
#undef listen
|
|
63
|
+
#endif
|
|
64
|
+
#define listen mock_listen
|
|
65
|
+
extern int mock_listen( int sockfd, int backlog );
|
|
66
|
+
|
|
67
|
+
#ifdef close
|
|
68
|
+
#undef close
|
|
69
|
+
#endif
|
|
70
|
+
#define close mock_close
|
|
71
|
+
extern int mock_close( int fd );
|
|
72
|
+
|
|
73
|
+
#ifdef connect
|
|
74
|
+
#undef connect
|
|
75
|
+
#endif
|
|
76
|
+
#define connect mock_connect
|
|
77
|
+
extern int mock_connect( int sockfd, const struct sockaddr *addr, socklen_t addrlen );
|
|
78
|
+
|
|
79
|
+
#ifdef select
|
|
80
|
+
#undef select
|
|
81
|
+
#endif
|
|
82
|
+
#define select mock_select
|
|
83
|
+
extern int mock_select( int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout );
|
|
84
|
+
|
|
85
|
+
#ifdef accept
|
|
86
|
+
#undef accept
|
|
87
|
+
#endif
|
|
88
|
+
#define accept mock_accept
|
|
89
|
+
extern int mock_accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen );
|
|
90
|
+
|
|
91
|
+
#ifdef recv
|
|
92
|
+
#undef recv
|
|
93
|
+
#endif
|
|
94
|
+
#define recv mock_recv
|
|
95
|
+
extern ssize_t mock_recv( int sockfd, void *buf, size_t len, int flags );
|
|
96
|
+
|
|
97
|
+
#ifdef send
|
|
98
|
+
#undef send
|
|
99
|
+
#endif
|
|
100
|
+
#define send mock_send
|
|
101
|
+
extern ssize_t mock_send( int sockfd, const void *buf, size_t len, int flags );
|
|
102
|
+
|
|
103
|
+
#ifdef setsockopt
|
|
104
|
+
#undef setsockopt
|
|
105
|
+
#endif
|
|
106
|
+
#define setsockopt mock_setsockopt
|
|
107
|
+
extern int mock_setsockopt( int s, int level, int optname, const void *optval, socklen_t optlen );
|
|
108
|
+
|
|
109
|
+
#ifdef clock_gettime
|
|
110
|
+
#undef clock_gettime
|
|
111
|
+
#endif
|
|
112
|
+
#define clock_gettime mock_clock_gettime
|
|
113
|
+
extern int mock_clock_gettime( clockid_t clk_id, struct timespec *tp );
|
|
114
|
+
|
|
115
|
+
#ifdef error
|
|
116
|
+
#undef error
|
|
117
|
+
#endif
|
|
118
|
+
#define error mock_error
|
|
119
|
+
extern void mock_error( const char *format, ... );
|
|
120
|
+
|
|
121
|
+
#ifdef debug
|
|
122
|
+
#undef debug
|
|
123
|
+
#endif
|
|
124
|
+
#define debug mock_debug
|
|
125
|
+
extern void mock_debug( const char *format, ... );
|
|
126
|
+
|
|
127
|
+
#ifdef warn
|
|
128
|
+
#undef warn
|
|
129
|
+
#endif
|
|
130
|
+
#define warn mock_warn
|
|
131
|
+
extern void mock_warn( const char *format, ... );
|
|
132
|
+
|
|
133
|
+
#ifdef add_periodic_event_callback
|
|
134
|
+
#undef add_periodic_event_callback
|
|
135
|
+
#endif
|
|
136
|
+
#define add_periodic_event_callback mock_add_periodic_event_callback
|
|
137
|
+
extern bool mock_add_periodic_event_callback( const time_t seconds, void ( *callback )( void *user_data ), void *user_data );
|
|
138
|
+
|
|
139
|
+
#endif // UNIT_TESTING
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
enum {
|
|
143
|
+
MESSAGE_TYPE_NOTIFY,
|
|
144
|
+
MESSAGE_TYPE_REQUEST,
|
|
145
|
+
MESSAGE_TYPE_REPLY,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
typedef struct message_buffer {
|
|
149
|
+
void *buffer;
|
|
150
|
+
size_t data_length;
|
|
151
|
+
size_t size;
|
|
152
|
+
size_t head_offset;
|
|
153
|
+
} message_buffer;
|
|
154
|
+
|
|
155
|
+
typedef struct messenger_socket {
|
|
156
|
+
int fd;
|
|
157
|
+
} messenger_socket;
|
|
158
|
+
|
|
159
|
+
typedef struct messenger_context {
|
|
160
|
+
uint32_t transaction_id;
|
|
161
|
+
int life_count;
|
|
162
|
+
void *user_data;
|
|
163
|
+
} messenger_context;
|
|
164
|
+
|
|
165
|
+
typedef struct receive_queue_callback {
|
|
166
|
+
void *function;
|
|
167
|
+
uint8_t message_type;
|
|
168
|
+
} receive_queue_callback;
|
|
169
|
+
|
|
170
|
+
typedef struct receive_queue {
|
|
171
|
+
char service_name[ MESSENGER_SERVICE_NAME_LENGTH ];
|
|
172
|
+
dlist_element *message_callbacks;
|
|
173
|
+
int listen_socket;
|
|
174
|
+
struct sockaddr_un listen_addr;
|
|
175
|
+
dlist_element *client_sockets;
|
|
176
|
+
message_buffer *buffer;
|
|
177
|
+
} receive_queue;
|
|
178
|
+
|
|
179
|
+
typedef struct send_queue {
|
|
180
|
+
char service_name[ MESSENGER_SERVICE_NAME_LENGTH ];
|
|
181
|
+
int server_socket;
|
|
182
|
+
int refused_count;
|
|
183
|
+
struct timespec reconnect_interval;
|
|
184
|
+
struct sockaddr_un server_addr;
|
|
185
|
+
message_buffer *buffer;
|
|
186
|
+
bool running_timer;
|
|
187
|
+
uint32_t overflow;
|
|
188
|
+
uint64_t overflow_total_length;
|
|
189
|
+
int socket_buffer_size;
|
|
190
|
+
} send_queue;
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
#define MESSENGER_RECV_BUFFER 100000
|
|
194
|
+
static const uint32_t messenger_send_queue_length = MESSENGER_RECV_BUFFER * 4;
|
|
195
|
+
static const uint32_t messenger_send_length_for_flush = MESSENGER_RECV_BUFFER;
|
|
196
|
+
static const uint32_t messenger_bucket_size = MESSENGER_RECV_BUFFER;
|
|
197
|
+
static const uint32_t messenger_recv_queue_length = MESSENGER_RECV_BUFFER * 2;
|
|
198
|
+
static const uint32_t messenger_recv_queue_reserved = MESSENGER_RECV_BUFFER;
|
|
199
|
+
|
|
200
|
+
char socket_directory[ PATH_MAX ];
|
|
201
|
+
static bool initialized = false;
|
|
202
|
+
static bool finalized = false;
|
|
203
|
+
static hash_table *receive_queues = NULL;
|
|
204
|
+
static hash_table *send_queues = NULL;
|
|
205
|
+
static hash_table *context_db = NULL;
|
|
206
|
+
static char *_dump_service_name = NULL;
|
|
207
|
+
static char *_dump_app_name = NULL;
|
|
208
|
+
static uint32_t last_transaction_id = 0;
|
|
209
|
+
|
|
210
|
+
static void on_accept( int fd, void *data );
|
|
211
|
+
static void on_recv( int fd, void *data );
|
|
212
|
+
static void on_send_write( int fd, void *data );
|
|
213
|
+
static void on_send_read( int fd, void *data );
|
|
214
|
+
|
|
215
|
+
static void
|
|
216
|
+
_delete_context( void *key, void *value, void *user_data ) {
|
|
217
|
+
assert( value != NULL );
|
|
218
|
+
UNUSED( key );
|
|
219
|
+
UNUSED( user_data );
|
|
220
|
+
messenger_context *context = value;
|
|
221
|
+
|
|
222
|
+
debug( "Deleting a context ( transaction_id = %#x, life_count = %d, user_data = %p ).",
|
|
223
|
+
context->transaction_id, context->life_count, context->user_data );
|
|
224
|
+
|
|
225
|
+
delete_hash_entry( context_db, &context->transaction_id );
|
|
226
|
+
xfree( context );
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
static void
|
|
231
|
+
delete_context( messenger_context *context ) {
|
|
232
|
+
assert( context != NULL );
|
|
233
|
+
|
|
234
|
+
_delete_context( &context->transaction_id, context, NULL );
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
static void
|
|
239
|
+
_age_context( void *key, void *value, void *user_data ) {
|
|
240
|
+
assert( value != NULL );
|
|
241
|
+
UNUSED( key );
|
|
242
|
+
UNUSED( user_data );
|
|
243
|
+
messenger_context *context = value;
|
|
244
|
+
context->life_count--;
|
|
245
|
+
if ( context->life_count <= 0 ) {
|
|
246
|
+
delete_context( context );
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
static void
|
|
252
|
+
age_context_db( void *user_data ) {
|
|
253
|
+
UNUSED( user_data );
|
|
254
|
+
|
|
255
|
+
debug( "Aging context database ( context_db = %p ).", context_db );
|
|
256
|
+
|
|
257
|
+
foreach_hash( context_db, _age_context, NULL );
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
bool
|
|
262
|
+
init_messenger( const char *working_directory ) {
|
|
263
|
+
assert( working_directory != NULL );
|
|
264
|
+
|
|
265
|
+
init_event_handler();
|
|
266
|
+
|
|
267
|
+
if ( initialized ) {
|
|
268
|
+
warn( "Messenger is already initialized." );
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
strcpy( socket_directory, working_directory );
|
|
273
|
+
|
|
274
|
+
receive_queues = create_hash( compare_string, hash_string );
|
|
275
|
+
send_queues = create_hash( compare_string, hash_string );
|
|
276
|
+
context_db = create_hash( compare_uint32, hash_uint32 );
|
|
277
|
+
|
|
278
|
+
initialized = true;
|
|
279
|
+
finalized = false;
|
|
280
|
+
|
|
281
|
+
return initialized;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
static void
|
|
286
|
+
delete_context_db( void ) {
|
|
287
|
+
debug( "Deleting context database ( context_db = %p ).", context_db );
|
|
288
|
+
|
|
289
|
+
if ( context_db != NULL ) {
|
|
290
|
+
foreach_hash( context_db, _delete_context, NULL );
|
|
291
|
+
delete_hash( context_db );
|
|
292
|
+
context_db = NULL;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
static void
|
|
298
|
+
free_message_buffer( message_buffer *buf ) {
|
|
299
|
+
assert( buf != NULL );
|
|
300
|
+
|
|
301
|
+
xfree( buf->buffer );
|
|
302
|
+
xfree( buf );
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
static void*
|
|
307
|
+
get_message_buffer_head( message_buffer *buf ) {
|
|
308
|
+
return ( char * ) buf->buffer + buf->head_offset;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
static void
|
|
313
|
+
delete_send_queue( send_queue *sq ) {
|
|
314
|
+
assert( NULL != sq );
|
|
315
|
+
|
|
316
|
+
debug( "Deleting a send queue ( service_name = %s, fd = %d ).", sq->service_name, sq->server_socket );
|
|
317
|
+
|
|
318
|
+
free_message_buffer( sq->buffer );
|
|
319
|
+
if ( sq->server_socket != -1 ) {
|
|
320
|
+
set_readable( sq->server_socket, false );
|
|
321
|
+
set_writable( sq->server_socket, false );
|
|
322
|
+
delete_fd_handler( sq->server_socket );
|
|
323
|
+
|
|
324
|
+
close( sq->server_socket );
|
|
325
|
+
}
|
|
326
|
+
if ( send_queues != NULL ) {
|
|
327
|
+
delete_hash_entry( send_queues, sq->service_name );
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
error( "All send queues are already deleted or not created yet." );
|
|
331
|
+
}
|
|
332
|
+
xfree( sq );
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
static void
|
|
337
|
+
delete_all_send_queues() {
|
|
338
|
+
hash_iterator iter;
|
|
339
|
+
hash_entry *e;
|
|
340
|
+
|
|
341
|
+
debug( "Deleting all send queues ( send_queues = %p ).", send_queues );
|
|
342
|
+
|
|
343
|
+
if ( send_queues != NULL ) {
|
|
344
|
+
init_hash_iterator( send_queues, &iter );
|
|
345
|
+
while ( ( e = iterate_hash_next( &iter ) ) != NULL ) {
|
|
346
|
+
delete_send_queue( e->value );
|
|
347
|
+
}
|
|
348
|
+
delete_hash( send_queues );
|
|
349
|
+
send_queues = NULL;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
error( "All send queues are already deleted or not created yet." );
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
static void
|
|
358
|
+
send_dump_message( uint16_t dump_type, const char *service_name, const void *data, uint32_t data_len ) {
|
|
359
|
+
assert( service_name != NULL );
|
|
360
|
+
|
|
361
|
+
debug( "Sending a dump message ( dump_type = %#x, service_name = %s, data = %p, data_len = %u ).",
|
|
362
|
+
dump_type, service_name, data, data_len );
|
|
363
|
+
|
|
364
|
+
size_t service_name_len, app_name_len;
|
|
365
|
+
char *dump_buf, *p;
|
|
366
|
+
message_dump_header *dump_hdr;
|
|
367
|
+
size_t dump_buf_len;
|
|
368
|
+
|
|
369
|
+
if ( _dump_service_name == NULL ) {
|
|
370
|
+
debug( "Dump service name is not set." );
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if ( strcmp( service_name, _dump_service_name ) == 0 ) {
|
|
374
|
+
debug( "Source service name and destination service name are the same ( service name = %s ).", service_name );
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
struct timespec now;
|
|
379
|
+
if ( clock_gettime( CLOCK_REALTIME, &now ) == -1 ) {
|
|
380
|
+
error( "Failed to retrieve system-wide real-time clock ( %s [%d] ).", strerror( errno ), errno );
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
service_name_len = strlen( service_name ) + 1;
|
|
385
|
+
app_name_len = strlen( _dump_app_name ) + 1;
|
|
386
|
+
dump_buf_len = sizeof( message_dump_header ) + app_name_len + service_name_len + data_len;
|
|
387
|
+
dump_buf = xmalloc( dump_buf_len );
|
|
388
|
+
dump_hdr = ( message_dump_header * ) dump_buf;
|
|
389
|
+
|
|
390
|
+
// header
|
|
391
|
+
dump_hdr->sent_time.sec = htonl( ( uint32_t ) now.tv_sec );
|
|
392
|
+
dump_hdr->sent_time.nsec = htonl( ( uint32_t ) now.tv_nsec );
|
|
393
|
+
dump_hdr->app_name_length = htons( ( uint16_t ) app_name_len );
|
|
394
|
+
dump_hdr->service_name_length = htons( ( uint16_t ) service_name_len );
|
|
395
|
+
dump_hdr->data_length = htonl( data_len );
|
|
396
|
+
|
|
397
|
+
// app name
|
|
398
|
+
p = dump_buf;
|
|
399
|
+
p += sizeof( message_dump_header );
|
|
400
|
+
memcpy( p, _dump_app_name, app_name_len );
|
|
401
|
+
|
|
402
|
+
// service name
|
|
403
|
+
p += app_name_len;
|
|
404
|
+
memcpy( p, service_name, service_name_len );
|
|
405
|
+
|
|
406
|
+
// data
|
|
407
|
+
p += service_name_len;
|
|
408
|
+
memcpy( p, data, data_len );
|
|
409
|
+
|
|
410
|
+
// send
|
|
411
|
+
send_message( _dump_service_name, dump_type, dump_buf, dump_buf_len );
|
|
412
|
+
|
|
413
|
+
xfree( dump_buf );
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* closes accepted sockets and listening socket, and releases memories.
|
|
419
|
+
*/
|
|
420
|
+
static void
|
|
421
|
+
delete_receive_queue( void *service_name, void *_rq, void *user_data ) {
|
|
422
|
+
debug( "Deleting a receive queue ( service_name = %s, _rq = %p, user_data = %p ).", service_name, _rq, user_data );
|
|
423
|
+
|
|
424
|
+
receive_queue *rq = _rq;
|
|
425
|
+
messenger_socket *client_socket;
|
|
426
|
+
dlist_element *element;
|
|
427
|
+
receive_queue_callback *cb;
|
|
428
|
+
|
|
429
|
+
assert( rq != NULL );
|
|
430
|
+
for ( element = rq->message_callbacks->next; element; element = element->next ) {
|
|
431
|
+
cb = element->data;
|
|
432
|
+
debug( "Deleting a callback ( function = %p, message_type = %#x ).", cb->function, cb->message_type );
|
|
433
|
+
xfree( cb );
|
|
434
|
+
}
|
|
435
|
+
delete_dlist( rq->message_callbacks );
|
|
436
|
+
|
|
437
|
+
for ( element = rq->client_sockets->next; element; element = element->next ) {
|
|
438
|
+
client_socket = element->data;
|
|
439
|
+
|
|
440
|
+
debug( "Closing a client socket ( fd = %d ).", client_socket->fd );
|
|
441
|
+
|
|
442
|
+
set_readable( client_socket->fd, false );
|
|
443
|
+
delete_fd_handler( client_socket->fd );
|
|
444
|
+
|
|
445
|
+
close( client_socket->fd );
|
|
446
|
+
xfree( client_socket );
|
|
447
|
+
send_dump_message( MESSENGER_DUMP_RECV_CLOSED, rq->service_name, NULL, 0 );
|
|
448
|
+
}
|
|
449
|
+
delete_dlist( rq->client_sockets );
|
|
450
|
+
|
|
451
|
+
set_readable( rq->listen_socket, false );
|
|
452
|
+
delete_fd_handler( rq->listen_socket );
|
|
453
|
+
|
|
454
|
+
close( rq->listen_socket );
|
|
455
|
+
free_message_buffer( rq->buffer );
|
|
456
|
+
unlink( rq->listen_addr.sun_path );
|
|
457
|
+
|
|
458
|
+
if ( receive_queues != NULL ) {
|
|
459
|
+
delete_hash_entry( receive_queues, rq->service_name );
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
error( "All receive queues are already deleted or not created yet." );
|
|
463
|
+
}
|
|
464
|
+
xfree( rq );
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
static void
|
|
469
|
+
delete_all_receive_queues() {
|
|
470
|
+
debug( "Deleting all receive queues ( receive_queues = %p ).", receive_queues );
|
|
471
|
+
|
|
472
|
+
if ( receive_queues != NULL ) {
|
|
473
|
+
foreach_hash( receive_queues, delete_receive_queue, NULL );
|
|
474
|
+
delete_hash( receive_queues );
|
|
475
|
+
receive_queues = NULL;
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
error( "All receive queues are already deleted or not created yet." );
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
bool
|
|
484
|
+
finalize_messenger() {
|
|
485
|
+
debug( "Finalizing messenger." );
|
|
486
|
+
|
|
487
|
+
if ( !initialized ) {
|
|
488
|
+
warn( "Messenger is not initialized yet." );
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
if ( finalized ) {
|
|
492
|
+
warn( "Messenger is already finalized." );
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if ( messenger_dump_enabled() ) {
|
|
497
|
+
stop_messenger_dump();
|
|
498
|
+
}
|
|
499
|
+
if ( receive_queues != NULL ) {
|
|
500
|
+
delete_all_receive_queues();
|
|
501
|
+
}
|
|
502
|
+
if ( send_queues != NULL ) {
|
|
503
|
+
delete_all_send_queues();
|
|
504
|
+
}
|
|
505
|
+
if ( context_db != NULL ) {
|
|
506
|
+
delete_context_db();
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
initialized = false;
|
|
510
|
+
finalized = true;
|
|
511
|
+
|
|
512
|
+
finalize_event_handler();
|
|
513
|
+
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
static message_buffer *
|
|
519
|
+
create_message_buffer( size_t size ) {
|
|
520
|
+
message_buffer *buf = xmalloc( sizeof( message_buffer ) );
|
|
521
|
+
|
|
522
|
+
buf->buffer = xmalloc( size );
|
|
523
|
+
buf->size = size;
|
|
524
|
+
buf->data_length = 0;
|
|
525
|
+
buf->head_offset = 0;
|
|
526
|
+
|
|
527
|
+
return buf;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
static receive_queue *
|
|
532
|
+
create_receive_queue( const char *service_name ) {
|
|
533
|
+
assert( service_name != NULL );
|
|
534
|
+
assert( strlen( service_name ) < MESSENGER_SERVICE_NAME_LENGTH );
|
|
535
|
+
|
|
536
|
+
debug( "Creating a receive queue (service_name = %s).", service_name );
|
|
537
|
+
|
|
538
|
+
assert( receive_queues != NULL );
|
|
539
|
+
receive_queue *rq = lookup_hash_entry( receive_queues, service_name );
|
|
540
|
+
if ( rq != NULL ) {
|
|
541
|
+
warn( "Receive queue for %s is already created.", service_name );
|
|
542
|
+
return rq;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
rq = xmalloc( sizeof( receive_queue ) );
|
|
546
|
+
memset( rq->service_name, 0, MESSENGER_SERVICE_NAME_LENGTH );
|
|
547
|
+
strncpy( rq->service_name, service_name, MESSENGER_SERVICE_NAME_LENGTH );
|
|
548
|
+
|
|
549
|
+
memset( &rq->listen_addr, 0, sizeof( struct sockaddr_un ) );
|
|
550
|
+
rq->listen_addr.sun_family = AF_UNIX;
|
|
551
|
+
sprintf( rq->listen_addr.sun_path, "%s/trema.%s.sock", socket_directory, service_name );
|
|
552
|
+
debug( "Set sun_path to %s.", rq->listen_addr.sun_path );
|
|
553
|
+
|
|
554
|
+
rq->listen_socket = socket( AF_UNIX, SOCK_SEQPACKET, 0 );
|
|
555
|
+
if ( rq->listen_socket == -1 ) {
|
|
556
|
+
error( "Failed to call socket (errno = %s [%d]).", strerror( errno ), errno );
|
|
557
|
+
xfree( rq );
|
|
558
|
+
return NULL;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
unlink( rq->listen_addr.sun_path ); // FIXME: handle error correctly
|
|
562
|
+
|
|
563
|
+
int ret;
|
|
564
|
+
ret = bind( rq->listen_socket, ( struct sockaddr * ) &rq->listen_addr, sizeof( struct sockaddr_un ) );
|
|
565
|
+
if ( ret == -1 ) {
|
|
566
|
+
error( "Failed to bind (fd = %d, sun_path = %s, errno = %s [%d]).",
|
|
567
|
+
rq->listen_socket, rq->listen_addr.sun_path, strerror( errno ), errno );
|
|
568
|
+
close( rq->listen_socket );
|
|
569
|
+
xfree( rq );
|
|
570
|
+
return NULL;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
ret = listen( rq->listen_socket, SOMAXCONN );
|
|
574
|
+
if ( ret == -1 ) {
|
|
575
|
+
error( "Failed to listen (fd = %d, sun_path = %s, errno = %s [%d]).",
|
|
576
|
+
rq->listen_socket, rq->listen_addr.sun_path, strerror( errno ), errno );
|
|
577
|
+
close( rq->listen_socket );
|
|
578
|
+
xfree( rq );
|
|
579
|
+
return NULL;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
ret = fcntl( rq->listen_socket, F_SETFL, O_NONBLOCK );
|
|
583
|
+
if ( ret < 0 ) {
|
|
584
|
+
error( "Failed to set O_NONBLOCK ( %s [%d] ).", strerror( errno ), errno );
|
|
585
|
+
close( rq->listen_socket );
|
|
586
|
+
xfree( rq );
|
|
587
|
+
return NULL;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
set_fd_handler( rq->listen_socket, on_accept, rq, NULL, NULL );
|
|
591
|
+
set_readable( rq->listen_socket, true );
|
|
592
|
+
|
|
593
|
+
rq->message_callbacks = create_dlist();
|
|
594
|
+
rq->client_sockets = create_dlist();
|
|
595
|
+
rq->buffer = create_message_buffer( messenger_recv_queue_length );
|
|
596
|
+
|
|
597
|
+
insert_hash_entry( receive_queues, rq->service_name, rq );
|
|
598
|
+
|
|
599
|
+
return rq;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
static bool
|
|
604
|
+
add_message_callback( const char *service_name, uint8_t message_type, void *callback ) {
|
|
605
|
+
assert( receive_queues != NULL );
|
|
606
|
+
assert( service_name != NULL );
|
|
607
|
+
assert( callback != NULL );
|
|
608
|
+
|
|
609
|
+
debug( "Adding a message callback (service_name = %s, message_type = %#x, callback = %p).",
|
|
610
|
+
service_name, message_type, callback );
|
|
611
|
+
|
|
612
|
+
receive_queue *rq = lookup_hash_entry( receive_queues, service_name );
|
|
613
|
+
if ( rq == NULL ) {
|
|
614
|
+
debug( "No receive queue found. Creating." );
|
|
615
|
+
rq = create_receive_queue( service_name );
|
|
616
|
+
if ( rq == NULL ) {
|
|
617
|
+
error( "Failed to create a receive queue." );
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
receive_queue_callback *cb = xmalloc( sizeof( receive_queue_callback ) );
|
|
623
|
+
cb->message_type = message_type;
|
|
624
|
+
cb->function = callback;
|
|
625
|
+
insert_after_dlist( rq->message_callbacks, cb );
|
|
626
|
+
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
static bool
|
|
632
|
+
_add_message_received_callback( const char *service_name, const callback_message_received callback ) {
|
|
633
|
+
assert( service_name != NULL );
|
|
634
|
+
assert( callback != NULL );
|
|
635
|
+
|
|
636
|
+
debug( "Adding a message received callback (service_name = %s, callback = %p).",
|
|
637
|
+
service_name, callback );
|
|
638
|
+
|
|
639
|
+
return add_message_callback( service_name, MESSAGE_TYPE_NOTIFY, callback );
|
|
640
|
+
}
|
|
641
|
+
bool ( *add_message_received_callback )( const char *service_name, const callback_message_received function ) = _add_message_received_callback;
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
static bool
|
|
645
|
+
_add_message_requested_callback( const char *service_name,
|
|
646
|
+
void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) ) {
|
|
647
|
+
assert( service_name != NULL );
|
|
648
|
+
assert( callback != NULL );
|
|
649
|
+
|
|
650
|
+
debug( "Adding a message requested callback ( service_name = %s, callback = %p ).",
|
|
651
|
+
service_name, callback );
|
|
652
|
+
|
|
653
|
+
return add_message_callback( service_name, MESSAGE_TYPE_REQUEST, callback );
|
|
654
|
+
}
|
|
655
|
+
bool ( *add_message_requested_callback )( const char *service_name, void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) ) = _add_message_requested_callback;
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
static bool
|
|
659
|
+
_add_message_replied_callback( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) ) {
|
|
660
|
+
assert( service_name != NULL );
|
|
661
|
+
assert( callback != NULL );
|
|
662
|
+
|
|
663
|
+
debug( "Adding a message replied callback ( service_name = %s, callback = %p ).",
|
|
664
|
+
service_name, callback );
|
|
665
|
+
|
|
666
|
+
return add_message_callback( service_name, MESSAGE_TYPE_REPLY, callback );
|
|
667
|
+
}
|
|
668
|
+
bool ( *add_message_replied_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) ) = _add_message_replied_callback;
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
static bool
|
|
672
|
+
delete_message_callback( const char *service_name, uint8_t message_type, void ( *callback ) ) {
|
|
673
|
+
assert( service_name != NULL );
|
|
674
|
+
assert( callback != NULL );
|
|
675
|
+
|
|
676
|
+
debug( "Deleting a message callback ( service_name = %s, message_type = %#x, callback = %p ).",
|
|
677
|
+
service_name, message_type, callback );
|
|
678
|
+
|
|
679
|
+
if ( receive_queues == NULL ) {
|
|
680
|
+
debug( "All receive queues are already deleted or not created yet." );
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
receive_queue *rq = lookup_hash_entry( receive_queues, service_name );
|
|
685
|
+
receive_queue_callback *cb;
|
|
686
|
+
|
|
687
|
+
if ( NULL != rq ) {
|
|
688
|
+
dlist_element *e;
|
|
689
|
+
for ( e = rq->message_callbacks->next; e; e = e->next ) {
|
|
690
|
+
cb = e->data;
|
|
691
|
+
if ( ( cb->function == callback ) && ( cb->message_type == message_type ) ) {
|
|
692
|
+
debug( "Deleting a callback ( message_type = %#x, callback = %p ).", message_type, callback );
|
|
693
|
+
xfree( cb );
|
|
694
|
+
delete_dlist_element( e );
|
|
695
|
+
if ( rq->message_callbacks->next == NULL ) {
|
|
696
|
+
debug( "No more callback for message_type = %#x.", message_type );
|
|
697
|
+
delete_receive_queue( rq->service_name, rq, NULL );
|
|
698
|
+
}
|
|
699
|
+
return true;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
error( "No registered message callback found." );
|
|
705
|
+
|
|
706
|
+
return false;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
static bool
|
|
711
|
+
_delete_message_received_callback( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len ) ) {
|
|
712
|
+
assert( service_name != NULL );
|
|
713
|
+
assert( callback != NULL );
|
|
714
|
+
|
|
715
|
+
debug( "Deleting a message received callback ( service_name = %s, callback = %p ).",
|
|
716
|
+
service_name, callback );
|
|
717
|
+
|
|
718
|
+
return delete_message_callback( service_name, MESSAGE_TYPE_NOTIFY, callback );
|
|
719
|
+
}
|
|
720
|
+
bool ( *delete_message_received_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len ) ) = _delete_message_received_callback;
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
static bool
|
|
724
|
+
_delete_message_requested_callback( const char *service_name,
|
|
725
|
+
void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) ) {
|
|
726
|
+
assert( service_name != NULL );
|
|
727
|
+
assert( callback != NULL );
|
|
728
|
+
|
|
729
|
+
debug( "Deleting a message requested callback ( service_name = %s, callback = %p ).",
|
|
730
|
+
service_name, callback );
|
|
731
|
+
|
|
732
|
+
return delete_message_callback( service_name, MESSAGE_TYPE_REQUEST, callback );
|
|
733
|
+
}
|
|
734
|
+
bool ( *delete_message_requested_callback )( const char *service_name, void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) ) = _delete_message_requested_callback;
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
static bool
|
|
738
|
+
_delete_message_replied_callback( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) ) {
|
|
739
|
+
assert( service_name != NULL );
|
|
740
|
+
assert( callback != NULL );
|
|
741
|
+
|
|
742
|
+
debug( "Deleting a message replied callback ( service_name = %s, callback = %p ).",
|
|
743
|
+
service_name, callback );
|
|
744
|
+
|
|
745
|
+
return delete_message_callback( service_name, MESSAGE_TYPE_REPLY, callback );
|
|
746
|
+
}
|
|
747
|
+
bool ( *delete_message_replied_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) ) = _delete_message_replied_callback;
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
static bool
|
|
751
|
+
_rename_message_received_callback( const char *old_service_name, const char *new_service_name ) {
|
|
752
|
+
assert( old_service_name != NULL );
|
|
753
|
+
assert( new_service_name != NULL );
|
|
754
|
+
assert( receive_queues != NULL );
|
|
755
|
+
|
|
756
|
+
debug( "Renaming a message received callback ( old_service_name = %s, new_service_name = %s ).",
|
|
757
|
+
old_service_name, new_service_name );
|
|
758
|
+
|
|
759
|
+
receive_queue *old_rq = lookup_hash_entry( receive_queues, old_service_name );
|
|
760
|
+
receive_queue *new_rq = lookup_hash_entry( receive_queues, new_service_name );
|
|
761
|
+
dlist_element *element;
|
|
762
|
+
receive_queue_callback *cb;
|
|
763
|
+
|
|
764
|
+
if ( old_rq == NULL ) {
|
|
765
|
+
error( "No receive queue for old service name ( %s ) found.", old_service_name );
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
else if ( new_rq != NULL ) {
|
|
769
|
+
error( "Receive queue for new service name ( %s ) is already created.", new_service_name );
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
for ( element = old_rq->message_callbacks->next; element; element = element->next ) {
|
|
774
|
+
cb = element->data;
|
|
775
|
+
add_message_callback( new_service_name, cb->message_type, cb->function );
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
delete_receive_queue( old_rq->service_name, old_rq, NULL );
|
|
779
|
+
|
|
780
|
+
return true;
|
|
781
|
+
}
|
|
782
|
+
bool ( *rename_message_received_callback )( const char *old_service_name, const char *new_service_name ) = _rename_message_received_callback;
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
static size_t
|
|
786
|
+
message_buffer_remain_bytes( message_buffer *buf ) {
|
|
787
|
+
assert( buf != NULL );
|
|
788
|
+
|
|
789
|
+
return buf->size - buf->data_length;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* connects send_queue to the service
|
|
795
|
+
* return value: -1:error, 0:refused (retry), 1:connected
|
|
796
|
+
*/
|
|
797
|
+
static int
|
|
798
|
+
send_queue_connect( send_queue *sq ) {
|
|
799
|
+
assert( sq != NULL );
|
|
800
|
+
|
|
801
|
+
sq->running_timer = false;
|
|
802
|
+
if ( ( sq->server_socket = socket( AF_UNIX, SOCK_SEQPACKET, 0 ) ) == -1 ) {
|
|
803
|
+
error( "Failed to call socket ( errno = %s [%d] ).", strerror( errno ), errno );
|
|
804
|
+
return -1;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if ( geteuid() == 0 ) {
|
|
808
|
+
int wmem_size = 1048576;
|
|
809
|
+
int ret = setsockopt( sq->server_socket, SOL_SOCKET, SO_SNDBUFFORCE, ( const void * ) &wmem_size, ( socklen_t ) sizeof( wmem_size ) );
|
|
810
|
+
if ( ret < 0 ) {
|
|
811
|
+
error( "Failed to set SO_SNDBUFFORCE to %d ( %s [%d] ).", wmem_size, strerror( errno ), errno );
|
|
812
|
+
close( sq->server_socket );
|
|
813
|
+
sq->server_socket = -1;
|
|
814
|
+
return -1;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
int ret = fcntl( sq->server_socket, F_SETFL, O_NONBLOCK );
|
|
818
|
+
if ( ret < 0 ) {
|
|
819
|
+
error( "Failed to set O_NONBLOCK ( %s [%d] ).", strerror( errno ), errno );
|
|
820
|
+
close( sq->server_socket );
|
|
821
|
+
sq->server_socket = -1;
|
|
822
|
+
return -1;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
if ( connect( sq->server_socket, ( struct sockaddr * ) &sq->server_addr, sizeof( struct sockaddr_un ) ) == -1 ) {
|
|
826
|
+
debug( "Connection refused ( service_name = %s, sun_path = %s, fd = %d, errno = %s [%d] ).",
|
|
827
|
+
sq->service_name, sq->server_addr.sun_path, sq->server_socket, strerror( errno ), errno );
|
|
828
|
+
|
|
829
|
+
send_dump_message( MESSENGER_DUMP_SEND_REFUSED, sq->service_name, NULL, 0 );
|
|
830
|
+
close( sq->server_socket );
|
|
831
|
+
sq->server_socket = -1;
|
|
832
|
+
|
|
833
|
+
return 0;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
set_fd_handler( sq->server_socket, on_send_read, sq, &on_send_write, sq );
|
|
837
|
+
set_readable( sq->server_socket, true );
|
|
838
|
+
|
|
839
|
+
if ( sq->buffer != NULL && sq->buffer->data_length >= sizeof( message_header ) ) {
|
|
840
|
+
set_writable( sq->server_socket, true );
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
debug( "Connection established ( service_name = %s, sun_path = %s, fd = %d ).",
|
|
844
|
+
sq->service_name, sq->server_addr.sun_path, sq->server_socket );
|
|
845
|
+
|
|
846
|
+
socklen_t optlen = sizeof ( sq->socket_buffer_size );
|
|
847
|
+
if ( getsockopt( sq->server_socket, SOL_SOCKET, SO_SNDBUF, &sq->socket_buffer_size, &optlen ) == -1 ) {
|
|
848
|
+
sq->socket_buffer_size = 0;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
send_dump_message( MESSENGER_DUMP_SEND_CONNECTED, sq->service_name, NULL, 0 );
|
|
852
|
+
|
|
853
|
+
return 1;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
static int send_queue_connect_timer( send_queue *sq );
|
|
858
|
+
|
|
859
|
+
static int
|
|
860
|
+
send_queue_connect_timeout( send_queue *sq ) {
|
|
861
|
+
sq->running_timer = false;
|
|
862
|
+
return send_queue_connect_timer( sq );
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// Remember to clean up timer if we delete the send_queue.
|
|
866
|
+
|
|
867
|
+
static int
|
|
868
|
+
send_queue_connect_timer( send_queue *sq ) {
|
|
869
|
+
struct itimerspec interval;
|
|
870
|
+
if ( sq->server_socket != -1 ) {
|
|
871
|
+
return 1;
|
|
872
|
+
}
|
|
873
|
+
if ( sq->running_timer ) {
|
|
874
|
+
sq->running_timer = false;
|
|
875
|
+
delete_timer_event( ( timer_callback )send_queue_connect_timeout, sq );
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
int ret = send_queue_connect( sq );
|
|
879
|
+
|
|
880
|
+
switch ( ret ) {
|
|
881
|
+
case -1:
|
|
882
|
+
// Print an error, and find a better way of indicating the send
|
|
883
|
+
// queue has an error.
|
|
884
|
+
sq->reconnect_interval.tv_sec = -1;
|
|
885
|
+
sq->reconnect_interval.tv_nsec = 0;
|
|
886
|
+
return -1;
|
|
887
|
+
|
|
888
|
+
case 0:
|
|
889
|
+
// Try again later.
|
|
890
|
+
sq->refused_count++;
|
|
891
|
+
sq->reconnect_interval.tv_sec = ( 1 << ( sq->refused_count > 4 ? 4 : sq->refused_count - 1 ) );
|
|
892
|
+
|
|
893
|
+
interval.it_interval.tv_sec = 0;
|
|
894
|
+
interval.it_interval.tv_nsec = 0;
|
|
895
|
+
interval.it_value = sq->reconnect_interval;
|
|
896
|
+
add_timer_event_callback( &interval, ( void (*)(void *) )send_queue_connect_timeout, ( void * ) sq );
|
|
897
|
+
sq->running_timer = true;
|
|
898
|
+
|
|
899
|
+
debug( "refused_count = %d, reconnect_interval = %u.", sq->refused_count, sq->reconnect_interval.tv_sec );
|
|
900
|
+
return 0;
|
|
901
|
+
|
|
902
|
+
case 1:
|
|
903
|
+
// Success.
|
|
904
|
+
sq->refused_count = 0;
|
|
905
|
+
sq->reconnect_interval.tv_sec = 0;
|
|
906
|
+
sq->reconnect_interval.tv_nsec = 0;
|
|
907
|
+
return 1;
|
|
908
|
+
|
|
909
|
+
default:
|
|
910
|
+
die( "Got invalid value from send_queue_connect_timer( send_queue* )." );
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
return -1;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
static int
|
|
918
|
+
send_queue_try_connect( send_queue *sq ) {
|
|
919
|
+
// TODO: Add a proper check for this.
|
|
920
|
+
if ( sq->reconnect_interval.tv_sec != 0 ) {
|
|
921
|
+
return 0;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
return send_queue_connect_timer( sq );
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* creates send_queue and connects to specified service name.
|
|
930
|
+
*/
|
|
931
|
+
static send_queue *
|
|
932
|
+
create_send_queue( const char *service_name ) {
|
|
933
|
+
assert( service_name != NULL );
|
|
934
|
+
|
|
935
|
+
debug( "Creating a send queue ( service_name = %s ).", service_name );
|
|
936
|
+
|
|
937
|
+
send_queue *sq;
|
|
938
|
+
|
|
939
|
+
assert( send_queues != NULL );
|
|
940
|
+
|
|
941
|
+
sq = lookup_hash_entry( send_queues, service_name );
|
|
942
|
+
if ( NULL != sq ) {
|
|
943
|
+
warn( "Send queue for %s is already created.", service_name );
|
|
944
|
+
return sq;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
sq = xmalloc( sizeof( send_queue ) );
|
|
948
|
+
memset( sq->service_name, 0, MESSENGER_SERVICE_NAME_LENGTH );
|
|
949
|
+
strncpy( sq->service_name, service_name, MESSENGER_SERVICE_NAME_LENGTH );
|
|
950
|
+
|
|
951
|
+
memset( &sq->server_addr, 0, sizeof( struct sockaddr_un ) );
|
|
952
|
+
sq->server_addr.sun_family = AF_UNIX;
|
|
953
|
+
sprintf( sq->server_addr.sun_path, "%s/trema.%s.sock", socket_directory, service_name );
|
|
954
|
+
debug( "Set sun_path to %s.", sq->server_addr.sun_path );
|
|
955
|
+
|
|
956
|
+
sq->server_socket = -1;
|
|
957
|
+
sq->buffer = NULL;
|
|
958
|
+
sq->refused_count = 0;
|
|
959
|
+
sq->reconnect_interval.tv_sec = 0;
|
|
960
|
+
sq->reconnect_interval.tv_nsec = 0;
|
|
961
|
+
sq->running_timer = false;
|
|
962
|
+
sq->overflow = 0;
|
|
963
|
+
sq->overflow_total_length = 0;
|
|
964
|
+
sq->socket_buffer_size = 0;
|
|
965
|
+
|
|
966
|
+
if ( send_queue_try_connect( sq ) == -1 ) {
|
|
967
|
+
xfree( sq );
|
|
968
|
+
error( "Failed to create a send queue for %s.", service_name );
|
|
969
|
+
return NULL;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
sq->buffer = create_message_buffer( messenger_send_queue_length );
|
|
973
|
+
|
|
974
|
+
insert_hash_entry( send_queues, sq->service_name, sq );
|
|
975
|
+
|
|
976
|
+
return sq;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
static bool
|
|
981
|
+
write_message_buffer( message_buffer *buf, const void *data, size_t len ) {
|
|
982
|
+
assert( buf != NULL );
|
|
983
|
+
|
|
984
|
+
if ( message_buffer_remain_bytes( buf ) < len ) {
|
|
985
|
+
return false;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
if ( ( buf->head_offset + buf->data_length + len ) <= buf->size ) {
|
|
989
|
+
memcpy( ( char * ) get_message_buffer_head( buf ) + buf->data_length, data, len );
|
|
990
|
+
}
|
|
991
|
+
else {
|
|
992
|
+
memmove( buf->buffer, ( char * ) get_message_buffer_head( buf ), buf->data_length );
|
|
993
|
+
buf->head_offset = 0;
|
|
994
|
+
memcpy( ( char * ) buf->buffer + buf->data_length, data, len );
|
|
995
|
+
}
|
|
996
|
+
buf->data_length += len;
|
|
997
|
+
|
|
998
|
+
return true;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
static bool
|
|
1003
|
+
push_message_to_send_queue( const char *service_name, const uint8_t message_type, const uint16_t tag, const void *data, size_t len ) {
|
|
1004
|
+
assert( service_name != NULL );
|
|
1005
|
+
|
|
1006
|
+
debug( "Pushing a message to send queue ( service_name = %s, message_type = %#x, tag = %#x, data = %p, len = %u ).",
|
|
1007
|
+
service_name, message_type, tag, data, len );
|
|
1008
|
+
|
|
1009
|
+
message_header header;
|
|
1010
|
+
|
|
1011
|
+
if ( send_queues == NULL ) {
|
|
1012
|
+
error( "All send queues are already deleted or not created yet." );
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
send_queue *sq = lookup_hash_entry( send_queues, service_name );
|
|
1017
|
+
|
|
1018
|
+
if ( NULL == sq ) {
|
|
1019
|
+
sq = create_send_queue( service_name );
|
|
1020
|
+
assert( sq != NULL );
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
header.version = 0;
|
|
1024
|
+
header.message_type = message_type;
|
|
1025
|
+
header.tag = htons( tag );
|
|
1026
|
+
uint32_t length = ( uint32_t ) ( sizeof( message_header ) + len );
|
|
1027
|
+
header.message_length = htonl( length );
|
|
1028
|
+
|
|
1029
|
+
if ( message_buffer_remain_bytes( sq->buffer ) < length ) {
|
|
1030
|
+
if ( sq->overflow == 0 ) {
|
|
1031
|
+
warn( "Could not write a message to send queue due to overflow ( service_name = %s, fd = %u, length = %u ).", sq->service_name, sq->server_socket, length );
|
|
1032
|
+
}
|
|
1033
|
+
++sq->overflow;
|
|
1034
|
+
sq->overflow_total_length += length;
|
|
1035
|
+
send_dump_message( MESSENGER_DUMP_SEND_OVERFLOW, sq->service_name, NULL, 0 );
|
|
1036
|
+
return false;
|
|
1037
|
+
}
|
|
1038
|
+
if ( sq->overflow > 1 ) {
|
|
1039
|
+
warn( "Could not write a message to send queue due to overflow ( service_name = %s, fd = %u, count = %u, total length = %" PRIu64 " ).", sq->service_name, sq->server_socket, sq->overflow, sq->overflow_total_length );
|
|
1040
|
+
}
|
|
1041
|
+
sq->overflow = 0;
|
|
1042
|
+
sq->overflow_total_length = 0;
|
|
1043
|
+
|
|
1044
|
+
write_message_buffer( sq->buffer, &header, sizeof( message_header ) );
|
|
1045
|
+
write_message_buffer( sq->buffer, data, len );
|
|
1046
|
+
|
|
1047
|
+
if ( sq->server_socket == -1 ) {
|
|
1048
|
+
debug( "Tried to send message on closed send queue, connecting..." );
|
|
1049
|
+
|
|
1050
|
+
send_queue_try_connect( sq );
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
set_writable( sq->server_socket, true );
|
|
1055
|
+
if ( sq->buffer->data_length > messenger_send_length_for_flush ) {
|
|
1056
|
+
on_send_write( sq->server_socket, sq );
|
|
1057
|
+
}
|
|
1058
|
+
return true;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
static bool
|
|
1063
|
+
_send_message( const char *service_name, const uint16_t tag, const void *data, size_t len ) {
|
|
1064
|
+
assert( service_name != NULL );
|
|
1065
|
+
|
|
1066
|
+
debug( "Sending a message ( service_name = %s, tag = %#x, data = %p, len = %u ).",
|
|
1067
|
+
service_name, tag, data, len );
|
|
1068
|
+
|
|
1069
|
+
return push_message_to_send_queue( service_name, MESSAGE_TYPE_NOTIFY, tag, data, len );
|
|
1070
|
+
}
|
|
1071
|
+
bool ( *send_message )( const char *service_name, const uint16_t tag, const void *data, size_t len ) = _send_message;
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
static messenger_context *
|
|
1075
|
+
insert_context( void *user_data ) {
|
|
1076
|
+
messenger_context *context = xmalloc( sizeof( messenger_context ) );
|
|
1077
|
+
|
|
1078
|
+
context->transaction_id = ++last_transaction_id;
|
|
1079
|
+
context->life_count = 10;
|
|
1080
|
+
context->user_data = user_data;
|
|
1081
|
+
|
|
1082
|
+
debug( "Inserting a new context ( transaction_id = %#x, life_count = %d, user_data = %p ).",
|
|
1083
|
+
context->transaction_id, context->life_count, context->user_data );
|
|
1084
|
+
|
|
1085
|
+
messenger_context *old = insert_hash_entry( context_db, &context->transaction_id, context );
|
|
1086
|
+
if ( old != NULL ) {
|
|
1087
|
+
delete_context( old );
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
return context;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
static bool
|
|
1095
|
+
_send_request_message( const char *to_service_name, const char *from_service_name, const uint16_t tag, const void *data, size_t len, void *user_data ) {
|
|
1096
|
+
assert( to_service_name != NULL );
|
|
1097
|
+
assert( from_service_name != NULL );
|
|
1098
|
+
|
|
1099
|
+
debug( "Sending a request message ( to_service_name = %s, from_service_name = %s, tag = %#x, data = %p, len = %u, user_data = %p ).",
|
|
1100
|
+
to_service_name, from_service_name, tag, data, len, user_data );
|
|
1101
|
+
|
|
1102
|
+
char *request_data, *p;
|
|
1103
|
+
size_t from_service_name_len = strlen( from_service_name ) + 1;
|
|
1104
|
+
size_t handle_len = sizeof( messenger_context_handle ) + from_service_name_len;
|
|
1105
|
+
messenger_context *context;
|
|
1106
|
+
messenger_context_handle *handle;
|
|
1107
|
+
bool return_value;
|
|
1108
|
+
|
|
1109
|
+
context = insert_context( user_data );
|
|
1110
|
+
|
|
1111
|
+
request_data = xmalloc( handle_len + len );
|
|
1112
|
+
handle = ( messenger_context_handle * ) request_data;
|
|
1113
|
+
handle->transaction_id = htonl( context->transaction_id );
|
|
1114
|
+
handle->service_name_len = htons( ( uint16_t ) from_service_name_len );
|
|
1115
|
+
strcpy( handle->service_name, from_service_name );
|
|
1116
|
+
p = request_data + handle_len;
|
|
1117
|
+
memcpy( p, data, len );
|
|
1118
|
+
|
|
1119
|
+
return_value = push_message_to_send_queue( to_service_name, MESSAGE_TYPE_REQUEST, tag, request_data, handle_len + len );
|
|
1120
|
+
|
|
1121
|
+
xfree( request_data );
|
|
1122
|
+
|
|
1123
|
+
return return_value;
|
|
1124
|
+
}
|
|
1125
|
+
bool ( *send_request_message )( const char *to_service_name, const char *from_service_name, const uint16_t tag, const void *data, size_t len, void *user_data ) = _send_request_message;
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
static bool
|
|
1129
|
+
_send_reply_message( const messenger_context_handle *handle, const uint16_t tag, const void *data, size_t len ) {
|
|
1130
|
+
assert( handle != NULL );
|
|
1131
|
+
|
|
1132
|
+
debug( "Sending a reply message ( handle = [ transaction_id = %#x, service_name_len = %u, service_name = %s ], "
|
|
1133
|
+
"tag = %#x, data = %p, len = %u ).",
|
|
1134
|
+
handle->transaction_id, handle->service_name_len, handle->service_name, tag, data, len );
|
|
1135
|
+
|
|
1136
|
+
char *reply_data;
|
|
1137
|
+
messenger_context_handle *reply_handle;
|
|
1138
|
+
bool return_value;
|
|
1139
|
+
|
|
1140
|
+
reply_data = xmalloc( sizeof( messenger_context_handle ) + len );
|
|
1141
|
+
reply_handle = ( messenger_context_handle * ) reply_data;
|
|
1142
|
+
reply_handle->transaction_id = htonl( handle->transaction_id );
|
|
1143
|
+
reply_handle->service_name_len = htons( 0 );
|
|
1144
|
+
memcpy( reply_handle->service_name, data, len );
|
|
1145
|
+
|
|
1146
|
+
return_value = push_message_to_send_queue( handle->service_name, MESSAGE_TYPE_REPLY, tag, reply_data, sizeof( messenger_context_handle ) + len );
|
|
1147
|
+
|
|
1148
|
+
xfree( reply_data );
|
|
1149
|
+
|
|
1150
|
+
return return_value;
|
|
1151
|
+
}
|
|
1152
|
+
bool ( *send_reply_message )( const messenger_context_handle *handle, const uint16_t tag, const void *data, size_t len ) = _send_reply_message;
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
static void
|
|
1156
|
+
number_of_send_queue( int *connected_count, int *sending_count, int *reconnecting_count, int *closed_count ) {
|
|
1157
|
+
assert( connected_count != NULL );
|
|
1158
|
+
assert( sending_count != NULL );
|
|
1159
|
+
assert( reconnecting_count != NULL );
|
|
1160
|
+
assert( closed_count != NULL );
|
|
1161
|
+
|
|
1162
|
+
debug( "Checking queue statuses." );
|
|
1163
|
+
|
|
1164
|
+
hash_iterator iter;
|
|
1165
|
+
hash_entry *e;
|
|
1166
|
+
|
|
1167
|
+
*connected_count = 0;
|
|
1168
|
+
*sending_count = 0;
|
|
1169
|
+
*reconnecting_count = 0;
|
|
1170
|
+
*closed_count = 0;
|
|
1171
|
+
|
|
1172
|
+
if ( send_queues == NULL ) {
|
|
1173
|
+
error( "All send queues are already deleted or not created yet." );
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
init_hash_iterator( send_queues, &iter );
|
|
1178
|
+
while ( ( e = iterate_hash_next( &iter ) ) != NULL ) {
|
|
1179
|
+
send_queue *sq = e->value;
|
|
1180
|
+
if ( sq->server_socket != -1 ) {
|
|
1181
|
+
if ( sq->buffer->data_length == 0 ) {
|
|
1182
|
+
( *connected_count )++;
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
if ( sq->refused_count > 0 ) {
|
|
1186
|
+
( *reconnecting_count )++;
|
|
1187
|
+
}
|
|
1188
|
+
else {
|
|
1189
|
+
( *sending_count )++;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
else {
|
|
1194
|
+
( *closed_count )++;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
debug( "connected_count = %d, reconnecting_count = %d, sending_count = %d, closed_count = %d.",
|
|
1199
|
+
*connected_count, *reconnecting_count, *sending_count, *closed_count );
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
static void
|
|
1204
|
+
add_recv_queue_client_fd( receive_queue *rq, int fd ) {
|
|
1205
|
+
assert( rq != NULL );
|
|
1206
|
+
assert( fd >= 0 );
|
|
1207
|
+
|
|
1208
|
+
debug( "Adding a client fd to receive queue ( fd = %d, service_name = %s ).", fd, rq->service_name );
|
|
1209
|
+
|
|
1210
|
+
messenger_socket *socket;
|
|
1211
|
+
|
|
1212
|
+
socket = xmalloc( sizeof( messenger_socket ) );
|
|
1213
|
+
socket->fd = fd;
|
|
1214
|
+
insert_after_dlist( rq->client_sockets, socket );
|
|
1215
|
+
|
|
1216
|
+
set_fd_handler( fd, on_recv, rq, NULL, NULL );
|
|
1217
|
+
set_readable( fd, true );
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
static void
|
|
1222
|
+
on_accept( int fd, void *data ) {
|
|
1223
|
+
receive_queue *rq = ( receive_queue* )data;
|
|
1224
|
+
|
|
1225
|
+
assert( rq != NULL );
|
|
1226
|
+
|
|
1227
|
+
int client_fd;
|
|
1228
|
+
struct sockaddr_un addr;
|
|
1229
|
+
|
|
1230
|
+
socklen_t addr_len = sizeof( struct sockaddr_un );
|
|
1231
|
+
|
|
1232
|
+
if ( ( client_fd = accept( fd, ( struct sockaddr * ) &addr, &addr_len ) ) == -1 ) {
|
|
1233
|
+
error( "Failed to accept ( fd = %d, errno = %s [%d] ).", fd, strerror( errno ), errno );
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
if ( geteuid() == 0 ) {
|
|
1238
|
+
int rmem_size = 1048576;
|
|
1239
|
+
int ret = setsockopt( client_fd, SOL_SOCKET, SO_RCVBUFFORCE, ( const void * ) &rmem_size, ( socklen_t ) sizeof( rmem_size ) );
|
|
1240
|
+
if ( ret < 0 ) {
|
|
1241
|
+
error( "Failed to set SO_RCVBUFFORCE to %d ( %s [%d] ).", rmem_size, strerror( errno ), errno );
|
|
1242
|
+
close( client_fd );
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
int ret = fcntl( client_fd, F_SETFL, O_NONBLOCK );
|
|
1247
|
+
if ( ret < 0 ) {
|
|
1248
|
+
error( "Failed to set O_NONBLOCK ( %s [%d] ).", strerror( errno ), errno );
|
|
1249
|
+
close( client_fd );
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
add_recv_queue_client_fd( rq, client_fd );
|
|
1254
|
+
send_dump_message( MESSENGER_DUMP_RECV_CONNECTED, rq->service_name, NULL, 0 );
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
static int
|
|
1259
|
+
del_recv_queue_client_fd( receive_queue *rq, int fd ) {
|
|
1260
|
+
assert( rq != NULL );
|
|
1261
|
+
assert( fd >= 0 );
|
|
1262
|
+
|
|
1263
|
+
messenger_socket *socket;
|
|
1264
|
+
dlist_element *element;
|
|
1265
|
+
|
|
1266
|
+
debug( "Deleting a client fd from receive queue ( fd = %d, service_name = %s ).", fd, rq->service_name );
|
|
1267
|
+
|
|
1268
|
+
for ( element = rq->client_sockets->next; element; element = element->next ) {
|
|
1269
|
+
socket = element->data;
|
|
1270
|
+
if ( socket->fd == fd ) {
|
|
1271
|
+
set_readable( fd, false );
|
|
1272
|
+
delete_fd_handler( fd );
|
|
1273
|
+
|
|
1274
|
+
debug( "Deleting fd ( %d ).", fd );
|
|
1275
|
+
delete_dlist_element( element );
|
|
1276
|
+
xfree( socket );
|
|
1277
|
+
return 1;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
return 0;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
static void
|
|
1286
|
+
truncate_message_buffer( message_buffer *buf, size_t len ) {
|
|
1287
|
+
assert( buf != NULL );
|
|
1288
|
+
|
|
1289
|
+
if ( len == 0 || buf->data_length == 0 ) {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
if ( len > buf->data_length ) {
|
|
1294
|
+
len = buf->data_length;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
if ( ( buf->head_offset + len ) <= buf->size ) {
|
|
1298
|
+
buf->head_offset += len;
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
memmove( buf->buffer, ( char * ) buf->buffer + buf->head_offset + len, buf->data_length - len );
|
|
1302
|
+
buf->head_offset = 0;
|
|
1303
|
+
}
|
|
1304
|
+
buf->data_length -= len;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
/**
|
|
1309
|
+
* pulls message data from recv_queue.
|
|
1310
|
+
* returns 1 if succeeded, otherwise 0.
|
|
1311
|
+
*/
|
|
1312
|
+
static int
|
|
1313
|
+
pull_from_recv_queue( receive_queue *rq, uint8_t *message_type, uint16_t *tag, void *data, size_t *len, size_t maxlen ) {
|
|
1314
|
+
assert( rq != NULL );
|
|
1315
|
+
assert( message_type != NULL );
|
|
1316
|
+
assert( tag != NULL );
|
|
1317
|
+
assert( data != NULL );
|
|
1318
|
+
assert( len != NULL );
|
|
1319
|
+
|
|
1320
|
+
debug( "Pulling a message from receive queue ( service_name = %s ).", rq->service_name );
|
|
1321
|
+
|
|
1322
|
+
message_header *header;
|
|
1323
|
+
|
|
1324
|
+
if ( rq->buffer->data_length < sizeof( message_header ) ) {
|
|
1325
|
+
debug( "Queue length is smaller than a message header ( queue length = %u ).", rq->buffer->data_length );
|
|
1326
|
+
return 0;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
header = ( message_header * ) get_message_buffer_head( rq->buffer );
|
|
1330
|
+
|
|
1331
|
+
uint32_t length = ntohl( header->message_length );
|
|
1332
|
+
assert( length != 0 );
|
|
1333
|
+
assert( length < messenger_recv_queue_length );
|
|
1334
|
+
if ( rq->buffer->data_length < length ) {
|
|
1335
|
+
debug( "Queue length is smaller than message length ( queue length = %u, message length = %u ).",
|
|
1336
|
+
rq->buffer->data_length, length );
|
|
1337
|
+
return 0;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
*message_type = header->message_type;
|
|
1341
|
+
*tag = ntohs( header->tag );
|
|
1342
|
+
*len = length - sizeof( message_header );
|
|
1343
|
+
memcpy( data, header->value, *len > maxlen ? maxlen : *len );
|
|
1344
|
+
truncate_message_buffer( rq->buffer, length );
|
|
1345
|
+
|
|
1346
|
+
debug( "A message is retrieved from receive queue ( message_type = %#x, tag = %#x, len = %u, data = %p ).",
|
|
1347
|
+
*message_type, *tag, *len, data );
|
|
1348
|
+
|
|
1349
|
+
return 1;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
static messenger_context *
|
|
1354
|
+
get_context( uint32_t transaction_id ) {
|
|
1355
|
+
debug( "Looking up a context ( transaction_id = %#x ).", transaction_id );
|
|
1356
|
+
|
|
1357
|
+
return lookup_hash_entry( context_db, &transaction_id );
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
static void
|
|
1362
|
+
call_message_callbacks( receive_queue *rq, const uint8_t message_type, const uint16_t tag, void *data, size_t len ) {
|
|
1363
|
+
assert( rq != NULL );
|
|
1364
|
+
|
|
1365
|
+
dlist_element *element;
|
|
1366
|
+
receive_queue_callback *cb;
|
|
1367
|
+
|
|
1368
|
+
debug( "Calling message callbacks ( service_name = %s, message_type = %#x, tag = %#x, data = %p, len = %u ).",
|
|
1369
|
+
rq->service_name, message_type, tag, data, len );
|
|
1370
|
+
|
|
1371
|
+
for ( element = rq->message_callbacks->next; element; element = element->next ) {
|
|
1372
|
+
cb = element->data;
|
|
1373
|
+
if ( cb->message_type != message_type ) {
|
|
1374
|
+
continue;
|
|
1375
|
+
}
|
|
1376
|
+
switch ( message_type ) {
|
|
1377
|
+
case MESSAGE_TYPE_NOTIFY:
|
|
1378
|
+
{
|
|
1379
|
+
void ( *received_callback )( uint16_t tag, void *data, size_t len );
|
|
1380
|
+
received_callback = cb->function;
|
|
1381
|
+
|
|
1382
|
+
debug( "Calling a callback ( %p ) for MESSAGE_TYPE_NOTIFY (%#x) ( tag = %#x, data = %p, len = %u ).",
|
|
1383
|
+
cb->function, message_type, tag, data, len );
|
|
1384
|
+
|
|
1385
|
+
received_callback( tag, data, len );
|
|
1386
|
+
}
|
|
1387
|
+
break;
|
|
1388
|
+
case MESSAGE_TYPE_REQUEST:
|
|
1389
|
+
{
|
|
1390
|
+
void ( *requested_callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len );
|
|
1391
|
+
messenger_context_handle *handle;
|
|
1392
|
+
char *requested_data;
|
|
1393
|
+
size_t header_len;
|
|
1394
|
+
|
|
1395
|
+
requested_callback = cb->function;
|
|
1396
|
+
handle = ( messenger_context_handle * ) data;
|
|
1397
|
+
handle->transaction_id = ntohl( handle->transaction_id );
|
|
1398
|
+
handle->service_name_len = ntohs( handle->service_name_len );
|
|
1399
|
+
header_len = sizeof( messenger_context_handle ) + handle->service_name_len;
|
|
1400
|
+
requested_data = ( ( char * ) data ) + header_len;
|
|
1401
|
+
|
|
1402
|
+
debug( "Calling a callback ( %p ) for MESSAGE_TYPE_REQUEST (%#x) ( handle = %p, tag = %#x, requested_data = %p, len = %u ).",
|
|
1403
|
+
cb->function, message_type, handle, tag, requested_data, len - header_len );
|
|
1404
|
+
|
|
1405
|
+
requested_callback( handle, tag, ( void * ) requested_data, len - header_len );
|
|
1406
|
+
}
|
|
1407
|
+
break;
|
|
1408
|
+
case MESSAGE_TYPE_REPLY:
|
|
1409
|
+
{
|
|
1410
|
+
debug( "Calling a callback ( %p ) for MESSAGE_TYPE_REPLY (%#x).", cb->function, message_type );
|
|
1411
|
+
|
|
1412
|
+
void ( *replied_callback )( uint16_t tag, void *data, size_t len, void *user_data );
|
|
1413
|
+
messenger_context_handle *reply_handle;
|
|
1414
|
+
messenger_context *context;
|
|
1415
|
+
|
|
1416
|
+
replied_callback = cb->function;
|
|
1417
|
+
reply_handle = data;
|
|
1418
|
+
reply_handle->transaction_id = ntohl( reply_handle->transaction_id );
|
|
1419
|
+
reply_handle->service_name_len = ntohs( reply_handle->service_name_len );
|
|
1420
|
+
|
|
1421
|
+
context = get_context( reply_handle->transaction_id );
|
|
1422
|
+
|
|
1423
|
+
if ( NULL != context ) {
|
|
1424
|
+
debug( "tag = %#x, data = %p, len = %u, user_data = %p.",
|
|
1425
|
+
tag, reply_handle->service_name, len - sizeof( messenger_context_handle ), context->user_data );
|
|
1426
|
+
replied_callback( tag, reply_handle->service_name, len - sizeof( messenger_context_handle ), context->user_data );
|
|
1427
|
+
delete_context( context );
|
|
1428
|
+
}
|
|
1429
|
+
else {
|
|
1430
|
+
warn( "No context found." );
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
break;
|
|
1434
|
+
default:
|
|
1435
|
+
error( "Unknown message type ( %#x ).", message_type );
|
|
1436
|
+
assert( 0 );
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
static void
|
|
1443
|
+
on_recv( int fd, void *data ) {
|
|
1444
|
+
receive_queue *rq = ( receive_queue* )data;
|
|
1445
|
+
|
|
1446
|
+
assert( rq != NULL );
|
|
1447
|
+
assert( fd >= 0 );
|
|
1448
|
+
|
|
1449
|
+
debug( "Receiving data from remote ( fd = %d, service_name = %s ).", fd, rq->service_name );
|
|
1450
|
+
|
|
1451
|
+
uint8_t buf[ MESSENGER_RECV_BUFFER ];
|
|
1452
|
+
ssize_t recv_len;
|
|
1453
|
+
size_t buf_len;
|
|
1454
|
+
uint8_t message_type;
|
|
1455
|
+
uint16_t tag;
|
|
1456
|
+
|
|
1457
|
+
while ( ( buf_len = message_buffer_remain_bytes( rq->buffer ) ) > messenger_recv_queue_reserved ) {
|
|
1458
|
+
if ( buf_len > sizeof( buf ) ) {
|
|
1459
|
+
buf_len = sizeof( buf );
|
|
1460
|
+
}
|
|
1461
|
+
recv_len = recv( fd, buf, buf_len, 0 );
|
|
1462
|
+
if ( recv_len == -1 ) {
|
|
1463
|
+
if ( errno != EAGAIN && errno != EWOULDBLOCK ) {
|
|
1464
|
+
error( "Failed to recv ( fd = %d, errno = %s [%d] ).", fd, strerror( errno ), errno );
|
|
1465
|
+
send_dump_message( MESSENGER_DUMP_RECV_CLOSED, rq->service_name, NULL, 0 );
|
|
1466
|
+
del_recv_queue_client_fd( rq, fd );
|
|
1467
|
+
close( fd );
|
|
1468
|
+
}
|
|
1469
|
+
else {
|
|
1470
|
+
debug( "Failed to recv ( fd = %d, errno = %s [%d] ).", fd, strerror( errno ), errno );
|
|
1471
|
+
}
|
|
1472
|
+
break;
|
|
1473
|
+
}
|
|
1474
|
+
else if ( recv_len == 0 ) {
|
|
1475
|
+
debug( "Connection closed ( fd = %d, service_name = %s ).", fd, rq->service_name );
|
|
1476
|
+
send_dump_message( MESSENGER_DUMP_RECV_CLOSED, rq->service_name, NULL, 0 );
|
|
1477
|
+
del_recv_queue_client_fd( rq, fd );
|
|
1478
|
+
close( fd );
|
|
1479
|
+
break;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
if ( !write_message_buffer( rq->buffer, buf, ( size_t ) recv_len ) ) {
|
|
1483
|
+
warn( "Could not write a message to receive queue due to overflow ( service_name = %s, len = %u ).", rq->service_name, recv_len );
|
|
1484
|
+
send_dump_message( MESSENGER_DUMP_RECV_OVERFLOW, rq->service_name, buf, ( uint32_t ) recv_len );
|
|
1485
|
+
}
|
|
1486
|
+
else {
|
|
1487
|
+
debug( "Pushing a message to receive queue ( service_name = %s, len = %u ).", rq->service_name, recv_len );
|
|
1488
|
+
send_dump_message( MESSENGER_DUMP_RECEIVED, rq->service_name, buf, ( uint32_t ) recv_len );
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
while ( pull_from_recv_queue( rq, &message_type, &tag, buf, &buf_len, sizeof( buf ) ) == 1 ) {
|
|
1493
|
+
call_message_callbacks( rq, message_type, tag, buf, buf_len );
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
static uint32_t
|
|
1499
|
+
get_send_data( send_queue *sq, size_t offset ) {
|
|
1500
|
+
assert( sq != NULL );
|
|
1501
|
+
|
|
1502
|
+
uint32_t bucket_size = messenger_bucket_size;
|
|
1503
|
+
if ( sq->socket_buffer_size != 0 ) {
|
|
1504
|
+
int used;
|
|
1505
|
+
if ( ioctl( sq->server_socket, SIOCOUTQ, &used ) == 0 ) {
|
|
1506
|
+
if ( used < sq->socket_buffer_size ) {
|
|
1507
|
+
bucket_size = ( uint32_t ) ( sq->socket_buffer_size - used ) << 1;
|
|
1508
|
+
if ( bucket_size > messenger_bucket_size ) {
|
|
1509
|
+
bucket_size = messenger_bucket_size;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
else {
|
|
1513
|
+
bucket_size = 1;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
uint32_t length = 0;
|
|
1519
|
+
message_header *header;
|
|
1520
|
+
while ( ( sq->buffer->data_length - offset ) >= sizeof( message_header ) ) {
|
|
1521
|
+
header = ( message_header * ) ( ( char * ) get_message_buffer_head( sq->buffer ) + offset );
|
|
1522
|
+
uint32_t message_length = ntohl( header->message_length );
|
|
1523
|
+
assert( message_length != 0 );
|
|
1524
|
+
assert( message_length < messenger_recv_queue_length );
|
|
1525
|
+
if ( length + message_length > bucket_size ) {
|
|
1526
|
+
if ( length == 0 ) {
|
|
1527
|
+
length = message_length;
|
|
1528
|
+
}
|
|
1529
|
+
break;
|
|
1530
|
+
}
|
|
1531
|
+
length += message_length;
|
|
1532
|
+
offset += message_length;
|
|
1533
|
+
}
|
|
1534
|
+
return length;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
static void
|
|
1539
|
+
on_send_read( int fd, void *data ) {
|
|
1540
|
+
UNUSED( fd );
|
|
1541
|
+
|
|
1542
|
+
char buf[ 256 ];
|
|
1543
|
+
send_queue *sq = ( send_queue* )data;
|
|
1544
|
+
|
|
1545
|
+
if ( recv( sq->server_socket, buf, sizeof( buf ), 0 ) <= 0 ) {
|
|
1546
|
+
send_dump_message( MESSENGER_DUMP_SEND_CLOSED, sq->service_name, NULL, 0 );
|
|
1547
|
+
|
|
1548
|
+
set_readable( sq->server_socket, false );
|
|
1549
|
+
set_writable( sq->server_socket, false );
|
|
1550
|
+
delete_fd_handler( sq->server_socket );
|
|
1551
|
+
|
|
1552
|
+
close( sq->server_socket );
|
|
1553
|
+
sq->server_socket = -1;
|
|
1554
|
+
|
|
1555
|
+
// Tries to reconnecting immediately, else adds a reconnect timer.
|
|
1556
|
+
if ( sq->buffer->data_length > 0 ) {
|
|
1557
|
+
send_queue_try_connect( sq );
|
|
1558
|
+
}
|
|
1559
|
+
else {
|
|
1560
|
+
delete_send_queue( sq );
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
static void
|
|
1567
|
+
on_send_write( int fd, void *data ) {
|
|
1568
|
+
send_queue *sq = ( send_queue* )data;
|
|
1569
|
+
|
|
1570
|
+
assert( sq != NULL );
|
|
1571
|
+
assert( fd >= 0 );
|
|
1572
|
+
|
|
1573
|
+
debug( "Sending data to remote ( fd = %d, service_name = %s, buffer = %p, data_length = %u ).",
|
|
1574
|
+
fd, sq->service_name, get_message_buffer_head( sq->buffer ), sq->buffer->data_length );
|
|
1575
|
+
|
|
1576
|
+
if ( sq->buffer->data_length < sizeof( message_header ) ) {
|
|
1577
|
+
set_writable( sq->server_socket, false );
|
|
1578
|
+
return;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
void *send_data;
|
|
1582
|
+
size_t send_len;
|
|
1583
|
+
ssize_t sent_len;
|
|
1584
|
+
size_t sent_total = 0;
|
|
1585
|
+
|
|
1586
|
+
while ( ( send_len = get_send_data( sq, sent_total ) ) > 0 ) {
|
|
1587
|
+
send_data = ( ( char * ) get_message_buffer_head( sq->buffer ) + sent_total );
|
|
1588
|
+
sent_len = send( fd, send_data, send_len, MSG_DONTWAIT );
|
|
1589
|
+
if ( sent_len == -1 ) {
|
|
1590
|
+
int err = errno;
|
|
1591
|
+
if ( err != EAGAIN && err != EWOULDBLOCK ) {
|
|
1592
|
+
error( "Failed to send ( service_name = %s, fd = %d, errno = %s [%d] ).",
|
|
1593
|
+
sq->service_name, fd, strerror( err ), err );
|
|
1594
|
+
send_dump_message( MESSENGER_DUMP_SEND_CLOSED, sq->service_name, NULL, 0 );
|
|
1595
|
+
|
|
1596
|
+
set_readable( sq->server_socket, false );
|
|
1597
|
+
set_writable( sq->server_socket, false );
|
|
1598
|
+
delete_fd_handler( sq->server_socket );
|
|
1599
|
+
|
|
1600
|
+
close( sq->server_socket );
|
|
1601
|
+
sq->server_socket = -1;
|
|
1602
|
+
sq->refused_count = 0;
|
|
1603
|
+
|
|
1604
|
+
// Tries to reconnecting immediately, else adds a reconnect timer.
|
|
1605
|
+
send_queue_try_connect( sq );
|
|
1606
|
+
}
|
|
1607
|
+
truncate_message_buffer( sq->buffer, sent_total );
|
|
1608
|
+
if ( err == EMSGSIZE || err == ENOBUFS || err == ENOMEM ) {
|
|
1609
|
+
warn( "Dropping %u bytes data in send queue ( service_name = %s ).", sq->buffer->data_length, sq->service_name );
|
|
1610
|
+
truncate_message_buffer( sq->buffer, sq->buffer->data_length );
|
|
1611
|
+
}
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
assert( sent_len != 0 );
|
|
1615
|
+
assert( send_len == ( size_t ) sent_len );
|
|
1616
|
+
send_dump_message( MESSENGER_DUMP_SENT, sq->service_name, send_data, ( uint32_t ) sent_len );
|
|
1617
|
+
sent_total += ( size_t ) sent_len;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
truncate_message_buffer( sq->buffer, sent_total );
|
|
1621
|
+
if ( sq->buffer->data_length == 0 ) {
|
|
1622
|
+
set_writable( sq->server_socket, false );
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
int
|
|
1628
|
+
flush_messenger() {
|
|
1629
|
+
int connected_count, sending_count, reconnecting_count, closed_count;
|
|
1630
|
+
|
|
1631
|
+
debug( "Flushing send queues." );
|
|
1632
|
+
|
|
1633
|
+
while ( true ) {
|
|
1634
|
+
number_of_send_queue( &connected_count, &sending_count, &reconnecting_count, &closed_count );
|
|
1635
|
+
if ( sending_count == 0 ) {
|
|
1636
|
+
return reconnecting_count;
|
|
1637
|
+
}
|
|
1638
|
+
run_event_handler_once( 100000 );
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
bool
|
|
1644
|
+
start_messenger() {
|
|
1645
|
+
debug( "Starting messenger." );
|
|
1646
|
+
|
|
1647
|
+
add_periodic_event_callback( 10, age_context_db, NULL );
|
|
1648
|
+
|
|
1649
|
+
return true;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
bool
|
|
1654
|
+
stop_messenger() {
|
|
1655
|
+
debug( "Terminating messenger." );
|
|
1656
|
+
|
|
1657
|
+
return true;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
void
|
|
1662
|
+
start_messenger_dump( const char *dump_app_name, const char *dump_service_name ) {
|
|
1663
|
+
assert( dump_app_name != NULL );
|
|
1664
|
+
assert( dump_service_name != NULL );
|
|
1665
|
+
|
|
1666
|
+
debug( "Starting a message dumper ( dump_app_name = %s, dump_service_name = %s ).",
|
|
1667
|
+
dump_app_name, dump_service_name );
|
|
1668
|
+
|
|
1669
|
+
if ( messenger_dump_enabled() ) {
|
|
1670
|
+
stop_messenger_dump();
|
|
1671
|
+
}
|
|
1672
|
+
_dump_service_name = xstrdup( dump_service_name );
|
|
1673
|
+
_dump_app_name = xstrdup( dump_app_name );
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
void
|
|
1678
|
+
stop_messenger_dump( void ) {
|
|
1679
|
+
assert( _dump_service_name != NULL );
|
|
1680
|
+
assert( _dump_app_name != NULL );
|
|
1681
|
+
|
|
1682
|
+
debug( "Terminating a message dumper ( dump_app_name = %s, dump_service_name = %s ).",
|
|
1683
|
+
_dump_app_name, _dump_service_name );
|
|
1684
|
+
|
|
1685
|
+
assert( send_queues != NULL );
|
|
1686
|
+
send_queue *sq = lookup_hash_entry( send_queues, _dump_service_name );
|
|
1687
|
+
if ( sq != NULL ) {
|
|
1688
|
+
delete_send_queue( sq );
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
xfree( _dump_service_name );
|
|
1692
|
+
_dump_service_name = NULL;
|
|
1693
|
+
|
|
1694
|
+
xfree( _dump_app_name );
|
|
1695
|
+
_dump_app_name = NULL;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
bool
|
|
1700
|
+
messenger_dump_enabled( void ) {
|
|
1701
|
+
if ( _dump_service_name != NULL && _dump_app_name != NULL ) {
|
|
1702
|
+
return true;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
return false;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
/*
|
|
1710
|
+
* Local variables:
|
|
1711
|
+
* c-basic-offset: 2
|
|
1712
|
+
* indent-tabs-mode: nil
|
|
1713
|
+
* End:
|
|
1714
|
+
*/
|