2002-03-06 23:13:23 +00:00
|
|
|
/** GSWDefaultAdaptorThread.m - <title>GSWeb: Class GSWDefaultAdaptorThread</title>
|
|
|
|
Copyright (C) 1999-2002 Free Software Foundation, Inc.
|
2000-01-22 12:49:49 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
Written by: Manuel Guesdon <mguesdon@orange-concept.com>
|
2000-01-22 12:49:49 +00:00
|
|
|
Date: Feb 1999
|
2002-03-06 23:13:23 +00:00
|
|
|
|
|
|
|
$Revision$
|
|
|
|
$Date$
|
2000-01-22 12:49:49 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
<abstract></abstract>
|
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
This file is part of the GNUstep Web Library.
|
2002-03-06 23:13:23 +00:00
|
|
|
|
|
|
|
<license>
|
2000-01-22 12:49:49 +00:00
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
2002-03-06 23:13:23 +00:00
|
|
|
</license>
|
|
|
|
**/
|
2000-01-22 12:49:49 +00:00
|
|
|
|
|
|
|
static char rcsId[] = "$Id$";
|
|
|
|
|
2000-10-30 15:36:50 +00:00
|
|
|
#include <GSWeb/GSWeb.h>
|
2000-03-20 15:50:51 +00:00
|
|
|
#include <unistd.h>
|
2002-03-06 23:13:23 +00:00
|
|
|
#include <math.h> //for fabs
|
2000-01-22 12:49:49 +00:00
|
|
|
#include "NSNonBlockingFileHandle.h"
|
2001-10-28 10:29:17 +00:00
|
|
|
#define ADAPTOR_THREAD_TIME_OUT (5*60) //threads waiting for more than 5 minutes are not processed
|
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
//====================================================================
|
|
|
|
@implementation GSWDefaultAdaptorThread
|
|
|
|
|
2000-03-16 16:16:49 +00:00
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(id)init
|
|
|
|
{
|
|
|
|
if ((self=[super init]))
|
2001-03-11 Manuel Guesdon <mguesdon@orange-concept.com>
* GSWeb.framework/GSWWOCompatibility.h/.m: added
* GSWeb.framework/GNUmakefile: added GSWWOCompatibility.h/.m
* GSWeb.framework/GSWApplication.h/m: added WOApplicationMain, handle WO/GSWeb names
* GSWeb.framework/GSWContext.m: handle WO/GSWeb names, added traces
* GSWeb.framework/GSWConstants.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWDynamicURLString.m: handle WO/GSWeb names
* GSWeb.framework/GSWProjectBundle.m/.h: handle WO/GSWeb names, suppress warnings
* GSWeb.framework/GSWSession.m: handle WO/GSWeb names
* GSWeb.framework/GSWRequest.m: handle WO/GSWeb names
* GSWeb.framework/GSWTemplateParser.m: handle WO/GSWeb names,
added tag counts to help errors hunt
* GSWeb.framework/GSWBundle.m: handle WO/GSWeb names, added traces
* GSWeb.framework/GSWResourceManager.m: handle WO/GSWeb names
* GSWeb.framework/GSWURLValuedElementData.m: handle WO/GSWeb names
* GSWeb.framework/GSWComponentRequestHandler.m: handle WO/GSWeb names
* GSWeb.framework/GSWDirectAction.m: handle WO/GSWeb names
* GSWeb.framework/GSWForm.m/.h: handle WO/GSWeb names
* GSWeb.framework/GSWHyperlink.m/.h: handle WO/GSWeb names
* GSWeb.framework/GSWResourceRequestHandler.m: handle WO/GSWeb names
* GSWeb.framework/GSWDirectActionRequestHandler.m: handle WO/GSWeb names
* GSWeb.framework/GSWActiveImage.m/.h: handle WO/GSWeb names
* GSWeb.framework/GSWBindingNameAssociation.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWBrowser.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWComponent.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWHTMLURLValuedElement.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWImageButton.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWInput.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWPopUpButton.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWString.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWAssociation.m: handle WO/GSWeb names
* GSWeb.framework/GSWCheckBox.m: handle WO/GSWeb names
* GSWeb.framework/GSWCheckBoxList.m: handle WO/GSWeb names
* GSWeb.framework/GSWComponentDefinition.m: handle WO/GSWeb names
* GSWeb.framework/GSWRadioButton.m: handle WO/GSWeb names
* GSWeb.framework/GSWRadioButtonList.m: handle WO/GSWeb names
* GSWeb.framework/GSWText.m: handle WO/GSWeb names
* GSWeb.framework/GSWTextField.m: handle WO/GSWeb names
* GSWeb.framework/GSWDeployedBundle.m: warnings
* GSWeb.framework/GSWeb.h: added include GSWeb/GSWSessionTimeOut.h, GSWWOCompatibility.h
* GSWeb.framework/GSWAdaptor.m: traces
* GSWeb.framework/GSWDefaultAdaptor.m: handle WO/GSWeb names, added traces
* GSWeb.framework/GSWDefaultAdaptorThread.m/.h: handle WO/GSWeb names
* GSWeb.framework/NSNonBlockingFileHandle.m: added traces
* GSWeb.framework/GSWTemplateParserANTLR.m: handle WO/GSWeb names
* GSWeb.framework/GSWTemplateParserXML.m: handle WO/GSWeb names
added tag count to help errors hunt
remove "Tag gsweb invalid" message
handle unicode strings in node content traces
remove html and body tags if they are not present in the template
* GSWeb.framework/GSWTemplateParseXML.h: added ivar _isHTMLTag, _isBodyTag
* GSWeb.framework/GSWSessionTimeOutManager.m: dealloc sessionOrderedTimeOuts instead
of deallocating 2 times sessionTimeOuts
* GSWExtensions.framework/French.lproj/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
tag mismatch, Encode french characters
* GSWExtensions.framework/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
tag mismatch
* GSWHTMLBareString.m: handle unicode strings in description
* GSWExtensions.framework/French.lproj/GSWExceptionPage.gswc/GSWExceptionPage.html:
Encode french characters, Tag Mismatch
* GSWExtensions.framework/French.lproj/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.html:
Encode french characters
* GSWExtensions.framework/French.lproj/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.html:
Encode french characters
* GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.html:
Tag Mismatch
* GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.gswd:
added convertHTMLEntities for strings
* GSWeb.framework/GSWRepetition.m: added traces, fix "count" property bug, standardize ivars
* GSWeb.framework/NSObject+IVarAccess+PerformSel.m: added traces, handle underscored ivars search
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@9332 72102866-910b-0410-8b05-ffd578937521
2001-03-11 17:15:44 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
ASSIGN(_creationDate,[NSDate date]);
|
|
|
|
_requestNamingConv=GSWebNamingConv;//GSWNAMES_INDEX or WONAMES_INDEX
|
2001-03-11 Manuel Guesdon <mguesdon@orange-concept.com>
* GSWeb.framework/GSWWOCompatibility.h/.m: added
* GSWeb.framework/GNUmakefile: added GSWWOCompatibility.h/.m
* GSWeb.framework/GSWApplication.h/m: added WOApplicationMain, handle WO/GSWeb names
* GSWeb.framework/GSWContext.m: handle WO/GSWeb names, added traces
* GSWeb.framework/GSWConstants.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWDynamicURLString.m: handle WO/GSWeb names
* GSWeb.framework/GSWProjectBundle.m/.h: handle WO/GSWeb names, suppress warnings
* GSWeb.framework/GSWSession.m: handle WO/GSWeb names
* GSWeb.framework/GSWRequest.m: handle WO/GSWeb names
* GSWeb.framework/GSWTemplateParser.m: handle WO/GSWeb names,
added tag counts to help errors hunt
* GSWeb.framework/GSWBundle.m: handle WO/GSWeb names, added traces
* GSWeb.framework/GSWResourceManager.m: handle WO/GSWeb names
* GSWeb.framework/GSWURLValuedElementData.m: handle WO/GSWeb names
* GSWeb.framework/GSWComponentRequestHandler.m: handle WO/GSWeb names
* GSWeb.framework/GSWDirectAction.m: handle WO/GSWeb names
* GSWeb.framework/GSWForm.m/.h: handle WO/GSWeb names
* GSWeb.framework/GSWHyperlink.m/.h: handle WO/GSWeb names
* GSWeb.framework/GSWResourceRequestHandler.m: handle WO/GSWeb names
* GSWeb.framework/GSWDirectActionRequestHandler.m: handle WO/GSWeb names
* GSWeb.framework/GSWActiveImage.m/.h: handle WO/GSWeb names
* GSWeb.framework/GSWBindingNameAssociation.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWBrowser.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWComponent.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWHTMLURLValuedElement.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWImageButton.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWInput.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWPopUpButton.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWString.h/.m: handle WO/GSWeb names
* GSWeb.framework/GSWAssociation.m: handle WO/GSWeb names
* GSWeb.framework/GSWCheckBox.m: handle WO/GSWeb names
* GSWeb.framework/GSWCheckBoxList.m: handle WO/GSWeb names
* GSWeb.framework/GSWComponentDefinition.m: handle WO/GSWeb names
* GSWeb.framework/GSWRadioButton.m: handle WO/GSWeb names
* GSWeb.framework/GSWRadioButtonList.m: handle WO/GSWeb names
* GSWeb.framework/GSWText.m: handle WO/GSWeb names
* GSWeb.framework/GSWTextField.m: handle WO/GSWeb names
* GSWeb.framework/GSWDeployedBundle.m: warnings
* GSWeb.framework/GSWeb.h: added include GSWeb/GSWSessionTimeOut.h, GSWWOCompatibility.h
* GSWeb.framework/GSWAdaptor.m: traces
* GSWeb.framework/GSWDefaultAdaptor.m: handle WO/GSWeb names, added traces
* GSWeb.framework/GSWDefaultAdaptorThread.m/.h: handle WO/GSWeb names
* GSWeb.framework/NSNonBlockingFileHandle.m: added traces
* GSWeb.framework/GSWTemplateParserANTLR.m: handle WO/GSWeb names
* GSWeb.framework/GSWTemplateParserXML.m: handle WO/GSWeb names
added tag count to help errors hunt
remove "Tag gsweb invalid" message
handle unicode strings in node content traces
remove html and body tags if they are not present in the template
* GSWeb.framework/GSWTemplateParseXML.h: added ivar _isHTMLTag, _isBodyTag
* GSWeb.framework/GSWSessionTimeOutManager.m: dealloc sessionOrderedTimeOuts instead
of deallocating 2 times sessionTimeOuts
* GSWExtensions.framework/French.lproj/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
tag mismatch, Encode french characters
* GSWExtensions.framework/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html:
tag mismatch
* GSWHTMLBareString.m: handle unicode strings in description
* GSWExtensions.framework/French.lproj/GSWExceptionPage.gswc/GSWExceptionPage.html:
Encode french characters, Tag Mismatch
* GSWExtensions.framework/French.lproj/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.html:
Encode french characters
* GSWExtensions.framework/French.lproj/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.html:
Encode french characters
* GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.html:
Tag Mismatch
* GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.gswd:
added convertHTMLEntities for strings
* GSWeb.framework/GSWRepetition.m: added traces, fix "count" property bug, standardize ivars
* GSWeb.framework/NSObject+IVarAccess+PerformSel.m: added traces, handle underscored ivars search
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@9332 72102866-910b-0410-8b05-ffd578937521
2001-03-11 17:15:44 +00:00
|
|
|
};
|
2000-03-16 16:16:49 +00:00
|
|
|
return self;
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
-(id)initWithApp:(GSWApplication*)application
|
|
|
|
withAdaptor:(GSWAdaptor*)adaptor
|
|
|
|
withStream:(NSFileHandle*)stream
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2000-03-16 16:16:49 +00:00
|
|
|
if ((self=[self init]))
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
_application=application;
|
|
|
|
_adaptor=adaptor;
|
|
|
|
ASSIGN(_stream,stream);
|
|
|
|
_keepAlive=NO;
|
|
|
|
_isMultiThread=[adaptor isMultiThreadEnabled];
|
|
|
|
NSDebugDeepMLLog(@"info",@"isMultiThread=%d",(int)_isMultiThread);
|
|
|
|
};
|
2000-01-22 12:49:49 +00:00
|
|
|
return self;
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(void)dealloc
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
GSWLogMemC("dealloc GSWDefaultAdaptorThread");
|
|
|
|
DESTROY(_stream);
|
|
|
|
GSWLogMemC("release dates");
|
|
|
|
DESTROY(_creationDate);
|
|
|
|
DESTROY(_runDate);
|
|
|
|
DESTROY(_dispatchRequestDate);
|
|
|
|
DESTROY(_sendResponseDate);
|
2002-05-14 11:28:50 +00:00
|
|
|
DESTROY(_remoteAddress);
|
2002-03-06 23:13:23 +00:00
|
|
|
GSWLogMemC("release pool");
|
|
|
|
// DESTROY(_pool);
|
|
|
|
GSWLogMemC("super dealloc");
|
2000-01-22 12:49:49 +00:00
|
|
|
[super dealloc];
|
2002-03-06 23:13:23 +00:00
|
|
|
GSWLogMemC("dealloc GSWDefaultAdaptorThread end");
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(GSWAdaptor*)adaptor
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
return _adaptor;
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(NSAutoreleasePool*)pool
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
return _pool;
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
-(void)setPool:(NSAutoreleasePool*)pool
|
|
|
|
destroyLast:(BOOL)destroy
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
if (destroy)
|
|
|
|
{
|
|
|
|
GSWLogMemC("dealloc pool\n");
|
|
|
|
DESTROY(_pool);
|
|
|
|
GSWLogMemC("end dealloc pool\n");
|
|
|
|
};
|
|
|
|
_pool=pool;
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
-(void)run:(id)nothing
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
BOOL requestOk=NO;
|
|
|
|
NSMutableDictionary* threadDictionary=nil;
|
|
|
|
NSString* requestLine=nil;
|
|
|
|
NSDictionary* headers=nil;
|
|
|
|
NSData* data=nil;
|
|
|
|
ASSIGN(_runDate,[NSDate date]);
|
|
|
|
DESTROY(_dispatchRequestDate);
|
|
|
|
DESTROY(_sendResponseDate);
|
|
|
|
#ifdef GSWDEBUG_DEEP
|
2000-03-20 15:50:51 +00:00
|
|
|
[GSWApplication statusLogWithFormat:@"Thread run START"];
|
2001-10-27 10:27:33 +00:00
|
|
|
#endif
|
2002-03-06 23:13:23 +00:00
|
|
|
_pool=[NSAutoreleasePool new];
|
|
|
|
#ifdef GSWDEBUG_DEEP
|
2000-03-20 15:50:51 +00:00
|
|
|
[GSWApplication logWithFormat:@"pool allocated!"];
|
2001-10-27 10:27:33 +00:00
|
|
|
#endif
|
2002-03-06 23:13:23 +00:00
|
|
|
if (_isMultiThread)
|
|
|
|
{
|
|
|
|
threadDictionary=GSCurrentThreadDictionary();
|
|
|
|
[threadDictionary setObject:self
|
|
|
|
forKey:GSWThreadKey_DefaultAdaptorThread];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:[self class]
|
|
|
|
selector:@selector(threadExited:)
|
|
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
|
|
object:[NSThread currentThread]];
|
|
|
|
/*
|
|
|
|
[NotificationDispatcher addObserver:[self class]
|
|
|
|
selector:@selector(threadExited:)
|
|
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
|
|
object:[NSThread currentThread]];
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
NSDebugDeepMLLog(@"low",@"application:%@",_application);
|
2000-01-22 12:49:49 +00:00
|
|
|
|
|
|
|
NS_DURING
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
requestOk=[self readRequestReturnedRequestLine:&requestLine
|
|
|
|
returnedHeaders:&headers
|
|
|
|
returnedData:&data];
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
NS_HANDLER
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: readRequestFromStream Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
NS_ENDHANDLER;
|
2002-03-06 23:13:23 +00:00
|
|
|
if (!requestOk)
|
|
|
|
{
|
|
|
|
//TODO
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
GSWRequest* request=nil;
|
|
|
|
GSWResponse* response=nil;
|
|
|
|
NSDebugMLLog(@"info",@"GSWDefaultAdaptorThread: runWithStream requestLine=%@ headers=%@ data=%@",
|
|
|
|
requestLine,
|
|
|
|
headers,
|
|
|
|
data);
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
request=[self createRequestFromRequestLine:requestLine
|
|
|
|
headers:headers
|
|
|
|
data:data];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: createRequestFromData Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
//call application resourceRequestHandlerKey (retourne wr)
|
|
|
|
//call requets requestHandlerKey (retorune nil)
|
|
|
|
NSDebugMLLog(@"info",@"GSWDefaultAdaptorThread: run handleRequest:%@",request);
|
|
|
|
ASSIGN(_dispatchRequestDate,[NSDate date]);
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
response=[_application dispatchRequest:request];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
BOOL isApplicationRequestHandlingLocked=[_application isRequestHandlingLocked];
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: dispatchRequest Exception:%@ (%@)%s",
|
|
|
|
localException,
|
|
|
|
[localException reason],
|
|
|
|
isApplicationRequestHandlingLocked ? " Request Handling Locked !" : "");
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
if (!response)
|
|
|
|
{
|
|
|
|
response=[GSWResponse responseWithMessage:@"Application returned no response"
|
|
|
|
inContext:nil
|
|
|
|
forRequest:request];
|
|
|
|
[response _finalizeInContext:nil]; //DO Call _finalizeInContext: !
|
|
|
|
};
|
|
|
|
if (response)
|
|
|
|
{
|
|
|
|
RETAIN(response);
|
|
|
|
ASSIGN(_sendResponseDate,[NSDate date]);
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
[self sendResponse:response];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
|
|
|
localException,
|
|
|
|
[localException reason],
|
|
|
|
[localException userInfo]);
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
NSDebugMLLog(@"low",@"application:%@",_application);
|
|
|
|
AUTORELEASE(response);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
NSDebugMLog(@"GSWDefaultAdaptorThread: ThreadID=%p run end",
|
|
|
|
(void*)objc_thread_id());
|
|
|
|
NSDebugMLLog(@"low",@"application:%@",
|
|
|
|
_application);
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGObjectFnStop();
|
2001-10-27 10:27:33 +00:00
|
|
|
#ifdef DEBUG
|
2000-03-20 15:50:51 +00:00
|
|
|
[GSWApplication statusLogWithFormat:@"threadWillExit START"];
|
2001-10-27 10:27:33 +00:00
|
|
|
#endif
|
2002-03-06 23:13:23 +00:00
|
|
|
[_application threadWillExit];
|
2001-10-27 10:27:33 +00:00
|
|
|
#ifdef DEBUG
|
2000-03-20 15:50:51 +00:00
|
|
|
[GSWApplication statusLogWithFormat:@"threadWillExit STOP"];
|
2001-10-27 10:27:33 +00:00
|
|
|
#endif
|
2002-03-06 23:13:23 +00:00
|
|
|
if (_isMultiThread)
|
|
|
|
{
|
|
|
|
NSAssert([NSThread isMultiThreaded],@"No MultiThread !");
|
|
|
|
[NSThread exit]; //???
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
[self threadExited];
|
2001-10-27 10:27:33 +00:00
|
|
|
#ifdef DEBUG
|
2000-03-20 15:50:51 +00:00
|
|
|
[GSWApplication statusLogWithFormat:@"run STOP"];
|
2001-10-27 10:27:33 +00:00
|
|
|
#endif
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(void)threadExited
|
|
|
|
{
|
|
|
|
// LOGObjectFnStart();
|
2001-10-28 10:29:17 +00:00
|
|
|
// NSDebugMLLog0(@"trace",@"GSWDefaultAdaptorThread: threadExited method");
|
|
|
|
// NSDebugMLLog(@"low",@"[_defaultAdaptorThread retainCount=%d",
|
|
|
|
// (int)[self retainCount]);
|
2002-03-06 23:13:23 +00:00
|
|
|
[_adaptor adaptorThreadExited:self];
|
2000-01-22 12:49:49 +00:00
|
|
|
[self setPool:nil
|
2002-03-06 23:13:23 +00:00
|
|
|
destroyLast:YES];
|
2000-01-22 12:49:49 +00:00
|
|
|
// LOGObjectFnStop();
|
2002-03-06 23:13:23 +00:00
|
|
|
GSWLogDeepC("threadExited\n");
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
+(id)threadExited:(NSNotification*)notif
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
NSThread* thread=nil;
|
|
|
|
NSMutableDictionary* threadDict=nil;
|
|
|
|
GSWDefaultAdaptorThread* adaptorThread=nil;
|
|
|
|
GSWLogDeepC("Start threadExited:");
|
2000-01-22 12:49:49 +00:00
|
|
|
NSAssert([NSThread isMultiThreaded],@"No MultiThread !");
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugMLLog(@"low",@"notif=%@",notif);
|
|
|
|
thread=[notif object];
|
|
|
|
NSDebugMLLog(@"low",@"thread=%@",thread);
|
|
|
|
threadDict = [thread threadDictionary];
|
|
|
|
NSDebugMLLog(@"low",@"threadDict=%@",threadDict);
|
|
|
|
adaptorThread=[threadDict objectForKey:GSWThreadKey_DefaultAdaptorThread];
|
|
|
|
NSDebugMLLog(@"low",@"adaptorThread=%@",adaptorThread);
|
|
|
|
[threadDict removeObjectForKey:GSWThreadKey_DefaultAdaptorThread];
|
2000-01-22 12:49:49 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
2002-03-06 23:13:23 +00:00
|
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
|
|
object:thread];
|
|
|
|
/* [NotificationDispatcher removeObserver:self
|
|
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
|
|
object:_thread];
|
|
|
|
*/
|
|
|
|
[adaptorThread threadExited];
|
|
|
|
GSWLogDeepC("Stop threadExited:");
|
|
|
|
GSWLogDeepC("threadExited really exit");
|
2000-01-22 12:49:49 +00:00
|
|
|
return nil; //??
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
+(NSMutableArray*)completeLinesWithData:(NSMutableData*)data
|
|
|
|
returnedConsumedCount:(int*)consumedCount
|
|
|
|
returnedHeadersEndFlag:(BOOL*)headersEndFlag
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
NSMutableArray* lines=nil;
|
|
|
|
int length=0;
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGClassFnStart();
|
2002-03-06 23:13:23 +00:00
|
|
|
length=[data length];
|
|
|
|
if (length>0)
|
|
|
|
{
|
|
|
|
NSRange range=NSMakeRange(0,0);
|
|
|
|
int i=0;
|
|
|
|
char* dataBytes=(char*)[data mutableBytes];
|
|
|
|
BOOL endHeaders=NO;
|
|
|
|
while(!endHeaders && i<length)
|
|
|
|
{
|
|
|
|
if (dataBytes[i]=='\n')
|
|
|
|
{
|
|
|
|
if (range.length>0)
|
|
|
|
{
|
|
|
|
NSString* tmpString=[[[NSString alloc]initWithData:[data subdataWithRange:range]
|
|
|
|
encoding:NSASCIIStringEncoding]autorelease];
|
|
|
|
if (!lines)
|
|
|
|
lines=[NSMutableArray array];
|
|
|
|
[lines addObject:tmpString];
|
|
|
|
}
|
|
|
|
else // End Header
|
|
|
|
{
|
|
|
|
endHeaders=YES;
|
|
|
|
};
|
|
|
|
range.location=i+1;
|
|
|
|
range.length=0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
range.length++;
|
|
|
|
i++;
|
|
|
|
};
|
|
|
|
range.length=length-range.location;
|
|
|
|
if (range.length>0)
|
|
|
|
memcpy(dataBytes,dataBytes+range.location,range.length);
|
|
|
|
[data setLength:range.length];
|
|
|
|
if (consumedCount)
|
|
|
|
*consumedCount=length-range.length;
|
|
|
|
if (headersEndFlag)
|
|
|
|
*headersEndFlag=endHeaders;
|
|
|
|
};
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGClassFnStop();
|
2002-03-06 23:13:23 +00:00
|
|
|
return lines;
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
/** read request from crrent stream and put request line, headers and data in
|
|
|
|
'requestLinePtr', 'headersPtr', 'dataPtr'. Returns YES if it's OK, NO otherwise
|
|
|
|
**/
|
|
|
|
-(BOOL)readRequestReturnedRequestLine:(NSString**)requestLinePtr
|
|
|
|
returnedHeaders:(NSDictionary**)headersPtr
|
|
|
|
returnedData:(NSData**)dataPtr
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
|
|
|
BOOL ok=NO;
|
|
|
|
LOGObjectFnStart();
|
2002-03-06 23:13:23 +00:00
|
|
|
if (!_stream)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
|
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"no stream");
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
else
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2000-08-25 10:36:16 +00:00
|
|
|
#define REQUEST_METHOD__UNKNOWN 0
|
|
|
|
#define REQUEST_METHOD__GET 1
|
|
|
|
#define REQUEST_METHOD__POST 2
|
2002-03-06 23:13:23 +00:00
|
|
|
NSMutableData* pendingData=nil;
|
2001-12-11 14:35:30 +00:00
|
|
|
NSDate* maxDate=[NSDate dateWithTimeIntervalSinceNow:360]; //360s
|
|
|
|
NSData* dataBlock=nil;
|
|
|
|
int sleepTime=250; //250ms
|
|
|
|
int readenBytesNb=0;
|
|
|
|
int headersBytesNb=0;
|
|
|
|
int dataBytesNb=0;
|
|
|
|
int dataBlockLength=0;
|
|
|
|
int contentLength=-1;
|
2002-03-06 23:13:23 +00:00
|
|
|
int requestMethod=REQUEST_METHOD__UNKNOWN;
|
|
|
|
BOOL isRequestLineSetted=NO;
|
|
|
|
BOOL isDataStep=NO;
|
|
|
|
BOOL isAllDataReaden=NO;
|
|
|
|
BOOL isElapsed=NO;
|
|
|
|
NSMutableDictionary* headers=nil;
|
|
|
|
NSString* userAgent=nil;
|
|
|
|
NSString* remoteAddr=nil;
|
|
|
|
NSDebugDeepMLog0(@"dataBlock try reading");
|
2001-12-11 14:35:30 +00:00
|
|
|
do
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
dataBlock=[_stream availableDataNonBlocking];
|
2001-12-11 14:35:30 +00:00
|
|
|
dataBlockLength=[dataBlock length];
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLog(@"dataBlockLength=%i",dataBlockLength);
|
2001-12-11 14:35:30 +00:00
|
|
|
if (dataBlockLength>0)
|
|
|
|
{
|
|
|
|
readenBytesNb+=dataBlockLength;
|
2002-03-06 23:13:23 +00:00
|
|
|
if (!pendingData)
|
|
|
|
pendingData=(NSMutableData*)[NSMutableData data];
|
|
|
|
[pendingData appendData:dataBlock];
|
|
|
|
if (isDataStep)
|
|
|
|
dataBytesNb=[pendingData length];
|
2001-12-11 14:35:30 +00:00
|
|
|
else
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
int newBytesCount=0;
|
|
|
|
NSMutableArray* newLines=[GSWDefaultAdaptorThread completeLinesWithData:pendingData
|
|
|
|
returnedConsumedCount:&newBytesCount
|
|
|
|
returnedHeadersEndFlag:&isDataStep];
|
|
|
|
NSDebugDeepMLLog(@"low",@"newLines=%p",newLines);
|
|
|
|
NSDebugDeepMLLog(@"low",@"newLines=%@",newLines);
|
|
|
|
NSDebugDeepMLLog(@"low",@"isDataStep=%s newBytesCount=%d",
|
|
|
|
isDataStep ? "YES" : "NO",
|
|
|
|
newBytesCount);
|
|
|
|
headersBytesNb+=newBytesCount;
|
|
|
|
if (newLines)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
|
|
|
int i=0;
|
2002-03-06 23:13:23 +00:00
|
|
|
for(i=0;i<[newLines count];i++)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
NSString* line=[newLines objectAtIndex:i];
|
|
|
|
NSDebugDeepMLLog(@"low",@"Line=%@",line);
|
|
|
|
NSAssert([line length]>0,@"No line length");
|
|
|
|
if (!isRequestLineSetted)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
*requestLinePtr=line;
|
|
|
|
isRequestLineSetted=YES;
|
2001-12-11 14:35:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
NSString* key=nil;
|
|
|
|
NSString* value=nil;
|
|
|
|
NSArray* newValue=nil;
|
|
|
|
NSArray* prevValue=nil;
|
|
|
|
NSRange keyRange=[line rangeOfString:@":"];
|
|
|
|
if (keyRange.length<=0)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
key=line;
|
|
|
|
NSDebugDeepMLLog(@"low",@"key=%@",key);
|
|
|
|
value=[NSString string];
|
2001-12-11 14:35:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
key=[line substringToIndex:keyRange.location];
|
|
|
|
NSDebugDeepMLLog(@"low",@"location=%d key=%@",
|
|
|
|
keyRange.location,
|
|
|
|
key);
|
|
|
|
key=[[key stringByTrimmingSpaces] lowercaseString];
|
|
|
|
NSDebugDeepMLLog(@"low",@"location=%d line length=%d key=%@",
|
|
|
|
keyRange.location,
|
|
|
|
[line length],
|
|
|
|
key);
|
|
|
|
if (keyRange.location+1<[line length])
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
value=[line substringFromIndex:keyRange.location+1];
|
|
|
|
NSDebugDeepMLLog(@"low",@"value lengt=%d value=*%@*",
|
|
|
|
[value length],
|
|
|
|
value);
|
|
|
|
value=[value stringByTrimmingSpaces];
|
|
|
|
NSDebugDeepMLLog(@"low",@"value=%@",
|
|
|
|
value);
|
2001-12-11 14:35:30 +00:00
|
|
|
}
|
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
value=[NSString string];
|
|
|
|
NSDebugDeepMLLog(@"low",@"value:%@",value);
|
2001-12-11 14:35:30 +00:00
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLLog(@"low",@"key:%@ value:%@",key,value);
|
|
|
|
if ([key isEqualToString:GSWHTTPHeader_ContentLength])
|
|
|
|
contentLength=[value intValue];
|
|
|
|
else if ([key isEqualToString:GSWHTTPHeader_Method[GSWNAMES_INDEX]]
|
|
|
|
|| [key isEqualToString:GSWHTTPHeader_Method[WONAMES_INDEX]])
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
if ([value isEqualToString:GSWHTTPHeader_MethodPost])
|
|
|
|
requestMethod=REQUEST_METHOD__POST;
|
|
|
|
else if ([value isEqualToString:GSWHTTPHeader_MethodGet])
|
|
|
|
requestMethod=REQUEST_METHOD__GET;
|
2001-12-11 14:35:30 +00:00
|
|
|
else
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
NSAssert1(NO,@"Unknown method %@",value);
|
2001-12-11 14:35:30 +00:00
|
|
|
};
|
|
|
|
}
|
2002-03-06 23:13:23 +00:00
|
|
|
else if ([key isEqualToString:GSWHTTPHeader_UserAgent])
|
|
|
|
userAgent=value;
|
|
|
|
else if ([key isEqualToString:GSWHTTPHeader_RemoteAddress[GSWNAMES_INDEX]]
|
|
|
|
||[key isEqualToString:GSWHTTPHeader_RemoteAddress[WONAMES_INDEX]])
|
|
|
|
remoteAddr=value;
|
|
|
|
if ([key isEqualToString:GSWHTTPHeader_AdaptorVersion[GSWNAMES_INDEX]]
|
|
|
|
|| [key isEqualToString:GSWHTTPHeader_ServerName[GSWNAMES_INDEX]])
|
|
|
|
_requestNamingConv=GSWNAMES_INDEX;
|
|
|
|
else if ([key isEqualToString:GSWHTTPHeader_AdaptorVersion[WONAMES_INDEX]]
|
|
|
|
|| [key isEqualToString:GSWHTTPHeader_ServerName[WONAMES_INDEX]])
|
|
|
|
_requestNamingConv=WONAMES_INDEX;
|
2001-12-11 14:35:30 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
prevValue=[headers objectForKey:key];
|
|
|
|
NSDebugDeepMLLog(@"low",@"prevValue:%@",prevValue);
|
|
|
|
if (prevValue)
|
|
|
|
newValue=[prevValue arrayByAddingObject:value];
|
2001-12-11 14:35:30 +00:00
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
newValue=[NSArray arrayWithObject:value];
|
|
|
|
if (!headers)
|
|
|
|
headers=(NSMutableDictionary*)[NSMutableDictionary dictionary];
|
|
|
|
[headers setObject:newValue
|
|
|
|
forKey:key];
|
2001-12-11 14:35:30 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLog(@"requestMethod=%d",requestMethod);
|
|
|
|
dataBytesNb=[pendingData length];
|
|
|
|
if (isDataStep)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
if (requestMethod==REQUEST_METHOD__GET)
|
|
|
|
isAllDataReaden=YES;
|
|
|
|
else if (requestMethod==REQUEST_METHOD__POST)
|
|
|
|
isAllDataReaden=(dataBytesNb>=contentLength);
|
2001-12-11 14:35:30 +00:00
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
if (!isAllDataReaden)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
isElapsed=[[NSDate date]compare:maxDate]==NSOrderedDescending;
|
|
|
|
if (!isElapsed)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
|
|
|
usleep(sleepTime);//Is this the good method ? //TODOV
|
2002-03-06 23:13:23 +00:00
|
|
|
isElapsed=[[NSDate date]compare:maxDate]==NSOrderedDescending;
|
2001-12-11 14:35:30 +00:00
|
|
|
};
|
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
} while (!isAllDataReaden && !isElapsed);
|
2002-05-14 11:28:50 +00:00
|
|
|
ASSIGN(_remoteAddress,remoteAddr);
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLog(@"GSWDefaultAdaptor: userAgent=%@ remoteAddr=%@ isAllDataReaden=%s isElapsed=%s readenBytesNb=%d contentLength=%d dataBytesNb=%d headersBytesNb=%d",
|
|
|
|
userAgent,
|
|
|
|
remoteAddr,
|
|
|
|
isAllDataReaden ? "YES" : "NO",
|
|
|
|
isElapsed ? "YES" : "NO",
|
2001-12-11 14:35:30 +00:00
|
|
|
readenBytesNb,
|
|
|
|
contentLength,
|
|
|
|
dataBytesNb,
|
|
|
|
headersBytesNb);
|
2002-03-06 23:13:23 +00:00
|
|
|
ok=isAllDataReaden;
|
|
|
|
if (isAllDataReaden)
|
2001-12-11 14:35:30 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
*headersPtr=[[headers copy] autorelease];
|
|
|
|
if ([pendingData length]>0)
|
|
|
|
*dataPtr=[pendingData copy];
|
2001-12-11 14:35:30 +00:00
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
*dataPtr=nil;
|
2001-12-11 14:35:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
*requestLinePtr=nil;
|
|
|
|
*headersPtr=nil;
|
|
|
|
*dataPtr=nil;
|
2001-12-11 14:35:30 +00:00
|
|
|
};
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGObjectFnStop();
|
|
|
|
return ok;
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
/** return a created request build with 'requestLine', 'headers' and 'data' **/
|
|
|
|
-(GSWRequest*)createRequestFromRequestLine:(NSString*)requestLine
|
|
|
|
headers:(NSDictionary*)headers
|
|
|
|
data:(NSData*)data
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
GSWRequest* request=nil;
|
|
|
|
NSArray* requestLineArray=nil;
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGObjectFnStart();
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLog0(@"GSWDefaultAdaptorThread: createRequestFromData");
|
|
|
|
requestLineArray=[requestLine componentsSeparatedByString:@" "];
|
|
|
|
NSDebugDeepMLLog(@"low",@"requestLine:%@",requestLine);
|
|
|
|
NSDebugDeepMLLog(@"info",@"requestLineArray:%@",requestLineArray);
|
|
|
|
if ([requestLineArray count]!=3)
|
|
|
|
{
|
|
|
|
ExceptionRaise(@"GSWDefaultAdaptorThread",
|
|
|
|
@"bad request first line (elements count %d != 3)",
|
|
|
|
[requestLineArray count]);
|
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
NSString* method=[requestLineArray objectAtIndex:0];
|
|
|
|
NSString* url=[requestLineArray objectAtIndex:1];
|
|
|
|
NSArray* http=[[requestLineArray objectAtIndex:2] componentsSeparatedByString:@"/"];
|
|
|
|
NSDebugDeepMLLog(@"info",@"method=%@",method);
|
|
|
|
NSDebugDeepMLLog(@"info",@"url=%@",url);
|
|
|
|
NSDebugDeepMLLog(@"info",@"http=%@",http);
|
|
|
|
if ([http count]!=2)
|
|
|
|
{
|
|
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"bad request first line (HTTP)");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString* httpVersion=[http objectAtIndex:1];
|
|
|
|
/* if (isHeaderKeysEqual(method,GSWHTTPHeader_MethodPost))
|
|
|
|
{
|
|
|
|
*/
|
|
|
|
request=[[[GSWRequest alloc] initWithMethod:method
|
|
|
|
uri:url
|
|
|
|
httpVersion:httpVersion
|
|
|
|
headers:headers
|
|
|
|
content:data
|
|
|
|
userInfo:nil]
|
|
|
|
autorelease];
|
|
|
|
/* };*/
|
|
|
|
};
|
|
|
|
};
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGObjectFnStop();
|
2002-03-06 23:13:23 +00:00
|
|
|
return request;
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
/** Send response 'response' to current stream using current naming convention **/
|
2000-01-22 12:49:49 +00:00
|
|
|
-(void)sendResponse:(GSWResponse*)response
|
|
|
|
{
|
2002-05-14 11:28:50 +00:00
|
|
|
NSMutableArray* headers=nil;
|
|
|
|
NSString* anHeader=nil;
|
|
|
|
NSTimeInterval ti=0;
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGObjectFnStart();
|
2002-05-14 11:28:50 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
headers=[NSMutableArray array];
|
|
|
|
anHeader=[NSString stringWithFormat:@"GSWRunDate: %@\n",
|
|
|
|
[_runDate descriptionWithCalendarFormat:@"%d/%m/%Y %H:%M:%S.%F"
|
|
|
|
timeZone:nil
|
|
|
|
locale:nil]];
|
|
|
|
[headers addObject:anHeader];
|
|
|
|
anHeader=[NSString stringWithFormat:@"GSWDispatchRequestDate: %@\n",
|
|
|
|
[_dispatchRequestDate descriptionWithCalendarFormat:@"%d/%m/%Y %H:%M:%S.%F"
|
|
|
|
timeZone:nil
|
|
|
|
locale:nil]];
|
|
|
|
[headers addObject:anHeader];
|
|
|
|
anHeader=[NSString stringWithFormat:@"GSWSendResponseDate: %@\n",
|
|
|
|
[_sendResponseDate descriptionWithCalendarFormat:@"%d/%m/%Y %H:%M:%S.%F"
|
|
|
|
timeZone:nil
|
|
|
|
locale:nil]];
|
|
|
|
[headers addObject:anHeader];
|
|
|
|
|
|
|
|
ti=[_dispatchRequestDate timeIntervalSinceDate:_runDate];
|
|
|
|
anHeader=[NSString stringWithFormat:@"GSWDispatchRequestDate-GSWRunDate: %.3f seconds (%.1f minutes)\n",
|
|
|
|
ti,(double)(ti/60)];
|
|
|
|
|
|
|
|
[headers addObject:anHeader];
|
|
|
|
ti=[_sendResponseDate timeIntervalSinceDate:_runDate];
|
|
|
|
anHeader=[NSString stringWithFormat:@"GSWSendResponseDate-GSWRunDate: %.3f seconds (%.1f minutes)\n",
|
|
|
|
ti,(double)(ti/60)];
|
|
|
|
[headers addObject:anHeader];
|
|
|
|
ti=[_sendResponseDate timeIntervalSinceDate:_dispatchRequestDate];
|
|
|
|
anHeader=[NSString stringWithFormat:@"GSWSendResponseDate-GSWDispatchRequestDate: %.3f seconds (%.1f minutes)\n",
|
|
|
|
ti,(double)(ti/60)];
|
|
|
|
[headers addObject:anHeader];
|
|
|
|
#endif
|
2001-10-28 10:29:17 +00:00
|
|
|
[[self class]sendResponse:response
|
2002-03-06 23:13:23 +00:00
|
|
|
toStream:_stream
|
2002-05-14 11:28:50 +00:00
|
|
|
withNamingConv:_requestNamingConv
|
|
|
|
withAdditionalHeaderLines:headers
|
|
|
|
withRemoteAddress:_remoteAddress];
|
2002-03-06 23:13:23 +00:00
|
|
|
ASSIGN(_stream,nil);
|
2001-10-28 10:29:17 +00:00
|
|
|
LOGObjectFnStop();
|
|
|
|
};
|
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
/** send response 'response' to stream 'aStream' using naming convention 'requestNamingConv'
|
|
|
|
Note: the stream is closed at the end of the write
|
|
|
|
**/
|
2001-10-28 10:29:17 +00:00
|
|
|
+(void)sendResponse:(GSWResponse*)response
|
|
|
|
toStream:(NSFileHandle*)aStream
|
2002-03-06 23:13:23 +00:00
|
|
|
withNamingConv:(int)requestNamingConv
|
2002-05-14 11:28:50 +00:00
|
|
|
withAdditionalHeaderLines:(NSArray*)addHeaders
|
|
|
|
withRemoteAddress:(NSString*)remoteAddress
|
2001-10-28 10:29:17 +00:00
|
|
|
{
|
|
|
|
BOOL ok=YES;
|
|
|
|
LOGObjectFnStart();
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLLog(@"low",@"response:%p",response);
|
2000-01-22 12:49:49 +00:00
|
|
|
[response willSend];
|
|
|
|
if (response)
|
2001-10-28 10:29:17 +00:00
|
|
|
{
|
|
|
|
int headerN=0;
|
|
|
|
int headerNForKey=0;
|
2002-05-14 11:28:50 +00:00
|
|
|
NSMutableData* allResponseData=nil;//to store response
|
|
|
|
NSMutableData* responseData=(NSMutableData*)[NSMutableData data];
|
2001-10-28 10:29:17 +00:00
|
|
|
NSArray* headerKeys=[response headerKeys];
|
|
|
|
NSArray* headersForKey=nil;
|
|
|
|
NSString* key=nil;
|
|
|
|
NSString* anHeader=nil;
|
|
|
|
NSString* head=[NSString stringWithFormat:@"HTTP/%@ %d %@%@\n",
|
|
|
|
[response httpVersion],
|
|
|
|
[response status],
|
|
|
|
GSWHTTPHeader_Response_OK,
|
|
|
|
GSWHTTPHeader_Response_HeaderLineEnd[requestNamingConv]];
|
2002-03-06 23:13:23 +00:00
|
|
|
NSString* empty=[NSString stringWithString:@"\n"];
|
2002-05-14 11:28:50 +00:00
|
|
|
NSDebugDeepMLLog(@"low",@"[GSWApplication saveResponsesPath]:%@",[GSWApplication saveResponsesPath]);
|
|
|
|
if ([GSWApplication saveResponsesPath])
|
|
|
|
allResponseData=(NSMutableData*)[NSMutableData data];
|
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLLog(@"low",@"head:%@",head);
|
|
|
|
NSDebugDeepMLLog(@"low",@"responseData:%@",responseData);
|
|
|
|
[responseData appendData:[head dataUsingEncoding:NSASCIIStringEncoding]];
|
|
|
|
NSDebugDeepMLLog(@"low",@"responseData:%@",responseData);
|
|
|
|
for(headerN=0;headerN<[headerKeys count];headerN++)
|
|
|
|
{
|
|
|
|
key=[headerKeys objectAtIndex:headerN];
|
|
|
|
headersForKey=[response headersForKey:key];
|
|
|
|
for(headerNForKey=0;headerNForKey<[headersForKey count];headerNForKey++)
|
|
|
|
{
|
|
|
|
anHeader=[NSString stringWithFormat:@"%@: %@\n",
|
|
|
|
key,
|
|
|
|
[headersForKey objectAtIndex:headerNForKey]];
|
|
|
|
[responseData appendData:[anHeader dataUsingEncoding:NSASCIIStringEncoding]];
|
|
|
|
NSDebugDeepMLLog(@"low",@"anHeader:%@",anHeader);
|
|
|
|
NSDebugDeepMLLog(@"low",@"responseData:%@",responseData);
|
|
|
|
};
|
|
|
|
};
|
2002-05-14 11:28:50 +00:00
|
|
|
for(headerN=0;headerN<[addHeaders count];headerN++)
|
|
|
|
[responseData appendData:[[addHeaders objectAtIndex:headerN]dataUsingEncoding:NSASCIIStringEncoding]];
|
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
// NSDebugDeepMLLog(@"low",@"cl:%@",cl);
|
|
|
|
NSDebugDeepMLLog(@"low",@"empty:%@",empty);
|
|
|
|
// [responseData appendData:[cl dataUsingEncoding:NSASCIIStringEncoding]];
|
|
|
|
NSDebugDeepMLLog(@"low",@"responseData:%@",responseData);
|
|
|
|
[responseData appendData:[empty dataUsingEncoding:NSASCIIStringEncoding]];
|
|
|
|
NSDebugDeepMLLog(@"low",@"responseData:%@",responseData);
|
|
|
|
|
2002-05-14 11:28:50 +00:00
|
|
|
[allResponseData appendData:responseData];
|
2002-03-06 23:13:23 +00:00
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
[aStream writeData:responseData];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
ok=NO;
|
2002-05-14 11:28:50 +00:00
|
|
|
LOGException(@"GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
2002-03-06 23:13:23 +00:00
|
|
|
localException,[localException reason]);
|
2002-05-14 11:28:50 +00:00
|
|
|
NSDebugMLog(@"EXCEPTION GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
[GSWApplication statusLogWithFormat:@"\nException while sending response\n"];
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
if (ok && [[response content] length]>0)
|
|
|
|
{
|
|
|
|
[responseData setLength:[[response content] length]];
|
|
|
|
[responseData setData:[response content]];
|
|
|
|
|
|
|
|
NSDebugDeepMLLog(@"low",@"[response content]:%@",[response content]);
|
|
|
|
NSDebugDeepMLLog(@"low",@"[[response content] length]=%d",[[response content] length]);
|
|
|
|
NSDebugDeepMLLog(@"low",@"Response content String NSASCIIStringEncoding:%@",
|
|
|
|
[[[NSString alloc] initWithData:[response content]
|
|
|
|
encoding:NSASCIIStringEncoding]
|
|
|
|
autorelease]);
|
|
|
|
NSDebugDeepMLLog(@"low",@"Response content String :%@",
|
|
|
|
[[[NSString alloc] initWithData:[response content]
|
|
|
|
encoding:NSISOLatin1StringEncoding]
|
|
|
|
autorelease]);
|
2002-05-14 11:28:50 +00:00
|
|
|
|
|
|
|
[allResponseData appendData:responseData];
|
2001-10-28 10:29:17 +00:00
|
|
|
NS_DURING
|
|
|
|
{
|
2001-12-11 14:35:30 +00:00
|
|
|
[aStream writeData:responseData];
|
2002-05-14 11:28:50 +00:00
|
|
|
[GSWApplication statusLogWithFormat:@"\nResponse Sent\n"];
|
2001-10-28 10:29:17 +00:00
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
ok=NO;
|
2002-05-14 11:28:50 +00:00
|
|
|
LOGException(@"GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
NSDebugMLog(@"EXCEPTION GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
[GSWApplication statusLogWithFormat:@"\nException while sending response\n"];
|
2001-10-28 10:29:17 +00:00
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLLog0(@"info",@"Response content Written");
|
|
|
|
};
|
2002-05-14 11:28:50 +00:00
|
|
|
if (allResponseData)
|
|
|
|
[self saveResponse:response
|
|
|
|
data:allResponseData
|
|
|
|
remoteAddress:remoteAddress];
|
2002-03-06 23:13:23 +00:00
|
|
|
};
|
|
|
|
[aStream closeFile];
|
2000-01-22 12:49:49 +00:00
|
|
|
LOGObjectFnStop();
|
|
|
|
};
|
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
/** Returns thread creation date **/
|
2001-10-28 10:29:17 +00:00
|
|
|
-(NSDate*)creationDate
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
return _creationDate;
|
2001-10-28 10:29:17 +00:00
|
|
|
};
|
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
/** Returns YES if the thread has expired (timed out) **/
|
2001-10-28 10:29:17 +00:00
|
|
|
-(BOOL)isExpired
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
BOOL isExpired=(fabs([_creationDate timeIntervalSinceNow])>ADAPTOR_THREAD_TIME_OUT);
|
|
|
|
NSDebugDeepMLog(@"EXPIRED %@ %f isExpired=%d\n",//connectOK=%d isExpired=%d\n",
|
|
|
|
_creationDate,
|
|
|
|
[_creationDate timeIntervalSinceNow],
|
|
|
|
//(int)(((UnixFileHandle*)stream)->connectOK),
|
|
|
|
isExpired);
|
2001-10-28 10:29:17 +00:00
|
|
|
return isExpired;
|
|
|
|
};
|
|
|
|
|
|
|
|
-(NSFileHandle*)stream
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
return _stream;
|
2001-10-28 10:29:17 +00:00
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
|
2001-10-28 10:29:17 +00:00
|
|
|
+(void)sendRetryLasterResponseToStream:(NSFileHandle*)stream
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
GSWResponse* response=nil;
|
2001-10-28 10:29:17 +00:00
|
|
|
NSAutoreleasePool* pool=nil;
|
|
|
|
pool=[NSAutoreleasePool new];
|
2002-03-06 23:13:23 +00:00
|
|
|
LOGDEEPClassFnStart();
|
2001-10-28 10:29:17 +00:00
|
|
|
response=[GSWResponse responseWithMessage:@"Temporary unavailable"
|
2002-03-06 23:13:23 +00:00
|
|
|
inContext:nil
|
|
|
|
forRequest:nil
|
|
|
|
forceFinalize:YES];
|
|
|
|
[response setStatus:503];//503=Service Unavailable
|
|
|
|
NSDebugDeepMLog0(@"sendResponse:\n");
|
|
|
|
[self sendResponse:response
|
|
|
|
toStream:stream
|
2002-05-14 11:28:50 +00:00
|
|
|
withNamingConv:GSWNAMES_INDEX
|
|
|
|
withAdditionalHeaderLines:nil
|
|
|
|
withRemoteAddress:nil];
|
2002-03-06 23:13:23 +00:00
|
|
|
LOGDEEPClassFnStop();
|
|
|
|
DESTROY(pool);
|
|
|
|
};
|
|
|
|
|
|
|
|
+(void)sendConnectionRefusedResponseToStream:(NSFileHandle*)stream
|
|
|
|
withMessage:(NSString*)message
|
|
|
|
{
|
|
|
|
GSWResponse* response=nil;
|
|
|
|
NSAutoreleasePool* pool=nil;
|
|
|
|
pool=[NSAutoreleasePool new];
|
|
|
|
LOGDEEPClassFnStart();
|
|
|
|
response=[GSWResponse responseWithMessage:message
|
|
|
|
inContext:nil
|
2001-10-28 10:29:17 +00:00
|
|
|
forRequest:nil
|
|
|
|
forceFinalize:YES];
|
|
|
|
[response setStatus:503];//503=Service Unavailable
|
2002-03-06 23:13:23 +00:00
|
|
|
NSDebugDeepMLog0(@"sendResponse:\n");
|
2001-10-28 10:29:17 +00:00
|
|
|
[self sendResponse:response
|
|
|
|
toStream:stream
|
2002-05-14 11:28:50 +00:00
|
|
|
withNamingConv:GSWNAMES_INDEX
|
|
|
|
withAdditionalHeaderLines:nil
|
|
|
|
withRemoteAddress:nil];
|
2002-03-06 23:13:23 +00:00
|
|
|
LOGDEEPClassFnStop();
|
2001-10-28 10:29:17 +00:00
|
|
|
DESTROY(pool);
|
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
|
2002-05-14 11:28:50 +00:00
|
|
|
+(NSString*)savedResponseFilenameWithResponse:(GSWResponse*)response
|
|
|
|
remoteAddress:(NSString*)remoteAddress
|
|
|
|
{
|
|
|
|
NSString* dateString=[[NSCalendarDate calendarDate] descriptionWithCalendarFormat:@"%Y-%m-%d_%H-%M-%S.%F"];
|
|
|
|
return [NSString stringWithFormat:@"GSWeb-%@-Response-%@-%@-%p",
|
|
|
|
[[GSWApplication application]name],
|
|
|
|
dateString,
|
|
|
|
(remoteAddress ? remoteAddress : @"unknown"),
|
|
|
|
response];
|
|
|
|
};
|
|
|
|
|
|
|
|
+(void)saveResponse:(GSWResponse*)response
|
|
|
|
data:(NSData*)allResponseData
|
|
|
|
remoteAddress:(NSString*)remoteAddress
|
|
|
|
{
|
|
|
|
NSString* path=nil;
|
|
|
|
LOGObjectFnStart();
|
|
|
|
path=[GSWApplication saveResponsesPath];
|
|
|
|
if (path)
|
|
|
|
{
|
|
|
|
path=[path stringByAppendingPathComponent:[self savedResponseFilenameWithResponse:response
|
|
|
|
remoteAddress:remoteAddress]];
|
|
|
|
NSDebugDeepMLog(@"path=%@:",path);
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
NSString* str=[[[NSString alloc]initWithData:allResponseData
|
|
|
|
encoding:NSASCIIStringEncoding]autorelease];
|
|
|
|
[str writeToFile:path
|
|
|
|
atomically:NO];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
NSDebugMLog(@"EXCEPTION GSWDefaultAdaptorThread: Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
}
|
|
|
|
LOGObjectFnStop();
|
|
|
|
}
|
2002-03-06 23:13:23 +00:00
|
|
|
|
2002-05-14 11:28:50 +00:00
|
|
|
@end
|