зеркало из https://github.com/mozilla/gecko-dev.git
Updates to HTTP. Need SyncStreamListener to complete the test.
This commit is contained in:
Родитель
a31e65c713
Коммит
230339cc2c
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче