Advertisement
WarPie90

Internet server Simba 1.4 | Experimental async

Dec 8th, 2024 (edited)
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 4.23 KB | None | 0 0
  1. program new;
  2.  
  3. type
  4.   TClientAcceptTimer = type TMMLTimer;
  5.  
  6.   TInternetClient = record
  7.     ID: Int32;
  8.     IP, Port: string;
  9.   end;
  10.  
  11.   PInternetServer = ^TInternetServer;
  12.   TInternetServer = record
  13.     ID: Int32;
  14.     IP, Port: string;
  15.     AcceptTimer: TClientAcceptTimer;
  16.     ClientQueue: array of TInternetClient;
  17.     Requests: Int32;
  18.   end;
  19.  
  20.  
  21. var
  22.   Server: TInternetServer;
  23.  
  24.  
  25. // SPINLOCK
  26. var
  27.   critical: Int32;
  28.  
  29. {$IFDEF LINUX}
  30. function CAS(x: ^Int32; y, z: Int32): Int32; static; external '__sync_val_compare_and_swap@libgcc_s.so.1 cdecl';
  31. {$ELSE}{$IFDEF WINDOWS}
  32. function CAS(x: ^Int32; y,z: Int32): Int32; static; external 'InterlockedCompareExchange@Kernel32.dll ' + {$IFDEF CPU386}'stdcall'{$ELSE}'win64'{$ENDIF};
  33. {$ENDIF}{$ENDIF}
  34.  
  35. procedure AcquireLock(Lock: Int32);
  36. begin
  37.   repeat
  38.     if CAS(@Lock, 1, 0) = 0 then Exit;
  39.   until False;
  40. end;
  41.  
  42. procedure ReleaseLock(Lock: Int32);
  43. begin
  44.   Lock := 0;
  45. end;
  46.  
  47. // ------------------------------------
  48.  
  49.  
  50.  
  51. procedure TInternetClient.WriteString(s: string);
  52. begin
  53.   SendSocket(Self.ID, s);
  54. end;
  55.  
  56. function TInternetClient.Read(bytes: Int32): string;
  57. begin
  58.   Result := RecvSocketEx(Self.ID, bytes);
  59. end;
  60.  
  61. procedure TInternetClient.SetTimeout(Time: Int32);
  62. begin
  63.   SetSocketTimeout(Self.ID, Time);
  64. end;
  65.  
  66. procedure TInternetClient.CloseAndFree();
  67. begin
  68.   CloseSocket(Self.ID);
  69.   FreeSocket(Self.ID);
  70.   Self.ID := -1;
  71. end;
  72.  
  73.  
  74. // -----------------------------------
  75.  
  76. procedure AsyncAcceptClient(Sender: TObject);
  77. var
  78.   client,i: Int32;
  79. begin
  80.   with Server do
  81.   begin
  82.     AcquireLock(critical);
  83.     begin
  84.       for i:=High(clientQueue) downto 0 do
  85.         if clientQueue[i].ID = -1 then
  86.           Delete(clientQueue, i, 1);
  87.     end;
  88.     ReleaseLock(critical);
  89.  
  90.     client := AcceptSocket(Server.ID);
  91.  
  92.     AcquireLock(critical);
  93.     begin
  94.       clientQueue += [client,'',''];
  95.       SocketInfo(client, clientQueue[High(clientQueue)].IP, clientQueue[High(clientQueue)].Port);
  96.       Requests += 1;
  97.     end;
  98.     ReleaseLock(critical);
  99.   end;
  100. end;
  101.  
  102. function TInternetServer.Create(IP: string; Port: string): TInternetServer; static;
  103. var f: Int32;
  104. begin
  105.   Result.ID   := CreateSocket();
  106.   Result.IP   := IP;
  107.   Result.Port := Port;
  108.   BindSocket(Result.ID, Result.IP, Result.Port);
  109.   ListenSocket(Result.ID);
  110. end;
  111.  
  112. function TInternetServer.AcceptClients(): TInternetClient;
  113. begin
  114.   Self.AcceptTimer.Init();
  115.   Self.AcceptTimer.SetInterval(128);
  116.   Self.AcceptTimer.SetOnTimer(@AsyncAcceptClient);
  117.   Self.AcceptTimer.SetEnabled(True);
  118. end;
  119.  
  120. procedure TInternetServer.CloseAndFree();
  121. begin
  122.   CloseSocket(Self.ID);
  123.   FreeSocket(Self.ID);
  124. end;
  125.  
  126. procedure TInternetServer.HandleClient(var Client: TInternetClient);
  127. var
  128.   Data,IP, port: string;
  129. begin
  130.   if Client.ID <= 0 then Exit;
  131.   Client.SetTimeout(1000*30); // 30 sec before we release without ping | cant keep it open for no reason
  132.  
  133.   AcquireLock(critical);
  134.   Self.Requests -= 1;         // We are handling one of the requests, reduce
  135.   ReleaseLock(critical);
  136.  
  137.   Writeln('Connection from: ', Client.IP, ':', Client.port);
  138.   while True do
  139.   begin
  140.     try
  141.       Data += Client.Read(1);
  142.  
  143.       if Pos('GET', Data) <> 0  then // Some expected string
  144.       begin
  145.         WriteLn('<<< ', Data);
  146.         Client.WriteString('TAKE THAT BACK!');
  147.         Data := '';
  148.       end;
  149.  
  150.       if Pos('EXIT', Data) <> 0  then // Some expected string
  151.       begin
  152.         break;
  153.       end;
  154.  
  155.     except
  156.       AcquireLock(critical);
  157.       Self.ID := -1; // so the thread clears it
  158.       ReleaseLock(critical);
  159.  
  160.       Exit;          // socket auto closed and free'd on timeout
  161.     end;
  162.   end;
  163.  
  164.   AcquireLock(critical);
  165.   Client.CloseAndFree();
  166.   ReleaseLock(critical);
  167. end;
  168.  
  169. procedure Main;
  170. var
  171.   client: TInternetClient;
  172. begin
  173.   Server := TInternetServer.Create('127.0.0.1', '27015'); // Example IP and Port
  174.   Server.AcceptClients();
  175.  
  176.   while True do
  177.   begin
  178.     client := [];
  179.  
  180.     AcquireLock(critical);
  181.     begin
  182.       if Server.Requests <> 0 then
  183.         client := Server.ClientQueue[High(Server.ClientQueue)];
  184.     end;
  185.     ReleaseLock(critical);
  186.  
  187.  
  188.     if client <> [] then
  189.       Server.HandleClient(client);
  190.  
  191.     Sleep(1000);
  192.   end;
  193.  
  194.   Server.CloseAndFree();
  195. end;
  196.  
  197. begin
  198.   Main;
  199. end.
  200.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement