A Dutch techie in China
14 Sep
The first thing developed for Mailjoe was its TCP server. There are many examples out there, but we didn’t find any that was multi-protocol, non-blocking and multi-process.
The snippets below are fairly small and self explanatory. Please keep in mind that all of this code worked fine during the Mailjoe beta, but is by no means finished or necessarily suitable for other purposes.
mailjoe.php, the main loop:
set_time_limit (0); require_once("config.php"); require_once(INCL_PATH.'Daemon.php'); $__daemon_listening = true; $__daemon_childs = 0; declare(ticks = 1); pcntl_signal(SIGTERM, 'daemon_sig_handler'); pcntl_signal(SIGINT, 'daemon_sig_handler'); pcntl_signal(SIGCHLD, 'daemon_sig_handler'); daemonize(); // Setup POP3 socket $sockPOP = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($sockPOP, SOL_SOCKET, SO_REUSEADDR, 1); socket_bind( $sockPOP, $listen_address, $listen_port_pop3) or die('Could not bind to POP3 port/address!'); socket_listen( $sockPOP, $max_clients); socket_set_nonblock($sockPOP); // Setup IMAP socket $sockIMAP = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($sockIMAP, SOL_SOCKET, SO_REUSEADDR, 1); socket_bind( $sockIMAP, $listen_address, $listen_port_imap) or die('Could not bind to IMAP port/address!'); socket_listen( $sockIMAP, $max_clients); socket_set_nonblock($sockIMAP); // Setup SMTP socket $sockSMTP = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($sockSMTP, SOL_SOCKET, SO_REUSEADDR, 1); socket_bind( $sockSMTP, $listen_address, $listen_port_smtp) or die('Could not bind to SMTP port/address!'); socket_listen( $sockSMTP, $max_clients); socket_set_nonblock($sockSMTP); // After we have privileged ports posix_setuid($posix_uid); function debug($s) { syslog(LOG_INFO, "[".posix_getpid()."] ".$s); } while ($__daemon_listening) { $newsock = @socket_accept($sockIMAP); if ($newsock === false) { } elseif ($newsock > 0) { daemon_client($sockIMAP, $newsock, "imap"); } else { die(socket_strerror($newsock)); } $newsock = @socket_accept($sockPOP); if ($newsock === false) { } elseif ($newsock > 0) { debug("Accepted POP connection"); daemon_client($sockPOP, $newsock, "pop"); } else { die(socket_strerror($newsock)); } $newsock = @socket_accept($sockSMTP); if ($newsock === false) { } elseif ($newsock > 0) { daemon_client($sockSMTP, $newsock, "smtp"); } else { die(socket_strerror($newsock)); } usleep(10000); }
The relevant part from config.php:
define(BASE_PATH,'/home/mailjoe/'); define(INCL_PATH,BASE_PATH.'lib/'); define(TEMP_PATH,'/tmp/'); $listen_address = '127.0.0.1'; $listen_port_pop3 = 110; $listen_port_smtp = 25; $listen_port_imap = 143;
As you can see, our process listens on localhost only. We were using Perdition to enable SSL as well as do some basic sanity checks for POP3 and IMAP4. SSLTunnel was used to enable SSL on the SMTP port.
We did initially use PHP’s built-in SSL capabilities but ran into a number of limitations.
daemon.php, which is based on several examples found on php.net:
function daemon_sig_handler($sig) { global $__daemon_childs; switch($sig) { case SIGTERM: case SIGINT: debug("SIGTERM received"); exit(); break; case SIGCHLD: debug("SIGCHLD received"); while(pcntl_waitpid(-1, $status, WNOHANG)>0) $__daemon_childs--; debug("SIGCHLD finished"); break; } } function daemon_client($sock, $newsock, $type) { global $__daemon_listening, $__daemon_childs; while($__daemon_childs >= MAX_CHILD) { usleep(10000); } $pid = pcntl_fork(); if ($pid == -1) { debug("Failed to fork!"); die(); } elseif ($pid == 0) { $__daemon_listening = false; socket_close($sock); socket_set_block($newsock); $client = new $type($newsock); while($client->connected) { $sockets[0] = $newsock; socket_select($sockets, $write = null, $except = null, $tv_sec = NULL); $client->Check(); } socket_close($newsock); } else { socket_close($newsock); $__daemon_childs++; } } function daemonize() { $pid = pcntl_fork(); if ($pid == -1) { debug("Failed to fork!"); exit(); } elseif ($pid) { exit(); } else { posix_setsid(); chdir('/'); umask(0); return posix_getpid(); } }
Important to note here is that daemon.php tries to create a new instance of $type, which could be POP3, SMTP or IMAP based on the socket used. You’ll have to put your own class here that can handle the connection.
12 Mar
The Chinese like to share their movies in RMVB (RealMedia) format as opposed to Xvid or DivX. Not sure why it got to be so popular (I would prefer the more open Xvid), but the file sizes and quality it produces are quite good.
A problem I ran into is that mplayer/vlc don’t seem to play these files without a bit of tinkering. I found a lot of how-to’s that tell you how to make it work, but non really straight forward on a 64-bit system.
Mplayer supports a number of codec libraries though, and more than one may get you result.
Where many how-to’s told me to install the RV40 codec (which I couldn’t find in 64-bit), I used the RV3040 that comes with Ubuntu by default instead. This fixes video.
For sound, the often mentioned solution was to install the w32codecs and use the cook codec. In my case however this resulted in choppy sound. Instead I use the ffcook codec (found in libmad) instead (also in Ubuntu by default.)
Finally my command line looks like:
mplayer -vc rv3040 -ac ffcook movie.rmvb