From: Elvandar on
Hi all. I wrote an MFC application to make an HTTP file transfer
between a client and a server. The application receives as input the
list of servers to call (in this case, servers are remote devices with
an embedded web server), and one by one it sends the file and closes
the connection. The sequence of the operations made is this:

1) Dial-up call to device X
2) Open socket on port 80
3) HTTP POST of the file to the device
4) Wait for the response, and analysis to understand if the transfer
has gone well or not
5) Open a new socket (after the response, the old socket is closed)
6) HTTP GET of the appropriate page to confirm operations to perform
after the call is closed
7) Wait for the response and close socket
8) Hang up of the connection

These operations are repeated for every device in the list. The problem
is that with the first device all goes well, while from the second
dial-up call, every time the method CSocket.Create() is called, the
application hangs with a "Unhandled Exception: Access violation"...

With a step-by-step analisys I saw the code is blocking here:

* MAP_PP.cpp File

void* CMapPtrToPtr::GetValueAt(void* key) const
// find value (or return NULL -- NULL values not different as a result)
{
if (m_pHashTable == NULL) // CODE HANGS HERE!!!
return NULL;

UINT nHash = HashKey(key) % m_nHashTableSize;

// see if it exists
CAssoc* pAssoc;
for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc =
pAssoc->pNext)
{
if (pAssoc->key == key)
return pAssoc->value;
}
return NULL;
}


While the code executed in the operations listed above is this:

* Thread to manage upload (here I removed every if and flow controls):

while(Tmp != NULL)
{
DialUp(Tmp->PhoneNumber);

CHTTPOnSocket* pClient = NULL;
pClient = new CHTTPOnSocket();

pClient->InitializePostArguments();
pClient->AddPostArgument("FwFile",FwFilename,TRUE);


pClient->DoRequest(SERVER_ADDRESS,UPLOAD_FW_PAGE,CHTTPOnSocket::RequestPostMultiPart);
LPSTR Response = pClient->QueryHTTPResponse();
pClient->DoRequest(SERVER_ADDRESS,
UPLOAD_OK_PAGE,CHTTPOnSocket::RequestGet);
Response = pClient->QueryHTTPResponse();

HangUp();

pClient->~CHTTPOnSocket();
Tmp = Tmp->Next;
}


* Useful methods of the class CHTTPSocket to send/receive data on the
socket

Socket and SocketFile are defined as class attributes in CHTTPSocket.h
in this way:

CSocket* Socket;
CSocketFile* SocketFile;



CHTTPOnSocket::CHTTPOnSocket()
{
Socket = NULL;
SocketFile = NULL;
AfxSocketInit(NULL);
}

LPSTR CHTTPOnSocket::QueryHTTPResponse()
{
LPSTR RecBuffer = (LPSTR)::LocalAlloc(LPTR,RECEIVING_BUFFER);

if(Socket == NULL)
RecBuffer = NULL;
else
{
try
{
CArchive *Receiver = new
CArchive(SocketFile,CArchive::load);

int n = Receiver->Read(RecBuffer,RECEIVING_BUFFER);

Receiver->Close();
Receiver->~CArchive();
}
catch (CException *e)
{
e->Delete();
RecBuffer = NULL;
}

this->CloseSocket();
}

return RecBuffer;
}

void CHTTPOnSocket::CloseSocket()
{
try
{
SocketFile->Close();
SocketFile->~CSocketFile();
if(Socket != NULL)
{
Socket->Close();
Socket->~CSocket();
}
}
catch (CException *e)
{
e->Delete();
}
Socket = NULL;
}

BOOL CHTTPOnSocket::DoRequest(LPCSTR ServerAddress, LPCSTR Url, int
Method)
{
try
{
if(Socket == NULL)
{
Socket = new CSocket();
Socket->Create();
}

Socket->Connect(ServerAddress,80);

SocketFile = new CSocketFile(Socket);
}
catch(CException *e)
{
e->Delete();
return FALSE;
}

switch(Method)
{
case CHTTPOnSocket::RequestGet:
return this->DoGet(ServerAddress, Url);
break;
case CHTTPOnSocket::RequestPost:
return this->DoPost(ServerAddress, Url);
break;
case CHTTPOnSocket::RequestPostMultiPart:
return this->DoPostMultiPart(ServerAddress, Url);
break;
default:
return FALSE;
break;
}
}

BOOL CHTTPOnSocket::DoGet(LPCSTR ServerAddress, LPCSTR Url)
{
CString UrlToGet;

try
{
CArchive *Sender = new CArchive(SocketFile,CArchive::store);

UrlToGet.Format("GET /%s HTTP/1.1\r\n\r\n",Url);


Sender->Write((PBYTE)UrlToGet.GetBuffer(UrlToGet.GetLength()),UrlToGet.GetLength());
Sender->Flush();
Sender->Close();
}
catch (CException *e)
{
e->Delete();
return FALSE;
}

return TRUE;
}

BOOL CHTTPOnSocket::DoPostMultiPart(LPCSTR ServerAddress, LPCSTR Url)
{
BOOL bRet = FALSE;

DWORD ContentLengthValue = GetContentLengthValue();

CString Headers = BuildPostHeaders(Url,ContentLengthValue);

PBYTE MultipartData;
MultipartData = (PBYTE)::LocalAlloc(LPTR, ContentLengthValue);

GetMultipartData(MultipartData,ContentLengthValue);

PBYTE PostRequest = (PBYTE)::LocalAlloc(LPTR,Headers.GetLength() +
ContentLengthValue);
PBYTE Tmp = PostRequest;

::CopyMemory(Tmp, Headers, Headers.GetLength());

Tmp += Headers.GetLength();
::CopyMemory(Tmp, MultipartData, ContentLengthValue);

// Here, in PostRequest we have the complete request to send to
remote host

try
{
CArchive *Sender = new CArchive(SocketFile,CArchive::store);

Tmp = PostRequest;
Sender->Write((PBYTE)Tmp,Headers.GetLength() +
ContentLengthValue);
Sender->Flush();
Sender->Close();
Sender->~CArchive();

bRet = TRUE;
}
catch (CException *e)
{
e->Delete();
}

return bRet;
}

CHTTPOnSocket::~CHTTPOnSocket()
{
try
{
if(Socket != NULL)
{
Socket->Close();
Socket->~CSocket();
}

}
catch (CException* e) // Socket already closed
{
e->Delete();
}
Socket = NULL;

AfxSocketTerm();
}

The problem is in the method DoRequest. When I call the second device,
and executed the instruction

pClient->DoRequest(SERVER_ADDRESS,UPLOAD_FW_PAGE,CHTTPOnSocket::RequestPostMultiPart);

the application hangs on

if(Socket == NULL)
{
Socket = new CSocket();
Socket->Create(); // CODE HANGS HERE!!!
}

of the method DoRequest in CHTTPSocket...I'm almost desperate, I
suppose I tried everything with no luck...could anyone please give me a
hand??? Thank you to anyone, and sorry for my bad English :P

Elvandar


From: Elvandar on
Elvandar has brought this to us :
> Hi all. I wrote an MFC application to make an HTTP file transfer between a
> client and a server. The application receives as input the list of servers to
> call (in this case, servers are remote devices with an embedded web server),
> and one by one it sends the file and closes the connection. The sequence of
> the operations made is this:
>
> [CUT]

Ok, doesn't matter. Just a fast search with google groups to find out
it is a bug in vc++ 6 without sp3... :) I solved with a workaround!
Sorry for the post, next time I'll first look on google, and after post
to a newsgroup for help :P

Elvandar


From: Scott McPhillips [MVP] on
Elvandar wrote:
> pClient = new CHTTPOnSocket();
> ...
> ...
> pClient->~CHTTPOnSocket();

Get rid of all your calls to destructors! That is the wrong way to
destroy objects and it leaks memory too.

delete pClient;

--
Scott McPhillips [VC++ MVP]

From: Norbert Unterberg on
Elvandar schrieb:
> Elvandar has brought this to us :
>> Hi all. I wrote an MFC application to make an HTTP file transfer
>> between a client and a server. The application receives as input the
>> list of servers to call (in this case, servers are remote devices with
>> an embedded web server), and one by one it sends the file and closes
>> the connection. The sequence of the operations made is this:
>>
>> [CUT]
>
> Ok, doesn't matter. Just a fast search with google groups to find out it
> is a bug in vc++ 6 without sp3... :) I solved with a workaround!

I hope the workaround was to install VC++ SP6!

Norbert
From: Elvandar on
Scott McPhillips [MVP] wrote :
> Elvandar wrote:
>> pClient = new CHTTPOnSocket();
>> ...
>> ...
>> pClient->~CHTTPOnSocket();
>
> Get rid of all your calls to destructors! That is the wrong way to destroy
> objects and it leaks memory too.
>
> delete pClient;

Thank you Scott, I'm new to C++ so I thought the call to destructor was
the right way to destroy objects! :)