mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-11 04:31:35 -10:00
Conflicts: .gitignore code/Makefile.am code/ai/ai.h code/ai/ai_profiles.cpp code/ai/ai_profiles.h code/ai/aibig.cpp code/ai/aicode.cpp code/ai/aiturret.cpp code/asteroid/asteroid.cpp code/asteroid/asteroid.h code/bmpman/bm_internal.h code/bmpman/bmpman.cpp code/bmpman/bmpman.h code/camera/camera.cpp code/camera/camera.h code/cfile/cfile.cpp code/cmdline/cmdline.cpp code/cmdline/cmdline.h code/controlconfig/controlsconfig.h code/controlconfig/controlsconfigcommon.cpp code/cutscene/movie.cpp code/cutscene/oggplayer.cpp code/debugconsole/consoleparse.cpp code/fred2/campaigneditordlg.cpp code/fred2/fred.cpp code/fred2/fred.rc code/fred2/missionsave.cpp code/fred2/resource.h code/fred2/sexp_tree.cpp code/fred2/sexp_tree.h code/fred2/shipflagsdlg.cpp code/fred2/shipflagsdlg.h code/fred2/shiptexturesdlg.cpp code/fred2/voiceactingmanager.cpp code/freespace2/freespace.cpp code/freespace2/freespace.rc code/gamehelp/contexthelp.cpp code/globalincs/alphacolors.cpp code/globalincs/alphacolors.h code/globalincs/version.h code/globalincs/vmallocator.h code/globalincs/windebug.cpp code/graphics/2d.cpp code/graphics/font.cpp code/graphics/generic.cpp code/graphics/generic.h code/graphics/grinternal.h code/graphics/gropengl.cpp code/graphics/gropengldraw.cpp code/graphics/gropenglextension.h code/graphics/gropenglpostprocessing.cpp code/graphics/gropenglstate.cpp code/graphics/gropenglstate.h code/graphics/gropengltexture.cpp code/graphics/gropengltnl.cpp code/hud/hud.cpp code/hud/hud.h code/hud/hudconfig.cpp code/hud/hudlock.cpp code/hud/hudmessage.cpp code/hud/hudparse.cpp code/hud/hudreticle.cpp code/hud/hudreticle.h code/hud/hudshield.cpp code/hud/hudsquadmsg.cpp code/hud/hudtarget.cpp code/hud/hudtarget.h code/hud/hudtargetbox.cpp code/inetfile/cftp.cpp code/inetfile/chttpget.cpp code/io/joy.cpp code/io/joy_ff.cpp code/io/key.cpp code/io/keycontrol.cpp code/io/mouse.cpp code/io/timer.cpp code/localization/localize.cpp code/localization/localize.h code/math/fvi.cpp code/math/vecmat.cpp code/menuui/credits.cpp code/menuui/mainhallmenu.cpp code/menuui/mainhallmenu.h code/menuui/optionsmenumulti.cpp code/menuui/playermenu.cpp code/mission/missionbriefcommon.cpp code/mission/missioncampaign.cpp code/mission/missiongoals.h code/mission/missionmessage.cpp code/mission/missionparse.cpp code/mission/missionparse.h code/missionui/missionbrief.cpp code/missionui/missioncmdbrief.cpp code/missionui/missiondebrief.cpp code/missionui/missionscreencommon.cpp code/missionui/missionshipchoice.cpp code/missionui/missionweaponchoice.cpp code/missionui/redalert.cpp code/missionui/redalert.h code/mod_table/mod_table.cpp code/mod_table/mod_table.h code/model/model.h code/model/modelcollide.cpp code/model/modelinterp.cpp code/model/modelread.cpp code/network/multi.cpp code/network/multi_dogfight.cpp code/network/multi_ingame.cpp code/network/multi_log.cpp code/network/multi_rate.cpp code/network/multiteamselect.cpp code/network/multiui.cpp code/network/multiutil.cpp code/network/stand_gui-unix.cpp code/object/collideshipship.cpp code/object/collideshipweapon.cpp code/object/object.cpp code/object/object.h code/object/objectsnd.cpp code/object/objectsort.cpp code/osapi/osapi.cpp code/osapi/osapi_unix.cpp code/osapi/outwnd.h code/parse/generic_log.cpp code/parse/lua.cpp code/parse/parselo.cpp code/parse/parselo.h code/parse/scripting.cpp code/parse/scripting.h code/parse/sexp.cpp code/parse/sexp.h code/physics/physics.cpp code/pilotfile/csg.cpp code/pilotfile/csg_convert.cpp code/pilotfile/pilotfile.cpp code/pilotfile/pilotfile_convert.h code/playerman/playercontrol.cpp code/radar/radardradis.cpp code/radar/radardradis.h code/radar/radarsetup.cpp code/radar/radarsetup.h code/ship/ship.cpp code/ship/ship.h code/ship/shipfx.cpp code/ship/shiphit.cpp code/sound/audiostr.cpp code/sound/ds.cpp code/sound/openal.cpp code/sound/rtvoice.cpp code/sound/sound.cpp code/sound/voicerec.cpp code/stats/medals.cpp code/stats/medals.h code/stats/scoring.cpp code/ui/ui.h code/weapon/beam.cpp code/weapon/weapon.h code/weapon/weapons.cpp code/wxfred2/aboutbox.cpp code/wxfred2/campaigneditor.cpp code/wxfred2/campaigneditor.h code/wxfred2/commandbriefingeditor.cpp code/wxfred2/debriefingeditor.cpp code/wxfred2/fredframe.cpp code/wxfred2/fredframe.h code/wxfred2/missionspecseditor.cpp code/wxfred2/missionspecseditor.h code/wxfred2/voiceactingmanagereditor.cpp code/wxfred2/wxfred.xrc code/wxfred2/wxfred2.cpp code/wxfred2/wxfred2.h configure.ac fs2open.Doxyfile jansson/LICENSE jansson/dump.c jansson/hashtable.c jansson/hashtable.h jansson/jansson.h jansson/jansson_config.h jansson/jansson_private.h jansson/load.c jansson/memory.c jansson/pack_unpack.c jansson/strbuffer.c jansson/strbuffer.h jansson/strconv.c jansson/utf.c jansson/utf.h jansson/value.c libpng/png.c libpng/png.h libpng/pngconf.h libpng/pngdebug.h libpng/pngerror.c libpng/pngget.c libpng/pnginfo.h libpng/pnglibconf.h libpng/pngmem.c libpng/pngpread.c libpng/pngpriv.h libpng/pngread.c libpng/pngrio.c libpng/pngrtran.c libpng/pngrutil.c libpng/pngset.c libpng/pngstruct.h libpng/pngtrans.c libpng/pngwio.c libpng/pngwrite.c libpng/pngwtran.c libpng/pngwutil.c projects/Eclipse/Freespace2/.project projects/MSVC_2005/Fred2.vcproj projects/MSVC_2005/Freespace2.sln projects/MSVC_2005/Freespace2.vcproj projects/MSVC_2005/code.vcproj projects/MSVC_2005/wxFRED2.vcproj projects/MSVC_2008/Fred2.vcproj projects/MSVC_2008/Freespace2.doxproj projects/MSVC_2008/Freespace2.vcproj projects/MSVC_2008/code.vcproj projects/MSVC_2010/Fred2.vcxproj projects/MSVC_2010/Freespace2.vcxproj projects/MSVC_2010/code.vcxproj projects/MSVC_2010/code.vcxproj.filters projects/MSVC_2010/wxFRED2.vcxproj projects/MSVC_2011/Fred2.vcxproj projects/MSVC_2011/Freespace2.vcxproj projects/MSVC_2011/code.vcxproj projects/MSVC_2011/code.vcxproj.filters projects/MSVC_2011/wxFRED2.vcxproj projects/MSVC_2013/Fred2.vcxproj projects/MSVC_2013/Freespace2.vcxproj projects/MSVC_2013/code.vcxproj projects/MSVC_2013/code.vcxproj.filters projects/MSVC_2013/libjpeg.vcxproj projects/MSVC_2013/liblua.vcxproj projects/MSVC_2013/libpng.vcxproj projects/MSVC_2013/wxFRED2.vcxproj projects/MSVC_2013/zlib.vcxproj projects/MSVC_6/Fred2.dsp projects/MSVC_6/Freespace2.dsp projects/MSVC_6/code.dsp projects/MSVC_6/wxFRED2.dsp projects/Xcode/English.lproj/InfoPlist.strings projects/Xcode/FS2_Open.xcodeproj/project.pbxproj projects/Xcode4/English.lproj/InfoPlist.strings projects/Xcode4/FS2_Open.xcodeproj/project.pbxproj projects/Xcode4/Frameworks.tgz projects/codeblocks/Freespace2/Freespace2.cbp zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/crc32.h zlib/deflate.c zlib/deflate.h zlib/infback.c zlib/inffast.c zlib/inffixed.h zlib/inflate.c zlib/inftrees.c zlib/trees.c zlib/uncompr.c zlib/zconf.h zlib/zlib.h zlib/zutil.c zlib/zutil.h
687 lines
12 KiB
C++
687 lines
12 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "globalincs/pstypes.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <process.h>
|
|
#else
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/select.h>
|
|
#include <errno.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#define WSAGetLastError() (errno)
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
|
|
#include "inetfile/inetgetfile.h"
|
|
#include "inetfile/chttpget.h"
|
|
|
|
|
|
|
|
#define NW_AGHBN_CANCEL 1
|
|
#define NW_AGHBN_LOOKUP 2
|
|
#define NW_AGHBN_READ 3
|
|
|
|
#ifdef WIN32
|
|
void __cdecl http_gethostbynameworker(void *parm);
|
|
#else
|
|
int http_gethostbynameworker(void *parm);
|
|
#endif
|
|
|
|
int http_Asyncgethostbyname(unsigned int *ip,int command, char *hostname);
|
|
|
|
int HTTPObjThread( void *obj )
|
|
{
|
|
((ChttpGet *)obj)->WorkerThread();
|
|
((ChttpGet *)obj)->m_Aborted = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ChttpGet::AbortGet()
|
|
{
|
|
m_Aborting = true;
|
|
while(!m_Aborted) Sleep(50); //Wait for the thread to end
|
|
}
|
|
|
|
ChttpGet::ChttpGet(char *URL,char *localfile,char *proxyip,unsigned short proxyport)
|
|
{
|
|
m_ProxyEnabled = true;
|
|
m_ProxyIP = proxyip;
|
|
m_ProxyPort = proxyport;
|
|
GetFile(URL,localfile);
|
|
}
|
|
|
|
ChttpGet::ChttpGet(char *URL,char *localfile)
|
|
{
|
|
m_ProxyEnabled = false;
|
|
GetFile(URL,localfile);
|
|
}
|
|
|
|
|
|
void ChttpGet::GetFile(char *URL,char *localfile)
|
|
{
|
|
m_DataSock = INVALID_SOCKET;
|
|
m_iBytesIn = 0;
|
|
m_iBytesTotal = 0;
|
|
m_State = HTTP_STATE_STARTUP;
|
|
m_Aborting = false;
|
|
m_Aborted = false;
|
|
thread_id = NULL;
|
|
|
|
strncpy(m_URL,URL,MAX_URL_LEN-1);
|
|
m_URL[MAX_URL_LEN-1] = 0;
|
|
|
|
LOCALFILE = fopen(localfile,"wb");
|
|
if(NULL == LOCALFILE)
|
|
{
|
|
m_State = HTTP_STATE_CANT_WRITE_FILE;
|
|
return;
|
|
}
|
|
m_DataSock = socket(AF_INET, SOCK_STREAM, 0);
|
|
if(INVALID_SOCKET == m_DataSock)
|
|
{
|
|
m_State = HTTP_STATE_SOCKET_ERROR;
|
|
return;
|
|
}
|
|
|
|
// uint arg = 1;
|
|
// ioctlsocket( m_DataSock, FIONBIO, &arg );
|
|
|
|
char *pURL = URL;
|
|
if(strnicmp(URL,"http:",5)==0)
|
|
{
|
|
pURL +=5;
|
|
while(*pURL == '/')
|
|
{
|
|
pURL++;
|
|
}
|
|
}
|
|
//There shouldn't be any : in this string
|
|
if(strchr(pURL,':'))
|
|
{
|
|
m_State = HTTP_STATE_URL_PARSING_ERROR;
|
|
return;
|
|
}
|
|
//read the filename by searching backwards for a /
|
|
//then keep reading until you find the first /
|
|
//when you found it, you have the host and dir
|
|
char *filestart = NULL;
|
|
char *dirstart = NULL;
|
|
for(int i = strlen(pURL);i>=0;i--)
|
|
{
|
|
if(pURL[i]== '/')
|
|
{
|
|
if(!filestart)
|
|
{
|
|
filestart = pURL+i+1;
|
|
dirstart = pURL+i+1;
|
|
strcpy_s(m_szFilename,filestart);
|
|
}
|
|
else
|
|
{
|
|
dirstart = pURL+i+1;
|
|
}
|
|
}
|
|
}
|
|
if((dirstart==NULL) || (filestart==NULL))
|
|
{
|
|
m_State = HTTP_STATE_URL_PARSING_ERROR;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strcpy_s(m_szDir,dirstart);//,(filestart-dirstart));
|
|
//m_szDir[(filestart-dirstart)] = NULL;
|
|
strncpy(m_szHost,pURL,(dirstart-pURL));
|
|
m_szHost[(dirstart-pURL)-1] = '\0';
|
|
}
|
|
|
|
if ( (thread_id = SDL_CreateThread(HTTPObjThread, "HTTP", this)) == NULL )
|
|
{
|
|
m_State = HTTP_STATE_INTERNAL_ERROR;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
ChttpGet::~ChttpGet()
|
|
{
|
|
if (thread_id)
|
|
SDL_WaitThread(thread_id, NULL);
|
|
|
|
fclose(LOCALFILE);
|
|
|
|
if (m_DataSock != INVALID_SOCKET) {
|
|
shutdown(m_DataSock, 2);
|
|
closesocket(m_DataSock);
|
|
}
|
|
}
|
|
|
|
int ChttpGet::GetStatus()
|
|
{
|
|
return m_State;
|
|
}
|
|
|
|
unsigned int ChttpGet::GetBytesIn()
|
|
{
|
|
return m_iBytesIn;
|
|
}
|
|
|
|
unsigned int ChttpGet::GetTotalBytes()
|
|
{
|
|
return m_iBytesTotal;
|
|
}
|
|
|
|
|
|
void ChttpGet::WorkerThread()
|
|
{
|
|
char szCommand[1000];
|
|
char *p;
|
|
int irsp = 0;
|
|
ConnectSocket();
|
|
if(m_Aborting)
|
|
{
|
|
fclose(LOCALFILE);
|
|
return;
|
|
}
|
|
if(m_State != HTTP_STATE_CONNECTED)
|
|
{
|
|
fclose(LOCALFILE);
|
|
return;
|
|
}
|
|
sprintf(szCommand,"GET %s%s HTTP/1.1\nAccept: */*\nAccept-Encoding: deflate\nHost: %s\n\n\n",m_ProxyEnabled?"":"/",m_ProxyEnabled?m_URL:m_szDir,m_szHost);
|
|
send(m_DataSock,szCommand,strlen(szCommand),0);
|
|
p = GetHTTPLine();
|
|
if (!p) return;
|
|
if(strnicmp("HTTP/",p,5)==0)
|
|
{
|
|
char *pcode;
|
|
pcode = strchr(p,' ')+1;
|
|
if(!pcode)
|
|
{
|
|
m_State = HTTP_STATE_UNKNOWN_ERROR;
|
|
fclose(LOCALFILE);
|
|
return;
|
|
|
|
}
|
|
pcode[3] = '\0';
|
|
irsp = atoi(pcode);
|
|
|
|
if(irsp == 0)
|
|
{
|
|
m_State = HTTP_STATE_UNKNOWN_ERROR;
|
|
fclose(LOCALFILE);
|
|
return;
|
|
}
|
|
if(irsp==200)
|
|
{
|
|
int idataready=0;
|
|
do
|
|
{
|
|
p = GetHTTPLine();
|
|
if(p==NULL)
|
|
{
|
|
m_State = HTTP_STATE_UNKNOWN_ERROR;
|
|
fclose(LOCALFILE);
|
|
return;
|
|
}
|
|
if(*p=='\0')
|
|
{
|
|
idataready = 1;
|
|
break;
|
|
}
|
|
if(strnicmp(p,"Content-Length:",strlen("Content-Length:"))==0)
|
|
{
|
|
char *s = strchr(p,' ')+1;
|
|
p = s;
|
|
if(s)
|
|
{
|
|
while(*s)
|
|
{
|
|
if(!isdigit(*s))
|
|
{
|
|
*s='\0';
|
|
}
|
|
s++;
|
|
};
|
|
m_iBytesTotal = atoi(p);
|
|
}
|
|
|
|
}
|
|
|
|
Sleep(1);
|
|
}while(!idataready);
|
|
ReadDataChannel();
|
|
return;
|
|
}
|
|
m_State = HTTP_STATE_FILE_NOT_FOUND;
|
|
fclose(LOCALFILE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
m_State = HTTP_STATE_UNKNOWN_ERROR;
|
|
fclose(LOCALFILE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
int ChttpGet::ConnectSocket()
|
|
{
|
|
unsigned int ip;
|
|
SERVENT *se;
|
|
SOCKADDR_IN hostaddr;
|
|
if(m_Aborting){
|
|
return 0;
|
|
}
|
|
|
|
ip = inet_addr((const char *)m_szHost);
|
|
|
|
int rcode = 0;
|
|
if(ip==INADDR_NONE)
|
|
{
|
|
http_Asyncgethostbyname(&ip,NW_AGHBN_LOOKUP,m_szHost);
|
|
do
|
|
{
|
|
if(m_Aborting)
|
|
{
|
|
http_Asyncgethostbyname(&ip,NW_AGHBN_CANCEL,m_szHost);
|
|
return 0;
|
|
}
|
|
rcode = http_Asyncgethostbyname(&ip,NW_AGHBN_READ,m_szHost);
|
|
|
|
Sleep(1);
|
|
}while(rcode==0);
|
|
}
|
|
|
|
if(rcode == -1)
|
|
{
|
|
m_State = HTTP_STATE_HOST_NOT_FOUND;
|
|
return 0;
|
|
}
|
|
//m_ControlSock
|
|
if(m_Aborting)
|
|
return 0;
|
|
se = getservbyname("http", NULL);
|
|
if(m_Aborting)
|
|
return 0;
|
|
if(se == NULL)
|
|
{
|
|
hostaddr.sin_port = htons(80);
|
|
}
|
|
else
|
|
{
|
|
hostaddr.sin_port = se->s_port;
|
|
}
|
|
hostaddr.sin_family = AF_INET;
|
|
memcpy(&hostaddr.sin_addr, &ip, 4);
|
|
|
|
if(m_ProxyEnabled)
|
|
{
|
|
//This is on a proxy, so we need to make sure to connect to the proxy machine
|
|
ip = inet_addr((const char *)m_ProxyIP);
|
|
|
|
if(ip==INADDR_NONE)
|
|
{
|
|
http_Asyncgethostbyname(&ip,NW_AGHBN_LOOKUP,m_ProxyIP);
|
|
rcode = 0;
|
|
do
|
|
{
|
|
if(m_Aborting)
|
|
{
|
|
http_Asyncgethostbyname(&ip,NW_AGHBN_CANCEL,m_ProxyIP);
|
|
return 0;
|
|
}
|
|
rcode = http_Asyncgethostbyname(&ip,NW_AGHBN_READ,m_ProxyIP);
|
|
|
|
Sleep(1);
|
|
}while(rcode==0);
|
|
|
|
|
|
if(rcode == -1)
|
|
{
|
|
m_State = HTTP_STATE_HOST_NOT_FOUND;
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
//Use either the proxy port or 80 if none specified
|
|
hostaddr.sin_port = htons((ushort)(m_ProxyPort ? m_ProxyPort : 80));
|
|
//Copy the proxy address...
|
|
memcpy(&hostaddr.sin_addr,&ip,4);
|
|
|
|
}
|
|
|
|
memset(&hostaddr.sin_zero, 0, sizeof(hostaddr.sin_zero));
|
|
|
|
//Now we will connect to the host
|
|
fd_set wfds;
|
|
|
|
timeval timeout;
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 0;
|
|
|
|
int serr = connect(m_DataSock, (SOCKADDR *)&hostaddr, sizeof(SOCKADDR));
|
|
int cerr = WSAGetLastError();
|
|
if (serr) {
|
|
while ( (cerr == WSAEALREADY) || (cerr == WSAEINVAL) || (cerr == WSAEWOULDBLOCK) ) {
|
|
FD_ZERO(&wfds);
|
|
FD_SET( m_DataSock, &wfds );
|
|
|
|
#ifdef WIN32
|
|
if ( select(0, NULL, &wfds, NULL, &timeout) )
|
|
#else
|
|
if ( select(m_DataSock+1, NULL, &wfds, NULL, &timeout) )
|
|
#endif
|
|
{
|
|
serr = 0;
|
|
break;
|
|
}
|
|
|
|
if (m_Aborting)
|
|
return 0;
|
|
|
|
serr = connect(m_DataSock, (SOCKADDR *)&hostaddr, sizeof(SOCKADDR));
|
|
|
|
if (serr == 0)
|
|
break;
|
|
|
|
cerr = WSAGetLastError();
|
|
|
|
if (cerr == WSAEISCONN) {
|
|
serr = 0;
|
|
break;
|
|
}
|
|
|
|
Sleep(1);
|
|
}
|
|
}
|
|
|
|
if (serr) {
|
|
m_State = HTTP_STATE_CANT_CONNECT;
|
|
return 0;
|
|
}
|
|
|
|
m_State = HTTP_STATE_CONNECTED;
|
|
|
|
return 1;
|
|
}
|
|
|
|
char *ChttpGet::GetHTTPLine()
|
|
{
|
|
int iBytesRead;
|
|
char chunk[2];
|
|
uint igotcrlf = 0;
|
|
memset(recv_buffer,0,1000);
|
|
do
|
|
{
|
|
chunk[0]='\0';
|
|
bool gotdata = false;
|
|
do
|
|
{
|
|
iBytesRead = recv(m_DataSock,chunk,1,0);
|
|
|
|
if(SOCKET_ERROR == iBytesRead)
|
|
{
|
|
int error = WSAGetLastError();
|
|
if(WSAEWOULDBLOCK==error)
|
|
{
|
|
gotdata = false;
|
|
continue;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
gotdata = true;
|
|
}
|
|
|
|
Sleep(1);
|
|
}while(!gotdata);
|
|
|
|
if(chunk[0]==0x0d)
|
|
{
|
|
//This should always read a 0x0a
|
|
do
|
|
{
|
|
iBytesRead = recv(m_DataSock,chunk,1,0);
|
|
|
|
if(SOCKET_ERROR == iBytesRead)
|
|
{
|
|
int error = WSAGetLastError();
|
|
if(WSAEWOULDBLOCK==error)
|
|
{
|
|
gotdata = false;
|
|
continue;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
gotdata = true;
|
|
}
|
|
|
|
Sleep(1);
|
|
}while(!gotdata);
|
|
igotcrlf = 1;
|
|
}
|
|
else
|
|
{ chunk[1] = '\0';
|
|
strcat_s(recv_buffer,chunk);
|
|
}
|
|
|
|
Sleep(1);
|
|
}while(igotcrlf==0);
|
|
return recv_buffer;
|
|
}
|
|
|
|
uint ChttpGet::ReadDataChannel()
|
|
{
|
|
char sDataBuffer[4096]; // Data-storage buffer for the data channel
|
|
int nBytesRecv = 0; // Bytes received from the data channel
|
|
|
|
fd_set wfds;
|
|
|
|
timeval timeout;
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 500;
|
|
|
|
m_State = HTTP_STATE_RECEIVING;
|
|
|
|
do {
|
|
FD_ZERO(&wfds);
|
|
FD_SET( m_DataSock, &wfds );
|
|
|
|
if ( (m_iBytesTotal) && (m_iBytesIn == m_iBytesTotal) )
|
|
break;
|
|
|
|
#ifdef WIN32
|
|
select(0, &wfds, NULL, NULL, &timeout);
|
|
#else
|
|
select(m_DataSock+1, &wfds, NULL, NULL, &timeout);
|
|
#endif
|
|
|
|
if (m_Aborting) {
|
|
fclose(LOCALFILE);
|
|
return 0;
|
|
}
|
|
|
|
nBytesRecv = recv(m_DataSock, (char *)&sDataBuffer, sizeof(sDataBuffer), 0);
|
|
|
|
if (m_Aborting) {
|
|
fclose(LOCALFILE);
|
|
return 0;
|
|
}
|
|
|
|
if (SOCKET_ERROR == nBytesRecv) {
|
|
int error = WSAGetLastError();
|
|
|
|
if (error == WSAEWOULDBLOCK) {
|
|
nBytesRecv = 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
m_iBytesIn += nBytesRecv;
|
|
|
|
if (nBytesRecv > 0 ) {
|
|
fwrite(sDataBuffer, nBytesRecv, 1, LOCALFILE);
|
|
}
|
|
|
|
Sleep(1);
|
|
} while (nBytesRecv > 0);
|
|
|
|
fclose(LOCALFILE);
|
|
|
|
// Close the file and check for error returns.
|
|
if (nBytesRecv == SOCKET_ERROR) {
|
|
//Ok, we got a socket error -- xfer aborted?
|
|
m_State = HTTP_STATE_RECV_FAILED;
|
|
return 0;
|
|
} else {
|
|
//done!
|
|
m_State = HTTP_STATE_FILE_RECEIVED;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct _async_dns_lookup
|
|
{
|
|
unsigned int ip; //resolved host. Write only to worker thread.
|
|
char * host;//host name to resolve. read only to worker thread
|
|
bool done; //write only to the worker thread. Signals that the operation is complete
|
|
bool error; //write only to worker thread. Thread sets this if the name doesn't resolve
|
|
bool abort; //read only to worker thread. If this is set, don't fill in the struct.
|
|
}async_dns_lookup;
|
|
|
|
async_dns_lookup httpaslu;
|
|
async_dns_lookup *http_lastaslu = NULL;
|
|
|
|
#ifdef WIN32
|
|
void __cdecl http_gethostbynameworker(void *parm);
|
|
#else
|
|
int http_gethostbynameworker(void *parm);
|
|
#endif
|
|
|
|
int http_Asyncgethostbyname(unsigned int *ip,int command, char *hostname)
|
|
{
|
|
|
|
if(command==NW_AGHBN_LOOKUP)
|
|
{
|
|
if(http_lastaslu)
|
|
http_lastaslu->abort = true;
|
|
|
|
async_dns_lookup *newaslu;
|
|
newaslu = (async_dns_lookup *)vm_malloc(sizeof(async_dns_lookup));
|
|
memset(&newaslu->ip,0,sizeof(unsigned int));
|
|
newaslu->host = hostname;
|
|
newaslu->done = false;
|
|
newaslu->error = false;
|
|
newaslu->abort = false;
|
|
http_lastaslu = newaslu;
|
|
httpaslu.done = false;
|
|
|
|
#ifdef WIN32
|
|
_beginthread(http_gethostbynameworker, 0, newaslu);
|
|
#else
|
|
HOSTENT *he = gethostbyname(hostname);
|
|
|
|
if (he == NULL) {
|
|
newaslu->error = true;
|
|
} else if ( !newaslu->abort ) {
|
|
memcpy( &newaslu->ip, he->h_addr_list[0], sizeof(uint) );
|
|
newaslu->done = true;
|
|
memcpy( &httpaslu,newaslu, sizeof(async_dns_lookup) );
|
|
}
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
else if(command==NW_AGHBN_CANCEL)
|
|
{
|
|
if(http_lastaslu)
|
|
http_lastaslu->abort = true;
|
|
http_lastaslu = NULL;
|
|
}
|
|
else if(command==NW_AGHBN_READ)
|
|
{
|
|
if(!http_lastaslu)
|
|
return -1;
|
|
if(httpaslu.done)
|
|
{
|
|
http_lastaslu = NULL;
|
|
memcpy(ip,&httpaslu.ip,sizeof(unsigned int));
|
|
return 1;
|
|
}
|
|
else if(httpaslu.error)
|
|
{
|
|
vm_free(http_lastaslu);
|
|
http_lastaslu = NULL;
|
|
return -1;
|
|
}
|
|
else return 0;
|
|
}
|
|
return -2;
|
|
|
|
}
|
|
|
|
// This is the worker thread which does the lookup.
|
|
#ifdef WIN32
|
|
void __cdecl http_gethostbynameworker(void *parm)
|
|
#else
|
|
int http_gethostbynameworker(void *parm)
|
|
#endif
|
|
{
|
|
#ifdef SCP_UNIX
|
|
// df_pthread_detach(df_pthread_self());
|
|
#endif
|
|
async_dns_lookup *lookup = (async_dns_lookup *)parm;
|
|
HOSTENT *he = gethostbyname(lookup->host);
|
|
if(he==NULL)
|
|
{
|
|
lookup->error = true;
|
|
#ifdef WIN32
|
|
return;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
else if(!lookup->abort)
|
|
{
|
|
memcpy(&lookup->ip,he->h_addr_list[0],sizeof(unsigned int));
|
|
lookup->done = true;
|
|
memcpy(&httpaslu,lookup,sizeof(async_dns_lookup));
|
|
}
|
|
vm_free(lookup);
|
|
|
|
#ifdef SCP_UNIX
|
|
return 0;
|
|
#endif
|
|
}
|