{"id":19389062,"url":"https://github.com/yyyar/yamp","last_synced_at":"2026-03-02T00:35:22.792Z","repository":{"id":73975779,"uuid":"91871920","full_name":"yyyar/yamp","owner":"yyyar","description":":speech_balloon: YAMP: Yet Another Messaging Protocol ","archived":false,"fork":false,"pushed_at":"2019-07-09T10:51:12.000Z","size":24,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-03T20:05:42.135Z","etag":null,"topics":["client-server","communication","messaging","protocol","protocols"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yyyar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2017-05-20T07:10:16.000Z","updated_at":"2020-12-19T21:40:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"228691b3-34c6-415b-b5ad-086c6e15a6ff","html_url":"https://github.com/yyyar/yamp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yyyar/yamp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yyyar%2Fyamp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yyyar%2Fyamp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yyyar%2Fyamp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yyyar%2Fyamp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yyyar","download_url":"https://codeload.github.com/yyyar/yamp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yyyar%2Fyamp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29988055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T22:42:38.399Z","status":"ssl_error","status_checked_at":"2026-03-01T22:41:51.863Z","response_time":124,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["client-server","communication","messaging","protocol","protocols"],"created_at":"2024-11-10T10:14:39.273Z","updated_at":"2026-03-02T00:35:22.766Z","avatar_url":"https://github.com/yyyar.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"/yamp-logo.png?raw=true\" alt=\"yamp\" width=\"256px\" /\u003e\n\n## Yamp - Application Messaging Protocol\n\n**Yamp** is simple and flexible messaging protocol for\nrealtime client-server applications. It provides custom messages\ntransfering alongside with request-response pattern. **Yamp** is transport\nand format agnostic and may be adopted to any specific needs.\n\nThis document describes **Yamp v1.0 Draft**.\n\n## Implementations\n- Javascript \u0026 Node.JS: [yamp-js](https://github.com/yyyar/yamp-js)\n- Golang: [yamp-go](https://github.com/yyyar/yamp-go)\n\n## Background\n\nThere are lots of messaging protocols out of there like AMQP, Thrift,\nRMI, MQTT, Socket.io, XMPP, ZMQ, and others. Many of them\nare overcomplicated and heavyweight, others suffer from lack of\nfeatures. Some of them (for example, WAMP) designed explecitely for IoT and \nrequire Router component as a mediator to be presented in a solution, even where\nit's redundant. On other hand, protocols like Websockets can't handle \nrequest-response pattern natively forcing developers to implement their own solutions.\n\n**Yamp** designed to provide application developers with the semantics they need\nto implement client-server bi-directional communication with the following features:\n\n- Events: publish/subsribe pattern. It's just that websocket can do.\n- Requests: RPC-like functionality (req/res), one party emits message on what other party responds.\n- Progressive responses, request canceling and timeouts.\n- Pluggable Transports: can be implemented on top of any reliable protocol: TCP, TLS, websocket, or other.\n- Pluggable Formats: message body may serialized/parsed with any setialization format.\n- Cross-Language: can be easily implemented in any language\n\n\n## Structure\n\nBasically, **Yamp** operates with frames that are tranfered over specific transport.\n\n```\n  frame\n  +-----------------------------------------------+\n  |                                               |\n  |  frame-specific data                          |\n  |                                               |\n  |  body (user frames only)                      |\n  |  +-----------------------------------------+  |\n  |  |               binary data               |  |\n  |  |      (protobuf, msgpack, json, etc)   \u003c-|--|------ format\n  |  |                                         |  |\n  |  +-----------------------------------------+  |\n  |                                               |\n  +-----------------------------------------------+\n+---------------------------------------------------+\n|                                                   |\n|            (tcp/tls, ws/wss, etc...)              | \u003c-- transport\n|                                                   |\n+---------------------------------------------------+\n\n```\n\n### Transport adapters\nFrom a transport adapter, **Yamp** expects ability to send/receive buffer (bytes array) of data.\n\n```\ntransport.write(buffer)\nbuffer = transport.read()\n```\n\n## Assumptions\n\n**Yamp** uses network byte order (big-endian).\nWe use C-alike pseudo language alongside pictures to describe messages structure.\n\n## Frame\n\nFrames is what **Yamp** tranfes through transport.\nFirst byte is frame is frame type, following bytes interpretation are specific to concrete frame type.\n\n```\n//\n//  0       7                  N\n//  +-------++~~~~~~~~~~~~~~ ~ ~ ~\n//  | 1     ||\n//  +-------++ depends on type\n//  | type  ||\n//  +-------++~~~~~~~~~~~~~~ ~ ~ ~\n//\n\nFrame {\n\n  byte type\n\n  select(type) {\n    0x00: system.handshake,\n    0x01: system.close,\n    0x02: system.ping,\n\n    0x10: event,\n    0x11: request,\n    0x12: cancel,\n    0x13: response\n  }\n}\n```\n\n\n## System Frames\n\nThese frames control internal communication between parties and are not exposed\nto user as user messages. While defining user procotol one should not rely on these\nframes and use User Messages instead.\n\n\n### 0x00 system.handshake\n\nShould be first frame after connection establishment client party sends\nto server party to identify itself. Server party should respond with the same\nhandshake (echo) in case it support client, or with `system.close` frame.\n\n```\n//\n//        0       15\n//  ~ ~ ~ +--------+\n//        | 2      |\n//        +--------+\n//        |version |\n//  ~ ~ ~ +--------+\n//\n\nsystem.handshake {\n\n  byte[2]      version     // (required)\n  \n}\n\n```\n\n\n### 0x01 system.close\nShould be sent by any party before gracefully closing connection.\nConnection or session drop should follow this message. Reason of connection\ndrop and recommendation on what action to do depends on code.\n\nIs server party wants client to use\nanother server with different url it sends code = 'redirect'. \nAfter this message server should close connection / session.\nIn this case `message` field should contain string in the following format: \n`\u003cprotocol\u003e://\u003chost\u003e:\u003cport\u003e[/uri]`, for example:\n`tcp://192.168.0.42:5000` or `ws://hostname:8888/hello/world?msg=goodmorning`\n\n```\n//\n//        0        7                 23                     N\n//  ~ ~ ~ +--------++----------------++------------~ ~ ~ ~--+ \n//        | 1      || 2              || 1 x size            | \n//        +--------++----------------++------------~ ~ ~ ~--+ \n//        | code   || size           || message             | \n//  ~ ~ ~ +--------++----------------++------------~ ~ ~ ~--+ \n//\n\nsystem.close {\n\n  byte           code = {    // (required)\n    0x00: unknown,\n    0x01: version_not_supported,\n    0x02: timeout,\n    0x03: redirect,\n  }\n\n  byte[2]        size       // (required)\n  string[size]   message    // (optional)\n\n}\n\n```\n\n\n\n### 0x02 system.ping\nMy be periodically sent by any party to another to check if it's alive or\nkeep underlying connection or session alive.\nEach `system.ping` frame with false 'ack' from one party should be followed with corresponding\n`system.ping` message from another party with 'ack' field set to 'true' and the \nsame payload within defined (reasonable) pediod of time.\n\n```\n//\n//        0        7         15                     N\n//  ~ ~ ~ +--------++--------++------------~ ~ ~ ~--+ \n//        | 1      || 1      || 1 x size            | \n//        +--------++--------++------------~ ~ ~ ~--+ \n//        | ack    || size   || payload             | \n//  ~ ~ ~ +--------++--------++------------~ ~ ~ ~--+ \n//\n\nsystem.ping {\n \n ack           byte(bool)  // (required)\n byte          size        // (required)\n string[size]  payload     // (optional)\n\n}\n\n```\n\n\n## User Message Frames\n\nThese messages are building blocks for user application protocol.\n\n\n### Basic Structures\n\nThese basic structures are reusable in several user messages so\nthey are defined separately to avoid duplication.\n\n\n#### UserMessageHeader\n\nCommon header for all user messages.\nContains unique message identifier and uri (name) of user message.\n\n```\n//\n//        0              127               127+1                    N\n//  ~ ~ ~ +-----~ ~ ~-----+ +----------------++------------~ ~ ~ ~--+ ~ ~ ~\n//        | 16            | | 1              || 1 x size            |\n//        +-----~ ~ ~-----+ +----------------++------------~ ~ ~ ~--+\n//        | uid           | | size           || uri                 |\n//  ~ ~ ~ +---------------+ +------------------------------~ ~ ~ ~--+ ~ ~ ~\n//\n\nUserMessageHeader {\n\n  byte[16]       uid    // (required)\n\n  byte           size   // (required)\n  string[size]   uri    // (required)\n}\n\n```\n\n#### UserMessageBody\n\nCommon body for most of user messages.\n\n```\n//\n//        0                31                     N\n//  ~ ~ ~ +--~~~~~~~~~~~~--++------------~ ~ ~ ~--+ ~ ~ ~\n//        | 4              || 1 x size            |\n//        +----------------++------------~ ~ ~ ~--+\n//        | size           || body                |\n//  ~ ~ ~ +-~~~~~~~~~~~~~~-++------------~ ~ ~ ~--+ ~ ~ ~\n//\n\nUserMessageBody {\n\n  byte[4]      size   // (required)\n  byte[size]   body   // (optional) maximum 4Gb\n\n}\n```\n\n\n### 0x10 event\n\nUser message (pub/sub event) with binary body in any serialization format\n\n```\n//\n//        0                     N                    N+M\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-+\n//        |                     ||                     |\n//        | UserMessageHeader   ||   UserMessageBody   |\n//        |                     ||                     |\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-+\n//\n\nevent {\n\n  UserMessageHeader  header  // (required)\n  UserMessageBody    body    // (required)\n\n}\n\n```\n\n\n### 0x11 request\n\nRequest from one party to another. Requester should wait until\ncorresponding `response` message comes to fulfull request. Requester\nparty should also define some reasonable timeout value after\nwhich requester should provide user with an timeout error.\n\n```\n//\n//        0                     N                      M\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-+\n//        |                     ||                     |\n//        | UserMessageHeader   ||   UserMessageBody   |\n//        |                     ||                     |\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-+\n//\n\nrequest {\n\n  UserMessageHeader  header       // (required)\n  UserMessageBody    body         // (required)\n\n}\n```\n\n\n### 0x12 cancel\n\nIf requester wants to ask requested party to cancel (or stop) processing\npreviously sent `request` it should use this message. Meaning of cancel\nis implementation dependent and may be graceful rollback or just halt.\n\n```\n//\n//        0                     N               N+128\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++---~~~~~~~~-----+\n//        |                     ||       16       |\n//        | UserMessageHeader   |+---~~~~~~~~-----+\n//        |                     ||   request_uid  |\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++---~~~~~~~~~----+\n//\n\ncancel {\n\n  UserMessageHeader  header       // (required)\n  byte[16]           request_uid  // (required) original request id to cancel\n\n}\n\n```\n\n\n### 0x13 response\n\nResponse is message sent by party that previously received `request` and:\n- successfully completed request (`done`)\n- faced error while processing request (`error`)\n- got next progress step, if responder supports progress (`progress`)\n- successfully cancelled request if got from requester `cancel` message.\n\n```\n//\n//        0                     N               N+128    N+128+8             N+128+8+M\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++---~~~~~~~~-----++--------++-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-+\n//        |                     ||       16       ||   1    ||                     |\n//        | UserMessageHeader   |+---~~~~~~~~-----++--------+|   UserMessageBody   |\n//        |                     ||   request_uid  ||  type  ||                     |\n//  ~ ~ ~ +-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-++---~~~~~~~~~----++--------++-~ ~ ~ ~ ~ ~ ~ ~ ~ ~-+\n//\n\nresponse {\n\n  UserMessageHeader header        // (required)\n  byte[16]          request_uid   // (required)\n\n  byte              type = {      // (required)\n    0x00: done,\n    0x01: error,\n    0x02: progress,\n    0x03: cancelled\n  }\n\n  UserMessageBody   body          // (required)\n}\n\n```\n\n## Authors\n- Yaroslav Pogrebnyak \u003cyyyaroslav@gmail.com\u003e\n- Illarion Kovalchuk \u003cillarion.kovalchuk@gmail.com\u003e\n\n## Logo\n- [Max Demchenko](https://www.linkedin.com/in/max-demchenko-116170112)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyyyar%2Fyamp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyyyar%2Fyamp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyyyar%2Fyamp/lists"}