A Perl script implements a singing, musical Internet
Beady-eyed!
Admittedly, the implementation shown here wastes resources on the local machine, but it can indeed convert quasi-parallel requests into sounds. To allow this to happen, the script keeps a reference to the wheel object that generates the sound because POE cleans the object up immediately if nobody takes care of it. The wheel's task of playing the sound does not end at sound_play(), because the POE kernel processes it slice by slice after the function terminates. To avoid an untimely demise, while at the same time avoiding keeping wheels for longer than necessary, line 79 saves a reference to the wheel object in the POE session heap with the key players and the wheel's ID.
Because the wheel defines a CloseEvent with a callback sound_ended, POE calls the function defined in line 48 when the sound process terminates; in turn, the function deletes the wheel reference to let POE move in for the kill.
Another issue is that POE::Wheel::Run does not automatically clean up terminated child processes, instead leaving them lying around as zombies on the Unix system. Therefore, line 68 defines a SIGCHLD handler that tells the parent process to issue a wait() for the terminated child process and prevent it from turning into a zombie.
As soon as a client connects to port 8080 on the POE::Component::Server::TCP server component, its state machine changes state to ClientConnected. In the callback, $_[HEAP]{client} contains a client object whose put() method is used by the server to send messages to the client. The server uses ClientConnected to inform the connecting client of the available sound files before announcing Ready when you are.
Whenever the client sends a line to the server, the server jumps to the subroutine mapped to the ClientInput state. The received message is available in $_[ARG0], one of the @_ argument array fields typical of POE.
To prevent the client from attacking the server with nasty shell commands, instead of sending a sound file as expected, line 29 checks the file name to see whether it contains anything apart from the normal characters and immediately issues an error message and rejects the request in this case.
The client sends the q character to indicate that it wants to quit the session; the server then switches to the shutdown state, terminating the current client connection but leaving the server running. If the client really does send the name of an existing sound file, the sound_play function plays the file and returns a status string, which the server sends via put() to the client to confirm successful execution.
End of the Tunnel
At the other end of the tunnel, the POE script (boom-sender) in Listing 2 monitors the web server's access logfile. It runs on the hosted machine and uses the POE framework's TCP client component to keep in touch with the server.
Listing 2
boom-sender
Among other things, the Client::TCP POE component defines the ServerInput and ConnectError events; the script jumps to the callbacks for these events if the server sends text back or a connection fails.
Boom-sender uses InlineStates to define the send state, which uses put() to send a message to the server that was passed in.
Thanks to the FollowTail wheel from the POE toolbox, the logfile monitoring session defined in line 29 notices when the web server appends a line to the logfile defined in line 35. Again, it is important to have a reference to the wheel to prevent POE cleaning it up after the _start callback terminates.
The reference is kept in the POE session heap under the tail key while the session is active – that is, until boom-sender terminates.
Production systems will tend to rotate their logfiles daily; FollowTail is prepared for this and jumps to the got_log_rollover callback mapped to ResetEvent in this case. All this does is write a debug message to let the user know what is going on. Whenever the wheel finds a newly appended line in the log, it changes state to got_log_line and executes the matching callback. It uses the CPAN ApacheLog::Parser module to analyze the new lines, which have the following format:
67.195.37.108 - - [01/Sep/2008:17:25:20-0700] "GET /1/p3.html HTTP/ 1.0" 200 8678 "-" "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.4) Gecko/20080721 BonEcho/2.0.0.4"
The parse_line_to_hash() function exported by this module returns a hash containing the file requested by the http request under the file key.
In line 12, the TCP client component defines an alias (boom) for its session. The FollowTail wheel, running in another session defined in line 29, can use the following lines to tell the TCP server which sound file it needs to play:
POE::Kernel->post("boom", "send",file2sound($file));
Because two different sessions are communicating here, I can't use yield() to send the event; instead, I must use post() with the alias of the receiving session. Then the name of the WAV file is sent by the POE kernel to the send callback in the boom session as argument ARG0. The callback then uses put() to send the name to the TCP client in line 21, which in turn passes it on to the sound server – not directly, but to port 8080 on the local machine, and thus through the tunnel to port 8080 on the sound server.
Avoiding Cacophony
If every entry in the access log were to trigger a sound, a web page with 20 images, which the browser retrieves in short succession, would trigger an annoying cluster of superimposed noises. For this reason, boom-sender filters the access log output and only transmits to the sound server in case of index pages, high-res images, and discussion forum activity.
The file2sound() function defined in line 59 expects the file path requested by the browser (for example, /index.html) and returns the name of the sound file to play.
To allow this to happen, it makes a few assumptions – for example, that a path that ends with a / should output an index.html file – that you might need to modify when installing.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.