{"id":13420397,"url":"https://github.com/seanmiddleditch/libtelnet","last_synced_at":"2025-03-15T06:32:53.844Z","repository":{"id":521488,"uuid":"149835","full_name":"seanmiddleditch/libtelnet","owner":"seanmiddleditch","description":"Simple RFC-complient TELNET implementation as a C library.","archived":true,"fork":false,"pushed_at":"2024-01-21T02:08:57.000Z","size":544,"stargazers_count":330,"open_issues_count":19,"forks_count":134,"subscribers_count":31,"default_branch":"develop","last_synced_at":"2025-03-09T00:44:42.966Z","etag":null,"topics":["c","telnet"],"latest_commit_sha":null,"homepage":"http://github.com/seanmiddleditch/libtelnet","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seanmiddleditch.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2009-03-13T03:34:18.000Z","updated_at":"2025-03-05T20:45:57.000Z","dependencies_parsed_at":"2024-10-26T17:49:31.885Z","dependency_job_id":"cb692a88-e02f-4d5b-b8e0-dbe9871a57ff","html_url":"https://github.com/seanmiddleditch/libtelnet","commit_stats":{"total_commits":353,"total_committers":25,"mean_commits":14.12,"dds":0.4447592067988668,"last_synced_commit":"5f5ecee776b9bdaa4e981e5f807079a9c79d633e"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanmiddleditch%2Flibtelnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanmiddleditch%2Flibtelnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanmiddleditch%2Flibtelnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanmiddleditch%2Flibtelnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seanmiddleditch","download_url":"https://codeload.github.com/seanmiddleditch/libtelnet/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243695456,"owners_count":20332622,"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":["c","telnet"],"created_at":"2024-07-30T22:01:32.812Z","updated_at":"2025-03-15T06:32:53.470Z","avatar_url":"https://github.com/seanmiddleditch.png","language":"C","funding_links":[],"categories":["TODO scan for Android support in followings","C"],"sub_categories":[],"readme":"[![Actions Status](https://github.com/seanmiddleditch/libtelnet/workflows/CI/badge.svg)](https://github.com/seanmiddleditch/libtelnet/actions)\n\nlibtelnet - TELNET protocol handling library\n============================================\n\n http://github.com/seanmiddleditch/libtelnet\n\n Sean Middleditch and contributors\n\n\nThe author or authors of this code dedicate any and all copyright\ninterest in this code to the public domain. We make this dedication\nfor the benefit of the public at large and to the detriment of our\nheirs and successors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\ncode under copyright law.\n\n\nI. Introduction\n---------------\n\nlibtelnet provides safe and correct handling of the core TELNET\nprotocol.  In addition to the base TELNET protocol, libtelnet also\nimplements the Q method of TELNET option negotiation.  libtelnet can\nbe used for writing servers, clients, or proxies.\n\nFor more information on the TELNET standards supported by libtelnet,\nvisit the following websites:\n\n* http://www.faqs.org/rfcs/rfc854.html\n* http://www.faqs.org/rfcs/rfc855.html\n* http://www.faqs.org/rfcs/rfc1091.html\n* http://www.faqs.org/rfcs/rfc1143.html\n* http://www.faqs.org/rfcs/rfc1408.html\n* http://www.faqs.org/rfcs/rfc1572.html\n\nII. API\n-------\n\nThe libtelnet API contains several distinct parts.  The first part is\nthe basic initialization and deinitialization routines.  The second\npart is a single function for pushing received data into the telnet\nprocessor.  The third part is the libtelnet output functions, which\ngenerate TELNET commands and ensure data is properly formatted before\nsending over the wire.  The final part is the event handler\ninterface.\n\nThis document covers only the most basic functions.  See the\nlibtelnet manual pages or HTML documentation for a complete\nreference.\n\n#### IIa. Initialization\n\n Using libtelnet requires the initialization of a telnet_t structure\n which stores all current state for a single TELNET connection.\n\n Initializing a telnet_t structure requires several pieces of data.\n One of these is the telopt support table, which specifies which\n TELNET options your application supports both locally and remotely.\n This table is comprised of telnet_telopt_t structures, one for each\n supported option.  Each entry specifies the option supported,\n whether the option is supported locally or remotely.\n\n```\nstruct telnet_telopt_t {\n    short telopt;\n    unsigned char us;\n    unsigned char him;\n};\n```\n\n The us field denotes whether your application supports the telopt\n locally.  It should be set to TELNET_WILL if you support it and to\n TELNET_WONT if you don't.  The him field denotes whether the telopt\n is supported on the remote end, and should be TELNET_DO if yes and\n TELNET_DONT if not.\n\n When definition the telopt table you must include an end marker\n entry, which is simply an entry with telopt set to -1.  For\n example:\n\n```\nstatic const telnet_telopt_t my_telopts[] = {\n    { TELNET_TELOPT_ECHO,      TELNET_WILL, TELNET_DONT },\n    { TELNET_TELOPT_TTYPE,     TELNET_WILL, TELNET_DONT },\n    { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO   },\n    { TELNET_TELOPT_ZMP,       TELNET_WONT, TELNET_DO   },\n    { TELNET_TELOPT_MSSP,      TELNET_WONT, TELNET_DO   },\n    { TELNET_TELOPT_BINARY,    TELNET_WILL, TELNET_DO   },\n    { TELNET_TELOPT_NAWS,      TELNET_WILL, TELNET_DONT },\n    { -1, 0, 0 }\n};\n```\n\n If you need to dynamically alter supported options on a\n per-connection basis then you may use a different table\n (dynamically allocated if necessary) per call to telnet_init() or\n you share a single constant table like the above example between\n all connections if you support a fixed set of options.  Most\n applications will support only a fixed set of options.\n\n* `telnet_t *telnet_init(const telnet_telopts_t *telopts,\n     telnet_event_handler_t handler, unsigned char flags,\n     void *user_data);`\n\n   The telnet_init() function is responsible for allocating memory\n   and initializing the data in a telnet_t structure.  It must be\n   called immediately after establishing a connection and before any\n   other libtelnet API calls are made.\n\n   The telopts field is the telopt support table as described above.\n\n   The handler parameter must be a function matching the\n   telnet_event_handler_t definition.  More information about events\n   can be found in section IId.\n\n   The user_data parameter is passed to the event handler whenver it\n   is invoked.  This will usually be a structure container\n   information about the connection, including a socket descriptor\n   for implementing TELNET_EV_SEND event handling.\n\n   The flags parameter can be any of the following flag constants\n   bit-or'd together, or 0 to leave all options disabled.\n\n    TELNET_FLAG_PROXY\n      Operate in proxy mode.  This disables the RFC1143 support and\n      enables automatic detection of COMPRESS2 streams.\n\n    TELNET_FLAG_NVT_EOL\n      Receive data with translation of the TELNET NVT CR NUL and CR LF\n      sequences specified in RFC854 to C carriage return (\\r) and C\n      newline (\\n), respectively.\n\n   If telnet_init() fails to allocate the required memory, the\n   returned pointer will be zero.\n\n* `void telnet_free(telnet_t *telnet);`\n\n   Releases any internal memory allocated by libtelnet for the given\n   telnet pointer.  This must be called whenever a connection is\n   closed, or you will incur memory leaks.  The pointer passed in may\n   no longer be used afterwards.\n\n#### IIb. Receiving Data\n\n* `void telnet_recv(telnet_t *telnet,\n     const char *buffer, unsigned int size, void *user_data);`\n\n   When your application receives data over the socket from the\n   remote end, it must pass the received bytes into this function.\n\n   As the TELNET stream is parsed, events will be generated and\n   passed to the event handler given to telnet_init().  Of particular\n   interest for data receiving is the TELNET_EV_DATA event, which is\n   triggered for any regular data such as user input or server\n   process output.\n\n#### IIc. Sending Data\n\n All of the output functions will invoke the TELNET_EV_SEND event.\n\n Note: it is very important that ALL data sent to the remote end of\n the connection be passed through libtelnet.  All user input or\n process output that you wish to send over the wire should be given\n to one of the following functions.  Do NOT send or buffer\n unprocessed output data directly!\n\n* `void telnet_iac(telnet_t *telnet, unsigned char cmd);`\n\n   Sends a single \"simple\" TELNET command, such as the GO-AHEAD\n   commands (255 249).\n\n* `void telnet_negotiate(telnet_t *telnet, unsigned char cmd,\n     unsigned char opt);`\n\n   Sends a TELNET negotiation command.  The cmd parameter must be one\n   of TELNET_WILL, TELNET_WONT, TELNET_DO, or TELNET_DONT.  The opt\n   parameter is the option to negotiate.\n\n   Unless in PROXY mode, the RFC1143 support may delay or ellide the\n   request entirely, as appropriate.  It will ignore duplicate\n   invocations, such as asking for WILL NAWS when NAWS is already on\n   or is currently awaiting response from the remote end.\n\n* `void telnet_send(telnet_t *telnet, const char *buffer, size_t size);`\n\n   Sends raw data, which would be either the process output from a\n   server or the user input from a client.\n\n   For sending regular text it may be more convenient to use\n   telnet_printf().\n\n* `void telnet_send_text(telnet_t *telnet, const char *buffer,\n     size_t size);`\n\n   Sends text characters with translation of C newlines (\\n) into\n   CR LF and C carriage returns (\\r) into CR NUL, as required by\n   RFC854, unless transmission in BINARY mode has been negotiated.\n\n   For sending regular text it may be more convenient to use\n   telnet_printf().\n\n* `void telnet_begin_sb(telnet_t *telnet, unsigned char telopt);`\n\n   Sends the header for a TELNET sub-negotiation command for the\n   specified option.  All send data following this command will be\n   part of the sub-negotiation data until a call is made to\n   telnet_finish_subnegotiation().\n\n   You should not use telnet_printf() for sending subnegotiation\n   data as it will perform newline translations that usually do not\n   need to be done for subnegotiation data, and may cause problems.\n\n* `void telnet_finish_sb(telnet_t *telnet);`\n\n   Sends the end marker for a TELNET sub-negotiation command.  This\n   must be called after (and only after) a call has been made to\n   telnet_begin_subnegotiation() and any negotiation data has been\n   sent.\n\n* `void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt,\n     const char *buffer, unsigned int size);`\n\n   Sends a TELNET sub-negotiation command.  The telopt parameter is\n   the sub-negotiation option.\n\n   Note that this function is just a shorthand for:\n   ```\n    telnet_begin_sb(telnet, telopt);\n    telnet_send(telnet, buffer, size);\n    telnet_end_sb(telnet);\n   ```\n\n   For some subnegotiations that involve a lot of complex formatted\n   data to be sent, it may be easier to make calls to both\n   telnet_begin_sb() and telnet_finish_sb() and using telnet_send()\n   or telnet_printf2() to format the data.\n\n   NOTE: telnet_subnegotiation() does have special behavior in\n   PROXY mode, as in that mode this function will automatically\n   detect the COMPRESS2 marker and enable zlib compression.\n\n* `int telnet_printf(telnet_t *telnet, const char *fmt, ...);`\n\n  This functions very similarly to fprintf, except that output is\n  sent through libtelnet for processing.  IAC bytes are properly\n  escaped, C newlines (\\n) are translated into CR LF, and C carriage\n  returns (\\r) are translated into CR NUL, all as required by\n  RFC854.  The return code is the length of the formatted text.\n\n  NOTE: due to an internal implementation detail, the maximum\n  lenth of the formatted text is 4096 characters.\n\n\n#### IId. Event Handling\n\n libtelnet relies on an event-handling mechanism for processing the\n parsed TELNET protocol stream as well as for buffering and sending\n output data.\n\n When you initialize a telnet_t structure with telnet_init() you had\n to pass in an event handler function.  This function must meet the\n following prototype:\n\n  `void (telnet_t *telnet, telnet_event_t *event, void *user_data);`\n\n The event structure is detailed below.  The user_data value is the\n pointer passed to telnet_init().\n\n The following is a summary of the most important parts of the\n telnet_event_t data type.  Please see the libtelnet manual pages or\n HTML document for a complete reference.\n\n```\nunion telnet_event_t {\n  enum telnet_event_type_t type;\n\n  struct data_t {\n    enum telnet_event_type_t _type;\n    const char *buffer;\n    size_t size;\n  } data;\n\n  struct error_t {\n    enum telnet_event_type_t _type;\n    const char *file;\n    const char *func;\n    const char *msg;\n    int line;\n    telnet_error_t errcode;\n  } error;\n\n  struct iac_t {\n    enum telnet_event_type_t _type;\n    unsigned char cmd;\n  } iac;\n\n  struct negotiate_t {\n    enum telnet_event_type_t _type;\n    unsigned char telopt;\n  } neg;\n\n  struct subnegotiate_t {\n    enum telnet_event_type_t _type;\n    const char *buffer;\n    size_t size;\n    unsigned char telopt;\n  } sub;\n};\n```\n\n The enumeration values of telnet_event_type_t are described in\n detail below.  Whenever the the event handler is invoked, the\n application must look at the event-\u003etype value and do any necessary\n processing.\n\n The only event that MUST be implemented is TELNET_EV_SEND.  Most\n applications will also always want to implement the event\n TELNET_EV_DATA.\n\n Here is an example event handler implementation which includes\n handlers for several important events.\n\n```\nvoid my_event_handler(telnet_t *telnet, telnet_event_t *ev,\n    void *user_data) {\n  struct user_info *user = (struct user_info *)user_data;\n\n  switch (ev-\u003etype) {\n  case TELNET_EV_DATA:\n    process_user_input(user, event-\u003edata.buffer, event-\u003edata.size);\n    break;\n  case TELNET_EV_SEND:\n    write_to_descriptor(user, event-\u003edata.buffer, event-\u003edata.size);\n    break;\n  case TELNET_EV_ERROR:\n    fatal_error(\"TELNET error: %s\", event-\u003eerror.msg);\n    break;\n  }\n}\n```\n\n* TELNET_EV_DATA\n\n   The DATA event is triggered whenever regular data (not part of any\n   special TELNET command) is received.  For a client, this will be\n   process output from the server.  For a server, this will be input\n   typed by the user.\n\n   The event-\u003edata.buffer value will contain the bytes received and the\n   event-\u003edata.size value will contain the number of bytes received.\n   Note that event-\u003edata.buffer is not NUL terminated!\n\n   NOTE: there is no guarantee that user input or server output\n   will be received in whole lines.  If you wish to process data\n   a line at a time, you are responsible for buffering the data and\n   checking for line terminators yourself!\n\n* TELNET_EV_SEND\n\n   This event is sent whenever libtelnet has generated data that must\n   be sent over the wire to the remove end.  Generally that means\n   calling send() or adding the data to your application's output\n   buffer.\n\n   The event-\u003edata.buffer value will contain the bytes to send and the\n   event-\u003edata.size value will contain the number of bytes to send.\n   Note that event-\u003edata.buffer is not NUL terminated, and may include\n   NUL characters in its data, so always use event-\u003edata.size!\n\n   NOTE: Your SEND event handler must send or buffer the data in\n   its raw form as provided by libtelnet.  If you wish to perform\n   any kind of preprocessing on data you want to send to the other\n\n* TELNET_EV_IAC\n\n   The IAC event is triggered whenever a simple IAC command is\n   received, such as the IAC EOR (end of record, also called go ahead\n   or GA) command.\n\n   The command received is in the event-\u003eiac.cmd value.\n\n   The necessary processing depends on the specific commands; see\n   the TELNET RFC for more information.\n\n* TELNET_EV_WILL / TELNET_EV_DO\n\n   The WILL and DO events are sent when a TELNET negotiation command\n   of the same name is received.\n\n   WILL events are sent by the remote end when they wish to be\n   allowed to turn an option on on their end, or in confirmation\n   after you have sent a DO command to them.\n\n   DO events are sent by the remote end when they wish for you to\n   turn on an option on your end, or in confirmation after you have\n   sent a WILL command to them.\n\n   In either case, the TELNET option under negotiation will be in\n   event-\u003eneg.telopt field.\n\n   libtelnet manages most of the pecularities of negotiation for you.\n   For information on libtelnet's negotiation method, see:\n\n    http://www.faqs.org/rfcs/rfc1143.html\n\n   Note that in PROXY mode libtelnet will do no processing of its\n   own for you.\n\n* TELNET_EV_WONT / TELNET_EV_DONT\n\n   The WONT and DONT events are sent when the remote end of the\n   connection wishes to disable an option, when they are refusing to\n   a support an option that you have asked for, or in confirmation of\n   an option you have asked to be disabled.\n\n   Most commonly WONT and DONT events are sent as rejections of\n   features you requested by sending DO or WILL events.  Receiving\n   these events means the TELNET option is not or will not be\n   supported by the remote end, so give up.\n\n   Sometimes WONT or DONT will be sent for TELNET options that are\n   already enabled, but the remote end wishes to stop using.  You\n   cannot decline.  These events are demands that must be complied\n   with.  libtelnet will always send the appropriate response back\n   without consulting your application.  These events are sent to\n   allow your application to disable its own use of the features.\n\n   In either case, the TELNET option under negotiation will be in\n   event-\u003eneg.telopt field.\n\n   Note that in PROXY mode libtelnet will do no processing of its\n   own for you.\n\n* TELNET_EV_SUBNEGOTIATION\n\n   Triggered whenever a TELNET sub-negotiation has been received.\n   Sub-negotiations include the NAWS option for communicating\n   terminal size to a server, the NEW-ENVIRON and TTYPE options for\n   negotiating terminal features, and MUD-centric protocols such as\n   ZMP, MSSP, and MCCP2.\n\n   The event-\u003esub-\u003etelopt value is the option under sub-negotiation.\n   The remaining data (if any) is passed in event-\u003esub.buffer and\n   event-\u003esub.size.  Note that most subnegotiation commands can include\n   embedded NUL bytes in the subnegotiation data, and the data\n   event-\u003esub.buffer is not NUL terminated, so always use the\n   event-\u003esub.size value!\n\n   The meaning and necessary processing for subnegotiations are\n   defined in various TELNET RFCs and other informal specifications.\n   A subnegotiation should never be sent unless the specific option\n   has been enabled through the use of the telnet negotiation\n   feature.\n\n   TTYPE/ENVIRON/NEW-ENVIRON/MSSP/ZMP SUPPORT:\n   libtelnet parses these subnegotiation commands.  A special\n   event will be sent for each, after the SUBNEGOTIATION event is\n   sent.  Except in special circumstances, the SUBNEGOTIATION event\n   should be ignored for these options and the special events should\n   be handled explicitly.\n\n* TELNET_EV_COMPRESS\n\n   The COMPRESS event notifies the app that COMPRESS2/MCCP2\n   compression has begun or ended.  Only servers can send compressed\n   data, and hence only clients will receive compressed data.\n\n   The event-\u003ecommand value will be 1 if compression has started and\n   will be 0 if compression has ended.\n\n* TELNET_EV_ZMP\n\n   The event-\u003ezmp.argc field is the number of ZMP parameters, including\n   the command name, that have been received.  The event-\u003ezmp.argv\n   field is an array of strings, one for each ZMP parameter.  The\n   command name will be in event-\u003ezmp.argv[0].\n\n* TELNET_EV_TTYPE\n\n   The event-\u003ettype.cmd field will be either TELNET_TTYPE_SEND,\n   TELNET_TTYPE_IS, TELNET_TTYPE_INFO.\n\n   The actual terminal type will be in event-\u003ettype.name.\n\n* TELNET_EV_ENVIRON\n\n   The event-\u003eenviron.cmd field will be either TELNET_ENVIRON_IS,\n   TELNET_ENVIRON_SEND, or TELNET_ENVIRON_INFO.\n\n   The actual environment variable sent or requested will be sent\n   in the event-\u003eenviron.values field.  This is an array of\n   structures with the following format:\n\n   ```\n     struct telnet_environ_t {\n       unsigned char type;\n       const char *var;\n       const char *value;\n     };\n   ```\n\n   The number of entries in the event-\u003eenviron.values array is\n   stored in event-\u003eenviron.count.\n\n   Note that libtelnet does not support the ESC byte for ENVIRON/\n   NEW-ENVIRON.  Data using escaped bytes will not be parsed\n   correctly.\n\n* TELNET_EV_MSSP\n\n   The event-\u003emssp.values field is an array of telnet_environ_t\n   structures.  The cmd field in each entry will have an\n   unspecified value, while the var and value fields will always\n   be set to the MSSP variable and value being set.  For multi-value\n   MSSP variables, there will be multiple entries in the values\n   array for each value, each with the same variable name set.\n\n   The number of entries in the event-\u003emssp.values array is\n   stored in event-\u003emssp.count.\n\n* TELNET_EV_WARNING\n\n   The WARNING event is sent whenever something has gone wrong inside\n   of libtelnet (possibly due to malformed data sent by the other\n   end) but which recovery is (likely) possible.  It may be safe to\n   continue using the connection, but some data may have been lost or\n   incorrectly interpreted.\n\n   The event-\u003eerror.msg field will contain a NUL terminated string\n   explaining the error.\n\n* TELNET_EV_ERROR\n\n   Similar to the WARNING event, the ERROR event is sent whenever\n   something has gone wrong.  ERROR events are non-recoverable,\n   however, and the application should immediately close the\n   connection.  Whatever has happened is likely going only to result\n   in garbage from libtelnet.  This is most likely to happen when a\n   COMPRESS2 stream fails, but other problems can occur.\n\n   The event-\u003eerror.msg field will contain a NUL terminated string\n   explaining the error.\n\nIII. Integrating libtelnet with common muds\n-------------------------------------------\n\nFIXME: fill in some notes about how to splice in libtelnet with\ncommon Diku/Merc/Circle/etc. MUD codebases.\n\nIV. Safety and correctness considerations\n-----------------------------------------\n\nYour existing application may make heavy use of its own output\nbuffering and transmission commands, including hand-made routines for\nsending TELNET commands and sub-negotiation requests.  There are at\ntimes subtle issues that need to be handled when communication over\nthe TELNET protocol, not least of which is the need to escape any\nbyte value 0xFF with a special TELNET command.\n\nFor these reasons, it is very important that applications making use\nof libtelnet always make use of the libtelnet output functions for\nall data being sent over the TELNET connection.\n\nIn particular, if you are writing a client, all user input must be\npassed through to telnet_send().  This also includes any input\ngenerated automatically by scripts, triggers, or macros.\n\nFor a server, any and all output -- including ANSI/VT100 escape\ncodes, regular text, newlines, and so on -- must be passed through to\ntelnet_send().\n\nAny TELNET commands that are to be sent must be given to one of the\nfollowing: telnet_iac, telnet_negotiate, or telnet_subnegotiation().\n\nIf you are attempting to enable COMPRESS2/MCCP2, you must use the\ntelnet_begin_compress2() function.\n\nV. MCCP2 compression\n--------------------\n\nThe MCCP2 (COMPRESS2) TELNET extension allows for the compression of\nall traffic sent from server to client.  For more information:\n\n http://www.mudbytes.net/index.php?a=articles\u0026s=mccp\n\nIn order for libtelnet to support MCCP2, zlib must be installed and\nenabled when compiling libtelnet.  Use -DHAVE_ZLIB to enable zlib\nwhen compiling libtelnet.c and pass -lz to the linker to link in the\nzlib shared library.\n\nlibtelnet transparently supports MCCP2.  For a server to support\nMCCP2, the application must begin negotiation of the COMPRESS2 option\nusing telnet_negotiate(), for example:\n\n `telnet_negotiate(\u0026telnet, TELNET_WILL,\n     TELNET_OPTION_COMPRESS2, user_data);`\n\nIf a favorable DO COMPRESS2 is sent back from the client then the\nserver application can begin compression at any time by calling\ntelnet_begin_compress2().\n\nIf a connection is in PROXY mode and COMPRESS2 support is enabled\nthen libtelnet will automatically detect the start of a COMPRESS2\nstream, in either the sending or receiving direction.\n\nVI. Zenith MUD Protocol (ZMP) support\n-------------------------------------\n\nThe Zenith MUD Protocol allows applications to send messages across\nthe TELNET connection outside of the normal user input/output data\nstream.  libtelnet offers some limited support for receiving and\nsending ZMP commands to make implementing a full ZMP stack easier.\nFor more information on ZMP:\n\n http://zmp.sourcemud.org/\n\nFor a server to enable ZMP, it must send the WILL ZMP negotitaion:\n\n `telnet_negotiate(\u0026telnet, TELNET_WILL, TELNET_TELOPT_ZMP);`\n\nFor a client to support ZMP it must include ZMP in the telopt table\npassed to telnet_init(), with the him field set to TELNET_DO:\n\n `{ TELNET_TELOPT_ZMP,       TELNET_WONT, TELNET_DO   },`\n\nNote that while ZMP is a bi-directional protocol, it is only ever\nenabled on the server end of the connection.  This automatically\nenables the client to send ZMP commands.  The client must never\nattempt to negotiate ZMP directly using telnet_negotiate().\n\nOnce ZMP is enabled, any ZMP commands received will automatically be\nsent to the event handler function with the TELNET_EV_SUBNEGOTIATION\nevent code.  The command will automatically be parsed and the ZMP\nparameters will be placed in the event-\u003eargv array and the number of\nparameters will be placed in the event-\u003eargc field.\n\nNOTE: if an error occured while parsing the ZMP command because it\nwas malformed, the event-\u003eargc field will be equal to 0 and the\nevent-\u003eargv field will be NULL.  You should always check for this\nbefore attempting to access the parameter array.\n\nTo send ZMP commands to the remote end, use either telnet_send_zmp()\nor telnet_send_zmpv().\n\n* `int telnet_send_zmp(telnet_t *telnet, size_t argv,\n    const char **argv);`\n\n  Sends a ZMP command to the remote end.  The argc parameter is the\n  number of ZMP parameters (including the command name!) to be sent.\n  The argv parameter is an array of strings containing the\n  parameters.  The element in argv[0] is the command name itself.\n  The argv array must have at least as many elements as the value\n  argc.\n\nVII. MUD Server Status Protocol (MSSP) support\n----------------------------------------------\n\nMSSP allows for crawlers or other clients to query a MUD server's\nsupported feature list.  This allows MUD listing states to\nautomatically stay up to date with the MUD's features, and not\nrequire MUD administrators to manually update listing sites for\ntheir MUD.  For more information on MSSP:\n\n http://tintin.sourceforge.net/mssp/\n\nVIII. Telnet proxy utility\n--------------------------\n\nThe telnet-proxy utility is a small application that serves both as a\ntestbed for libtelnet and as a powerful debugging tool for TELNET\nservers and clients.\n\nTo use telnet-proxy, you must first compile it using:\n\n```\n $ (mkdir -p build \u0026\u0026 cd build \u0026\u0026 cmake .. \u0026\u0026 make)\n```\n\nIf you do not have zlib installed and wish to disable MCCP2 support\nthen you must first edit the Makefile and remove the -DHAVE_ZLIB and\nthe -lz from the compile flags.\n\nTo run telnet-proxy, you simply give it the server's host name or IP\naddress, the server's port number, and the port number that\ntelnet-proxy should listen on.  For example, to connect to the server\non mud.example.com port 7800 and to listen on port 5000, run:\n\n```\n $ ./build/util/telnet-proxy mud.example.com 7800 5000\n```\n\nYou can then connect to the host telnet-proxy is running on (e.g.\n127.0.0.1) on port 5000 and you will automatically be proxied into\nmud.example.com.\n\ntelnet-proxy will display status information about the data passing\nthrough both ends of the tunnel.  telnet-proxy can only support a\nsingle tunnel at a time.  It will continue running until an error\noccurs or a terminating signal is sent to the proxy process.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseanmiddleditch%2Flibtelnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseanmiddleditch%2Flibtelnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseanmiddleditch%2Flibtelnet/lists"}