📄 dpid.txt
字号:
Aug 2003, Jorge Arellano Cid, Ferdi Franceschini --Last update: Dec 2004 ------ dpid -------------------Nomenclature:------------- dpi: generic term referring to dillo's plugin system (version1). dpi1: specific term for dillo's plugin spec version 1. at: http://www.dillo.org/dpi1.html dpi program: any plugin program itself. dpi framework: the code base inside and outside dillo that makes dpi1 working possible (it doesn't include dpi programs). dpip: dillo plugin protocol. The HTML/XML like set of command tags and information that goes inside the communication sockets. Note: not yet fully defined, but functional. Note2: it was designed to be extensible. dpid: dillo plugin daemon. server plugin: A plugin that is capable of accepting connections on a socket. Dpid will never run more than one instance of a server plugin at a time. filter plugin: Any program/script that can read or write to stdio. If you can write a shell script you can write one of these (see examples at the end). Warning, dpid will run multiple instances of filter plugins if requested. This is safe if the plugin only writes to stdout which is what the filter type dpis do at the moment.-----------About dpid:----------- * dpid is a program which manages dpi connections. * dpid is a daemon that serves dillo using unix domain sockets (UDS). * dpid launches dpi programs and arranges socket communication between the dpi program and dillo. The concept and motivation is similar to that of inetd. Theplugin manager (dpid) listens for a service request on a Unixdomain socket and returns the socket name of a plugin thathandles the service. It also watches sockets of inactive pluginsand starts them when a connection is requested.-----------------------------------------------------------What's the problem with managing dpi programs inside dillo?----------------------------------------------------------- That's the other way to handle it, but it started to show someproblems (briefly outlined here): * When having two or more running instances of Dillo, one should prevail, and take control of dpi managing (but all dillos carry the managing code). * If the managing dillo exits, it must pass control to another instance, or leave it void if there's no other dillo running! * The need to synchronise all the running instances of dillo arises. * If the controlling instance finishes and quits, all the dpi-program PIDs are lost. * Terminating hanged dpis is hard if it's not done with signals (PIDs) * Forks can be expensive (Dillo had to fork its dpis). * When a managing dillo exits, the new one is no longer the parent of the forked dpis. * If the Unix domain sockets for the dpis were to be named randomly, it gets very hard to recover their names if the controlling instance of dillo exits and another must "take over" the managing. * It increments dillo's core size. * ... That's why the managing daemon scheme was chosen.----------------------What does dpid handle?---------------------- It solves all the above mentioned shortcomings and also can do: * Multiple dillos: dpid can communicate and serve more than one instance of dillo. * Multiple dillo windows: two or more windows of the same dillo instance accessing dpis at the same time. * Different implementations of the same service dpi programs ("dpis") are just an implementation of a service. There's no problem in having more than one for the same service. * Upgrading a service: to a new version or implementation without requiring bringing down the dpid or patching dillo's core. And finally, being aware that this design can support thefollowing functions is very helpful: SCHEME Example ------------------------------------------------------------ * "one demand/one response" man, preferences, ... * "resident while working" downloads, mp3, ... * "resident until TERM signal" bookmarks, ... * "one client only" cd burner, ... * "one client per instance" man, ... * "multiple clients/one instance" downloads, cookies ...--------Features-------- * Dpi programs go in: "EPREFIX/dillo/dpi" or "~/.dillo/dpi". The binaries are named <name>.dpi as "bookmarks.dpi" and <name>.filter.dpi as in "hello.filter.dpi". The ".filter" plugins simply read and write to stdio and can be implemented with a shell script easily. * Register/update/remove dpis from list of available dpis when a <dpi cmd='register_all'> is received. * dpid terminates when it receives a <dpi cmd='DpiBye'> command. * dpis can be terminated with a <dpi cmd='DpiBye'> command. * dpidc control program for dpid, currently allows register and stop.-----todo:----- These features are already designed, waiting for implementation: * How to register/update/remove/ individual dpis? * How to kill dpis? (signals) How: A useful and flexible way is to have a "control program" fordpid (it avoids having to find its PID among others). Let's say: dpidc [register | upgrade | stop | ...] It can talk to a dpid UDS that serves for that (the same thatdillo would use). That way we may also have a dpidc dpi! :-) Seriously, what I like from this approach is that it is veryflexible and can be implemented incrementally ("dpidc register"is enough to start). It also avoids the burden of having to periodically check thedpis directory structure for changes). It also lets shell scripts an easy way to do the "dirty" workof installing dpis; as is required with distros' packagesystems. <note> How do we tell a crashed dpi? That's the question. We're thinking about using the "lease" concept (as in JINI).</note>-----------------How does it work?-----------------o on startup dpid reads dpidrc for the path to the dpi directory (usually EPREFIX/lib/dillo/dpi). ~/.dillo/dpi is scanned first.o both directories are scanned for the list of available plugins. ~/.dillo/dpi overrides system-wide dpis.o ~/.dillo/dpi_socket_dir is then checked for the name of the dpi socket directory, if dpi_socket_dir does not exist it will be created.o next it creates Unix domain sockets for the available plugins and then listens for service requests on its own socket (dpid.srs) and for connections to the sockets of inactive plugins.o dpid returns the name of a plugin's socket when a client (dillo) requests a service.o if the requested plugin is a 'server' then 1) dpid stops watching the socket for activity 2) forks and starts the plugin 3) resumes watching the socket when the plugin exitso if the requested plugin is a 'filter' then 1) dpid accepts the connection 2) duplicates the connection on stdio 3) forks and starts the plugin 4) continues to watch the socket for new connections---------------------------dpi service process diagram--------------------------- These drawings should be worth a thousand words! :)(I) .--- s1 s2 s3 ... sn | [dpid] [dillo] | '--- srs The dpid is running listening on several sockets.(II) .--- s1 s2 s3 ... sn | [dpid] [dillo] | | '--- srs ------------------' dillo needs a service so it connects to the service request socket of the dpid (srs) and asks for the socket name of the required plugin (using dpip).(III) .--- s1 s2 s3 ... sn | | [dpid] | [dillo] | | | '--- srs '---------------' then it connects to that socket (s3, still serviced by dpid!)(IV) .--- s1 s2 s3 ... sn | | .[dpid] | [dillo] . | | | . '--- srs '---------------' . .............[dpi program] when s3 has activity (incoming data), dpid forks the dpi program for it...(V) .--- s1 s2 (s3) ... sn | [dpid] [dillo] | | '--- srs .---------------' | [dpi program] ... and lets it "to take over" the socket. Once there's a socket channel for dpi and dillo, the wholecommunication process takes place until the task is done. Whenthe dpi program exits, dpid resumes listening on the socket (s3).-----------------------------------------------How are the unix-domain-sockets for dpis named?----------------------------------------------- Let's say we have two users, "fred" and "joe". When Fred's dillo starts its dpid, the dpid creates thefollowing directory (rwx------): /tmp/fred-XXXXXX using mkdtemp(). and saves that filename within "~/.dillo/dpi_socket_dir". That way, another dillo instance of user Fred can easily findthe running dpid's service request socket at: /tmp/fred-XXXXXX/dpid.srs (because it is saved in "~/.dillo/dpi_socket_dir"). Now, we have a dpi directory per user, and its permissions arelocked so only the user has access, thus the following directorytree structure should pose no problems: /tmp/fred-XXXXXX/bookmarks /downloads /cookies /ftp ... dpid.srs If user Joe starts his dillo, the same happens for him: /tmp/joe-XXXXXX/bookmarks /downloads /cookies /ftp ... dpid.srs What should dpid do at start time: Check if both, ~/.dillo/dpi_socket_dir and its directory, exist (it can also check the ownership and permissions). If (both exist) use them! else delete ~/.dillo/dpi_socket_dir create another /tmp/<user>-XXXXXX directory save the new directory name into ~/.dillo/dpi_socket_dir (we could also add some paranoid level checks) To some degree, this scheme solves the tmpnam issue, differentusers of dillo at the same time, multiple dillo instances,polluting /tmp (cosmetic), and reasonably accounts for aneventual dillo or dpid crash. It has worked very well so far!--------------------------------So, how do I make my own plugin?-------------------------------- First, at least, read the "Developing a dillo plugin" sectionof dpi1 spec! :-) Note that the dpi1 spec may not be absolutely accurate, but themain ideas remain. Once you've got the concepts, contrast them with the drawingsin this document. Once it all makes sense, start playing withhello.dpi, you can run it by starting dillo with dillo dpi:/hello/or entering dpi:/hello/as the url. Then try to understand how it works (use the drawings)and finally look at its code. Really, the order is not that important, what really matters isto do it all. Start modifying hello.dpi, and then some more. When you feellike trying new things, review the code of the other plugins forideas. The hardest part is to try to modify the dpi framework codeinside dillo; you have been warned! It already supports a lot offunctionality, but if you need to do some very custom stuff, tryextending the "chat" command.---------------------------------Examples: Simple 'filter' plugins--------------------------------- For a quick and dirty introduction to dpis try the following shell scripts. #!/bin/sh read -d'>' dpip_tag # Read dillo's request # Don't forget the empty line after the Content-type cat <<EOF <dpi cmd='start_send_page' url='dpi:/hi/hi.filter.dpi'> Content-type: text EOF echo Hi Of course you should use html in a real application (perl makes this easy). A more useful example uses the "si" system info viewer: #!/bin/sh # si - System Information Viewer read -d'>' dpip_tag # We don't need to send the Content-type because "si --html" does this # for us. cat <<EOF <dpi cmd='start_send_page' url='dpi:/si/si.dpi.filter'> EOF si --html just make sure that you have si installed or you wont get far.To try out the examples create two directories for the scripts under your home directory as follows: mkdir -p ~/.dillo/dpi/hi mkdir -p ~/.dillo/dpi/sithen create the scripts and put them in the dpi service directories so that you end up with ~/.dillo/dpi/hi/hi.filter.dpi ~/.dillo/dpi/si/si.filter.dpiDon't forget to make them executable.If dpid is already running register the new plugins with dpidc registerYou can now test them by entering dpi:/hi/or dpi:/si/as the url. Or simply passing the url to dillo on startup dillo dpi:/si/ You can edit the files in place while dpid is running and reload them indillo to see the result, however if you change the file name or add a newscript you must run 'dpidc register'.WARNINGMultiple instances of a filter plugin may be run concurrently, this could be aproblem if your plugin records data in a file, however it is safe if you simplywrite to stdout. Alternatively you could write a 'server' plugin instead asthey are guaranteed not to run concurrently. >>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -