{"id":27301500,"url":"https://github.com/eprosima/websocket-sh","last_synced_at":"2025-04-12T01:46:31.427Z","repository":{"id":44436863,"uuid":"346607827","full_name":"eProsima/WebSocket-SH","owner":"eProsima","description":"eProsima's Integration Service System Handle for WebSocket.","archived":false,"fork":false,"pushed_at":"2022-07-12T14:47:31.000Z","size":2252,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-06-23T04:55:52.982Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eProsima.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-11T06:58:47.000Z","updated_at":"2024-06-23T04:55:52.985Z","dependencies_parsed_at":"2022-08-19T18:51:04.029Z","dependency_job_id":null,"html_url":"https://github.com/eProsima/WebSocket-SH","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eProsima%2FWebSocket-SH","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eProsima%2FWebSocket-SH/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eProsima%2FWebSocket-SH/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eProsima%2FWebSocket-SH/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eProsima","download_url":"https://codeload.github.com/eProsima/WebSocket-SH/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248505952,"owners_count":21115354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-12T01:46:30.786Z","updated_at":"2025-04-12T01:46:31.417Z","avatar_url":"https://github.com/eProsima.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://integration-service.docs.eprosima.com/\"\u003e\u003cimg src=\"https://github.com/eProsima/Integration-Service/blob/main/docs/images/logo.png?raw=true\" hspace=\"8\" vspace=\"2\" height=\"100\" \u003e\u003c/a\u003e\n\n# WebSocket System Handle\n\n[![WebSocket SH CI Status](https://github.com/eProsima/WebSocket-SH/actions/workflows/ci.yml/badge.svg)](https://github.com/eProsima/WebSocket-SH/actions)\n\u0026nbsp;\u0026nbsp;[![Have an issue?](https://img.shields.io/badge/-Open%20an%20issue-orange)](https://github.com/eProsima/Integration-Service/issues/new)\n\n## Introduction\n\n### What is a System Handle?\n\nA [System Handle](https://integration-service.docs.eprosima.com/en/latest/user_manual/systemhandle/sh.html) is a plugin that allows a certain middleware\nor communication protocol to speak the same language used by the [eProsima Integration Service](https://github.com/eProsima/Integration-Service),\nthat is, *Extensible and Dynamic Topic Types for DDS* (**xTypes**);\nspecifically, *Integration Service* bases its intercommunication abilities on eProsima's open source\nimplementation for the *xTypes* protocol, that is, [eProsima xTypes](https://github.com/eProsima/xtypes).\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://integration-service.docs.eprosima.com/en/latest/user_manual/systemhandle/sh.html\"\u003e\u003cimg src=\"docs/images/system-handle-architecture.png\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n### The WebSocket SystemHandle\n\n\u003ca href=\"https://www.websocket.org/\"\u003e\u003cimg src=\"docs/images/websocket_logo.png\" align=\"left\" hspace=\"8\" vspace=\"2\" width=\"90\"\u003e\u003c/a\u003e\n\nThis repository contains the source code of *Integration Service* **System Handle**\nfor the [WebSocket](https://www.websocket.org/) middleware protocol, widely used in the robotics field.\n\nThe main purpose of the *WebSocket System Handle* is that of establishing a connection between a *WebSocket*\napplication and an application running over a different middleware implementation.\nThis is the classic use-case approach for *Integration Service*.\n\n## Dependencies\n\nThis section provides a list of the dependencies needed in order to compile *WebSocket System Handle*.\n\n* [OpenSSL](https://www.openssl.org/): Toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols.\n* [WebSocket++](https://github.com/zaphoyd/websocketpp): *WebSocket* Protocol C++ library implementation.\n\nThese libraries can be installed using your Linux distribution package manager with the following command:\n\n```\nsudo apt-get install -y libssl-dev libwebsocketpp-dev\n```\n\n## Configuration\n\n*Integration Service* is configured by means of a YAML configuration file, which specifies\nthe middlewares, topics and/or services involved in the intercommunication process, as well as\ntheir topic/service types and the data exchange flow. This configuration file is loaded during\nruntime, so there is no need to recompile any package before switching to a whole new\nintercommunication architecture.\n\nTo get a more precise idea on how these YAML files have to be filled and which fields they require\nin order to succesfully configure and launch an *Integration Service* project, please refer to the\n[dedicated configuration section](https://integration-service.docs.eprosima.com/en/latest/user_manual/yaml_config.html) of the official documentation.\n\nRegarding the *WebSocket System Handle*, there are several specific parameters which can be configured\nfor the WebSocket middleware. All of these parameters fall as suboptions of the main\nfive sections described in the *Configuration* chapter of *Integration Service* repository:\n\n* `systems`: The system `type` must be `websocket_server` or `websocket_client`. In addition to the\n  `type` and `types-from` fields, the *WebSocket System Handle* accepts a wide variety of specific\n  configuration fields, depending on the selected operation mode (*Client* or *Server*):\n\n  For the `websocket_server` *System Handle*, there are two possible configuration scenarios:\n  the former one uses a TLS endpoint, and the latter uses a TCP endpoint.\n\n  **TLS**\n  ```yaml\n  systems:\n    websocket:\n      type: websocket_server\n      port: 80\n      cert: path/to/cert/file.crt\n      key: path/to/key/file.key\n      authentication:\n       policies: [\n           { secret: this-is-a-secret, algo: HS256, rules: {example: *regex*} }\n       ]\n  ```\n\n  **TCP**\n  ```yaml\n  systems:\n    websocket:\n      type: websocket_server\n      port: 80\n      security: none\n      encoding: json\n      authentication:\n       policies: [\n           { secret: this-is-a-secret, algo: HS256, rules: {example: *regex*} }\n       ]\n  ```\n\n    * `port`: The specific port where the *server* will listen for incoming connections. This field is\n      required.\n    * `security`: If this field is not present, a secure TLS endpoint will be created. If the special\n      value `none` is written, a TCP *WebSocket server* will be set up.\n    * `cert`: The *X.509* certificate that the *server* should use. This field is mandatory if\n      `security` is enabled.\n    * `key`: A path to the file containing the public key used to verify credentials with the specified\n      certificate. If `security` is enabled, this field must exist and must be filled in properly.\n    * `authentication`: It is a list of `policies`. Each policy accepts the following keys:\n      * `secret`: When using **MAC** *(Message Authentication Code)* method for verification,\n        this field allows to set the secret used to authenticate the client requesting a connection to the server.\n      * `pubkey`: Path to a file containing a **PEM** encoded public key.\n\n        \u003e **_NOTE:_** Either a `secret` or a `pubkey` is required.\n\n      * `rules`: List of additional claims that should be checked. It should contain a map with keys\n        corresponding to the claim identifier, and values corresponding to regex patterns that should match\n        the payload's value. In the example above, the rule will check that the payload contains\n        an `example` claim and that its value contains the *regex* keyword in any position of the message. This field is optional.\n      * `algo`: The algorithm that should be used for encrypting the connection token. If the incoming token\n        is not encrypted with the same algorithm, it will be discarded. If not specified, the HS256 algorithm will be used.\n    * `encoding`: Specifies the protocol, built over JSON, that allows users to exchange useful information\n      between the client and the server, by means of specifying which keys are valid for the JSON\n      sent/received messages and how they should be formatted for the server to accept and process these\n      messages. By default, `json` encoding is provided in the *WebSocket System Handle* and used\n      if not specified otherwise. Users can implement their own encoding by implementing the\n      [Encoding class](src/Encoding.hpp).\n    #\n    For the `websocket_client` *System Handle*, there are also two possible configuration scenarios:\n    using TLS or TCP.\n\n    **TLS**\n    ```yaml\n    systems:\n      websocket:\n        type: websocket_client\n        host: localhost\n        port: 80\n        cert_authorities: [my_cert_authority.ca.crt]\n        authentication:\n            token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey...\n    ```\n\n    **TCP**\n    ```yaml\n    systems:\n      websocket:\n        type: websocket_client\n        port: 80\n        security: none\n        encoding: json\n        authentication:\n            token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey...\n    ```\n\n    * `port`: The specific port where the *client* will attempt to establish a connection to a\n      *WebSocket server*. This field is mandatory.\n    * `host`: Address where the *WebSocket server* is hosted. If not specified, it will use\n      `localhost` as the default value.\n    * `security`: If this field is not present, a secure TLS endpoint will be created. If the special\n      value `none` is written, a TCP *WebSocket client* will be set up.\n    * `cert_authorities`: List of *certificate authorities* used to validate the client against the\n      server. This field is optional and only applicable if `security` is not disabled.\n    * `authentication`: allows to specify the public `token` used to perform the secure authentication process\n      with the server. This field is mandatory.\n    * `encoding`: Specifies the protocol, built over JSON, that allows users to exchange useful information\n      between the client and the server, by means of specifying which keys are valid for the JSON\n      sent/received messages and how they should be formatted for the server to accept and process these\n      messages. By default, `json` encoding is provided in the *WebSocket System Handle* and used\n      if not specified otherwise. Users can implement their own encoding by implementing the\n      [Encoding class](src/Encoding.hpp).\n\n## JSON encoding protocol\n\nIn order to communicate with the *WebSocket System Handle* using the JSON encoding, the messages should follow a specific pattern. This pattern will be different depending on the paradigm used for the connection (*pub/sub* or *client/server*) and the communication purpose.\n\nSeveral fields can be used in those messages, but not all of them are mandatory. All of them will be described in this section, as well as in which cases they are optional:\n\n* `op`: The *Operation Code* is mandatory in every communication as it specifies the purpose of the message. This field can assume nine different values, which are the ones detailed below.\n  * `advertise`: It notifies that there is a new publisher that is going to publish messages on a specific topic. The fields that can be set for this operation are: `topic`, `type` and optionally the `id`.\n\n    ```json\n      {\"op\": \"advertise\", \"topic\": \"helloworld\", \"type\": \"HelloWorld\", \"id\": \"1\"}\n    ```\n\n  * `unadvertise`: It states that a publisher is not going to publish any more messages on a specific topic. The fields that can be set for this operation are: `topic` and optionally the `id`.\n\n    ```json\n      {\"op\": \"unadvertise\", \"topic\": \"helloworld\", \"id\": \"1\"}\n    ```\n\n  * `publish`: It identifies a message that wants to be published over a specific topic. The fields that can be set for this operation are: `topic` and `msg`.\n\n    ```json\n      {\"op\": \"publish\", \"topic\": \"helloworld\", \"msg\": {\"data\": \"Hello\"}}\n    ```\n\n  * `subscribe`: It notifies that a subscriber wants to receive the messages published under a specific topic. The fields that can be set for this operation are: `topic` and optionally the `id` and `type`.\n\n    ```json\n      {\"op\": \"subscribe\", \"topic\": \"helloworld\", \"type\": \"HelloWorld\", \"id\": \"1\"}\n    ```\n\n  * `unsubscribe`: It states that a subscriber doesn't want to receive messages from a specific topic anymore. The fields that can be set for this operation are: `topic` and optionally the `id`.\n\n    ```json\n      {\"op\": \"unsubscribe\", \"topic\": \"helloworld\", \"id\": \"1\"}\n    ```\n\n  * `call_service`: It identifies a message request that wants to be published on a specific service. The fields that can be set for this operation are: `service`, `args` and optionally the `id`.\n\n    ```json\n      {\"op\": \"call_service\", \"service\": \"hello_serv\", \"args\": {\"req\": \"req\"}, \"id\": \"1\"}\n    ```\n\n  * `advertise_service`: It notifies that a new server is going to attend to the requests done on a specific service. The fields that can be set for this operation are: `request_type`, `reply_type` and `service`.\n\n    ```json\n      {\"op\": \"advertise_service\", \"service\": \"hello_serv\", \"request_type\":\n       \"HelloRequest\", \"reply_type\": \"HelloReply\"}\n    ```\n\n  * `unadvertise_service`: It states that a server is not going to attend any more the requests done on a specific service. The fields that can be set for this operation are: `type` and `service`.\n\n    ```json\n      {\"op\": \"unadvertise_service\", \"service\": \"hello_serv\", \"type\": \"HelloReply\"}\n    ```\n\n  * `service_response`: It identifies a message reply that wants to be published as response to a specific request.The fields that can be set for this operation are: `service`, `values` and optionally the `id`.\n\n     ```json\n      {\"op\": \"service_response\", \"service\": \"hello_serv\", \"values\": {\"resp\": \"resp\"},\n       \"id\": \"1\"}\n    ```\n\n* `id`: Code that identifies the message.\n* `topic`: Name that identifies a specific topic.\n* `type`: Name of the type that wants to be used for publishing messages on a specific topic.\n* `request_type`: Name of the type that wants to be used for the service requests.\n* `reply_type`: Name of the type that wants to be used for the service responses.\n* `msg`: Message that is going to be published under a specific topic.\n* `service`: Name that identifies a specific service.\n* `args`: Message that is going to be published under a specific service as a request.\n* `values`: Message that is going to be published under a specific service as a response.\n* `result`: Value that states if the request has been successful.\n\n## Examples\n\nThere are several *Integration Service* examples using the *WebSocket System Handle* available\nin the project's [main source code repository]([https://](https://github.com/eProsima/Integration-Service/tree/main/examples)).\n\nOne of these examples, where the *WebSocket System Handle* takes part in the intercommunication process, is introduced here.\n\n\u003ca href=\"https://integration-service.docs.eprosima.com/en/latest/examples/different_protocols/pubsub/ros2-websocket.html\"\u003e\u003cimg align=\"left\" width=\"15\" height=\"38\" src=\"https://via.placeholder.com/15/40c15d/000000?text=+\" alt=\"Green icon\"\u003e\u003c/a\u003e\n\n### WebSocket - ROS 2 bridge  (publisher - subscriber)\n\nIn this example, *Integration Service* uses both the *WebSocket Server System Handle* and the *ROS 2 System Handle*\nto transmit data coming from a WebSocket Client into the ROS 2 data space, so that it can be\nconsumed by a ROS 2 subscriber on the same topic, and viceversa.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://integration-service.docs.eprosima.com/en/latest/examples/different_protocols/pubsub/ros2-websocket.html\"\u003e\u003cimg src=\"docs/images/websocket_ros2_pubsub_example.png\" width=\"450\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nThe configuration file used by *Integration Service* for this example can be found\n[here](https://github.com/eProsima/Integration-Service/blob/main/examples/basic/ros2_websocket__helloworld.yaml).\n\nFor a detailed step by step guide on how to build and test this example, please refer to the\n[dedicated section](https://integration-service.docs.eprosima.com/en/latest/examples/different_protocols/pubsub/ros2-websocket.html) in the official documentation.\n\n\n\n\u003ca href=\"https://integration-service.docs.eprosima.com/en/latest/examples/different_protocols/services/websocket-server.html\"\u003e\u003cimg align=\"left\" width=\"15\" height=\"38\" src=\"https://via.placeholder.com/15/40c15d/000000?text=+\" alt=\"Green icon\"\u003e\u003c/a\u003e\n\n### WebSocket service server\n\nIn this example, the *WebSocket System Handle* tackles the task of bridging a WebSocket server with one or more client applications,\nplaying the role of a service server capable of processing incoming requests from several middlewares (*DDS*, *ROS1*, *ROS2*) and producing an appropriate answer for them.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://integration-service.docs.eprosima.com/en/latest/examples/different_protocols/services/websocket-server.html\"\u003e\u003cimg src=\"docs/images/websocket_services_example.png\" width=\"550\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nThe configuration file used by *Integration Service* for this example can be found\n[here](https://github.com/eProsima/Integration-Service/blob/main/examples/basic/websocket_server__addtwoints.yaml).\n\nFor a detailed step by step guide on how to build and test this example, please refer to the\n[dedicated section](https://integration-service.docs.eprosima.com/en/latest/examples/different_protocols/services/websocket-server.html) in the official documentation.\n\n## Compilation flags\n\nBesides the [global compilation flags](https://integration-service.docs.eprosima.com/en/latest/installation_manual/installation.html#global-compilation-flags) available for the\nwhole *Integration Service* product suite, there are some specific flags which apply only to the\n*WebSocket System Handle*; they are listed below:\n\n* `BUILD_WEBSOCKET_TESTS`: Allows to specifically compile the *WebSocket System Handle* unitary and\n  integration tests; this is useful to avoid compiling each *System Handle's* test suite present\n  in the `colcon` workspace, which is what would happen if using the `BUILD_TESTS` flag; and thus,\n  minimizing the building time; to use it, after making sure that the *WebSocket System Handle*\n  is present in the `colcon` workspace, the following command must be executed:\n  ```bash\n  ~/is_ws$ colcon build --cmake-args -DBUILD_WEBSOCKET_TESTS=ON\n  ```\n\n## Documentation\n\nThe official documentation for the *WebSocket System Handle* is included within the official *Integration Service*\ndocumentation, hosted by [Read the Docs](https://integration-service.docs.eprosima.com/), and comprises the following sections:\n\n* [Installation Manual](https://integration-service.docs.eprosima.com/en/latest/installation_manual/installation_manual.html)\n* [User Manual](https://integration-service.docs.eprosima.com/en/latest/user_manual/systemhandle/websocket_sh.html)\n* [API Reference](https://integration-service.docs.eprosima.com/en/latest/api_reference/websocket_sh/api_is_websocket_sh.html)\n\n## License\n\nThis repository is open-sourced under the *Apache-2.0* license. See the [LICENSE](LICENSE) file for more details.\n\n## Getting help\n\nIf you need support you can reach us by mail at `support@eProsima.com` or by phone at `+34 91 804 34 48`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feprosima%2Fwebsocket-sh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feprosima%2Fwebsocket-sh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feprosima%2Fwebsocket-sh/lists"}