425 lines
12 KiB
C++
425 lines
12 KiB
C++
#include <socket/socket.hpp>
|
|
#include <common/diskinfo.hpp>
|
|
#include <common/openfile.hpp>
|
|
#include <common/filemap.hpp>
|
|
#include <common/pview.hpp>
|
|
#include <common/profile.hpp>
|
|
#include <common/block.hpp>
|
|
|
|
bool Socket::create(Domain domain,Type type,Protocol protocol)
|
|
{
|
|
destroy();
|
|
if(!isInitialized())return isOkay();
|
|
mSocket=::socket((int)domain,(int)type,(int)protocol);
|
|
mReceiveCache.socket(mSocket);
|
|
mDisposition=CloseSocket;
|
|
return isOkay();
|
|
}
|
|
|
|
void Socket::destroy(void)
|
|
{
|
|
if(!isOkay()||!isInitialized())return;
|
|
if(CloseSocket==mDisposition)::closesocket(mSocket);
|
|
mSocket=INVALID_SOCKET;
|
|
isConnected(FALSE);
|
|
isBound(FALSE);
|
|
isListening(FALSE);
|
|
}
|
|
|
|
Socket &Socket::operator=(const Socket &someSocket)
|
|
{
|
|
destroy();
|
|
mSocket=someSocket.mSocket;
|
|
mReceiveCache.socket(mSocket);
|
|
mDisposition=AssumedSocket;
|
|
isConnected(someSocket.isConnected());
|
|
isBound(someSocket.isBound());
|
|
isListening(someSocket.isListening());
|
|
return *this;
|
|
}
|
|
|
|
Socket &Socket::operator=(SOCKET someSOCKET)
|
|
{
|
|
destroy();
|
|
mSocket=someSOCKET;
|
|
mReceiveCache.socket(mSocket);
|
|
mDisposition=CloseSocket;
|
|
isConnected(FALSE);
|
|
isBound(FALSE);
|
|
isListening(FALSE);
|
|
return *this;
|
|
}
|
|
|
|
DWORD Socket::receive(char *buffer,DWORD count,bool waitForData)
|
|
{
|
|
DWORD cbytes(0);
|
|
|
|
for(;cbytes<count;cbytes++)
|
|
{
|
|
if(!mReceiveCache.receive(*buffer,waitForData))break;
|
|
buffer++;
|
|
}
|
|
return cbytes;
|
|
}
|
|
|
|
bool Socket::receive(char &charData,bool waitForData)
|
|
{
|
|
if(!isConnected())return false;
|
|
if(!mReceiveCache.receive(charData,waitForData))return false;
|
|
return true;
|
|
}
|
|
|
|
bool Socket::receive(String &receiveString,bool waitForData)
|
|
{
|
|
char rcvChar;
|
|
|
|
receiveString.reserve(MaxLength);
|
|
while(TRUE)
|
|
{
|
|
if(!isConnected())return false;
|
|
if(!mReceiveCache.receive(rcvChar,waitForData))
|
|
{
|
|
if(receiveString.isNull())return false;
|
|
break;
|
|
}
|
|
if(rcvChar==0x0D)continue;
|
|
else if(rcvChar==0x0A)break;
|
|
else receiveString+=rcvChar;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Socket::receive(Block<String> &receiveStrings)
|
|
{
|
|
String stringData;
|
|
String seriesItem;
|
|
|
|
receiveStrings.remove();
|
|
while(TRUE)
|
|
{
|
|
if(!receive(stringData))break;
|
|
if(!receiveStrings.size())seriesItem=stringData.substr(0,2);
|
|
receiveStrings.insert(&stringData);
|
|
if(!(stringData.operator[](3)=='-'&&stringData.substr(0,2)==seriesItem))break;
|
|
if(!isConnected())break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Socket::receiveFrom(void *pBuffer,int buflen,DWORD msgType,INETSocketAddress &from)
|
|
{
|
|
int fromLength(sizeof(sockaddr_in));
|
|
if(!isOkay()||!pBuffer||buflen<=0)return false;
|
|
return !(-1==::recvfrom(mSocket,(char*)pBuffer,buflen,msgType,(sockaddr*)&(from.getsockaddr()),&fromLength));
|
|
}
|
|
|
|
bool Socket::receivePage(Block<String> &receiveStrings)
|
|
{
|
|
String stringData;
|
|
|
|
receiveStrings.remove();
|
|
while(TRUE)
|
|
{
|
|
if(!receive(stringData))break;
|
|
receiveStrings.insert(&stringData);
|
|
if(stringData.substr(0,6)==String("</html>")||stringData.substr(0,6)==String("</HTML>"))break;
|
|
else if(stringData.substr(0,13)==String("</body></html>")||stringData.substr(0,13)==String("</BODY></HTML>"))break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Socket::receiveHeader(Block<String> &headerLines)
|
|
{
|
|
String stringData;
|
|
|
|
headerLines.remove();
|
|
while(true)
|
|
{
|
|
if(!receive(stringData))break;
|
|
if(stringData.isNull())break;
|
|
stringData.lower();
|
|
headerLines.insert(&stringData);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Socket::receiveImage(String pathFileName,TimeInfo &someTimeInfo)
|
|
{
|
|
String strDirectory(pathFileName);
|
|
DiskInfo diskInfo;
|
|
Profile iniProfile;
|
|
char rcvChar[BlockLength];
|
|
DWORD bufferLength;
|
|
DWORD receiveCount(0);
|
|
Block<String> headerLines;
|
|
DWORD sizeData(0);
|
|
|
|
if(!isConnected())return false;
|
|
if(diskInfo.getDiskFreeSpace()<sizeData)return false;
|
|
if(pathFileName.isNull())return false;
|
|
if(iniProfile.makeDirectoryName(strDirectory))diskInfo.createDirectory(strDirectory);
|
|
receiveHeader(headerLines);
|
|
for(int lineIndex=0;lineIndex<headerLines.size();lineIndex++)
|
|
{
|
|
String &headerLine=headerLines[lineIndex];
|
|
if(headerLine.betweenString(0,':')==String("content-length"))sizeData=::atoi(headerLine.betweenString(':',0));
|
|
}
|
|
if(!sizeData)return receiveBinary(pathFileName,250000,someTimeInfo);
|
|
FileHandle writeFile(pathFileName,FileHandle::Write,FileHandle::ShareRead,FileHandle::Overwrite);
|
|
if(!writeFile.isOkay())return false;
|
|
someTimeInfo.startTime();
|
|
while(receiveCount<sizeData)
|
|
{
|
|
if(receiveCount+sizeof(rcvChar)>sizeData)bufferLength=sizeData-receiveCount;
|
|
else bufferLength=sizeof(rcvChar);
|
|
while(!mReceiveCache.isReady(FALSE));
|
|
mReceiveCache.receive(rcvChar,bufferLength,bufferLength);
|
|
if(!bufferLength)continue;
|
|
writeFile.write((unsigned char*)rcvChar,bufferLength);
|
|
receiveCount+=bufferLength;
|
|
if(!isConnected())break;
|
|
}
|
|
someTimeInfo.endTime(sizeData);
|
|
writeFile.close();
|
|
return true;
|
|
}
|
|
|
|
bool Socket::receiveBinary(String pathFileName,DWORD sizeData,TimeInfo &someTimeInfo)
|
|
{
|
|
String strDirectory(pathFileName);
|
|
DiskInfo diskInfo;
|
|
Profile iniProfile;
|
|
char rcvChar[BlockLength];
|
|
DWORD bufferLength;
|
|
DWORD receiveCount(0);
|
|
|
|
if(!isConnected())return false;
|
|
if(diskInfo.getDiskFreeSpace()<sizeData)return false;
|
|
if(pathFileName.isNull())return false;
|
|
if(iniProfile.makeDirectoryName(strDirectory))diskInfo.createDirectory(strDirectory);
|
|
FileHandle writeFile(pathFileName,FileHandle::Write,FileHandle::ShareRead,FileHandle::Overwrite);
|
|
if(!writeFile.isOkay())return false;
|
|
someTimeInfo.startTime();
|
|
while(receiveCount<sizeData)
|
|
{
|
|
if(receiveCount+sizeof(rcvChar)>sizeData)bufferLength=sizeData-receiveCount;
|
|
else bufferLength=sizeof(rcvChar);
|
|
while(!mReceiveCache.isReady(FALSE));
|
|
if(!mReceiveCache.receive(rcvChar,sizeof(rcvChar),bufferLength))break;
|
|
writeFile.write((unsigned char*)rcvChar,bufferLength);
|
|
receiveCount+=bufferLength;
|
|
if(!isConnected())break;
|
|
}
|
|
someTimeInfo.endTime(sizeData);
|
|
return false;
|
|
}
|
|
|
|
bool Socket::receiveBinary(String pathFileName,TimeInfo &someTimeInfo)
|
|
{
|
|
Profile iniProfile;
|
|
char rcvChar[BlockLength];
|
|
DWORD bufferLength(sizeof(rcvChar));
|
|
DWORD receiveCount(0);
|
|
|
|
if(!isConnected())return false;
|
|
iniProfile.makeFileName(pathFileName);
|
|
if(pathFileName.isNull())return false;
|
|
FileHandle writeFile(pathFileName,FileHandle::Write,FileHandle::ShareRead,FileHandle::Overwrite);
|
|
someTimeInfo.startTime();
|
|
while(true)
|
|
{
|
|
while(!mReceiveCache.isReady(false));
|
|
if(!mReceiveCache.receive(rcvChar,sizeof(rcvChar),bufferLength))break;
|
|
writeFile.write((unsigned char*)rcvChar,bufferLength);
|
|
receiveCount+=bufferLength;
|
|
if(!isConnected())break;
|
|
}
|
|
someTimeInfo.endTime(receiveCount);
|
|
return true;
|
|
}
|
|
|
|
bool Socket::send(const char *buffer,DWORD count)
|
|
{
|
|
if(!isConnected())return false;
|
|
if(!count)return false;
|
|
canWrite();
|
|
if(SOCKET_ERROR==::send(mSocket,buffer,count,0))return false;
|
|
return true;
|
|
}
|
|
|
|
bool Socket::send(const char &charData)
|
|
{
|
|
if(!isConnected())return false;
|
|
canWrite();
|
|
if(SOCKET_ERROR==::send(mSocket,&((char&)charData),sizeof(charData),0))return false;
|
|
return true;
|
|
}
|
|
|
|
bool Socket::send(Block<String> &strings)
|
|
{
|
|
for(int index=0;index<strings.size();index++)
|
|
{
|
|
if(!send(strings[index]))return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Socket::send(const String &sendString)
|
|
{
|
|
String strLineString;
|
|
String crlf("\r\n");
|
|
int strLength;
|
|
|
|
// if(!isConnected()||sendString.isNull())return false;
|
|
if(!isConnected())return false;
|
|
strLineString=sendString+crlf;
|
|
strLength=strLineString.length();
|
|
canWrite();
|
|
if(::send(mSocket,(LPSTR)((String&)strLineString),strLength,0)<strLength)return false;
|
|
return true;
|
|
}
|
|
|
|
bool Socket::sendBinary(String pathFileName,TimeInfo &someTimeInfo)
|
|
{
|
|
FileHandle sendFile(pathFileName,FileHandle::Read,FileHandle::ShareRead);
|
|
FileMap sendMap(sendFile);
|
|
PureViewOfFile sendView(sendMap);
|
|
char sndChar[BlockLength];
|
|
DWORD sndLength;
|
|
|
|
if(!sendFile.isOkay())return false;
|
|
someTimeInfo.startTime();
|
|
while(true)
|
|
{
|
|
sndLength=sendView.read(sndChar,sizeof(sndChar));
|
|
if(!sndLength)break;
|
|
canWrite();
|
|
if(SOCKET_ERROR==::send(mSocket,sndChar,sndLength,0))break;
|
|
if(!isConnected())break;
|
|
}
|
|
someTimeInfo.endTime(sendFile.size());
|
|
return true;
|
|
}
|
|
|
|
bool Socket::sendTo(void *pBuffer,int buflen,INETSocketAddress &inetSocketAddress)
|
|
{
|
|
if(!isOkay()||!pBuffer||!buflen)return false;
|
|
return ::sendto(mSocket,(const char*)pBuffer,buflen,0,(sockaddr*)&((sockaddr_in&)inetSocketAddress),sizeof(sockaddr_in))?true:false;
|
|
}
|
|
|
|
bool Socket::bind(INETSocketAddress &internetSocketAddress)
|
|
{
|
|
int nameLength(sizeof(sockaddr_in));
|
|
if(isConnected()||isBound())return false;
|
|
if(!isOkay()&&!create())return false;
|
|
if(!::bind(mSocket,(sockaddr*)&((sockaddr_in&)internetSocketAddress),sizeof(sockaddr)))isBound(true);
|
|
if(isBound())::getsockname(mSocket,(sockaddr*)&((sockaddr_in&)internetSocketAddress),&nameLength);
|
|
return isBound();
|
|
}
|
|
|
|
bool Socket::bind(SocketAddress &socketAddress)
|
|
{
|
|
if(isConnected()||isBound())return false;
|
|
if(!isOkay()&&!create())return false;
|
|
if(!::bind(mSocket,(sockaddr*)&((sockaddr_in&)socketAddress),SocketAddress::length()))isBound(true);
|
|
return isBound();
|
|
}
|
|
|
|
bool Socket::connect(INETSocketAddress &internetSocketAddress)
|
|
{
|
|
if(isConnected())return false;
|
|
if(!isOkay()&&!create())return false;
|
|
if(!::connect(mSocket,(sockaddr*)&((sockaddr_in&)internetSocketAddress),sizeof(sockaddr_in)))isConnected(TRUE);
|
|
return isConnected();
|
|
}
|
|
|
|
bool Socket::getSocketName(INETSocketAddress &internetSocketAddress)
|
|
{
|
|
int length(sizeof(sockaddr_in));
|
|
if(!isOkay())return false;
|
|
if(SOCKET_ERROR==::getsockname(mSocket,(sockaddr*)&((sockaddr_in&)internetSocketAddress),&length))return false;
|
|
return true;
|
|
}
|
|
|
|
bool Socket::getPeerName(INETSocketAddress &internetSocketAddress)
|
|
{
|
|
int length(sizeof(sockaddr_in));
|
|
|
|
if(!isConnected())return false;
|
|
if(SOCKET_ERROR==::getpeername(mSocket,(sockaddr*)&((sockaddr_in&)internetSocketAddress),&length))return false;
|
|
return true;
|
|
}
|
|
|
|
bool Socket::listen(int maxPendingRequests)
|
|
{
|
|
if(!isOkay()||!isBound())return FALSE;
|
|
if(!::listen(mSocket,maxPendingRequests))isListening(TRUE);
|
|
return isListening();
|
|
}
|
|
|
|
bool Socket::accept(Socket &someSocket)
|
|
{
|
|
someSocket.destroy();
|
|
if(!isOkay()||!isListening())return FALSE;
|
|
someSocket=::accept(mSocket,0,0);
|
|
if(someSocket.isOkay())someSocket.isConnected(TRUE);
|
|
return someSocket.isOkay();
|
|
}
|
|
|
|
bool Socket::accept(Socket &someSocket,INETSocketAddress &internetSocketAddress)
|
|
{
|
|
int addressLength(sizeof(sockaddr_in));
|
|
|
|
someSocket.destroy();
|
|
if(!isOkay()||!isListening())return FALSE;
|
|
someSocket=::accept(mSocket,(sockaddr*)&internetSocketAddress,&addressLength);
|
|
if(someSocket.isOkay())someSocket.isConnected(TRUE);
|
|
return someSocket.isOkay();
|
|
}
|
|
|
|
bool Socket::reuseAddress(bool reuseAddress)
|
|
{
|
|
int reuse(reuseAddress);
|
|
if(!isOkay())return false;
|
|
return !(::setsockopt(mSocket,SOL_SOCKET,SO_REUSEADDR,(char*)&reuse,sizeof(int)));
|
|
}
|
|
|
|
bool Socket::setLinger(int seconds)
|
|
{
|
|
LINGER linger;
|
|
if(!isOkay())return false;
|
|
linger.l_onoff=1;
|
|
linger.l_linger=seconds;
|
|
return !(::setsockopt(mSocket,SOL_SOCKET,SO_DONTLINGER,(char*)&linger,sizeof(linger)));
|
|
}
|
|
|
|
bool Socket::setDontLinger(void)
|
|
{
|
|
LINGER linger;
|
|
if(!isOkay())return false;
|
|
linger.l_onoff=0;
|
|
linger.l_linger=0;
|
|
return !(::setsockopt(mSocket,SOL_SOCKET,SO_DONTLINGER,(char*)&linger,sizeof(linger)));
|
|
}
|
|
|
|
bool Socket::addMembership(IPMReq &ipMReq)
|
|
{
|
|
return !(::setsockopt(mSocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&((ip_mreq&)ipMReq),IPMReq::length()));
|
|
}
|
|
|
|
bool Socket::dropMembership(IPMReq &ipMReq)
|
|
{
|
|
return !(::setsockopt(mSocket,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char*)&((ip_mreq&)ipMReq),IPMReq::length()));
|
|
}
|
|
|
|
bool Socket::setMulticastTTL(int ttl)
|
|
{
|
|
return !(::setsockopt(mSocket,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&ttl,sizeof(ttl)));
|
|
}
|
|
|
|
bool Socket::setMulticastLoopback(bool loopback)
|
|
{
|
|
int loop(loopback);
|
|
return !(::setsockopt(mSocket,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&loop,sizeof(loop)));
|
|
}
|