{"id":13420186,"url":"https://github.com/facebook/wangle","last_synced_at":"2025-10-20T10:32:37.648Z","repository":{"id":24485278,"uuid":"27889694","full_name":"facebook/wangle","owner":"facebook","description":"Wangle is a framework providing a set of common client/server abstractions for building services in a consistent, modular, and composable way.","archived":false,"fork":false,"pushed_at":"2025-05-08T16:39:13.000Z","size":9127,"stargazers_count":3082,"open_issues_count":44,"forks_count":541,"subscribers_count":168,"default_branch":"main","last_synced_at":"2025-05-09T00:54:14.414Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"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/facebook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-12-11T20:12:30.000Z","updated_at":"2025-05-08T16:39:18.000Z","dependencies_parsed_at":"2023-10-14T23:12:37.034Z","dependency_job_id":"327feec3-3217-4204-beac-064adcbd17fa","html_url":"https://github.com/facebook/wangle","commit_stats":{"total_commits":6659,"total_committers":381,"mean_commits":"17.477690288713912","dds":0.4849076437903589,"last_synced_commit":"a9b845957058c19e8aac66146f655b97a791ab52"},"previous_names":[],"tags_count":446,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fwangle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fwangle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fwangle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facebook%2Fwangle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/facebook","download_url":"https://codeload.github.com/facebook/wangle/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254047571,"owners_count":22005828,"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":"2024-07-30T22:01:28.252Z","updated_at":"2025-10-20T10:32:32.600Z","avatar_url":"https://github.com/facebook.png","language":"C++","readme":"[![Support Ukraine](https://img.shields.io/badge/Support-Ukraine-FFD500?style=flat\u0026labelColor=005BBB)](https://opensource.fb.com/support-ukraine) [![Travis Build Status](https://api.travis-ci.com/facebook/wangle.svg?branch=master)](https://travis-ci.com/facebook/wangle)\n[![CI Status](https://github.com/facebook/wangle/workflows/CI/badge.svg?branch=master)](https://github.com/facebook/wangle/actions?workflow=CI)\n\u003csection class=\"dex_guide\"\u003e\u003ch1 class=\"dex_title\"\u003eWangle\u003c/h1\u003e\u003csection class=\"dex_document\"\u003e\u003ch1\u003e\u003c/h1\u003e\u003cp class=\"dex_introduction\"\u003eC++ networking library\u003c/p\u003e\u003cp\u003eWangle is a library that makes it easy to build protocols, application clients, and application servers.\u003c/p\u003e\n\n\u003cp\u003eIt\u0026#039;s like Netty + Finagle smooshed together, but in C++\u003c/p\u003e\n\n## Building and Installing\n\nThe main dependencies are:\n* The folly library from https://github.com/facebook/folly\n* The fizz library from https://github.com/facebookincubator/fizz\n* CMake\n* OpenSSL, at least version 1.0.2+, preferably with TLS extension support.\n\nOnce folly is installed, run the following inside the wangle directory to build, test, and install wangle:\n```\ncmake .\nmake\nctest\nsudo make install\n```\n\n## Tutorial\n\nThere is a tutorial [here](tutorial.md) that explains the basics of Wangle and shows how to build an echo server/client.\n\n## Examples\n\nSee the examples/ directory for some example Wangle servers and clients\n\n## License\nWangle is Apache 2.0-licensed.\n\n## Contributing\nSee the CONTRIBUTING file for how to help out.\n\n## Documentation\n\n\u003cp\u003eWangle interfaces are asynchronous.  Interfaces are currently based on \u003ca href=\"https://github.com/facebook/folly/tree/master/folly/futures\"\u003eFutures\u003c/a\u003e, but we\u0026#039;re also exploring how to support fibers\u003c/p\u003e\n\n\u003ch2 id=\"client-server-abstractio\"\u003eClient / Server abstraction \u003ca href=\"#client-server-abstractio\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eYou\u0026#039;re probably familiar with Java\u0026#039;s Netty, or Python\u0026#039;s twisted, or similar libraries.\u003c/p\u003e\n\n\u003cp\u003eIt is built on top of folly/async/io, so it\u0026#039;s one level up the stack from that (or similar abstractions like boost::asio)\u003c/p\u003e\n\n\u003cp\u003eServerBootstrap - easily manage creation of threadpools and pipelines\u003c/p\u003e\n\n\u003cp\u003eClientBootstrap - the same for clients\u003c/p\u003e\n\n\u003cp\u003ePipeline - set up a series of handlers that modify your socket data\u003c/p\u003e\n\n\u003ch2 id=\"request-response-abstrac\"\u003eRequest / Response abstraction \u003ca href=\"#request-response-abstrac\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eThis is roughly equivalent to the \u003ca href=\"https://twitter.github.io/finagle/\" target=\"_blank\"\u003eFinagle\u003c/a\u003e library.\u003c/p\u003e\n\n\u003cp\u003eAims to provide easy testing, load balancing, client pooling, retry logic, etc.  for any request/response type service - i.e. thrift, http, etc.\u003c/p\u003e\n\n\u003cp\u003eService - a matched interface between client/server.  A server will implement this interface, and a client will call in to it.  These are protocol-specific\u003c/p\u003e\n\n\u003cp\u003eServiceFilter - a generic filter on a service. Examples: stats, request timeouts, rate limiting\u003c/p\u003e\n\n\u003cp\u003eServiceFactory - A factory that creates client connections.  Any protocol specific setup code goes here\u003c/p\u003e\n\n\u003cp\u003eServiceFactoryFilter - Generic filters that control how connections are created.  Client examples: load balancing, pooling,  idle timeouts, markdowns, etc.\u003c/p\u003e\u003c/section\u003e\u003csection class=\"dex_document\"\u003e\u003ch1\u003eServerBootstrap\u003c/h1\u003e\u003cp class=\"dex_introduction\"\u003eEasily create a new server\u003c/p\u003e\u003cp\u003eServerBootstrap does the work to set up one or multiple acceptor threads, and one or multiple sets of IO threads.  The thread pools can be the same.  SO_REUSEPORT is automatically supported for multiple accept threads. tcp is most common, although udp is also supported.\u003c/p\u003e\n\n\u003ch2 id=\"methods\"\u003eMethods \u003ca href=\"#methods\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003e\u003cstrong\u003echildPipeline(PipelineFactory\u0026lt;Pipeline\u0026gt;)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eSets the pipeline factory for each new connection.  One pipeline per connection will be created.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003egroup(IOThreadPoolExecutor accept, IOThreadPoolExecutor io)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eSets the thread pools for accept and io thread pools.  If more than one thread is in the accept group, SO_REUSEPORT is used.  Defaults to a single accept thread, and one io thread per core.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003ebind(SocketAddress),bind(port)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eBinds to a port. Automatically starts to accept after bind.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003estop()\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eStops listening on all sockets.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003ejoin()\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eJoins all threadpools - all current reads and writes will be completed before this method returns.\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-note\"\u003e\u003cspan class=\"remarkup-note-word\"\u003eNOTE:\u003c/span\u003e however that both accept and io thread pools will be stopped using this method, so the thread pools can\u0026#039;t be shared, or care must be taken using shared pools during shutdown.\u003c/div\u003e\n\n\u003cp\u003e\u003cstrong\u003ewaitForStop()\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eWaits for stop() to be called from another thread.\u003c/p\u003e\n\n\u003ch2 id=\"other-methods\"\u003eOther methods \u003ca href=\"#other-methods\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003e\u003cstrong\u003echannelFactory(ServerSocketFactory)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eSets up the type of server.  Defaults to TCP AsyncServerSocket, but AsyncUDPServerSocket is also supported to receive udp messages.  In practice, ServerBootstrap is only useful for udp if you need to multiplex the messages across many threads, or have TCP connections going on at the same time, etc.  Simple usages of AsyncUDPSocket probably don\u0026#039;t need the complexity of ServerBootstrap.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003epipeline(PipelineFactory\u0026lt;AcceptPipeline\u0026gt;)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eThis pipeline method is used to get the accepted socket (or udp message) \u003cstrong\u003ebefore\u003c/strong\u003e it has been handed off to an IO thread.  This can be used to steer the accept thread to a particular thread, or for logging.\u003c/p\u003e\n\n\u003cp\u003eSee also AcceptRoutingHandler and RoutingDataHandler for additional help in reading data off of the accepted socket \u003cstrong\u003ebefore\u003c/strong\u003e it gets attached to an IO thread.  These can be used to hash incoming sockets to specific threads.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003echildHandler(AcceptorFactory)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003ePreviously facebook had lots of code that used AcceptorFactories instead of Pipelines, this is a method to support this code and be backwards compatible.  The AcceptorFactory is responsible for creating acceptors, setting up pipelines, setting up AsyncSocket read callbacks, etc.\u003c/p\u003e\n\n\u003ch2 id=\"examples\"\u003eExamples \u003ca href=\"#examples\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eA simple example:\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"no\"\u003eServerBootstrap\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eTelnetPipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"no\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e;\u003c/span\u003e                                                                                                      \n\u003cspan class=\"no\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"childPipeline\"\u003echildPipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\" data-symbol-name=\"std\"\u003estd\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"std\" data-symbol-name=\"make_shared\"\u003emake_shared\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eTelnetPipelineFactory\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;());\u003c/span\u003e                                                                             \n\u003cspan class=\"no\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"bind\"\u003ebind\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003eFLAGS_port\u003c/span\u003e\u003cspan class=\"o\"\u003e);\u003c/span\u003e                                                                                                                     \n\u003cspan class=\"no\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"waitForStop\"\u003ewaitForStop\u003c/span\u003e\u003cspan class=\"o\"\u003e();\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/section\u003e\u003csection class=\"dex_document\"\u003e\u003ch1\u003eClientBootstrap\u003c/h1\u003e\u003cp class=\"dex_introduction\"\u003eCreate clients easily\u003c/p\u003e\u003cp\u003eClientBootstrap is a thin wrapper around AsyncSocket that provides a future interface to the connect callback, and a Pipeline interface to the read callback.\u003c/p\u003e\n\n\u003ch2 id=\"methods\"\u003eMethods \u003ca href=\"#methods\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003e\u003cstrong\u003egroup(IOThreadPoolExecutor)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eSets the thread or group of threads where the IO will take place.  Callbacks are also made on this thread.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003ebind(port)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eOptionally bind to a specific port\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eFuture\u0026lt;Pipeline*\u0026gt; connect(SocketAddress)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eConnect to the selected address.  When the future is complete, the initialized pipeline will be returned.\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-note\"\u003e\u003cspan class=\"remarkup-note-word\"\u003eNOTE:\u003c/span\u003e future.cancel() can be called to cancel an outstanding connection attempt.\u003c/div\u003e\n\n\u003cp\u003e\u003cstrong\u003epipelineFactory(PipelineFactory\u0026lt;Pipeline\u0026gt;)\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eSet the pipeline factory to use after a connection is successful.\u003c/p\u003e\n\n\u003ch2 id=\"example\"\u003eExample \u003ca href=\"#example\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"no\"\u003eClientBootstrap\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eTelnetPipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"no\"\u003eclient\u003c/span\u003e\u003cspan class=\"o\"\u003e;\u003c/span\u003e\n\u003cspan class=\"no\"\u003eclient\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"group\"\u003egroup\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\" data-symbol-name=\"std\"\u003estd\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"std\" data-symbol-name=\"make_shared\"\u003emake_shared\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nc\" data-symbol-name=\"folly\"\u003efolly\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"folly\" data-symbol-name=\"wangle\"\u003ewangle\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-name=\"IOThreadPoolExecutor\"\u003eIOThreadPoolExecutor\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"o\"\u003e));\u003c/span\u003e\n\u003cspan class=\"no\"\u003eclient\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"pipelineFactory\"\u003epipelineFactory\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\" data-symbol-name=\"std\"\u003estd\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"std\" data-symbol-name=\"make_shared\"\u003emake_shared\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eTelnetPipelineFactory\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;());\u003c/span\u003e\n\u003cspan class=\"c\"\u003e// synchronously wait for the connect to finish\u003c/span\u003e\n\u003cspan class=\"no\"\u003eauto\u003c/span\u003e \u003cspan class=\"no\"\u003epipeline\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"no\"\u003eclient\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"connect\"\u003econnect\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"SocketAddress\"\u003eSocketAddress\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003eFLAGS_host\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\u003cspan class=\"no\"\u003eFLAGS_port\u003c/span\u003e\u003cspan class=\"o\"\u003e)).\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"get\"\u003eget\u003c/span\u003e\u003cspan class=\"o\"\u003e();\u003c/span\u003e\n\n\u003cspan class=\"c\"\u003e// close the pipeline when finished\u003c/span\u003e\n\u003cspan class=\"no\"\u003epipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan class=\"na\" data-symbol-name=\"close\"\u003eclose\u003c/span\u003e\u003cspan class=\"o\"\u003e();\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/section\u003e\u003csection class=\"dex_document\"\u003e\u003ch1\u003ePipeline\u003c/h1\u003e\u003cp class=\"dex_introduction\"\u003eSend your socket data through a series of tubes\u003c/p\u003e\u003cp\u003eA Pipeline is a series of Handlers that intercept inbound or outbound events, giving full control over how events are handled.  Handlers can be added dynamically to the pipeline.\u003c/p\u003e\n\n\u003cp\u003eWhen events are called, a Context* object is passed to the Handler - this means state can be stored in the context object, and a single instantiation of any individual Handler can be used for the entire program.\u003c/p\u003e\n\n\u003cp\u003eNetty\u0026#039;s documentation: \u003ca href=\"http://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html\" target=\"_blank\"\u003eChannelHandler\u003c/a\u003e\u003c/p\u003e\n\n\u003cp\u003eUsually, the bottom of the Pipeline is a wangle::AsyncSocketHandler to read/write to a socket, but this isn\u0026#039;t a requirement.\u003c/p\u003e\n\n\u003cp\u003eA pipeline is templated on the input and output types:\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"no\"\u003eEventBase\u003c/span\u003e \u003cspan class=\"no\"\u003ebase_\u003c/span\u003e\u003cspan class=\"o\"\u003e;\u003c/span\u003e\n\u003cspan class=\"no\"\u003ePipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eIOBufQueue\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026amp;,\u003c/span\u003e \u003cspan class=\"nc\" data-symbol-name=\"std\"\u003estd\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"std\" data-symbol-name=\"unique_ptr\"\u003eunique_ptr\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eIOBuf\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan class=\"no\"\u003epipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e;\u003c/span\u003e\n\u003cspan class=\"no\"\u003epipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"addBack\"\u003eaddBack\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"AsyncSocketHandler\"\u003eAsyncSocketHandler\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\" data-symbol-name=\"AsyncSocket\"\u003eAsyncSocket\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-context=\"AsyncSocket\" data-symbol-name=\"newSocket\"\u003enewSocket\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003eeventBase\u003c/span\u003e\u003cspan class=\"o\"\u003e)));\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003eThe above creates a pipeline and adds a single AsyncSocket handler, that will push read events through the pipeline when the socket gets bytes.  Let\u0026#039;s try handling some socket events:\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"k\"\u003eclass\u003c/span\u003e \u003cspan class=\"no\"\u003eMyHandler\u003c/span\u003e \u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"k\"\u003epublic\u003c/span\u003e \u003cspan class=\"no\"\u003eInboundHandler\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nc\" data-symbol-name=\"folly\"\u003efolly\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"folly\" data-symbol-name=\"IOBufQueue\"\u003eIOBufQueue\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026amp;\u0026gt;\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026#123;\u003c/span\u003e\n \u003cspan class=\"k\"\u003epublic\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\n\n  \u003cspan class=\"no\"\u003evoid\u003c/span\u003e \u003cspan class=\"nf\" data-symbol-name=\"read\"\u003eread\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003eContext\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e \u003cspan class=\"no\"\u003ectx\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e \u003cspan class=\"nc\" data-symbol-name=\"folly\"\u003efolly\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"na\" data-symbol-context=\"folly\" data-symbol-name=\"IOBufQueue\"\u003eIOBufQueue\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026amp;\u003c/span\u003e \u003cspan class=\"no\"\u003eq\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"no\"\u003eoverride\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026#123;\u003c/span\u003e\n    \u003cspan class=\"no\"\u003eIOBufQueue\u003c/span\u003e \u003cspan class=\"no\"\u003edata\u003c/span\u003e\u003cspan class=\"o\"\u003e;\u003c/span\u003e   \n    \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003eq\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"chainLength\"\u003echainLength\u003c/span\u003e\u003cspan class=\"o\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026#123;\u003c/span\u003e\n       \u003cspan class=\"no\"\u003edata\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"append\"\u003eappend\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003eq\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\" data-symbol-name=\"split\"\u003esplit\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"o\"\u003e));\u003c/span\u003e\n       \u003cspan class=\"no\"\u003ectx\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan class=\"na\" data-symbol-name=\"fireRead\"\u003efireRead\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003edata\u003c/span\u003e\u003cspan class=\"o\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"o\"\u003e\u0026#125;\u003c/span\u003e \n  \u003cspan class=\"o\"\u003e\u0026#125;\u003c/span\u003e\n\u003cspan class=\"o\"\u003e\u0026#125;;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003eThis handler only handles read (inbound) data, so we can inherit from InboundHandler, and ignore the outbound type (so the ordering of inbound/outbound handlers in your pipeline doesn\u0026#039;t matter).   It checks if there are at least 4 bytes of data available, and if so, passes them on to the next handler.  If there aren\u0026#039;t yet four bytes of data available, it does nothing, and waits for more data.\u003c/p\u003e\n\n\u003cp\u003eWe can add this handler to our pipeline like so:\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nx\"\u003epipeline\u003c/span\u003e\u003cspan class=\"k\"\u003e.\u003c/span\u003e\u003cspan data-symbol-name=\"addBack\" class=\"nf\"\u003eaddBack\u003c/span\u003e\u003cspan class=\"k\"\u003e(\u003c/span\u003e\u003cspan data-symbol-name=\"MyHandler\" class=\"nf\"\u003eMyHandler\u003c/span\u003e\u003cspan class=\"k\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\u003cspan class=\"k\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003eand remove it just as easily:\u003c/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"no\"\u003epipeline\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"no\"\u003eremove\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"no\"\u003eMyHandler\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;();\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\u003ch3 id=\"staticpipeline\"\u003eStaticPipeline \u003ca href=\"#staticpipeline\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eInstantiating all these handlers and pipelines can hit the allocator pretty hard.  There are two ways to try to do fewer allocations.  StaticPipeline allows \u003cstrong\u003eall\u003c/strong\u003e the handlers, and the pipeline, to be instantiated all in the same memory block, so we only hit the allocator once.\u003c/p\u003e\n\n\u003cp\u003eThe other option is to allocate the handlers once at startup, and reuse them in many pipelines.  This means all state has to be saved in the HandlerContext object instead of the Handler itself, since each handler can be in multiple pipelines.  There is one context per pipeline to get around this limitation.\u003c/p\u003e\u003c/section\u003e\u003csection class=\"dex_document\"\u003e\u003ch1\u003eBuilt-in handlers\u003c/h1\u003e\u003cp class=\"dex_introduction\"\u003eThe stuff that comes with the box\u003c/p\u003e\u003ch2 id=\"byte-to-byte-handlers\"\u003eByte to byte handlers \u003ca href=\"#byte-to-byte-handlers\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003ch3 id=\"asyncsockethandler\"\u003eAsyncSocketHandler \u003ca href=\"#asyncsockethandler\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eThis is almost always the first handler in the pipeline for clients and servers - it connects an AsyncSocket to the pipeline.  Having it as a handler is nice, because mocking it out for tests becomes trivial.\u003c/p\u003e\n\n\u003ch3 id=\"outputbufferinghandler\"\u003eOutputBufferingHandler \u003ca href=\"#outputbufferinghandler\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eOutput is buffered and only sent once per event loop.  This logic is exactly what is in ThriftServer, and very similar to what exists in proxygen - it can improve throughput for small writes by up to 300%.\u003c/p\u003e\n\n\u003ch3 id=\"eventbasehandler\"\u003eEventBaseHandler \u003ca href=\"#eventbasehandler\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003ePutting this right after an AsyncSocketHandler means that writes can happen from any thread, and eventBase-\u0026gt;runInEventBaseThread() will automatically be called to put them in the correct thread.  It doesn\u0026#039;t intrinsically make the pipeline thread-safe though, writes from different threads may be interleaved, other handler stages must be only used from one thread or be thread safe, etc.\u003c/p\u003e\n\n\u003cp\u003eIn addition, reads are still always called on the eventBase thread.\u003c/p\u003e\n\n\u003ch2 id=\"codecs\"\u003eCodecs \u003ca href=\"#codecs\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003ch3 id=\"fixedlengthframedecoder\"\u003eFixedLengthFrameDecoder \u003ca href=\"#fixedlengthframedecoder\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eA decoder that splits received IOBufs by a fixed number of bytes.  Used for fixed-length protocols\u003c/p\u003e\n\n\u003ch3 id=\"lengthfieldprepender\"\u003eLengthFieldPrepender \u003ca href=\"#lengthfieldprepender\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003ePrepends a fixed-length field length.  Field length is configurable.\u003c/p\u003e\n\n\u003ch3 id=\"lengthfieldbasedframedec\"\u003eLengthFieldBasedFrameDecoder \u003ca href=\"#lengthfieldbasedframedec\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eThe receiving portion of LengthFieldPrepender - decodes based on a fixed frame length, with optional header/tailer data sections.\u003c/p\u003e\n\n\u003ch3 id=\"linebasedframedecoder\"\u003eLineBasedFrameDecoder \u003ca href=\"#linebasedframedecoder\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eDecodes by line (with optional ending detection types), to be used for text-based protocols\u003c/p\u003e\n\n\u003ch3 id=\"stringcodec\"\u003eStringCodec \u003ca href=\"#stringcodec\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h3\u003e\n\n\u003cp\u003eConverts from IOBufs to std::strings and back for text-based protocols.  Must be used after one of the above frame decoders\u003c/p\u003e\u003c/section\u003e\u003csection class=\"dex_document\"\u003e\u003ch1\u003eServices\u003c/h1\u003e\u003cp class=\"dex_introduction\"\u003eHow to add a new protocol\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://twitter.github.io/finagle/guide/ServicesAndFilters.html\" target=\"_blank\"\u003eFinagle\u0026#039;s documentation\u003c/a\u003e on Services is highly recommended\u003c/p\u003e\n\n\u003ch2 id=\"services\"\u003eServices \u003ca href=\"#services\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eA Pipeline was read() and write() methods - it streams bytes in one or both directions.  write() returns a future, but the future is set when the bytes are successfully written.   Using pipeline there is no easy way to match up requests and responses for RPC.\u003c/p\u003e\n\n\u003cp\u003eA Service is an RPC abstraction - Both clients and servers implement the interface.   Servers implement it by handling the request.  Clients implement it by sending the request to the server to complete.\u003c/p\u003e\n\n\u003cp\u003eA Dispatcher is the adapter between the Pipeline and Service that matches up the requests and responses.  There are several built in Dispatchers, however if you are doing anything advanced, you may need to write your own.\u003c/p\u003e\n\n\u003cp\u003eBecause both clients and servers implement the same interface, mocking either clients or servers is trivially easy.\u003c/p\u003e\n\n\u003ch2 id=\"servicefilters\"\u003eServiceFilters \u003ca href=\"#servicefilters\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eServiceFilters provide a way to wrap filters around every request and response.  Things like logging, timeouts, retrying requests, etc. can be implemented as ServiceFilters.\u003c/p\u003e\n\n\u003cp\u003eExisting ServiceFilters include:\u003c/p\u003e\n\n\u003cul\u003e\n\u003cli\u003eCloseOnReleaseFilter - rejects requests after connection is closed.  Often used in conjunction with\u003c/li\u003e\n\u003cli\u003eExpiringFilter - idle timeout and max connection time (usually used for clients)\u003c/li\u003e\n\u003cli\u003eTimeoutFilter - request timeout time.  Usually used on servers.  Clients can use future.within to specify timeouts individually.\u003c/li\u003e\n\u003cli\u003eExecutorFilter - move requests to a different executor.\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 id=\"servicefactories\"\u003eServiceFactories \u003ca href=\"#servicefactories\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eFor some services, a Factory can help instantiate clients.   In Finagle, these are frequently provided for easy use with specific protocols, i.e. http, memcache, etc.\u003c/p\u003e\n\n\u003ch2 id=\"servicefactoryfilters\"\u003eServiceFactoryFilters \u003ca href=\"#servicefactoryfilters\" class=\"headerLink\"\u003e#\u003c/a\u003e\u003c/h2\u003e\n\n\u003cp\u003eServiceFactoryFilters provide filters for getting clients.  These include most connection-oriented things, like connection pooling, selection, dispatch, load balancing, etc.\u003c/p\u003e\n\n\u003cp\u003eExisting ServiceFactoryFilters:\u003c/p\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003c/li\u003e\n\u003cli\u003e\u003c/li\u003e\n\u003c/ul\u003e\u003c/section\u003e\n","funding_links":[],"categories":["TODO scan for Android support in followings","Networking","C++","Frameworks / Runtimes","内存分配"],"sub_categories":["网络"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebook%2Fwangle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffacebook%2Fwangle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacebook%2Fwangle/lists"}