RealThinClient SDK v8 updates log

There was a request on the Google+ groups to publish a complete list of updates in the RTC SDK v8 release on the RTC website, so … here it is. Enjoy!

========================================================================
— Short summary of changes from v7.78 (2017.Q1) to v8.08 (2017.Q2) —
========================================================================

1. “TRtcConnection” component extended to provide direct access to all
properties and most methods of “TRtcDataClient” and “TRtcDataServer”
components by using the “Sender:TRtcConnection” parameter directly
from RTC events, without the (previous) need for explicit typecasts.
See v7.101 update log for details.

2. “TRtcDataRequest” component extended with “Write”, “WriteEx” and “PostMethod”
methods to simplify preparing and sending of requests with no request content
body and/or content body small enough to fit into Clients Memory and to remove
the (previous) requirement to *always* implement the “OnBeginRequest” event.
See v7.102 update log for details.

3. RTC components extended with a number of new methods and events for centralized
logging and monitoring of all content being received (Client and Server side)
without messing up the original content, while at the same time allowing raw
data to be modified in-place if needed, before it goes into “processing”.
See v7.103 update log for details.

4. Fixed a bug in the “TRtcHttpClient” component which resulted in the “OnResponseDone”
event and the last “OnDataReceived” event (with Response.Done=TRUE) NOT triggering
on the Client if the Server was closing the connection after every request (HTTP/1.0)

5. TRtcValue objects extended with new methods for “REST” support and improved parsing and
generation of XML-RPC and JSON content (including support for “JSON-RPC 1.0″ and “2.0″)
See v7.105 update log for details.

6. RTC Remote Functions (“TRtcServerModule” and “TRtcClientModule” components) extended
with built-in support for “JSON-RPC 1.0″, “JSON-RPC 2.0″ and plain “JSON” Data Formats,
plus a number of new “Data Request Modes” which can be used to communicate with a lot
of different 3rd-Party APIs and/or write APIs for use by 3rd-Parties – including “REST”
and other request modes where any part of a remote function call can be in the “URI”.
With “DataReqModes”, you can even make complex remote function calls from the Address
line of any Web Browser – if you enable this mode on your “TRtcServerModule” component,
which can be used for quick testing or to provide public APIs for use by a 3rd-party.
See v7.106 – v7.109 update logs for details.

7. “TRtcFunctionInfo” class (used to store and transport remote function objects),
has been extended with new methods and properties to simplify writing and calling
remote functions which accept parameters as an array (usually sent/received in
the ‘params’ array) in addition to (or as a replacement for) named parameters.
See v7.110 update log for details.

8. Added support for using anonymous methods as an alternative way to write event
handlers for all RTC components. For this purpose, new “Anon” methods have been
added to all RTC components, with an overloaded method for each event type.
See v7.111 and v7.112 update logs for details.

9. When using the “TRtcClientModule” component with built-in RTC Encryption,
the last Result received from the Server before closing the Session was
being rejected by the Client, because the Client was closing its Session
before decrypting the Result received. This has now been fixed.

10. Added support for using anonymous methods with “PostQuickJob” and “PostGUIJob”
procedures – available in the “rtcThrPool” unit as a simple way for posting quick
jobs to be executed asynchronously from the RTC Thread Pool or the Main Thread (GUI).

11. All “Updates*.txt” files moved from the “Help” folder to “Help/UpdatesLog” sub-folder.

12. “RealThinClient SDK Components Hierarchy” image and PDF file (ready to print) are
now available in the “Help” folder (rtcSDK_Components.png and rtcSDK_Components.pdf),
providing a simple overview of all components included in the RealThinClient SDK.

13. The “Obj” property on “TRtcInfo” and “TRtcSession” classes was REPLACED with
new “asObj” and “asPtr” properties, making the “TRtcObject” class OBSOLETE,
so it was REMOVED! RTC Demos and Example Projects have been updated, as needed.
Read below for more details (manual changes in user code might be required).

14. “Version_SDK” property moved from “TRtcConnection” to “TRtcComponent”
class, and … public variables on RTC Value Objects updated to properties.

15. Added and/or replaced several properties on “TRtcClientModule” and
“TRtcServerModule” components to improve Automatic Session handling, and
fixed “TRtcServerModule” and “TRtcClientModule” Automatic Session handling.

16. TRtcHttpClient, TRtcHttpServer, TRtcDataProvider, TRtcDataRequest, TRtcDataRouter
and TRtcLoadBalancer components have been extended with support for WEB SOCKETS.

17. Introduced “RTC_OBJECT_CLASS” and “RTC_OBJECT_CLASS2″ compiler defines as
a “quick fix” for Projects extending the “TRtcObject” class, without the
need for (other) manual changes described in points (A) and (B) below.

18. Improved TRtcHttpGateClient components Login and AutoLogin functionality.

19. Support for RAD Studio 10.2 Tokyo.

20. Fixed the default Cookie delimiter for HTTP Requests.
See v8.02 updates for details (below).

21. Fixed “OnResponseAbort” event NOT triggering.
See v8.03 updates for details (below).

22. Fixed “Sync” method, which was catching and silently
swallowing all Exceptions raised in the Main Thread.
See v8.04 updates for details (below).

23. Fixed a regression bug in the “TRtcClientModule” component, which
broke remote function reposting in case of a failed Connect attempt,
a Disconnect with a Reconnect, or in case of Session expiration.
See v8.01 and v8.05 updates for details (below).

24. Fixed a problem with the old listening socket still blocking
the Port for some time after that socket was already closed.
See v8.05 update for details (below).

25. Fixed the SHA1 function on 64-bit platforms (WebSockets).
See v8.06 update for details (below).

26. Improved compatibility with the FPC 3.0+ compiler.

27. Fixed “FORCE_ANSI_STRING” and “FORCE_WIDE_STRING” support.

28. Fixed Win64 blocking socket support for FPC.

29. Added package file for CodeTyphon from PilotLogic.

=========================================================
—- Detailed list of all changes from v7.78 to v8.08 —
=========================================================
Continue reading

RTC HTTP Server in 199 lines of code

Open a Text Editor of your choice, copy/paste the code below and save it as “MyHttpServer.dpr”.

program MyHttpServer;

{$APPTYPE CONSOLE}

uses
  SysUtils,

  rtcTypes,
  rtcConn,
  rtcDataSrv,
  rtcHttpSrv,
  rtcInfo;

type
// This is our self-contained HTTP Server class ...
  TMyServer=class(TObject)
  protected
    HttpSrv:TRtcHttpServer;
    DataProv:TRtcDataProvider;

  public
    constructor Create(PortNumber:String='80';
                       IPVer:RtcIPV=rtc_IPVDefault);
    destructor Destroy; override;

    procedure DataProv_CheckRequest(Sender: TRtcConnection);
    procedure DataProv_DataReceived(Sender: TRtcConnection);

    procedure HttpSrv_ListenStart(Sender: TRtcConnection);
    procedure HttpSrv_ListenError(Sender: TRtcConnection; E:Exception);
    procedure HttpSrv_ListenStop(Sender: TRtcConnection);
    procedure HttpSrv_RequestNotAccepted(Sender: TRtcConnection);
    end;

constructor TMyServer.Create(PortNumber:String='80'; IPVer:RtcIPV=rtc_IPVDefault);
  begin
  // Create HttpServer and DataProvider components ...
  HttpSrv:=TRtcHttpServer.Create(nil);
  DataProv:=TRtcDataProvider.Create(nil);

  // Assign Server for our Data Provider ...
  DataProv.Server:=HttpSrv;

  // Assign Data Provider Events (handles Valid Requests) ...
  DataProv.OnCheckRequest:=DataProv_CheckRequest;
  DataProv.OnDataReceived:=DataProv_DataReceived;

  // Assign Server Events (handles the rest) ...
  HttpSrv.OnRequestNotAccepted:=HttpSrv_RequestNotAccepted;
  HttpSrv.OnListenStart:=HttpSrv_ListenStart;
  HttpSrv.OnListenStop:=HttpSrv_ListenStop;
  HttpSrv.OnListenError:=HttpSrv_ListenError;

  // Configure the Server ...
  HttpSrv.ServerPort:=PortNumber;
  HttpSrv.ServerIPV:=IPVer;
  HttpSrv.MultiThreaded:=True;

  // Start the Server listener ...
  HttpSrv.Listen();
  end;

destructor TMyServer.Destroy;
  begin
  // Stop the Server listener ...
  HttpSrv.StopListenNow();

  // Destroy the components ...
  HttpSrv.Free;
  DataProv.Free;
  end;

procedure TMyServer.DataProv_CheckRequest(Sender: TRtcConnection);
  begin
  // Check Request headers and "Accept" all Requests
  // we want to handle with our Data Provider ...
  with TRtcDataServer(Sender) do
    if (Request.Method='GET') and  // we only want "GET" requests
       (Request.ContentLength=0) then // ... with no content body
        if (Request.URI='/html') or
           (Request.URI='/json') or
           (Request.URI='/xml') or
           (Request.URI='/code') then
          Accept; // Accept the Request
  end;

procedure TMyServer.DataProv_DataReceived(Sender: TRtcConnection);
  var
    t:TRtcRecord;
  begin
  with TRtcDataServer(Sender) do
  // We will start processing the request only if
  // we have received the complee request content body ...
    if Request.Complete then
      if Request.URI='/html' then
        begin
        // We can use multiple "Write" calls
        // to prepare our HTML response ...
        Response.ContentType:='text/html';
        Write('<html><body>');
        Write('Your IP: '+PeerAddr+'<br>');
        Write('Your Port: '+PeerPort+'<br>');
        Write('Date & Time: <b>'+DateTimeToStr(Now)+'</b><br>');
        Write('Agent: <i>'+Request['User-Agent']+'</i><br>');
        Write('</body></html>');
        // All "Write" calls will be buffered,
        // RTC will calculate the "Content-Length" for us
        // and send the whole content body out as a single
        // Response - when we are finished with our event.
        end
      else
        begin
        // Using TRtcRecord to prepare our response Object ...
        t:=TRtcRecord.Create;
        try
          t.asText['agent']:=Request['User-Agent'];
          t.asText['ip']:=PeerAddr;
          t.asText['port']:=PeerPort;
          t.asDateTime['now']:=Now;
          if Request.URI='/json' then
            begin
            // Serialize to "JSON" ...
            Response.ContentType:='application/json';
            Write(t.toJSON);
            end
          else if Request.URI='/xml' then
            begin
            // Serialize to "XML-RPC" ...
            Response.ContentType:='text/xml';
            Write(t.toXMLrpc);
            end
          else if Request.URI='/code' then
            begin
            // Serialize to "Code" (RTC format) ...
            Response.ContentType:='text/plain';
            Write(t.toCode);
            end;
        finally
          t.Free;
          end;
        end
  end;

procedure TMyServer.HttpSrv_RequestNotAccepted(Sender: TRtcConnection);
  begin
  // Request wasn't accepted ...
  with TRtcDataServer(Sender) do
    begin
    // Send "404" status code back ...
    Response.Status(404,'Not Found');
    Response.ContentType:='text/plain';
    // Something to show in the Web Browser ...
    Write('Bad command.');
    // And ... Disconnect the Client.
    Disconnect;
    end;
  end;

procedure TMyServer.HttpSrv_ListenError(Sender: TRtcConnection; E: Exception);
  begin
  Writeln('Server Error: '+E.Message);
  end;

procedure TMyServer.HttpSrv_ListenStart(Sender: TRtcConnection);
  begin
  Writeln('Server started.');
  end;

procedure TMyServer.HttpSrv_ListenStop(Sender: TRtcConnection);
  begin
  Writeln('Server stopped.');
  end;

var
  MyServer:TMyServer;

begin
  try
    // Create and start our Server ...
    MyServer:=TMyServer.Create('80');
    try
      // Since this is a console application and our
      // Server is Multi-Threaded, we can do whatever
      // we want here. For simplicity reasons, we will
      // just use "ReadLn" to allow the Server to run
      // while we wait for the user to press <Enter>.

      Writeln('Press <Enter> to Quit ...');
      ReadLn;

      // User has pressed <Enter> - time to kill our Server.
    finally
      MyServer.Free;
      end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Continue reading

Accessing Databases (Main Article)

This demo will be divided in a Server and a Client.

Basically, we are going to be serving several queries to the clients from a server. To accomplish this, we will be using a database created with SQLite. SQLite is an awesome SQL Server embedded that can be easily used in Delphi. To make the connection to the database we are going to use ZeosDB components, they are open source and stable. For all the communication, of course, we will be using RTC SDK components.

So, let’s go ahead. Choose your destiny:

  1. The Server.
  2. The Client.

Accessing Databases (Server side)

The Server.

This demo will show how really simple is to create a server that can send the content of tables in a database to a client.

Steps.

  1. Create a new project in Delphi 7
  2. Create a DataModule to connect to Database and send responses back to the client
  3. Create a Form to control the Server.
  4. Compile and run the Server. Continue reading

Accessing Databases (Client side)

The Client

This is the article for the client in the Accessing Databases article. At this moment, we have our Server ready, so now it’s time to create the Client that will ask for the data. In this case, this client is really simple, in fact, as simple as it could be. This Client will call a function on the Server and get back the content of the table tbl_products in our Server’s database.

Steps.

  1. Create a form for the Client with the needed components.
  2. Write the code to  call the Remote Function. Continue reading

Beware of the “As Administrator” option on Windows 8

Yesterday, I was preparing my Windows 8 Tablet PC for development and testing. As always, I went to use the “_clear.cmd” file from the “Lib” folder to delete old files before preparing a new package. But – wait! Windows 8 won’t let me run CMD files just like that! It blocked every time. So … to outsmart this new Windows 8 feature (I think it’s called “Screen-Scan”), I’ve simply selected “As Administrator” to run the “_clear.cmd” file with higher access rights.

Continue reading

Write your first Remote Function (Lesson 5)

In this lesson, we’ll be building a solution with a Server and a Client. This first lesson with a Client side made with RealThinClient Components is simple but shows the concept behind a client – server system that could be the base for a larger application. We’ll be using Remote Functions to accomplish this task.

This Post has three sections.

  1. The Server.
  2. The Client.
  3. Make it work.

Continue reading

Send large files from a Server (Lesson 4)

This demo continues over Demo 3 (Sending small files). Now, we are going to make a webserver that is able to send files no matter their size.

We must be careful with our server’s memory, we may have a really big file in our server and we don’t want to use all of it.

At our first two examples we have been sending all of our content at once on the OnCheckRequest and OnDataReceived events of our RtcDataProvider components.

Continue reading

Send small files from a Server (Lesson 3)

By this moment, we have been sending content generated by our Server. Now we are going to see how to send small files from a folder that resides inside our Server’s running directory. We’ll do it this way because with this approach we can control what files can be accessed from the Server.

We’ll use some functions to secure our Server and check that the content (file size in this case) is small enough to send.

In the next lesson we’ll see how to deal with bigger file sizes.

We’ll need the code of our Lesson 2b post which you can download at Code For RealThinClient SDK Lesson 2b. Continue reading