Advertisement
WarPie90

TInternetServer - using Simba WinAPI for threading

Dec 12th, 2024
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 5.15 KB | None | 0 0
  1. program new;
  2. {$I Windows/Windows.simba}
  3. {$I Windows/Threading.simba}
  4. {$I SRL/osr.simba}
  5.  
  6. type
  7.   TClientAcceptTimer = type TMMLTimer;
  8.   TClientThread = type TMMLTimer;
  9.  
  10.  
  11.   TInternetClient = record
  12.     ID: Int32;
  13.     IP, Port: string;
  14.     Index: Int32;
  15.   end;
  16.  
  17.   PInternetServer = ^TInternetServer;
  18.   TInternetServer = record
  19.     ID: Int32;
  20.     IP, Port: string;
  21.     AcceptTimer: TClientAcceptTimer;
  22.     ClientThread: TClientThread;
  23.     ClientQueue: array of TInternetClient;
  24.     Requests: Int32;
  25.   end;
  26.  
  27.  
  28. var
  29.   Server: TInternetServer;
  30.  
  31.  
  32. // SPINLOCK
  33. var
  34.   critical: Int32;
  35.  
  36. {$IFDEF LINUX}
  37. function CAS(x: ^Int32; y, z: Int32): Int32; static; external '__sync_val_compare_and_swap@libgcc_s.so.1 cdecl';
  38. {$ELSE}{$IFDEF WINDOWS}
  39. function CAS(x: ^Int32; y,z: Int32): Int32; static; external 'InterlockedCompareExchange@Kernel32.dll ' + {$IFDEF CPU386}'stdcall'{$ELSE}'win64'{$ENDIF};
  40. {$ENDIF}{$ENDIF}
  41.  
  42. procedure AcquireLock(Lock: Int32);
  43. begin
  44.   repeat
  45.     if CAS(@Lock, 1, 0) = 0 then Exit;
  46.   until False;
  47. end;
  48.  
  49. procedure ReleaseLock(Lock: Int32);
  50. begin
  51.   Lock := 0;
  52. end;
  53.  
  54. // ------------------------------------
  55.  
  56.  
  57. function TInternetClient.Create(IP: string; Port: string): TInternetServer; static;
  58. var f: Int32;
  59. begin
  60.   Result.ID   := CreateSocket();
  61.   Result.IP   := IP;
  62.   Result.Port := Port;
  63.   BindSocket(Result.ID, Result.IP, Result.Port);
  64.   ListenSocket(Result.ID);
  65. end;
  66.  
  67. procedure TInternetClient.WriteString(s: string);
  68. begin
  69.   SendSocket(Self.ID, s);
  70. end;
  71.  
  72. function TInternetClient.Read(bytes: Int32): string;
  73. begin
  74.   Result := RecvSocketEx(Self.ID, bytes);
  75. end;
  76.  
  77. function TInternetClient.ReadStr(): string;
  78. begin
  79.   Result := RecvSocketStr(Self.ID);
  80. end;
  81.  
  82. procedure TInternetClient.SetTimeout(Time: Int32);
  83. begin
  84.   SetSocketTimeout(Self.ID, Time);
  85. end;
  86.  
  87. procedure TInternetClient.CloseAndFree();
  88. begin
  89.   try
  90.     CloseSocket(Self.ID);
  91.     FreeSocket(Self.ID);
  92.   except
  93.     //dumb auto free
  94.   end;
  95.  
  96.   Self.ID := -1;
  97.   Delete(Server.ClientQueue, Self.Index, 1);
  98. end;
  99.  
  100.  
  101. // -----------------------------------
  102.  
  103. procedure AsyncAcceptClient(Sender: TObject);
  104. var
  105.   client,i: Int32;
  106. begin
  107.   with Server do
  108.   begin
  109.     client := AcceptSocket(Server.ID);
  110.  
  111.     AcquireLock(critical);
  112.     begin
  113.       clientQueue += [client,'','', Length(ClientQueue)];
  114.       SocketInfo(client, clientQueue[High(clientQueue)].IP, clientQueue[High(clientQueue)].Port);
  115.       Requests += 1;
  116.     end;
  117.     ReleaseLock(critical);
  118.   end;
  119. end;
  120.  
  121. function TInternetServer.Create(IP: string; Port: string): TInternetServer; static;
  122. var f: Int32;
  123. begin
  124.   Result.ID   := CreateSocket();
  125.   Result.IP   := IP;
  126.   Result.Port := Port;
  127.   BindSocket(Result.ID, Result.IP, Result.Port);
  128.   ListenSocket(Result.ID);
  129. end;
  130.  
  131. procedure TInternetServer.AcceptClients();
  132. begin
  133.   Self.AcceptTimer.Init();
  134.   Self.AcceptTimer.SetInterval(128);
  135.   Self.AcceptTimer.SetOnTimer(@AsyncAcceptClient);
  136.   Self.AcceptTimer.SetEnabled(True);
  137. end;
  138.  
  139. procedure TInternetServer.CloseAndFree();
  140. begin
  141.   try
  142.     CloseSocket(Self.ID);
  143.     FreeSocket(Self.ID);
  144.   except
  145.     //it was autofree'd because simba is dumb
  146.   end;
  147. end;
  148.  
  149. procedure HandleClient(lpParam: Pointer);
  150. var
  151.   Data,IP, port, tmp, Header: string;
  152.   Content: string;
  153.   client: TInternetClient;
  154.   t: Double;
  155. begin
  156.   t := PerformanceTimer();
  157.   client := TInternetClient(lpParam^);
  158.  
  159.   if Client.ID <= 0 then Exit;
  160.   try
  161.     Client.SetTimeout(1000*30); // 30 sec before we release without ping | cant keep it open for no reason
  162.   except
  163.     Exit;
  164.   end;
  165.  
  166.   AcquireLock(critical);
  167.   Server.Requests -= 1;         // We are handling one of the requests, reduce
  168.   ReleaseLock(critical);
  169.  
  170.   Writeln('>>> Connection from: ', Client.IP, ':', Client.port);
  171.  
  172.   (* Get headers *)
  173.   repeat
  174.     try
  175.       tmp := Client.ReadStr();
  176.       header += tmp;
  177.     except
  178.       AcquireLock(critical);
  179.       Client.CloseAndFree();
  180.       ReleaseLock(critical);
  181.       Exit;
  182.     end;
  183.   until tmp = '';
  184.  
  185.   (* Reply with OK *)
  186.   Content := '<b>Welcome to my simba webserver</b><br \><br \> Responded in '+ ToStr(Round(PerformanceTimer() - t,6))+ 'ms';
  187.   Client.WriteString('HTTP/1.1 200 OK'+#13#10);
  188.   Client.WriteString('Content-Type: text/html'+#13#10);
  189.   Client.WriteString('Connection: close'+#13#10);
  190.   Client.WriteString('Content-Length: ' + IntToStr(Length(Content))+#13#10#13#10);
  191.   Client.WriteString(Content);
  192.   WriteLn('>>> Content data sent!');
  193.  
  194.   AcquireLock(critical);
  195.   Client.CloseAndFree();
  196.   ReleaseLock(critical);
  197. end;
  198.  
  199. procedure Main;
  200. var
  201.   client: TInternetClient;
  202.   threads: array of TLapeThread;
  203.  
  204. begin
  205.   Server := TInternetServer.Create('127.0.0.1', '80');
  206.   Server.AcceptClients();
  207.  
  208.   while True do
  209.   begin
  210.     client := [];
  211.  
  212.     AcquireLock(critical);
  213.     begin
  214.       if Server.Requests <> 0 then
  215.         client := Server.ClientQueue[High(Server.ClientQueue)];
  216.     end;
  217.     ReleaseLock(critical);
  218.  
  219.  
  220.     if client <> [] then
  221.     begin
  222.       threads += TLapeThread.Create(@HandleClient,@client);
  223.       threads[High(threads)].Execute();
  224.       //HandleClient(client);
  225.     end;
  226.  
  227.     Sleep(1);
  228.   end;
  229.  
  230.   Server.CloseAndFree();
  231. end;
  232.  
  233. begin
  234.   Main;
  235. end.
  236.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement