Browse Source

* ID is now handled in webassembly

Michaël Van Canneyt 6 months ago
parent
commit
708a479fdd

+ 19 - 2
packages/wasm-utils/src/wasm.websocket.api.pas

@@ -40,13 +40,14 @@ const
   wllError    = wasm.logger.api.wllError;
   wllError    = wasm.logger.api.wllError;
   wllCritical = wasm.logger.api.wllCritical;
   wllCritical = wasm.logger.api.wllCritical;
 
 
+
 function __wasm_websocket_allocate(
 function __wasm_websocket_allocate(
     aURL : PByte;
     aURL : PByte;
     aUrlLen : Longint;
     aUrlLen : Longint;
     aProtocols : PByte;
     aProtocols : PByte;
     aProtocolLen : Longint;
     aProtocolLen : Longint;
     aUserData : Pointer;
     aUserData : Pointer;
-    aWebsocketID : PWasmWebSocketID) : TWasmWebsocketResult; external websocketExportName name websocketFN_Allocate;
+    aWebsocketID : TWasmWebSocketID) : TWasmWebsocketResult; external websocketExportName name websocketFN_Allocate;
 
 
 function __wasm_websocket_close(
 function __wasm_websocket_close(
     aWebsocketID : TWasmWebSocketID;
     aWebsocketID : TWasmWebSocketID;
@@ -71,9 +72,11 @@ Type
   TWasmWebsocketCloseCallback = procedure(aWebSocketID : TWasmWebSocketID; aUserData : Pointer; aCode: Longint; const aReason : String; aClean : Boolean);
   TWasmWebsocketCloseCallback = procedure(aWebSocketID : TWasmWebSocketID; aUserData : Pointer; aCode: Longint; const aReason : String; aClean : Boolean);
   TWasmWebsocketOpenCallback = procedure(aWebSocketID : TWasmWebSocketID; aUserData : Pointer);
   TWasmWebsocketOpenCallback = procedure(aWebSocketID : TWasmWebSocketID; aUserData : Pointer);
   TWasmWebsocketLogHook = procedure (Level : TWasmWebSocketLogLevel; const Msg : string) of object;
   TWasmWebsocketLogHook = procedure (Level : TWasmWebSocketLogLevel; const Msg : string) of object;
+  TWasmWebsocketReleasePacketCallback = procedure(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aPacket : Pointer; var Result : boolean);
 
 
 // Callee is responsible for freeing incoming buffers
 // Callee is responsible for freeing incoming buffers
 Function __wasm_websocket_allocate_buffer(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aBufferLen : Longint) : Pointer;
 Function __wasm_websocket_allocate_buffer(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aBufferLen : Longint) : Pointer;
+Function __wasm_websocket_release_packet(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aPacket : Pointer) : longint;
 Function __wasm_websocket_on_error (aWebsocketID : TWasmWebSocketID; aUserData : Pointer) : TWebsocketCallBackResult;
 Function __wasm_websocket_on_error (aWebsocketID : TWasmWebSocketID; aUserData : Pointer) : TWebsocketCallBackResult;
 Function __wasm_websocket_on_message (aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aMessageType : TWasmWebSocketMessageType; aMessage : Pointer; aMessageLen : Integer) : TWebsocketCallBackResult;
 Function __wasm_websocket_on_message (aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aMessageType : TWasmWebSocketMessageType; aMessage : Pointer; aMessageLen : Integer) : TWebsocketCallBackResult;
 Function __wasm_websocket_on_open (aWebsocketID : TWasmWebSocketID; aUserData : Pointer) : TWebsocketCallBackResult;
 Function __wasm_websocket_on_open (aWebsocketID : TWasmWebSocketID; aUserData : Pointer) : TWebsocketCallBackResult;
@@ -89,6 +92,7 @@ var
   WebSocketMessageCallback : TWasmWebsocketMessageCallback;
   WebSocketMessageCallback : TWasmWebsocketMessageCallback;
   WebSocketCloseCallback : TWasmWebsocketCloseCallback;
   WebSocketCloseCallback : TWasmWebsocketCloseCallback;
   WebSocketOpenCallback : TWasmWebsocketOpenCallback;
   WebSocketOpenCallback : TWasmWebsocketOpenCallback;
+  WebSocketReleasePackageCallBack : TWasmWebsocketReleasePacketCallback;
 
 
 implementation
 implementation
 
 
@@ -112,7 +116,7 @@ end;
 Function __wasm_websocket_allocate_buffer(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aBufferLen : Longint) : Pointer;
 Function __wasm_websocket_allocate_buffer(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aBufferLen : Longint) : Pointer;
 
 
 begin
 begin
-    // Silence compiler warning
+  // Silence compiler warning
   if (aWebSocketID=0) or (aUserData=Nil) then ;
   if (aWebSocketID=0) or (aUserData=Nil) then ;
   Result:=GetMem(aBufferLen);
   Result:=GetMem(aBufferLen);
 end;
 end;
@@ -220,8 +224,21 @@ begin
   end;
   end;
 end;
 end;
 
 
+Function __wasm_websocket_release_packet(aWebsocketID : TWasmWebSocketID; aUserData : Pointer; aPacket : Pointer) : longint;
+
+var
+  lRes : Boolean;
+
+begin
+  lRes:=Assigned(WebSocketReleasePackageCallBack);
+  if lRes then
+    WebSocketReleasePackageCallBack(aWebsocketID,aUserData,aPacket,lRes);
+  Result:=Ord(Not lRes); // 0 is OK, 1 is error.
+end;
+
 exports
 exports
   __wasm_websocket_allocate_buffer,
   __wasm_websocket_allocate_buffer,
+  __wasm_websocket_release_packet,
   __wasm_websocket_on_error,
   __wasm_websocket_on_error,
   __wasm_websocket_on_message,
   __wasm_websocket_on_message,
   __wasm_websocket_on_open,
   __wasm_websocket_on_open,

+ 124 - 40
packages/wasm-utils/src/wasm.websocket.objects.pas

@@ -42,6 +42,10 @@ Type
 
 
   TWasmWebsocket = class(TComponent)
   TWasmWebsocket = class(TComponent)
   private
   private
+    class var _NextID : TWasmWebSocketID;
+    class function GetNextWebsocketID : TWasmWebSocketID;
+  private
+    FKeepDataAlive: Boolean;
     FOnClose: TWasmWebsocketCloseEvent;
     FOnClose: TWasmWebsocketCloseEvent;
     FOnError: TWasmWebsocketErrorEvent;
     FOnError: TWasmWebsocketErrorEvent;
     FOnMessage: TWasmWebsocketMessageEvent;
     FOnMessage: TWasmWebsocketMessageEvent;
@@ -50,7 +54,10 @@ Type
     FURL: String;
     FURL: String;
     FWebSocketID: TWasmWebSocketID;
     FWebSocketID: TWasmWebSocketID;
     FClosed : Boolean;
     FClosed : Boolean;
+    FData : Array of TBytes;
+    FDataCount : Integer;
     procedure DoSendMessage(aBytes: TBytes; aType: longint);
     procedure DoSendMessage(aBytes: TBytes; aType: longint);
+    procedure SetKeepDataAlive(AValue: Boolean);
   Protected
   Protected
     procedure CheckWebsocketRes(aResult: TWasmWebsocketResult; const aMsg: String; aLogOnly: Boolean=false);
     procedure CheckWebsocketRes(aResult: TWasmWebsocketResult; const aMsg: String; aLogOnly: Boolean=false);
     Procedure DoOpen(const aURL : String; const aProtocols : String); virtual;
     Procedure DoOpen(const aURL : String; const aProtocols : String); virtual;
@@ -60,7 +67,9 @@ Type
     procedure HandleOpen; virtual;
     procedure HandleOpen; virtual;
     procedure HandleMessage(aType : Longint; aMessage : TBytes); virtual;
     procedure HandleMessage(aType : Longint; aMessage : TBytes); virtual;
     procedure HandleClose(aCode : Longint; aReason : string; aIsClean : Boolean); virtual;
     procedure HandleClose(aCode : Longint; aReason : string; aIsClean : Boolean); virtual;
-
+    // Data management
+    procedure ReleaseAllData;
+    Procedure KeepData(const aData : TBytes);
   Public
   Public
     Constructor create(aOwner : TComponent); override;
     Constructor create(aOwner : TComponent); override;
     Destructor Destroy; override;
     Destructor Destroy; override;
@@ -68,6 +77,7 @@ Type
     Procedure Close(aCode : Longint; aReason: UTF8String);
     Procedure Close(aCode : Longint; aReason: UTF8String);
     Procedure SendMessage(aBytes : TBytes);
     Procedure SendMessage(aBytes : TBytes);
     Procedure SendMessage(const aString : String);
     Procedure SendMessage(const aString : String);
+    function ReleaseData(const aData : TBytes) : boolean;
     Property WebSocketID : TWasmWebSocketID Read FWebSocketID;
     Property WebSocketID : TWasmWebSocketID Read FWebSocketID;
     Property OnError : TWasmWebsocketErrorEvent Read FOnError Write FOnError;
     Property OnError : TWasmWebsocketErrorEvent Read FOnError Write FOnError;
     Property OnMessage : TWasmWebsocketMessageEvent Read FOnMessage Write FOnMessage;
     Property OnMessage : TWasmWebsocketMessageEvent Read FOnMessage Write FOnMessage;
@@ -75,6 +85,7 @@ Type
     Property OnOpen : TWasmWebsocketOpenEvent Read FOnOpen Write FOnOpen;
     Property OnOpen : TWasmWebsocketOpenEvent Read FOnOpen Write FOnOpen;
     Property URL : String Read FURL;
     Property URL : String Read FURL;
     Property Protocols : String Read FProtocols;
     Property Protocols : String Read FProtocols;
+    Property KeepDataAlive : Boolean Read FKeepDataAlive Write SetKeepDataAlive;
   end;
   end;
 
 
   { TWasmWebSocketManager }
   { TWasmWebSocketManager }
@@ -85,10 +96,17 @@ Type
   private
   private
     Flist : TFPList; // Todo: change to thread list.
     Flist : TFPList; // Todo: change to thread list.
   protected
   protected
-    class procedure HandleClose(aWebSocketID: TWasmWebSocketID; aUserData: Pointer; aCode: Longint; const aReason: String; aClean: Boolean); static;
-    class procedure HandleError(aWebSocketID: TWasmWebSocketID; aUserData: Pointer); static;
-    class procedure HandleMessage(aWebSocketID: TWasmWebSocketID; aUserData: Pointer; aMessageType: TWasmWebSocketMessageType;  aMessage: TBytes); static;
-    class procedure HandleOpen(aWebSocketID: TWasmWebSocketID; aUserData: Pointer); static;
+    class procedure HandleReleasePackageCallBack(aWebsocketID: TWasmWebSocketID; aUserData: Pointer; aPacket: Pointer; var Result: boolean); static;
+    class procedure HandleCloseCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer; aCode: Longint; const aReason: String; aClean: Boolean); static;
+    class procedure HandleErrorCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer); static;
+    class procedure HandleMessageCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer; aMessageType: TWasmWebSocketMessageType;  aMessage: TBytes); static;
+    class procedure HandleOpenCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer); static;
+    function HandleReleasePacket(aSocket : TWasmWebSocket; aPacket : Pointer) : Boolean; virtual;
+    procedure HandleClose(aSocket : TWasmWebSocket; aCode: Longint; const aReason: String; aClean: Boolean); virtual;
+    procedure HandleError(aSocket:  TWasmWebSocket); virtual;
+    procedure HandleMessage(aSocket: TWasmWebSocket; aMessageType: TWasmWebSocketMessageType;  aMessage: TBytes); virtual;
+    procedure HandleOpen(aSocket: TWasmWebSocket); virtual;
+
     procedure RegisterWebSocket(aWebSocket : TWasmWebSocket);
     procedure RegisterWebSocket(aWebSocket : TWasmWebSocket);
     procedure UnRegisterWebSocket(aWebSocket : TWasmWebSocket);
     procedure UnRegisterWebSocket(aWebSocket : TWasmWebSocket);
     function IsValidWebSocket(aWebSocketID: TWasmWebSocketID; aUserData: Pointer) : Boolean;
     function IsValidWebSocket(aWebSocketID: TWasmWebSocketID; aUserData: Pointer) : Boolean;
@@ -102,8 +120,16 @@ Type
 
 
 implementation
 implementation
 
 
+
+
 { TWasmWebsocket }
 { TWasmWebsocket }
 
 
+class procedure TWasmWebSocketManager.HandleReleasePackageCallBack(aWebsocketID: TWasmWebSocketID; aUserData: Pointer; aPacket: Pointer; var Result: boolean);
+begin
+  If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
+    Result:=Instance.HandleReleasePacket(TWasmWebSocket(aUserData),aPacket);
+end;
+
 constructor TWasmWebsocket.create(aOwner : TComponent);
 constructor TWasmWebsocket.create(aOwner : TComponent);
 
 
 begin
 begin
@@ -112,7 +138,6 @@ begin
   FClosed:=False
   FClosed:=False
 end;
 end;
 
 
-
 procedure TWasmWebsocket.DoClose(aCode: Longint; aReason: UTF8String; aRaiseError: Boolean);
 procedure TWasmWebsocket.DoClose(aCode: Longint; aReason: UTF8String; aRaiseError: Boolean);
 
 
 var
 var
@@ -125,28 +150,24 @@ begin
   CheckWebsocketRes(Res,'close',not aRaiseError);
   CheckWebsocketRes(Res,'close',not aRaiseError);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.HandleError;
 procedure TWasmWebsocket.HandleError;
 begin
 begin
   if assigned(FonError) then
   if assigned(FonError) then
     FOnError(Self);
     FOnError(Self);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.HandleOpen;
 procedure TWasmWebsocket.HandleOpen;
 begin
 begin
   if assigned(FonOpen) then
   if assigned(FonOpen) then
     FOnOpen(Self);
     FOnOpen(Self);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.HandleMessage(aType: Longint; aMessage: TBytes);
 procedure TWasmWebsocket.HandleMessage(aType: Longint; aMessage: TBytes);
 begin
 begin
   if assigned(FOnMessage) then
   if assigned(FOnMessage) then
     FOnMessage(Self,aType=WASMWS_MESSAGE_TYPE_TEXT,aMessage);
     FOnMessage(Self,aType=WASMWS_MESSAGE_TYPE_TEXT,aMessage);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.HandleClose(aCode: Longint; aReason: string; aIsClean: Boolean);
 procedure TWasmWebsocket.HandleClose(aCode: Longint; aReason: string; aIsClean: Boolean);
 begin
 begin
   FClosed:=True;
   FClosed:=True;
