Updates to HTTP. Need SyncStreamListener to complete the test.

This commit is contained in:
gagan%netscape.com 1999-06-02 13:25:29 +00:00
Родитель a31e65c713
Коммит 230339cc2c
7 изменённых файлов: 155 добавлений и 65 удалений

Просмотреть файл

@ -94,9 +94,9 @@ nsHTTPConnection::GetInputStream(nsIInputStream* *o_Stream)
{
if (!m_bConnected)
Open();
// How do I block here?
if (m_pResponse)
return m_pResponse->GetInputStream(o_Stream);
NS_ERROR("No response!");
return NS_OK; // change to error ? or block till response is set up?
}
@ -224,6 +224,7 @@ nsHTTPConnection::Open(void)
m_State = HS_WAITING_FOR_RESPONSE;
m_bConnected = PR_TRUE;
NS_RELEASE(temp);
}
else
NS_ERROR("Failed to create/get a transport!");
@ -241,18 +242,14 @@ nsHTTPConnection::QueryInterface(REFNSIID aIID, void** aInstancePtr)
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
if (aIID.Equals(nsIProtocolConnection::GetIID())) {
*aInstancePtr = (void*) ((nsIProtocolConnection*)this);
if (aIID.Equals(nsIProtocolConnection::GetIID()) ||
aIID.Equals(kISupportsIID)) {
*aInstancePtr = NS_STATIC_CAST(nsIProtocolConnection*, this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIHTTPConnection::GetIID())) {
*aInstancePtr = (void*) ((nsIHTTPConnection*)this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) ((nsISupports*)(nsIProtocolConnection*)this);
*aInstancePtr = NS_STATIC_CAST(nsIHTTPConnection*, this);
NS_ADDREF_THIS();
return NS_OK;
}

Просмотреть файл

@ -43,7 +43,7 @@ class nsHTTPResponse;
-Gagan Saksena 02/25/99
*/
class nsHTTPConnection : public nsIHTTPConnection , public nsIProtocolConnection
class nsHTTPConnection : public nsIHTTPConnection //, public nsIProtocolConnection
{
public:
@ -97,6 +97,8 @@ public:
nsIEventQueue* EventQueue(void) const { return m_pEventQ; };
NS_IMETHOD SetResponse(nsHTTPResponse* i_pResp) { if (i_pResp) m_pResponse = i_pResp; return NS_OK;};
private:
nsCOMPtr<nsIURL> m_pURL;
PRBool m_bConnected;

Просмотреть файл

@ -98,6 +98,9 @@ nsHTTPHandler::NewConnection(nsIURL* i_URL,
// Verify that the event sink is http
nsCOMPtr<nsIHTTPEventSink> httpEventSink (do_QueryInterface(i_eventSink));
// This doesn't seem right... a caller cant know if its going to be http!
// so how do we do this right?
NS_ASSERTION(httpEventSink, "Bad interface passed for httpEventSink");
// Create one
nsHTTPConnection* pNewInstance = new nsHTTPConnection(

Просмотреть файл

@ -28,6 +28,7 @@
#include "nsITransport.h"
#include "nsHTTPConnection.h"
#include "nsHTTPResponseListener.h"
#include "nsCRT.h"
nsHTTPRequest::nsHTTPRequest(nsIUrl* i_pURL, HTTPMethod i_Method, nsITransport* i_pTransport):
m_pURI(i_pURL),
@ -59,9 +60,9 @@ nsHTTPRequest::~nsHTTPRequest()
delete m_Request;
m_Request = 0;
}
/*
if (m_pTransport)
NS_RELEASE(m_pTransport);
/*
if (m_pConnection)
NS_RELEASE(m_pConnection);
*/
@ -88,7 +89,11 @@ nsHTTPRequest::Build()
NS_ASSERTION(m_pURI, "No URL to build request for!");
rv = m_pURI->GetPath(&filename);
PL_strcat(lineBuffer, filename);
PL_strcat(lineBuffer, " HTTP/1.1\n");
PL_strcat(lineBuffer, " HTTP/1.0");
PL_strcat(lineBuffer, CRLF);
rv = m_Request->Fill(lineBuffer, PL_strlen(lineBuffer), &bytesWritten);
if (NS_FAILED(rv)) return rv;
/* switch (m_Method)
{
@ -111,6 +116,7 @@ nsHTTPRequest::Build()
break;
}
*/
// Write the request method and HTTP version
// Add additional headers if any
@ -125,7 +131,7 @@ nsHTTPRequest::Build()
element->atom->ToString(lineBuffStr);
lineBuffStr.Append(": ");
lineBuffStr.Append((const nsString&)*element->value);
lineBuffStr.Append('\n');
lineBuffStr.Append(CRLF);
NS_ASSERTION((lineBuffStr.Length() <= 1024), "Increase line buffer length!");
lineBuffStr.ToCString(lineBuffer, lineBuffStr.Length());
lineBuffer[lineBuffStr.Length()] = '\0';
@ -134,6 +140,12 @@ nsHTTPRequest::Build()
lineBuffer[0] = '\0';
}
}
// Send the final \n
lineBuffer[0] = CR;
lineBuffer[1] = LF;
lineBuffer[2] = '\0';
rv = m_Request->Fill(lineBuffer, PL_strlen(lineBuffer), &bytesWritten);
if (NS_FAILED(rv)) return rv;
}
@ -876,6 +888,10 @@ nsHTTPRequest::OnStopBinding(nsISupports* i_pContext,
//TODO check this portion here...
return pListener ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
else
{
NS_ERROR("Failed to write to server!");
}
/*
Somewhere here we need to send a message up the event sink
@ -890,6 +906,7 @@ nsHTTPRequest::SetTransport(nsITransport* i_pTransport)
{
NS_ASSERTION(!m_pTransport, "Transport being overwritten!");
m_pTransport = i_pTransport;
NS_ADDREF(m_pTransport);
return NS_OK;
}

Просмотреть файл

@ -29,7 +29,6 @@ class nsVoidArray;
class nsIByteBufferInputStream;
class nsITransport;
class nsHTTPConnection;
/*
The nsHTTPRequest class is the request object created for each HTTP
request before the connection. A request object may be cloned and

Просмотреть файл

@ -28,6 +28,9 @@
nsHTTPResponse::nsHTTPResponse(nsIHTTPConnection* i_pCon, nsIInputStream* i_InputStream):
m_pConn(dont_QueryInterface(i_pCon)),
m_pArray(new nsVoidArray()),
mRefCnt(0),
m_pStatusString(0),
m_pInputStream(i_InputStream)
{
}
@ -37,6 +40,12 @@ nsHTTPResponse::~nsHTTPResponse()
// m_pConn is released by nsCOMPtr.
if (m_pStatusString)
delete[] m_pStatusString;
if (m_pArray)
{
delete m_pArray;
m_pArray = 0;
}
}
NS_IMPL_ADDREF(nsHTTPResponse);
@ -433,10 +442,12 @@ nsHTTPResponse::SetHeader(const char* i_Header, const char* i_Value)
NS_METHOD
nsHTTPResponse::SetHeaderInternal(const char* i_Header, const char* i_Value)
{
NS_ASSERTION(m_pArray, "Ooops! array vanished!");
if (i_Value)
{
//The tempValue gets copied so we can do away with it...
nsString tempValue(i_Value);
tempValue.Trim(" \r\n");
nsHeaderPair* pair = new nsHeaderPair(i_Header, &tempValue);
if (pair)
{
@ -459,13 +470,13 @@ nsHTTPResponse::GetHeader(const char* i_Header, const char* *o_Value) const
// TODO
// Common out the headerpair array functionality from
// request and put it in a class
nsIAtom* iAtom = NS_NewAtom(i_Header);
if (m_pArray && (0< m_pArray->Count()))
{
for (PRInt32 i = m_pArray->Count() - 1; i >= 0; --i)
{
nsHeaderPair* element = NS_STATIC_CAST(nsHeaderPair*, m_pArray->ElementAt(i));
if ((element->atom == NS_NewAtom(i_Header)) && o_Value)
if ((element->atom == iAtom) && o_Value)
{
*o_Value = (element->value) ? element->value->ToNewCString() : nsnull;
return NS_OK;

Просмотреть файл

@ -17,10 +17,12 @@
*/
#include "nsIString.h"
#include "nsIStreamListener.h"
#include "nsHTTPResponseListener.h"
#include "nsITransport.h"
#include "nsIInputStream.h"
#include "nsIHTTPConnection.h"
#include "nsHTTPConnection.h"
#include "nsHTTPResponse.h"
#include "nsIHttpEventSink.h"
#include "nsCRT.h"
@ -31,6 +33,7 @@ static const int kMAX_FIRST_LINE_SIZE= 256;
nsHTTPResponseListener::nsHTTPResponseListener():
m_pConnection(nsnull),
m_bFirstLineParsed(PR_FALSE),
m_pResponse(nsnull),
m_bHeadersDone(PR_FALSE)
{
NS_INIT_REFCNT();
@ -40,6 +43,8 @@ nsHTTPResponseListener::~nsHTTPResponseListener()
{
if (m_pConnection)
NS_RELEASE(m_pConnection);
if (m_pResponse)
NS_RELEASE(m_pResponse);
}
NS_IMPL_ISUPPORTS(nsHTTPResponseListener,nsIStreamListener::GetIID());
@ -50,43 +55,54 @@ nsHTTPResponseListener::OnDataAvailable(nsISupports* context,
PRUint32 i_SourceOffset,
PRUint32 i_Length)
{
//move these to member variables later TODO
static char extrabuffer[kMAX_FIRST_LINE_SIZE];
static int extrabufferlen = 0;
// we should probably construct the stream only when we get the data...
// but for now...
nsIStreamListener* syncListener;
nsIInputStream* inStr;
/* Jud... getting some unresolved stuff here... noticed that
nsSyncStreamListener isn't being exported!?! */
//nsresult rv = NS_NewSyncStreamListener(&syncListener, &inStr);
//if (NS_FAILED(rv))
// return rv;
// Should I save this as a member variable? yes... todo
nsIHTTPEventSink* pSink= nsnull;
m_pConnection->EventSink(&pSink);
NS_VERIFY(pSink, "No HTTP Event Sink!");
NS_ASSERTION(i_pStream, "Fake stream!");
// Set up the response
if (!m_pResponse)
{
m_pResponse = new nsHTTPResponse (m_pConnection, i_pStream);
// why do I need the connection in the constructor... get rid.. TODO
m_pResponse = new nsHTTPResponse (m_pConnection, inStr);
if (!m_pResponse)
{
NS_ERROR("Failed to create the response object!");
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(m_pResponse);
nsHTTPConnection* pTestCon = NS_STATIC_CAST(nsHTTPConnection*, m_pConnection);
pTestCon->SetResponse(m_pResponse);
}
//printf("nsHTTPResponseListener::OnDataAvailable...\n");
/*
Check its current state,
if we have already found the end of headers mark,
then just stream this on to the listener
else read
*/
if (m_bHeadersDone)
{
// TODO push extrabuffer up the stream too.. How?
// Should I save this as a member variable? yes... todo
nsIHTTPEventSink* pSink= nsnull;
NS_VERIFY(m_pConnection->EventSink(&pSink), "No HTTP Event Sink!");
return pSink->OnDataAvailable(context, i_pStream, i_SourceOffset, i_Length);
}
else if (!m_bFirstLineParsed)
char extrabuffer[kMAX_FIRST_LINE_SIZE];
int extrabufferlen = 0;
char partHeader[kMAX_FIRST_LINE_SIZE];
int partHeaderLen = 0;
PRBool bHeadersDone = PR_FALSE;
PRBool bFirstLineParsed = PR_FALSE;
while (!bHeadersDone)
{
//TODO optimize this further!
char server_version[8]; // HTTP/1.1
char buffer[kMAX_FIRST_LINE_SIZE];
PRUint32 length;
@ -94,37 +110,80 @@ nsHTTPResponseListener::OnDataAvailable(nsISupports* context,
NS_ASSERTION(buffer, "Argh...");
char* p = buffer;
while ((*p != LF) && buffer+length > p)
++p;
while (buffer+length > p)
{
char* lineStart = p;
if (*lineStart == '\0' || *lineStart == CR)
{
bHeadersDone = PR_TRUE;
// we read extra so save it for the other headers
if (buffer+length > p)
{
extrabufferlen = length - (buffer - p);
PL_strncpy(extrabuffer, p, extrabufferlen);
}
//TODO process headers here.
if (p != (buffer+length))
{
PRUint32 stat = 0;
char stat_str[kMAX_FIRST_LINE_SIZE];
*p = '\0';
sscanf(buffer, "%8s %d %s", server_version, &stat, stat_str);
m_pResponse->SetServerVersion(server_version);
m_pResponse->SetStatus(stat);
m_pResponse->SetStatusString(stat_str);
p++;
}
pSink->OnHeadersAvailable(context);
break; // break off this buffer while
}
while ((*p != LF) && (buffer+length > p))
++p;
if (!bFirstLineParsed)
{
char server_version[8]; // HTTP/1.1
PRUint32 stat = 0;
char stat_str[kMAX_FIRST_LINE_SIZE];
*p = '\0';
sscanf(lineStart, "%8s %d %s", server_version, &stat, stat_str);
m_pResponse->SetServerVersion(server_version);
m_pResponse->SetStatus(stat);
m_pResponse->SetStatusString(stat_str);
p++;
bFirstLineParsed = PR_TRUE;
}
else
{
char* header = lineStart;
char* value = PL_strchr(lineStart, ':');
*p = '\0';
if(value)
{
*value = '\0';
value++;
if (partHeaderLen == 0)
m_pResponse->SetHeaderInternal(header, value);
else
{
//append the header to the partheader
header = PL_strcat(partHeader, header);
m_pResponse->SetHeaderInternal(header, value);
//Reset partHeader now
partHeader[0]='\0';
partHeaderLen = 0;
}
}
else // this is just a part of the header so save it for later use...
{
partHeaderLen = p-header;
PL_strncpy(partHeader, lineStart, partHeaderLen);
}
p++;
}
// we read extra so save it for the other headers
if (buffer+length > p)
{
extrabufferlen = length - (buffer - p);
PL_strncpy(extrabuffer, p, extrabufferlen);
}
m_bFirstLineParsed = PR_TRUE;
return NS_OK;
}
else
if (bHeadersDone)
{
if (extrabufferlen > 0)
{
// TODO - revive!
}
// TODO push extrabuffer up the stream too.. How? JUD?
return pSink->OnDataAvailable(context, inStr, i_SourceOffset, i_Length);
}
return NS_OK;
}
@ -151,12 +210,14 @@ nsHTTPResponseListener::OnStopBinding(nsISupports* i_pContext,
nsIString* i_pMsg)
{
//printf("nsHTTPResponseListener::OnStopBinding...\n");
NS_ASSERTION(m_pResponse, "Response object vanished!");
//NS_ASSERTION(m_pResponse, "Response object not created yet or died?!");
// Should I save this as a member variable? yes... todo
nsIHTTPEventSink* pSink= nsnull;
NS_VERIFY(m_pConnection->EventSink(&pSink), "No HTTP Event Sink!");
nsresult rv = pSink->OnStopBinding(i_pContext, i_Status,i_pMsg);
NS_RELEASE(m_pResponse);
nsresult rv = m_pConnection->EventSink(&pSink);
if (NS_FAILED(rv))
NS_ERROR("No HTTP Event Sink!");
rv = pSink->OnStopBinding(i_pContext, i_Status,i_pMsg);
return rv;
}