Create a generic UDP transport class
authorBryan Davis <bd808@wikimedia.org>
Mon, 15 Dec 2014 22:05:13 +0000 (15:05 -0700)
committerBryan Davis <bd808@wikimedia.org>
Mon, 15 Dec 2014 22:06:43 +0000 (15:06 -0700)
Code moved from MWLoggerLegacyLogger::emit(), which was formerly
in wfErrorLog().

Bug: T74572
Bug: T78599
Change-Id: I9e0e63d41bed6ccb468f3a9f1d52f156acc355a8

autoload.php
includes/debug/logger/legacy/Logger.php
includes/libs/UDPTransport.php [new file with mode: 0644]
includes/rcfeed/UDPRCFeedEngine.php

index 107ab81..fd2781c 100644 (file)
@@ -1182,6 +1182,7 @@ $wgAutoloadLocalClasses = array(
        'TransformTooBigImageAreaError' => __DIR__ . '/includes/media/MediaTransformOutput.php',
        'TransformationalImageHandler' => __DIR__ . '/includes/media/TransformationalImageHandler.php',
        'UDPRCFeedEngine' => __DIR__ . '/includes/rcfeed/UDPRCFeedEngine.php',
+       'UDPTransport' => __DIR__ . '/includes/libs/UDPTransport.php',
        'UIDGenerator' => __DIR__ . '/includes/utils/UIDGenerator.php',
        'UcdXmlReader' => __DIR__ . '/maintenance/language/generateCollationData.php',
        'UncategorizedCategoriesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedcategories.php',
index e7c69b8..69c3feb 100644 (file)
@@ -324,48 +324,8 @@ class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
        */
        public static function emit( $text, $file ) {
                if ( substr( $file, 0, 4 ) == 'udp:' ) {
-                       # Needs the sockets extension
-                       if ( preg_match( '!^udp:(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
-                               // IPv6 bracketed host
-                               $host = $m[1];
-                               $port = intval( $m[2] );
-                               $prefix = isset( $m[3] ) ? $m[3] : false;
-                               $domain = AF_INET6;
-                       } elseif ( preg_match( '!^udp:(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
-                               $host = $m[1];
-                               if ( !IP::isIPv4( $host ) ) {
-                                       $host = gethostbyname( $host );
-                               }
-                               $port = intval( $m[2] );
-                               $prefix = isset( $m[3] ) ? $m[3] : false;
-                               $domain = AF_INET;
-                       } else {
-                               throw new MWException( __METHOD__ . ': Invalid UDP specification' );
-                       }
-
-                       // Clean it up for the multiplexer
-                       if ( strval( $prefix ) !== '' ) {
-                               $text = preg_replace( '/^/m', $prefix . ' ', $text );
-
-                               // Limit to 64KB
-                               if ( strlen( $text ) > 65506 ) {
-                                       $text = substr( $text, 0, 65506 );
-                               }
-
-                               if ( substr( $text, -1 ) != "\n" ) {
-                                       $text .= "\n";
-                               }
-                       } elseif ( strlen( $text ) > 65507 ) {
-                               $text = substr( $text, 0, 65507 );
-                       }
-
-                       $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
-                       if ( !$sock ) {
-                               return;
-                       }
-
-                       socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
-                       socket_close( $sock );
+                       $transport = UDPTransport::newFromString( $file );
+                       $transport->emit( $text );
                } else {
                        wfSuppressWarnings();
                        $exists = file_exists( $file );
diff --git a/includes/libs/UDPTransport.php b/includes/libs/UDPTransport.php
new file mode 100644 (file)
index 0000000..7fad882
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * A generic class to send a message over UDP
+ *
+ * If a message prefix is provided to the constructor or via
+ * UDPTransport::newFromString(), the payload of the UDP datagrams emitted
+ * will be formatted with the prefix and a single space at the start of each
+ * line. This is the payload format expected by the udp2log service.
+ *
+ * @since 1.25
+ */
+class UDPTransport {
+       private $host, $port, $prefix, $domain;
+
+       /**
+        * @param string $host IP address to send to
+        * @param int $port port number
+        * @param int $domain AF_INET or AF_INET6 constant
+        * @param string|bool $prefix Prefix to use, false for no prefix
+        */
+       public function __construct( $host, $port, $domain, $prefix = false ) {
+               $this->host = $host;
+               $this->port = $port;
+               $this->domain = $domain;
+               $this->prefix = $prefix;
+       }
+
+       /**
+        * @param string $info In the format of "udp://host:port/prefix"
+        * @return UDPTransport
+        * @throws InvalidArgumentException
+        */
+       public static function newFromString( $info ) {
+               if ( preg_match( '!^udp:(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $info, $m ) ) {
+                       // IPv6 bracketed host
+                       $host = $m[1];
+                       $port = intval( $m[2] );
+                       $prefix = isset( $m[3] ) ? $m[3] : false;
+                       $domain = AF_INET6;
+               } elseif ( preg_match( '!^udp:(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $info, $m ) ) {
+                       $host = $m[1];
+                       if ( !IP::isIPv4( $host ) ) {
+                               $host = gethostbyname( $host );
+                       }
+                       $port = intval( $m[2] );
+                       $prefix = isset( $m[3] ) ? $m[3] : false;
+                       $domain = AF_INET;
+               } else {
+                       throw new InvalidArgumentException( __METHOD__ . ': Invalid UDP specification' );
+               }
+
+               return new self( $host, $port, $domain, $prefix );
+       }
+
+       /**
+        * @param string $text
+        */
+       public function emit( $text ) {
+               // Clean it up for the multiplexer
+               if ( $this->prefix !== false ) {
+                       $text = preg_replace( '/^/m', $this->prefix . ' ', $text );
+
+                       // Limit to 64KB
+                       if ( strlen( $text ) > 65506 ) {
+                               $text = substr( $text, 0, 65506 );
+                       }
+
+                       if ( substr( $text, -1 ) != "\n" ) {
+                               $text .= "\n";
+                       }
+               } elseif ( strlen( $text ) > 65507 ) {
+                       $text = substr( $text, 0, 65507 );
+               }
+
+               $sock = socket_create( $this->domain, SOCK_DGRAM, SOL_UDP );
+               if ( !$sock ) { // @todo should this throw an exception?
+                       return;
+               }
+
+               socket_sendto( $sock, $text, strlen( $text ), 0, $this->host, $this->port );
+               socket_close( $sock );
+       }
+}
index 8554670..9afae66 100644 (file)
@@ -29,6 +29,7 @@ class UDPRCFeedEngine implements RCFeedEngine {
         * @see RCFeedEngine::send
         */
        public function send( array $feed, $line ) {
-               wfErrorLog( $line, $feed['uri'] );
+               $transport = UDPTransport::newFromString( $feed['uri'] );
+               $transport->emit( $line );
        }
 }