@@ -154,7 +175,6 @@ begin
     FOnClose(Self,aCode,aReason,aIsClean);
     FOnClose(Self,aCode,aReason,aIsClean);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.DoOpen(const aURL: String; const aProtocols: String);
 procedure TWasmWebsocket.DoOpen(const aURL: String; const aProtocols: String);
 
 
 var
 var
@@ -165,11 +185,10 @@ begin
   FProtocols:=aProtocols;
   FProtocols:=aProtocols;
   lURL:=UTF8Encode(aURL);
   lURL:=UTF8Encode(aURL);
   lProtocols:=UTF8Encode(aProtocols);
   lProtocols:=UTF8Encode(aProtocols);
-  if __wasm_websocket_allocate(PByte(lURL),Length(lURL),PByte(lProtocols),Length(lProtocols),Self,@FWebSocketID)<>WASMWS_RESULT_SUCCESS then
+  if __wasm_websocket_allocate(PByte(lURL),Length(lURL),PByte(lProtocols),Length(lProtocols),Self,FWebSocketID)<>WASMWS_RESULT_SUCCESS then
     Raise EWasmWebsocket.CreateFmt('Failed to allocate websocket for URL %s',[aURL]);
     Raise EWasmWebsocket.CreateFmt('Failed to allocate websocket for URL %s',[aURL]);
 end;
 end;
 
 
