{ "info": { "author": "Kevin L. Mitchell", "author_email": "klmitch@mit.edu", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: No Input/Output (Daemon)", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License (GPL)", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "==============================================\nTendril Frame-based Network Connection Tracker\n==============================================\n\nTendril is a network communication library based on two main features:\nit is based on sending and receiving frames, and it tracks the state\nof an abstract connection as defined by the application. Tendril is\ndesigned to be easy to use: creating an application requires\nsubclassing the ``Application`` class and providing an implementation\nfor the recv_frame() method; then get a ``TendrilManager`` class\ninstance and start it, and Tendril manages the rest.\n\nTendril Concepts\n================\n\nFrames\n------\n\nTendril is based on the concept of passing around frames or packets of\ndata. The fact is, most network protocols are based on sending and\nreceiving frames; for instance, in the SMTP protocol used for sending\nemail, the sender will start off sending the frame \"MAIL FROM\nemail@example.com\" followed by a line termination sequence (a carriage\nreturn followed by a newline). The SMTP server will then respond with\nanother frame acknowledging the \"MAIL FROM\" frame, and that frame will\nalso end with a line termination sequence. Thus, even though SMTP is\ndefined on top of the TCP protocol, which provides an undivided stream\nof data between the client and server, a framing boundary is imposed\nupon it--in this case, the carriage return followed by a newline that\nterminates each frame.\n\nTendril includes the concept of *framers*. A framer is nothing more\nthan a subclass of ``Framer`` which has one method which extracts a\nsingle frame from the stream of undifferentiated data, and another\nmethod which converts a frame into an appropriate representation. In\nthe case of the SMTP protocol exchange above, the ``frameify()``\nmethod finds each line terminated by the carriage return-newline pair,\nstrips off those characters, and returns just the frame. In the same\nway, the corresponding ``streamify()`` method takes the frame and\nappends a carriage return-newline pair.\n\nFor text-based protocols such as SMTP, this may seem like overkill.\nHowever, for binary-based protocols, a lot of code is dedicated to\ndetermining the boundaries between frames, and in some cases even\ndecoding the frame. Tendril's concept of a framer for a connection\nenables the framing logic to be isolated from the rest of the\napplication, and even reused: Tendril comes with several pre-built\nframers, including framers designed to work with a text-based protocol\nsuch as SMTP.\n\nAnother important advantage of the framer concept is the ability to\nswitch between framers as needed. Taking again the example of the\nSMTP protocol--the actual email data is transferred to the server by\nthe client first sending a \"DATA\" frame; the server responds\nindicating that it is ready to begin receiving the message data, and\nthen the client simply sends the message data, ending it with a line\ncontaining only a single period (\".\"). In this case, an SMTP server\napplication based on Tendril may wish to receive the message data as a\nsingle frame; it can do this by creating a framer which buffers stream\ndata until it sees that ending sentinel (the period on a line by\nitself), then returns the whole message as a single frame. Once the\nserver receives the \"DATA\" frame from the client, all it has to do is\ntemporarily switch out the framer in use for the receiving side of the\nconnection, then switch it back to the standard line-based framer once\nit has received the message frame.\n\nTendril allows for different framers to be used on the receiving side\nand sending side of the connection. This could be used in a case like\nthe SMTP server example cited above, where the server still wishes to\nsend line-oriented frames to the client, even while buffering a\nmessage data frame. In addition, although the provided framers deal\nwith byte data, Tendril itself treats the frames as opaque;\napplications can use this to build a framer that additionally parses a\ngiven frame into a class object that the rest of the application then\nprocesses as necessary.\n\nConnection Tracking\n-------------------\n\nTendril is also based on the concept of tracking connection state.\nFor connection-oriented protocols such as TCP, obviously, this is not\na big problem; however, Tendril is also designed to support\nconnectionless protocols such as UDP, where some applications need to\nmanage state information relevant to a given exchange. As an\nadmittedly contrived example, consider DNS, which is based on UDP. A\nclient of the DNS system will send a request to a DNS server over UDP;\nwhen a response is received from that DNS server, the connection state\ninformation tracked by Tendril can help connect that response with the\nappropriate request, ensuring that the response goes to the right\nplace.\n\nThis connection state tracking is primarily intended to assist\napplications which desire to be available over both\nconnection-oriented protocols such as TCP and over connectionless\nprotocols such as UDP. Although Tendril does not address reliability\nor frame ordering, its connection state tracking eases the\nimplementation of an application which utilizes both types of\nprotocols.\n\nExtensibility\n-------------\n\nCareful readers may have noticed the use of the terms, \"such as TCP\"\nand \"such as UDP.\" Although Tendril only has built-in support for TCP\nand UDP connections, it is possible to extend Tendril to support other\nprotocols. All that is required is to create subclasses of\n``Tendril`` (representing an individual connection) and of\n``TendrilManager`` (which accepts and creates connections and manages\nany necessary socket data flows), and to register the\n``TendrilManager`` subclasses as ``pkg_resources`` entry points under\nthe ``tendril.manager`` namespace. See the ``setup.py`` for Tendril\nfor an example of how this may be done.\n\nIn addition to allowing Tendril to support protocols other than TCP\nand UDP, it is also possible to implement new framers by subclassing\nthe ``Framer`` class. (Note: as Tendril deals with ``Framer``\nobjects, it is not necessary to register these framers using\n``pkg_resources`` entry points.) Objects of these classes may then\nsimply be assigned to the appropriate ``framers`` attribute on the\n``Tendril`` instance representing the connection.\n\nAdvanced Interfaces\n-------------------\n\nTendril also provides an advanced interface that allows a given raw\nsocket to be \"wrapped.\" Using this feature, an ordinary TCP socket\ncould be converted into an SSL socket. Other uses for this interface\nare possible, such as setting socket options for the socket. Tendril\nalso provides an interface to allow multiple of these wrapper\nfunctions to be called in a given order.\n\nStandard Usage\n==============\n\nThe first step in using Tendril is to define an application by\nsubclassing the ``Application`` class. (Subclassing is not strictly\nnecessary--Tendril uses Python's standard ``abc`` package for defining\nabstract base classes--but using subclassing will pull in a few\nhelpful and/or required methods.) The subclass need merely implement\nthe recv_frame() method, which will be called when a frame is\nreceived. The ``Application`` subclass constructor itself can be the\n*acceptor* to be used by Tendril (more on acceptors in a moment).\n\nOnce the ``Application`` subclass has been created, the developer then\nneeds to get a ``TendrilManager`` instance, using the\n``get_manager()`` factory function. The exact call to\n``get_manager()`` depends on the needs; for making outgoing\nconnections, simply calling ``get_manager(\"tcp\")`` is sufficient. If\nlistening on a port or making an outgoing connection from a specific\naddress and/or port is desired, the second argument to\n``get_manager()`` may be a tuple of the desired local IP address and\nthe port number (i.e., ``(\"127.0.0.1\", 80)``).\n\nAll managers must be started, and ``get_manager()`` does not start the\nmanager by itself. Check the manager's ``running`` attribute to see\nif the manager is already running, and if it is not, call its\n``start()`` method. To accept connections, pass ``start()`` the\n*acceptor* (usually the ``Application`` subclass). The ``start()``\nmethod also accepts a *wrapper*, which will be called with the\nlistening socket when it is created.\n\nIf, instead of accepting connections (as a server would do), the\ndesire is to make outgoing connections, simply call ``start()`` with\nno arguments, then call the ``connect()`` method of the manager. This\nmethod takes the *target* of the connection (i.e., the IP address and\nport number, as a tuple) and the *acceptor*. (It also has an optional\n*wrapper*, which will be called with the outgoing socket just prior to\ninitiating the connection.)\n\nAcceptors\n---------\n\nAn *acceptor* is simply a callable taking a single argument--the\n``Tendril`` instance representing the connection--and returning an\ninstance of a subclass of ``Application``, which will be assigned to\nthe ``application`` attribute of the ``Tendril`` instance. The\nacceptor initializes the application; it also has the opportunity to\nmanipulate that ``Tendril``, such as setting framers, calling the\n``Tendril`` instance's ``wrap()`` method, or simply closing the\nconnection.\n\nAlthough the ``TendrilManager`` does not provide the opportunity to\npass arguments to the acceptor, it is certainly possible to do so.\nThe standard Python ``functools.partial()`` is one obvious interface,\nbut Tendril additionally provides its own ``TendrilPartial`` utility;\nthe advantage of ``TendrilPartial`` is that the positional argument\npassed to the acceptor--the ``Tendril`` instance--will be the first\npositional argument, rather than the last one, as would be the case\nwith ``functools.partial()``.\n\nWrappers\n--------\n\nA *wrapper* is simply a callable again taking a single argument--in\nthis case, the socket object--and returning a wrapped version of that\nargument; that wrapped version of the socket will then be used in\nsubsequent network calls. A wrapper which manipulates socket options\ncan simply return the socket object which was passed in, while one\nwhich performs SSL encapsulation can return the SSL wrapper. Again,\nalthough there is no opportunity to pass arguments to the wrapper in a\nmanager ``start()`` or ``connect()`` call (or a ``Tendril`` object's\n``wrap()`` call), ``functools.partial()`` or Tendril's\n``TendrilPartial`` utility can be used. In particular, in conjunction\nwith ``TendrilPartial``, the ``ssl.wrap_socket()`` call can be used as\na socket wrapper directly, enabling an SSL connection to be set up\neasily.\n\nOf course, it may be necessary to perform multiple \"wrapping\"\nactivities on a connection, such as setting socket options followed by\nwrapping the socket in an SSL connection. For this case, Tendril\nprovides the ``WrapperChain``; it can be initialized in the same way\nthat ``TendrilPartial`` is, but additional wrappers can be added by\ncalling the ``chain()`` method; when called, the ``WrapperChain``\nobject will call each wrapper in the order defined, returning the\nfinal wrapped socket in the end.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/klmitch/tendril", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "Tendril", "package_url": "https://pypi.org/project/Tendril/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/Tendril/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/klmitch/tendril" }, "release_url": "https://pypi.org/project/Tendril/0.1.1/", "requires_dist": null, "requires_python": null, "summary": "Frame-based Network Connection Tracker", "version": "0.1.1" }, "last_serial": 1002881, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "ad136e715c88fff25d997d3f7481e0f4", "sha256": "e74d44c4e0fcb71ac1b91b0b32c5973371c50d36e39eaeb138b3bb775b3f59a4" }, "downloads": -1, "filename": "Tendril-0.1.0.tar.gz", "has_sig": false, "md5_digest": "ad136e715c88fff25d997d3f7481e0f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 58418, "upload_time": "2012-10-11T02:45:18", "url": "https://files.pythonhosted.org/packages/34/08/692f290515f4649027fc7fbe5e8a1b69fc5d260f8586d9f000d8c1447db6/Tendril-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "c31329bf7d2ef1c719ad7e2bbafdd7be", "sha256": "08c90f741db23938cbfd9dba427b486ebd617bde6b2210e7dfc37c5940490b8a" }, "downloads": -1, "filename": "Tendril-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c31329bf7d2ef1c719ad7e2bbafdd7be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 58787, "upload_time": "2014-02-18T01:23:37", "url": "https://files.pythonhosted.org/packages/41/ba/b6af6283dbed26ac6e22235a7f347848a3ef8977edd41db4b60e0ce8610d/Tendril-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c31329bf7d2ef1c719ad7e2bbafdd7be", "sha256": "08c90f741db23938cbfd9dba427b486ebd617bde6b2210e7dfc37c5940490b8a" }, "downloads": -1, "filename": "Tendril-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c31329bf7d2ef1c719ad7e2bbafdd7be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 58787, "upload_time": "2014-02-18T01:23:37", "url": "https://files.pythonhosted.org/packages/41/ba/b6af6283dbed26ac6e22235a7f347848a3ef8977edd41db4b60e0ce8610d/Tendril-0.1.1.tar.gz" } ] }