THRIFT-4490 Allow a default service as fallback for multiplex processors connected by old clients
Client: Delphi
Patch: Jens Geyer
diff --git a/lib/delphi/src/Thrift.Processor.Multiplex.pas b/lib/delphi/src/Thrift.Processor.Multiplex.pas
index 4cd80ba..8cf23db 100644
--- a/lib/delphi/src/Thrift.Processor.Multiplex.pas
+++ b/lib/delphi/src/Thrift.Processor.Multiplex.pas
@@ -53,11 +53,11 @@
 
 type
   IMultiplexedProcessor = interface( IProcessor)
-    ['{810FF32D-22A2-4D58-B129-B0590703ECEC}']
+    ['{807F9D19-6CF4-4789-840E-93E87A12EB63}']
     // Register a service with this TMultiplexedProcessor.  This allows us
     // to broker requests to individual services by using the service name
     // to select them at request time.
-    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor);
+    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean = FALSE);
   end;
 
 
@@ -76,6 +76,7 @@
 
   private
     FServiceProcessorMap : TDictionary<String, IProcessor>;
+    FDefaultProcessor : IProcessor;
 
     procedure Error( const oprot : IProtocol; const msg : TThriftMessage;
                      extype : TApplicationExceptionSpecializedClass; const etxt : string);
@@ -87,7 +88,7 @@
     // Register a service with this TMultiplexedProcessorImpl.  This allows us
     // to broker requests to individual services by using the service name
     // to select them at request time.
-    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor);
+    procedure RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean = FALSE);
 
     { This implementation of process performs the following steps:
       - Read the beginning of the message.
@@ -135,9 +136,15 @@
 end;
 
 
-procedure TMultiplexedProcessorImpl.RegisterProcessor( const serviceName : String; const processor : IProcessor);
+procedure TMultiplexedProcessorImpl.RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean);
 begin
   FServiceProcessorMap.Add( serviceName, processor);
+
+  if asDefault then begin
+    if FDefaultProcessor = nil
+    then FDefaultProcessor := processor
+    else raise TApplicationExceptionInternalError.Create('Only one default service allowed');
+  end;
 end;
 
 
@@ -184,28 +191,37 @@
   end;
 
   // Extract the service name
+  // use FDefaultProcessor as fallback if there is no separator
   idx := Pos( TMultiplexedProtocol.SEPARATOR, msg.Name);
-  if idx < 1 then begin
+  if idx > 0 then begin
+
+    // Create a new TMessage, something that can be consumed by any TProtocol
+    sService := Copy( msg.Name, 1, idx-1);
+    if not FServiceProcessorMap.TryGetValue( sService, processor)
+    then begin
+      Error( oprot, msg,
+             TApplicationExceptionInternalError,
+             Format(ERROR_UNKNOWN_SERVICE,[sService]));
+      Exit( FALSE);
+    end;
+
+    // Create a new TMessage, removing the service name
+    Inc( idx, Length(TMultiplexedProtocol.SEPARATOR));
+    Init( newMsg, Copy( msg.Name, idx, MAXINT), msg.Type_, msg.SeqID);
+
+  end
+  else if FDefaultProcessor <> nil then begin
+    processor := FDefaultProcessor;
+    newMsg    := msg;  // no need to change
+
+  end
+  else begin
     Error( oprot, msg,
            TApplicationExceptionInvalidProtocol,
            Format(ERROR_INCOMPATIBLE_PROT,[msg.Name]));
     Exit( FALSE);
   end;
 
-  // Create a new TMessage, something that can be consumed by any TProtocol
-  sService := Copy( msg.Name, 1, idx-1);
-  if not FServiceProcessorMap.TryGetValue( sService, processor)
-  then begin
-    Error( oprot, msg,
-           TApplicationExceptionInternalError,
-           Format(ERROR_UNKNOWN_SERVICE,[sService]));
-    Exit( FALSE);
-  end;
-
-  // Create a new TMessage, removing the service name
-  Inc( idx, Length(TMultiplexedProtocol.SEPARATOR));
-  Init( newMsg, Copy( msg.Name, idx, MAXINT), msg.Type_, msg.SeqID);
-
   // Dispatch processing to the stored processor
   protocol := TStoredMessageProtocol.Create( iprot, newMsg);
   result   := processor.process( protocol, oprot, events);
@@ -213,4 +229,3 @@
 
 
 end.
-