-
 destructor TWasmWebsocket.Destroy;
 destructor TWasmWebsocket.Destroy;
 
 
 var
 var
@@ -182,16 +201,16 @@ begin
   CheckWebsocketRes(Res,'Deallocating websocket',True);
   CheckWebsocketRes(Res,'Deallocating websocket',True);
   FWebSocketID:=0;
   FWebSocketID:=0;
   TWasmWebSocketManager.Instance.UnRegisterWebSocket(Self);
   TWasmWebSocketManager.Instance.UnRegisterWebSocket(Self);
+  ReleaseAllData;
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
-
 procedure TWasmWebsocket.Open(const aURL: String; const aProtocols: String);
 procedure TWasmWebsocket.Open(const aURL: String; const aProtocols: String);
 begin
 begin
+  FWebSocketID:=GetNextWebsocketID;
   DoOpen(aURL,aProtocols);
   DoOpen(aURL,aProtocols);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.Close(aCode: Longint; aReason: UTF8String);
 procedure TWasmWebsocket.Close(aCode: Longint; aReason: UTF8String);
 
 
 begin
 begin
@@ -199,7 +218,6 @@ begin
   FClosed:=True;
   FClosed:=True;
 end;
 end;
 
 
-
 procedure TWasmWebsocket.CheckWebsocketRes(aResult : TWasmWebsocketResult; const aMsg :String; aLogOnly : Boolean = false);
 procedure TWasmWebsocket.CheckWebsocketRes(aResult : TWasmWebsocketResult; const aMsg :String; aLogOnly : Boolean = false);
 
 
 var
 var
@@ -214,6 +232,10 @@ begin
     Raise EWasmWebsocket.Create(Err);
     Raise EWasmWebsocket.Create(Err);
 end;
 end;
 
 
+class function TWasmWebsocket.GetNextWebsocketID: TWasmWebSocketID;
+begin
+  Result:=InterlockedIncrement(_NextID);
+end;
 
 
 procedure TWasmWebsocket.DoSendMessage(aBytes: TBytes; aType : longint);
 procedure TWasmWebsocket.DoSendMessage(aBytes: TBytes; aType : longint);
 
 
@@ -229,9 +251,52 @@ begin
   if DataLen=0 then
   if DataLen=0 then
     exit;
     exit;
   Res:=__wasm_websocket_send(FWebsocketID,PByte(aBytes),DataLen,aType);
   Res:=__wasm_websocket_send(FWebsocketID,PByte(aBytes),DataLen,aType);
+  if (Res=WASMWS_RESULT_SUCCESS) and KeepDataAlive then
+    KeepData(aBytes);
   CheckWebsocketRes(Res,'Failed to send '+aTypes[aType=WASMWS_MESSAGE_TYPE_TEXT]+' data on websocket');
   CheckWebsocketRes(Res,'Failed to send '+aTypes[aType=WASMWS_MESSAGE_TYPE_TEXT]+' data on websocket');
 end;
 end;
 
 
