connection error fixes

This commit is contained in:
André Mussche 2014-01-23 10:17:13 +01:00
parent 0181d6b8ab
commit 8187b7f06a
3 changed files with 53 additions and 16 deletions

View file

@ -46,6 +46,8 @@ type
FSocketIOHandshakeResponse: string;
FSocketIO: TIdSocketIOHandling_Ext;
FSocketIOContext: ISocketIOContext;
FSocketIOConnectBusy: Boolean;
FHeartBeat: TTimer;
procedure HeartBeatTimer(Sender: TObject);
function GetSocketIO: TIdSocketIOHandling;
@ -242,6 +244,17 @@ begin
IOHandler.Clear;
FHeartBeat.Enabled := True;
if SocketIOCompatible and
not FSocketIOConnectBusy then
begin
FSocketIOConnectBusy := True;
try
TryUpgradeToWebsocket; //socket.io connects using HTTP, so no seperate .Connect needed (only gives Connection closed gracefully exceptions because of new http command)
finally
FSocketIOConnectBusy := False;
end;
end
else
inherited Connect;
end;
@ -325,8 +338,9 @@ begin
if (IOHandler <> nil) then
IOHandler.Clear;
Self.ConnectTimeout := 100;
Self.Connect;
Self.ConnectTimeout := 100; //100ms otherwise GUI hangs too much -> todo: do it in background thread!
if not Connected then
Self.Connect;
TryUpgradeToWebsocket;
except
//skip, just retried
@ -373,6 +387,8 @@ function TIdHTTPWebsocketClient.TryUpgradeToWebsocket: Boolean;
var
sError: string;
begin
if (IOHandler <> nil) and IOHandler.IsWebsocket then Exit(True);
InternalUpgradeToWebsocket(False{no raise}, sError);
Result := (sError = '');
end;
@ -381,6 +397,7 @@ procedure TIdHTTPWebsocketClient.UpgradeToWebsocket;
var
sError: string;
begin
if not IOHandler.IsWebsocket then
InternalUpgradeToWebsocket(True{raise}, sError);
end;
@ -392,7 +409,7 @@ var
sKey, sResponseKey: string;
sSocketioextended: string;
begin
Assert(not IOHandler.IsWebsocket);
Assert((IOHandler = nil) or not IOHandler.IsWebsocket);
strmResponse := TMemoryStream.Create;
try
@ -1094,16 +1111,14 @@ begin
for i := 0 to l.Count - 1 do
begin
chn := TIdHTTPWebsocketClient(l.Items[i]);
ws := chn.IOHandler as TIdIOHandlerWebsocket;
if ws.TryLock then //IOHandler.Readable cannot be done during pending action!
try
try
//try to process all events
while chn.IOHandler.HasData or
chn.IOHandler.Readable(0) do //has some data
begin
ws := chn.IOHandler as TIdIOHandlerWebsocket;
//no pending dispatch active? (so actually we only read events here?)
if ws.TryLock then
begin
try
if strmEvent = nil then
strmEvent := TMemoryStream.Create;
strmEvent.Clear;
@ -1115,9 +1130,6 @@ begin
//ignore ping/pong messages
if wscode in [wdcPing, wdcPong] then Continue;
finally
ws.Unlock;
end;
//fire event
//offload event dispatching to different thread! otherwise deadlocks possible? (do to synchronize)
@ -1135,15 +1147,15 @@ begin
chn.AsyncDispatchEvent(string(swstext));
end;
end;
end
else
sleep(1);
end;
except
l := nil;
FChannels.UnlockList;
chn.ResetChannel;
raise;
end;
finally
ws.Unlock;
end;
end;

View file

@ -1038,10 +1038,10 @@ procedure TSocketIOContext.EmitEvent(const aEventName: string; const aData: ISup
const aCallback: TSocketIOMsgJSON; const aOnError: TSocketIOError);
begin
if not Assigned(aCallback) then
FHandling.WriteSocketIOEvent(Self, '', aEventName, aData.AsJSon, nil, nil)
FHandling.WriteSocketIOEvent(Self, '', aEventName, '[' + aData.AsJSon + ']', nil, nil)
else
begin
FHandling.WriteSocketIOEventRef(Self, '', aEventName, aData.AsJSon,
FHandling.WriteSocketIOEventRef(Self, '', aEventName, '[' + aData.AsJSon + ']',
procedure(const aData: string)
begin
aCallback(Self, SO(aData), nil);
@ -1135,6 +1135,9 @@ procedure TSocketIOContext.ServerContextDestroy(AContext: TIdContext);
begin
Self.Context := nil;
Self.FIOHandler := nil;
if FHandling <> nil then
Self.FHandling.FreeConnection(AContext);
end;
procedure TSocketIOContext.SetConnectSend(const Value: Boolean);

View file

@ -42,6 +42,7 @@ type
procedure ResetChannel;
function TryUpgradeToWebsocket: Boolean;
procedure CheckConnection;
protected
procedure IntDispatch(aRequest, aResponse: TStream); override;
function CreateIndyClient: TIdHTTP; override;
@ -160,6 +161,25 @@ begin
end);
end;
procedure TROIndyHTTPWebsocketChannel.CheckConnection;
begin
try
if IndyClient.Connected then
IndyClient.IOHandler.CheckForDisconnect(True, True)
except
IndyClient.Disconnect(False);
end;
if not IndyClient.Connected then
begin
if IndyClient.IOHandler <> nil then
IndyClient.IOHandler.Clear;
IndyClient.Connect;
if not IndyClient.IOHandler.IsWebsocket then //not already upgraded?
TryUpgradeToWebsocket;
FTriedUpgrade := True; //one shot
end;
end;
function TROIndyHTTPWebsocketChannel.CreateIndyClient: TIdHTTP;
var
wsclient: TROIndyHTTPSocketIOClient;
@ -232,6 +252,8 @@ begin
aRequest.Write(iMsgNr, SizeOf(iMsgNr));
aRequest.Position := 0;
CheckConnection;
//write
IndyClient.IOHandler.Write(aRequest);