2002-03-06 23:13:23 +00:00
|
|
|
/** GSWDefaultAdaptorThread.m - <title>GSWeb: Class GSWDefaultAdaptorThread</title>
|
2003-02-01 19:07:25 +00:00
|
|
|
|
2004-03-03 08:52:13 +00:00
|
|
|
Copyright (C) 1999-2004 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>
|
2003-03-21 14:32:57 +00:00
|
|
|
Date: Feb 1999
|
2002-03-06 23:13:23 +00:00
|
|
|
|
|
|
|
$Revision$
|
|
|
|
$Date$
|
2003-01-19 15:33:07 +00:00
|
|
|
$Id$
|
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
|
|
|
|
2003-03-21 14:32:57 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
RCS_ID("$Id$")
|
2000-01-22 12:49:49 +00:00
|
|
|
|
2003-01-22 Manuel Guesdon <mguesdon@orange-concept.com>
* GSWeb.framework/Makefile.postamble:
o use $(LN_S) -f in install-WO-headers
o added $(MKDIRS) $(GNUSTEP_HEADERS)/$(GSWExtensions_wo_HEADER_FILES_INSTALL_DIR);
* GSWExtensionsGSW.framework/Makefile.postamble: use $(LN_S) -f in install-WO-headers
2003-01-20 David Ayers <d.ayers@inode.at>
* Makefile.postamble
o added support for make gswnames=(gsw,wo,all) (corrected
typo)
o reinserted support for $(INSTALL_ROOT_DIR)
* config.h.in
o added HAVE_GDL2
* configure
o added support for --with-gswnames=(gsw,wo,all)
o set LIBWRAP during configure
o added config.mak.in as configurable file
* configure.ac
o (see configure)
* config.mak: removed (replaced by config.mak.in)
* config.mak.in: new file
o added support for make gswnames=(gsw,wo,all)
* gsweb.make.in
o add GSANTLR as auxiliary lib
o add gsweb libs to AUXILIARY_GSW_LIBS
o include correct extensions for GSW/WO-libs
* gsweb_wo.make: new file
* GSWeb/GSWConfig.h
o changed support for GSWEB_WONAMES
o conditionally import file GSWWOCompatiblity
here instead of in GSWeb.h
* GSWeb/GNUMakefile
o added support for make gswnames=(gsw,wo,all)
o ensure each lib gets built with its own object files
o removed deactivated framework extension determination code
o removed reference to unused files:
GSWeb.m, GSWWOCompatibility.m
o added references to new files:
GSWExtenstions.h, GSWExtWOCompatibility.h
o added support to create WO header files
* GSWeb/Makefile.postamble
o changed support to install WO header files according to
make gswnames=(gsw,wo,all)
o remove Makefile.preamble during distclean
* GSWeb/Makefile.preamble.in
o fixed typo
* GSWeb/GSWeb.h
o moved GSW/WO-Name-mapping to GSWWOCompatibility.h
o replaced inclusions of
<GSWeb/file.h> with "file.h"
* GSWeb/GSWeb.m: removed
* GSWeb/GSWWOCompatibility.h
o changed GSWEB_WONAMES handling
o removed hybrid namespace WO subclasses
o moved & reorganized GSW/WO-Name-mapping from GSWeb.h
o inlucluded missing GSW/WO-Name-mappings
* GSWeb/GSWWOCompatibility.m: removed
* GSWeb/*.m
o replaced inclusions of
<GSWeb/file.h> with "file.h"
* GSWeb/GSWApplication.m
o remove special GSW/WO handling of WOApp
* GSWeb/WebObject/WO*: removed
* GSWeb/WebObject/WebObjects
o replaced inclusions of
<GSWeb/file.h> with "file.h"
* GSWExtensions/GNUMakefile
o added support for make gswnames=(gsw,wo,all)
o ensure each lib gets built with its own object files
o removed deactivated framework extension determination code
o added references to new files:
GSWExtenstions.h, GSWExtWOCompatibility.h
o added support to create WO header files
* GSWExtensions/Makefile.preamble
o let gnustep make figure whether to link agains debug libs
o added support for make gswnames=(gsw,wo,all)
* GSWExtensions/Makefile.postamble
o changed support to install WO header files according to
make gswnames=(gsw,wo,all)
* GSWExtensions/*.m
o replaced inclusions of
<GSWeb/GSWeb.h> with "GSWExtWOCompatibility.h"
o replaces inclusions of
<GSWExtensions/file.h> with "file.h"
* GSWExtensions/GSWExtensions.h: new file
* GSWExtensions/WOExtensions.h: new file
* GSWExtensions/GSWExtWOCompatibility.h: new file
* GSWExtensionsGSW/GNUMakefile
o added support for make gswnames=(gsw,wo,all)
o ensure each lib gets built with its own object files
o removed deactivated framework extension determination code
o added references to new file GSWExtGSWWOCompatibility.h
o added support to create WO header files
* GSWExtensionsGSW/Makefile.pramble
o let gnustep make figure whether to link agains debug libs
o added support for make gswnames=(gsw,wo,all)
o removed GSWExtensions from ADDITIONAL_LIB_DIRS
* GSWExtensionsGSW/*.m
o replaced inclusions of
<GSWeb/GSWeb.h> with "GSWExtGSWWOCompatibility.h"
* GSWExtensions/GSWExtGSWWOCompatibility.h: new file
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@15675 72102866-910b-0410-8b05-ffd578937521
2003-01-22 12:24:26 +00:00
|
|
|
#include "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"
|
2004-12-31 14:33:16 +00:00
|
|
|
#define ADAPTOR_THREAD_TIME_OUT (5*60) // in seconds. threads waiting for more than 5 minutes are not processed
|
2001-10-28 10:29:17 +00:00
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
static SEL objectAtIndexSEL=NULL;
|
|
|
|
static SEL appendDataSEL=NULL;
|
|
|
|
static NSData* lineFeedData=nil;
|
2000-01-22 12:49:49 +00:00
|
|
|
//====================================================================
|
|
|
|
@implementation GSWDefaultAdaptorThread
|
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (self == [GSWDefaultAdaptorThread class])
|
|
|
|
{
|
|
|
|
objectAtIndexSEL=@selector(objectAtIndex:);
|
|
|
|
appendDataSEL=@selector(appendData:);
|
|
|
|
ASSIGN(lineFeedData,([[NSString stringWithString:@"\n"]
|
|
|
|
dataUsingEncoding:NSASCIIStringEncoding]));
|
|
|
|
};
|
|
|
|
};
|
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
|
|
|
{
|
2004-12-31 14:33:16 +00:00
|
|
|
_creationTS=GSWTime_now();
|
2002-03-06 23:13:23 +00:00
|
|
|
_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];
|
|
|
|
};
|
2000-01-22 12:49:49 +00:00
|
|
|
return self;
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(void)dealloc
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
DESTROY(_stream);
|
2002-05-14 11:28:50 +00:00
|
|
|
DESTROY(_remoteAddress);
|
2005-12-17 16:44:58 +00:00
|
|
|
DESTROY(_pool);
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
[super dealloc];
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(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
|
|
|
{
|
2007-04-13 18:32:02 +00:00
|
|
|
if (destroy) {
|
2002-03-06 23:13:23 +00:00
|
|
|
DESTROY(_pool);
|
2007-04-13 18:32:02 +00:00
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
_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;
|
2004-03-03 08:52:13 +00:00
|
|
|
|
2005-12-17 16:44:58 +00:00
|
|
|
DESTROY(_pool);
|
2004-03-03 08:52:13 +00:00
|
|
|
_pool=[NSAutoreleasePool new];
|
|
|
|
#ifdef GSWDEBUG_DEEP
|
2005-04-05 15:54:24 +00:00
|
|
|
[GSWApplication logString:@"pool allocated!"];
|
2004-03-03 08:52:13 +00:00
|
|
|
#endif
|
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
_runTS=GSWTime_now();
|
|
|
|
_beginDispatchRequestTS=GSWTime_zero();
|
|
|
|
_endDispatchRequestTS=GSWTime_zero();
|
|
|
|
_sendResponseTS=GSWTime_zero();
|
2004-03-03 08:52:13 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
#ifdef GSWDEBUG_DEEP
|
2005-04-05 15:54:24 +00:00
|
|
|
[GSWApplication statusLogString:@"Thread run START"];
|
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:)
|
2004-02-26 16:26:31 +00:00
|
|
|
name:NSThreadWillExitNotification
|
2002-03-06 23:13:23 +00:00
|
|
|
object:[NSThread currentThread]];
|
|
|
|
/*
|
|
|
|
[NotificationDispatcher addObserver:[self class]
|
|
|
|
selector:@selector(threadExited:)
|
2004-02-26 16:26:31 +00:00
|
|
|
name:NSThreadWillExitNotification
|
2002-03-06 23:13:23 +00:00
|
|
|
object:[NSThread currentThread]];
|
|
|
|
*/
|
|
|
|
};
|
2000-01-22 12:49:49 +00:00
|
|
|
NS_DURING
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
requestOk=[self readRequestReturnedRequestLine:&requestLine
|
|
|
|
returnedHeaders:&headers
|
2007-04-13 18:32:02 +00:00
|
|
|
returnedData:&data];
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
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;
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
request=[self createRequestFromRequestLine:requestLine
|
|
|
|
headers:headers
|
|
|
|
data:data];
|
2007-06-22 23:48:25 +00:00
|
|
|
//NSLog(@"%s %@",__PRETTY_FUNCTION__, request);
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: createRequestFromData Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
//call application resourceRequestHandlerKey (retourne wr)
|
|
|
|
//call requets requestHandlerKey (retorune nil)
|
2004-12-31 14:33:16 +00:00
|
|
|
_beginDispatchRequestTS=GSWTime_now();
|
2002-03-06 23:13:23 +00:00
|
|
|
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;
|
2004-12-31 14:33:16 +00:00
|
|
|
_endDispatchRequestTS=GSWTime_now();
|
2002-03-06 23:13:23 +00:00
|
|
|
if (!response)
|
|
|
|
{
|
|
|
|
response=[GSWResponse responseWithMessage:@"Application returned no response"
|
|
|
|
inContext:nil
|
|
|
|
forRequest:request];
|
|
|
|
[response _finalizeInContext:nil]; //DO Call _finalizeInContext: !
|
|
|
|
};
|
|
|
|
if (response)
|
|
|
|
{
|
|
|
|
RETAIN(response);
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
[self sendResponse:response];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
|
|
|
localException,
|
|
|
|
[localException reason],
|
|
|
|
[localException userInfo]);
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
AUTORELEASE(response);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
[_application threadWillExit];
|
|
|
|
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];
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(void)threadExited
|
|
|
|
{
|
2002-03-06 23:13:23 +00:00
|
|
|
[_adaptor adaptorThreadExited:self];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
[self setPool:nil
|
2002-03-06 23:13:23 +00:00
|
|
|
destroyLast:YES];
|
2005-12-17 16:44:58 +00:00
|
|
|
[GSWApp debugAdaptorThreadExited];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
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;
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
NSAssert([NSThread isMultiThreaded],@"No MultiThread !");
|
2002-03-06 23:13:23 +00:00
|
|
|
thread=[notif object];
|
|
|
|
threadDict = [thread threadDictionary];
|
|
|
|
adaptorThread=[threadDict objectForKey:GSWThreadKey_DefaultAdaptorThread];
|
|
|
|
[threadDict removeObjectForKey:GSWThreadKey_DefaultAdaptorThread];
|
2000-01-22 12:49:49 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
2004-02-26 16:26:31 +00:00
|
|
|
name:NSThreadWillExitNotification
|
2002-03-06 23:13:23 +00:00
|
|
|
object:thread];
|
|
|
|
/* [NotificationDispatcher removeObserver:self
|
2004-02-26 16:26:31 +00:00
|
|
|
name:NSThreadWillExitNotification
|
2002-03-06 23:13:23 +00:00
|
|
|
object:_thread];
|
|
|
|
*/
|
|
|
|
[adaptorThread threadExited];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
return nil; //??
|
|
|
|
};
|
|
|
|
|
2007-04-13 18:32:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
NSMutableArray* unpackData(NSMutableData* data)
|
2000-01-22 12:49:49 +00:00
|
|
|
{
|
2007-04-13 18:32:02 +00:00
|
|
|
NSMutableArray* lines = [NSMutableArray new];
|
|
|
|
int length = [data length];
|
|
|
|
|
|
|
|
if (length>0) {
|
2002-03-06 23:13:23 +00:00
|
|
|
NSRange range=NSMakeRange(0,0);
|
|
|
|
int i=0;
|
2007-04-13 18:32:02 +00:00
|
|
|
int lastIndex=0;
|
|
|
|
NSString * tmpString = nil;
|
2002-03-06 23:13:23 +00:00
|
|
|
char* dataBytes=(char*)[data mutableBytes];
|
|
|
|
BOOL endHeaders=NO;
|
|
|
|
while(!endHeaders && i<length)
|
|
|
|
{
|
2007-04-13 18:32:02 +00:00
|
|
|
if (dataBytes[i]=='\n') {
|
|
|
|
range.location=lastIndex;
|
|
|
|
range.length=(i-range.location);
|
|
|
|
lastIndex = i+1;
|
|
|
|
|
|
|
|
if (range.length > 1) {
|
|
|
|
tmpString=[[NSString alloc] initWithData: [data subdataWithRange:range]
|
|
|
|
encoding:NSASCIIStringEncoding];
|
|
|
|
|
|
|
|
[lines addObject: [tmpString stringByTrimmingSpaces]];
|
|
|
|
[tmpString release];
|
|
|
|
} else {
|
|
|
|
endHeaders=YES;
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
|
|
|
i++;
|
2007-04-13 18:32:02 +00:00
|
|
|
} else {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [lines autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSDictionary*) unpackHeaders:(NSArray*) lines
|
|
|
|
{
|
|
|
|
NSMutableDictionary* headers = [NSMutableDictionary dictionary];
|
|
|
|
int count = 0;
|
|
|
|
int i = 0;
|
|
|
|
NSArray* prevValue = nil;
|
|
|
|
|
|
|
|
if ((lines) && ([lines count] > 1)) {
|
|
|
|
count = [lines count];
|
|
|
|
for (i=1;i<count-1;i++) {
|
|
|
|
NSString * tmpLine = [lines objectAtIndex:i];
|
|
|
|
NSArray * components = [tmpLine componentsSeparatedByString:@": "];
|
|
|
|
NSString * value = nil;
|
|
|
|
NSArray * newValue = nil;
|
|
|
|
NSString * key = nil;
|
|
|
|
|
|
|
|
if ((components) && ([components count] == 2)) {
|
|
|
|
value = [components objectAtIndex:1];
|
|
|
|
key = [components objectAtIndex:0];
|
|
|
|
key = [[key stringByTrimmingSpaces] lowercaseString];
|
|
|
|
|
|
|
|
if ([key isEqualToString:GSWHTTPHeader_AdaptorVersion[GSWNAMES_INDEX]]
|
|
|
|
|| [key isEqualToString:GSWHTTPHeader_ServerName[GSWNAMES_INDEX]]) {
|
|
|
|
_requestNamingConv=GSWNAMES_INDEX;
|
|
|
|
goto keyDone;
|
|
|
|
}
|
|
|
|
if ([key isEqualToString:GSWHTTPHeader_AdaptorVersion[WONAMES_INDEX]]
|
|
|
|
|| [key isEqualToString:GSWHTTPHeader_ServerName[WONAMES_INDEX]]) {
|
|
|
|
_requestNamingConv=WONAMES_INDEX;
|
|
|
|
goto keyDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
keyDone:
|
|
|
|
|
|
|
|
prevValue=[headers objectForKey:key];
|
|
|
|
if (prevValue) {
|
|
|
|
newValue=[prevValue arrayByAddingObject:value];
|
|
|
|
} else {
|
|
|
|
newValue=[NSArray arrayWithObject:value];
|
|
|
|
}
|
|
|
|
|
|
|
|
[headers setObject: newValue
|
|
|
|
forKey: key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return headers;
|
|
|
|
}
|
|
|
|
|
2007-06-22 23:48:25 +00:00
|
|
|
- (NSData*) _readPostDataMultipart:(BOOL) multip boundary:(NSString*) boundary
|
2007-06-22 16:12:16 +00:00
|
|
|
{
|
|
|
|
|
2007-06-22 23:48:25 +00:00
|
|
|
#define UPLOAD_LIMIT 1024*1024*10 // 10 MB
|
|
|
|
#define TIME_LIMIT 15 // seconds
|
|
|
|
|
|
|
|
time_t starttime, now;
|
|
|
|
BOOL crSeen = NO;
|
|
|
|
BOOL nlSeen = NO;
|
|
|
|
BOOL crnlSeen = NO;
|
|
|
|
int crlfCount = 1;
|
|
|
|
int tmpPos = 0;
|
|
|
|
unsigned bytesSinceNewLine = 0;
|
|
|
|
BOOL isElapsed = NO;
|
|
|
|
NSMutableData* allMimeData = (NSMutableData*)[NSMutableData data];
|
|
|
|
NSData* boundaryData = nil;
|
|
|
|
unsigned boundaryLen = NSNotFound;
|
|
|
|
|
|
|
|
char buffer[5];
|
|
|
|
char buffer1[100];
|
2007-06-22 16:12:16 +00:00
|
|
|
|
2007-06-22 23:48:25 +00:00
|
|
|
if (multip) {
|
|
|
|
NSString * totalString = [[@"--" stringByAppendingString: boundary] stringByAppendingString:@"--"];
|
|
|
|
boundaryLen = [totalString length];
|
|
|
|
boundaryData = [totalString dataUsingEncoding: NSUTF8StringEncoding];
|
|
|
|
}
|
2007-06-22 16:12:16 +00:00
|
|
|
time(&starttime);
|
|
|
|
|
2007-06-22 23:48:25 +00:00
|
|
|
NS_DURING
|
|
|
|
|
|
|
|
while ((! isElapsed) && ([allMimeData length] <= UPLOAD_LIMIT) && (crlfCount > 0)) {
|
|
|
|
NSData* dataBlock = [_stream readDataOfLength:1];
|
|
|
|
if ((dataBlock) && ([dataBlock length])) {
|
|
|
|
[dataBlock getBytes:buffer];
|
|
|
|
if (buffer[0] == 0xd) {
|
|
|
|
crSeen = YES;
|
|
|
|
time(&now);
|
|
|
|
isElapsed = ((now - starttime) > TIME_LIMIT);
|
|
|
|
} else {
|
|
|
|
if (buffer[0] == 0xa) {
|
|
|
|
nlSeen = YES;
|
|
|
|
} else {
|
|
|
|
crSeen = NO;
|
|
|
|
nlSeen = NO;
|
|
|
|
crnlSeen = NO;
|
|
|
|
bytesSinceNewLine++;
|
|
|
|
}
|
2007-06-22 16:12:16 +00:00
|
|
|
}
|
2007-06-22 23:48:25 +00:00
|
|
|
|
|
|
|
if (crlfCount > 0) {
|
|
|
|
[allMimeData appendData:dataBlock];
|
|
|
|
// printf("%c (%x)\n", buffer[0], buffer[0]); // cr (0d) + nl (0a)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (crSeen && nlSeen) {
|
|
|
|
crnlSeen = YES;
|
|
|
|
crSeen = NO;
|
|
|
|
nlSeen = NO;
|
|
|
|
|
|
|
|
if (boundaryLen == bytesSinceNewLine) {
|
|
|
|
NSRange range = NSMakeRange([allMimeData length]-2-boundaryLen, boundaryLen);
|
|
|
|
NSData * tmpData = [allMimeData subdataWithRange: range];
|
|
|
|
|
|
|
|
if ([tmpData isEqual: boundaryData]) {
|
|
|
|
crlfCount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tmpPos = [allMimeData length];
|
|
|
|
if (multip == NO) {
|
|
|
|
crlfCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bytesSinceNewLine = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_HANDLER
|
|
|
|
NSLog(@"%@", [localException reason]);
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
|
|
|
if ([allMimeData length] == 0) {
|
|
|
|
return nil;
|
2007-06-22 16:12:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return allMimeData;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2007-04-13 18:32:02 +00:00
|
|
|
NSMutableData* pendingData=nil;
|
|
|
|
NSData* dataBlock=nil;
|
|
|
|
NSData* dataBlock2=nil;
|
|
|
|
int totalBytes=0;
|
|
|
|
int tries=0;
|
|
|
|
int dataBlockLength=0;
|
|
|
|
int contentLength=-1;
|
|
|
|
BOOL newLineSeen=NO;
|
|
|
|
BOOL allDataRead=NO;
|
|
|
|
BOOL isElapsed=NO;
|
|
|
|
BOOL headersDone=NO;
|
|
|
|
NSArray *listItems = nil;
|
|
|
|
NSMutableData * allMimeData = nil;
|
|
|
|
NSDictionary * headerDict = nil;
|
|
|
|
|
|
|
|
#define MAX_HEADER_BYTES 1000
|
|
|
|
|
|
|
|
time_t starttime, now;
|
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
if (!_stream)
|
2007-04-13 18:32:02 +00:00
|
|
|
{
|
|
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"no stream");
|
|
|
|
}
|
|
|
|
|
|
|
|
time(&starttime);
|
|
|
|
struct timeval timeout;
|
|
|
|
|
|
|
|
timeout.tv_sec = 5;
|
|
|
|
timeout.tv_usec = 0;
|
|
|
|
|
|
|
|
setsockopt([_stream fileDescriptor], SOL_SOCKET, SO_RCVTIMEO, &timeout,sizeof(timeout));
|
|
|
|
|
|
|
|
while (((allDataRead == NO) && (isElapsed == NO)) && (totalBytes < MAX_HEADER_BYTES)) {
|
|
|
|
char buffer[5];
|
|
|
|
|
|
|
|
dataBlock= [_stream readDataOfLength:1];
|
|
|
|
dataBlockLength=[dataBlock length];
|
|
|
|
|
|
|
|
if (dataBlockLength>0) {
|
|
|
|
[dataBlock getBytes:buffer];
|
|
|
|
|
|
|
|
if ((buffer[0] == 0xa)) {
|
|
|
|
if ((newLineSeen)) {
|
|
|
|
headersDone = YES;
|
|
|
|
}
|
|
|
|
newLineSeen = YES;
|
|
|
|
} else {
|
|
|
|
if ((buffer[0] != 0xd)) { // cr
|
|
|
|
newLineSeen = NO;
|
|
|
|
}
|
2001-12-11 14:35:30 +00:00
|
|
|
}
|
2007-04-13 18:32:02 +00:00
|
|
|
buffer[1] = '\0';
|
|
|
|
|
|
|
|
if (headersDone) {
|
|
|
|
NSArray * myArray = nil;
|
|
|
|
|
|
|
|
listItems = unpackData(pendingData);
|
|
|
|
headerDict = [self unpackHeaders:listItems];
|
|
|
|
*headersPtr = headerDict;
|
|
|
|
myArray = [headerDict objectForKey:@"content-length"];
|
|
|
|
|
|
|
|
if ((myArray) && ([myArray count])) {
|
|
|
|
contentLength = [[myArray objectAtIndex:0] intValue];
|
2007-06-22 16:12:16 +00:00
|
|
|
//
|
2007-04-13 18:32:02 +00:00
|
|
|
if (contentLength > 0) {
|
|
|
|
if (!allMimeData) {
|
|
|
|
allMimeData = (NSMutableData*)[NSMutableData data];
|
|
|
|
}
|
|
|
|
while ((contentLength > 0) && (! isElapsed)) {
|
|
|
|
dataBlock2 = [_stream readDataOfLength: contentLength];
|
|
|
|
[allMimeData appendData:dataBlock2];
|
|
|
|
contentLength = contentLength-[dataBlock2 length];
|
|
|
|
time(&now);
|
|
|
|
isElapsed = ((now - starttime) > 30);
|
|
|
|
}
|
|
|
|
}
|
2007-06-22 16:12:16 +00:00
|
|
|
//
|
|
|
|
} else { // no content length info
|
2007-06-22 23:48:25 +00:00
|
|
|
myArray = [headerDict objectForKey:@"content-type"];
|
|
|
|
if ((myArray) && ([myArray count])) {
|
|
|
|
NSString * multiStr = [myArray objectAtIndex:0];
|
|
|
|
BOOL multipart = ([multiStr hasPrefix:@"multipart/form-data;"]);
|
|
|
|
NSString * boundStr = nil;
|
|
|
|
if (multipart) {
|
|
|
|
boundStr = [multiStr substringFromIndex:30];
|
|
|
|
}
|
|
|
|
|
|
|
|
allMimeData = [self _readPostDataMultipart: multipart boundary: boundStr];
|
|
|
|
}
|
2007-04-13 18:32:02 +00:00
|
|
|
}
|
|
|
|
allDataRead = YES;
|
|
|
|
} else {
|
|
|
|
totalBytes+=dataBlockLength;
|
|
|
|
if (!pendingData)
|
|
|
|
pendingData=(NSMutableData*)[NSMutableData data];
|
|
|
|
[pendingData appendData:dataBlock];
|
|
|
|
tries=0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (((totalBytes>2) && (tries>3)) && (newLineSeen)) {
|
|
|
|
allDataRead = YES;
|
|
|
|
}
|
|
|
|
tries++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allMimeData) {
|
|
|
|
*dataPtr = [[allMimeData retain] autorelease];
|
|
|
|
}
|
|
|
|
|
|
|
|
// check headers for contents?
|
|
|
|
if (!headerDict) {
|
|
|
|
*requestLinePtr=nil;
|
|
|
|
*headersPtr=nil;
|
|
|
|
*dataPtr=nil;
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*requestLinePtr = [listItems objectAtIndex:0];
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
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;
|
2004-12-14 12:54:40 +00:00
|
|
|
int requestLineLength=0;
|
|
|
|
|
|
|
|
requestLineLength=[requestLine length];
|
|
|
|
if (requestLineLength==0)
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
ExceptionRaise(@"GSWDefaultAdaptorThread",
|
2004-12-14 12:54:40 +00:00
|
|
|
@"bad request first line: '%@'",
|
|
|
|
requestLine);
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
2000-01-22 12:49:49 +00:00
|
|
|
else
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
2004-12-14 12:54:40 +00:00
|
|
|
NSRange spaceRange;
|
|
|
|
NSRange urlRange;
|
|
|
|
NSString* method=nil;
|
|
|
|
NSString* url=nil;
|
|
|
|
NSString* protocolString=nil;
|
|
|
|
NSArray* protocol=nil;
|
|
|
|
|
|
|
|
spaceRange=[requestLine rangeOfString:@" "];
|
|
|
|
if (spaceRange.length==0 || spaceRange.location+spaceRange.length>=requestLineLength)
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
2004-12-14 12:54:40 +00:00
|
|
|
ExceptionRaise(@"GSWDefaultAdaptorThread",
|
|
|
|
@"bad request first line: No method or no protocol '%@'",
|
|
|
|
requestLine);
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-12-14 12:54:40 +00:00
|
|
|
method=[requestLine substringToIndex:spaceRange.location];
|
|
|
|
urlRange.location=spaceRange.location+spaceRange.length;//+1 to skip space
|
|
|
|
spaceRange=[requestLine rangeOfString:@" "
|
|
|
|
options:NSBackwardsSearch
|
|
|
|
range:NSMakeRange(urlRange.location,requestLineLength-urlRange.location)];
|
|
|
|
if (spaceRange.length==0 || spaceRange.location<=urlRange.location)
|
|
|
|
{
|
|
|
|
ExceptionRaise(@"GSWDefaultAdaptorThread",
|
|
|
|
@"bad request first line: No protocol or no url '%@'",
|
|
|
|
requestLine);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
protocolString=[requestLine substringFromIndex:spaceRange.location+spaceRange.length];
|
|
|
|
protocol=[protocolString componentsSeparatedByString:@"/"];
|
|
|
|
urlRange.length=spaceRange.location-urlRange.location;
|
|
|
|
url=[requestLine substringFromRange:urlRange];
|
|
|
|
|
|
|
|
if ([protocol count]!=2)
|
|
|
|
{
|
|
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"bad request first line (HTTP)");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString* httpVersion=[protocol objectAtIndex:1];
|
2007-04-13 18:32:02 +00:00
|
|
|
if ((httpVersion) && ([httpVersion length] > 3)) {
|
|
|
|
httpVersion = [httpVersion substringToIndex:3];
|
|
|
|
}
|
2004-12-14 12:54:40 +00:00
|
|
|
request=[_application createRequestWithMethod:method
|
|
|
|
uri:url
|
|
|
|
httpVersion:httpVersion
|
|
|
|
headers:headers
|
|
|
|
content:data
|
|
|
|
userInfo:nil];
|
|
|
|
/* };*/
|
|
|
|
};
|
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
};
|
|
|
|
};
|
2004-12-14 12:54:40 +00:00
|
|
|
|
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
|
|
|
NSString* anHeader=nil;
|
2004-12-31 14:33:16 +00:00
|
|
|
|
|
|
|
_sendResponseTS=GSWTime_now();
|
2002-05-14 11:28:50 +00:00
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
// Based on requestTS
|
|
|
|
anHeader=[NSString stringWithFormat:@"%@: applicationThreadCreation=+%0.3fs applicationThreadRun=+%0.3fs applicationBeginDispatchRequest=+%0.3fs applicationEndDispatchRequest=+%0.3fs applicationDispatchRequest=%0.3fs applicationBeginSendResponse=+%0.3fs applicationTimeSpent=%0.3fs",
|
|
|
|
GSWHTTPHeader_AdaptorStats[_requestNamingConv],
|
|
|
|
GSWTime_floatSec(_creationTS-_requestTS),
|
|
|
|
GSWTime_floatSec(_runTS-_requestTS),
|
|
|
|
GSWTime_floatSec(_beginDispatchRequestTS-_requestTS),
|
|
|
|
GSWTime_floatSec(_endDispatchRequestTS-_requestTS),
|
|
|
|
GSWTime_floatSec(_endDispatchRequestTS-_beginDispatchRequestTS),
|
|
|
|
GSWTime_floatSec(_sendResponseTS-_requestTS),
|
|
|
|
GSWTime_floatSec(_sendResponseTS-_requestTS)];
|
2002-05-14 11:28:50 +00:00
|
|
|
|
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
|
2004-12-31 14:33:16 +00:00
|
|
|
withAdditionalHeaderLines:[NSArray arrayWithObject:anHeader]
|
2002-05-14 11:28:50 +00:00
|
|
|
withRemoteAddress:_remoteAddress];
|
2002-03-06 23:13:23 +00:00
|
|
|
ASSIGN(_stream,nil);
|
2001-10-28 10:29:17 +00:00
|
|
|
};
|
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
//--------------------------------------------------------------------
|
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;
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2000-01-22 12:49:49 +00:00
|
|
|
[response willSend];
|
|
|
|
if (response)
|
2001-10-28 10:29:17 +00:00
|
|
|
{
|
2004-12-31 14:33:16 +00:00
|
|
|
IMP objectAtIndexIMP=NULL;
|
|
|
|
int addHeadersCount=[addHeaders count];
|
2001-10-28 10:29:17 +00:00
|
|
|
int headerN=0;
|
|
|
|
int headerNForKey=0;
|
2002-05-14 11:28:50 +00:00
|
|
|
NSMutableData* responseData=(NSMutableData*)[NSMutableData data];
|
2004-12-31 14:33:16 +00:00
|
|
|
IMP appendDataIMP=[responseData methodForSelector:appendDataSEL];
|
2001-10-28 10:29:17 +00:00
|
|
|
NSArray* headerKeys=[response headerKeys];
|
2004-12-31 14:33:16 +00:00
|
|
|
int headerKeysCount=[headerKeys count];
|
2001-10-28 10:29:17 +00:00
|
|
|
NSArray* headersForKey=nil;
|
|
|
|
NSString* key=nil;
|
|
|
|
NSString* anHeader=nil;
|
2003-03-21 14:32:57 +00:00
|
|
|
NSString* head=[NSString stringWithFormat:@"HTTP/%@ %d %@ %@\n",
|
2001-10-28 10:29:17 +00:00
|
|
|
[response httpVersion],
|
|
|
|
[response status],
|
|
|
|
GSWHTTPHeader_Response_OK,
|
|
|
|
GSWHTTPHeader_Response_HeaderLineEnd[requestNamingConv]];
|
2002-05-14 11:28:50 +00:00
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
(*appendDataIMP)(responseData,appendDataSEL,
|
|
|
|
[head dataUsingEncoding:NSASCIIStringEncoding]);
|
|
|
|
|
|
|
|
objectAtIndexIMP=[headerKeys methodForSelector:objectAtIndexSEL];
|
|
|
|
for(headerN=0;headerN<headerKeysCount;headerN++)
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
2004-12-31 14:33:16 +00:00
|
|
|
int headersForKeyCount=0;
|
|
|
|
key=(*objectAtIndexIMP)(headerKeys,objectAtIndexSEL,headerN);
|
2002-03-06 23:13:23 +00:00
|
|
|
headersForKey=[response headersForKey:key];
|
2004-12-31 14:33:16 +00:00
|
|
|
headersForKeyCount=[headersForKey count];
|
|
|
|
for(headerNForKey=0;headerNForKey<headersForKeyCount;headerNForKey++)
|
2002-03-06 23:13:23 +00:00
|
|
|
{
|
|
|
|
anHeader=[NSString stringWithFormat:@"%@: %@\n",
|
|
|
|
key,
|
|
|
|
[headersForKey objectAtIndex:headerNForKey]];
|
2004-12-31 14:33:16 +00:00
|
|
|
|
|
|
|
(*appendDataIMP)(responseData,appendDataSEL,
|
|
|
|
[anHeader dataUsingEncoding:NSASCIIStringEncoding]);
|
2002-03-06 23:13:23 +00:00
|
|
|
};
|
|
|
|
};
|
2002-05-14 11:28:50 +00:00
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
objectAtIndexIMP=[addHeaders methodForSelector:objectAtIndexSEL];
|
|
|
|
for(headerN=0;headerN<addHeadersCount;headerN++)
|
|
|
|
{
|
|
|
|
(*appendDataIMP)(responseData,appendDataSEL,
|
|
|
|
[(*objectAtIndexIMP)(addHeaders,objectAtIndexSEL,headerN)
|
|
|
|
dataUsingEncoding:NSASCIIStringEncoding]);
|
|
|
|
(*appendDataIMP)(responseData,appendDataSEL,lineFeedData);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Headers/Content separator
|
|
|
|
(*appendDataIMP)(responseData,appendDataSEL,lineFeedData);
|
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]);
|
2005-04-05 15:54:24 +00:00
|
|
|
[GSWApplication statusLogString:@"\nException while sending response\n"];
|
2002-03-06 23:13:23 +00:00
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
2002-05-14 11:28:50 +00:00
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
NSData* responseContent=[response content];
|
|
|
|
int responseContentLength=[responseContent length];
|
|
|
|
if (responseContentLength>0)
|
2001-10-28 10:29:17 +00:00
|
|
|
{
|
2004-12-31 14:33:16 +00:00
|
|
|
[responseData setLength:responseContentLength];
|
|
|
|
[responseData setData:responseContent];
|
|
|
|
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
[aStream writeData:responseData];
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
ok=NO;
|
|
|
|
LOGException(@"GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",
|
|
|
|
localException,[localException reason]);
|
2005-04-05 15:54:24 +00:00
|
|
|
[GSWApplication statusLogString:@"\nException while sending response\n"];
|
2004-12-31 14:33:16 +00:00
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
};
|
2002-03-06 23:13:23 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
[aStream closeFile];
|
2000-01-22 12:49:49 +00:00
|
|
|
};
|
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
//--------------------------------------------------------------------
|
|
|
|
/** Returns thread creation TS **/
|
|
|
|
-(GSWTime)creationTS
|
2001-10-28 10:29:17 +00:00
|
|
|
{
|
2004-12-31 14:33:16 +00:00
|
|
|
return _creationTS;
|
2001-10-28 10:29:17 +00:00
|
|
|
};
|
|
|
|
|
2004-12-31 14:33:16 +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
|
|
|
|
{
|
2004-12-31 14:33:16 +00:00
|
|
|
time_t elapsedSeconds=GSWTime_secPart(GSWTime_now()-_creationTS);
|
|
|
|
BOOL isExpired=(elapsedSeconds>ADAPTOR_THREAD_TIME_OUT);
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2001-10-28 10:29:17 +00:00
|
|
|
return isExpired;
|
|
|
|
};
|
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
//--------------------------------------------------------------------
|
|
|
|
-(void)setRequestTS:(GSWTime)requestTS
|
|
|
|
{
|
|
|
|
_requestTS=requestTS;
|
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2001-10-28 10:29:17 +00:00
|
|
|
-(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
|
|
|
|
2004-12-31 14:33:16 +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];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
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
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
[self sendResponse:response
|
|
|
|
toStream:stream
|
2002-05-14 11:28:50 +00:00
|
|
|
withNamingConv:GSWNAMES_INDEX
|
|
|
|
withAdditionalHeaderLines:nil
|
|
|
|
withRemoteAddress:nil];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
DESTROY(pool);
|
|
|
|
};
|
|
|
|
|
2004-12-31 14:33:16 +00:00
|
|
|
//--------------------------------------------------------------------
|
2002-03-06 23:13:23 +00:00
|
|
|
+(void)sendConnectionRefusedResponseToStream:(NSFileHandle*)stream
|
|
|
|
withMessage:(NSString*)message
|
|
|
|
{
|
|
|
|
GSWResponse* response=nil;
|
|
|
|
NSAutoreleasePool* pool=nil;
|
|
|
|
pool=[NSAutoreleasePool new];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
2002-03-06 23:13:23 +00:00
|
|
|
response=[GSWResponse responseWithMessage:message
|
|
|
|
inContext:nil
|
2001-10-28 10:29:17 +00:00
|
|
|
forRequest:nil
|
|
|
|
forceFinalize:YES];
|
|
|
|
[response setStatus:503];//503=Service Unavailable
|
2007-04-13 18:32:02 +00:00
|
|
|
|
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];
|
2007-04-13 18:32:02 +00:00
|
|
|
|
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
|
|
|
@end
|
2004-12-31 14:33:16 +00:00
|
|
|
|