+procedure TWasmWebsocket.SetKeepDataAlive(AValue: Boolean);
+begin
+  if FKeepDataAlive=AValue then Exit;
+  FKeepDataAlive:=AValue;
+  if not FKeepDataAlive then
+    ReleaseAllData;
+end;
+
+procedure TWasmWebsocket.ReleaseAllData;
+
+begin
+  SetLength(FData,0);
+end;
+
+procedure TWasmWebsocket.KeepData(const aData: TBytes);
+var
+  lLen : Integer;
+begin
+  lLen:=Length(FData);
+  if (FDataCount=lLen) then
+    SetLength(FData,lLen+10);
+  FData[FDataCount]:=aData;
+  Inc(FDataCount);
+end;
+
+function TWasmWebsocket.ReleaseData(const aData: TBytes): boolean;
+var
+  lIdx : Integer;
+begin
+  Result:=False;
+  lIdx:=FDataCount-1;
+  While (lIdx>=0) and (FData[lIdx]<>aData) do
+    Dec(lIdx);
+  if (lIdx<0) then
+    exit;
+  if lIdx<FDataCount-1 then
+    FData[lIdx]:=FData[FDataCount-1];
+  FData[FDataCount-1]:=Nil;
+  Dec(FDataCount);
+  Result:=True;
+end;
 
 
 procedure TWasmWebsocket.SendMessage(aBytes: TBytes);
 procedure TWasmWebsocket.SendMessage(aBytes: TBytes);
 
 
@@ -239,7 +304,6 @@ begin
   DoSendMessage(aBytes,WASMWS_MESSAGE_TYPE_BINARY);
   DoSendMessage(aBytes,WASMWS_MESSAGE_TYPE_BINARY);
 end;
 end;
 
 
-
 procedure TWasmWebsocket.SendMessage(const aString: String);
 procedure TWasmWebsocket.SendMessage(const aString: String);
 
 
 var
 var
@@ -268,83 +332,103 @@ begin
     begin
     begin
     C:=DefaultInstanceType;
     C:=DefaultInstanceType;
     if C=Nil then C:=TWasmWebSocketManager;
     if C=Nil then C:=TWasmWebSocketManager;
-    _instance:=TWasmWebSocketManager.Create;
+    _instance:=C.Create;
     end;
     end;
-  Result:=_instance;
+  Result:=_Instance;
 end;
 end;
 
 
-
 procedure TWasmWebSocketManager.RegisterWebSocket(aWebSocket: TWasmWebSocket);
 procedure TWasmWebSocketManager.RegisterWebSocket(aWebSocket: TWasmWebSocket);
 begin
 begin
-  Writeln(Format('adding websocket [%p]',[Pointer(aWebSocket)]));
   Flist.Add(aWebSocket);
   Flist.Add(aWebSocket);
 end;
 end;
 
 
-
 procedure TWasmWebSocketManager.UnRegisterWebSocket(aWebSocket: TWasmWebSocket);
 procedure TWasmWebSocketManager.UnRegisterWebSocket(aWebSocket: TWasmWebSocket);
 begin
 begin
   Flist.Remove(aWebSocket);
   Flist.Remove(aWebSocket);
 end;
 end;
 
 
-
 function TWasmWebSocketManager.IsValidWebSocket(aWebSocketID: TWasmWebSocketID; aUserData: Pointer): Boolean;
 function TWasmWebSocketManager.IsValidWebSocket(aWebSocketID: TWasmWebSocketID; aUserData: Pointer): Boolean;
 begin
 begin
   Result:=FList.IndexOf(aUserData)<>-1;
   Result:=FList.IndexOf(aUserData)<>-1;
   If Result then
   If Result then
     Result:=TWasmWebSocket(aUserData).WebSocketID=aWebSocketID;
     Result:=TWasmWebSocket(aUserData).WebSocketID=aWebSocketID;
   if not Result then
   if not Result then
+    begin
     __wasmwebsocket_log(wllError,'Invalid websocket received: %d [%p]',[aWebsocketID,aUserData]);
     __wasmwebsocket_log(wllError,'Invalid websocket received: %d [%p]',[aWebsocketID,aUserData]);
+    end;
 end;
 end;
 
 
+class procedure TWasmWebSocketManager.HandleErrorCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer);
+begin
+  If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
+    Instance.HandleError(TWasmWebSocket(aUserData));
+end;
 
 
-class procedure TWasmWebSocketManager.HandleError(aWebSocketID : TWasmWebSocketID; aUserData : Pointer);
+class procedure TWasmWebSocketManager.HandleMessageCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer;
+  aMessageType: TWasmWebSocketMessageType; aMessage: TBytes);
 begin
 begin
   If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
   If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
-    TWasmWebSocket(aUserData).HandleError;
+    Instance.HandleMessage(TWasmWebSocket(aUserData),aMessageType,aMessage);
 end;
 end;
 
 
+class procedure TWasmWebSocketManager.HandleCloseCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer; aCode: Longint;
+  const aReason: String; aClean: Boolean);
+begin
+  If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
+    Instance.HandleClose(TWasmWebSocket(aUserData),aCode,aReason,aClean);
+end;
 
 
-class procedure TWasmWebSocketManager.HandleMessage(aWebSocketID : TWasmWebSocketID; aUserData : Pointer; aMessageType : TWasmWebSocketMessageType; aMessage : TBytes);
+class procedure TWasmWebSocketManager.HandleOpenCallBack(aWebSocketID: TWasmWebSocketID; aUserData: Pointer);
 begin
 begin
   If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
   If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
-    TWasmWebSocket(aUserData).HandleMessage(aMessageType,aMessage);
+    Instance.HandleOpen(TWasmWebSocket(aUserData));
 end;
 end;
 
 
+function TWasmWebSocketManager.HandleReleasePacket(aSocket: TWasmWebSocket; aPacket: Pointer): Boolean;
+begin
+  aSocket.ReleaseData(TBytes(aPacket));
+end;
 
 
-class procedure TWasmWebSocketManager.HandleClose(aWebSocketID : TWasmWebSocketID; aUserData : Pointer; aCode: Longint; const aReason : String; aClean : Boolean);
+procedure TWasmWebSocketManager.HandleClose(aSocket: TWasmWebSocket; aCode: Longint; const aReason: String; aClean: Boolean);
 begin
 begin
-  If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
-    TWasmWebSocket(aUserData).HandleClose(aCode,aReason,aClean)
+  aSocket.HandleClose(aCode,aReason,aClean);
 end;
 end;
 
 
+procedure TWasmWebSocketManager.HandleError(aSocket: TWasmWebSocket);
+begin
+  aSocket.HandleError;
+end;
 
 
-class procedure TWasmWebSocketManager.HandleOpen(aWebSocketID : TWasmWebSocketID; aUserData : Pointer);
+procedure TWasmWebSocketManager.HandleMessage(aSocket: TWasmWebSocket; aMessageType: TWasmWebSocketMessageType; aMessage: TBytes);
 begin
 begin
-  If Instance.IsValidWebSocket(aWebSocketID,aUserData) then
-    TWasmWebSocket(aUserData).HandleOpen;
+  aSocket.HandleMessage(aMessageType,aMessage);
 end;
 end;
 
 
-class constructor TWasmWebSocketManager.init;
+procedure TWasmWebSocketManager.HandleOpen(aSocket: TWasmWebSocket);
 begin
 begin
-  WebSocketErrorCallback:=@HandleError;
-  WebSocketMessageCallback:=@HandleMessage;
-  WebSocketCloseCallback:=@HandleClose;
-  WebSocketOpenCallback:=@HandleOpen;
+  aSocket.HandleOpen;
 end;
 end;
 
 
 
 
+class constructor TWasmWebSocketManager.init;
+begin
+  WebSocketErrorCallback:=@HandleErrorCallBack;
+  WebSocketMessageCallback:=@HandleMessageCallBack;
+  WebSocketCloseCallback:=@HandleCloseCallBack;
+  WebSocketOpenCallback:=@HandleOpenCallBack;
+  WebSocketReleasePackageCallBack:=@HandleReleasePackageCallBack;
+end;
+
 constructor TWasmWebSocketManager.create;
 constructor TWasmWebSocketManager.create;
 begin
 begin
   Flist:=TFPList.Create;
   Flist:=TFPList.Create;
 end;
 end;
 
 
-
 destructor TWasmWebSocketManager.destroy;
 destructor TWasmWebSocketManager.destroy;
 begin
 begin
   FreeAndNil(Flist);
   FreeAndNil(Flist);
   inherited destroy;
   inherited destroy;
 end;
 end;
 
 
-
 end.
 end.