CClientThread::CClientThread(SOCKET pSocket, CTCPFileServ* pParent)
{
	int_socket=pSocket;
	DisableNagle();

	stopped=false;
	killable=false;
	has_socket=true;

	parent=pParent;

#ifdef _WIN32
	bufmgr=new CBufMgr(NBUFFERS,READSIZE);
#else
	bufmgr=NULL;
#endif

	hFile=0;

#ifdef _WIN32
	int window_size;
	int window_size_len=sizeof(window_size);
	getsockopt(pSocket, SOL_SOCKET, SO_SNDBUF,(char *) &window_size, &window_size_len );
	Log("Info: Window size="+nconvert(window_size));
#endif

	close_the_socket=true;
	errcount=0;
	clientpipe=Server->PipeFromSocket(pSocket);
	mutex=NULL;
	cond=NULL;
	state=CS_NONE;
	update_file=NULL;
	chunk_send_thread_ticket=ILLEGAL_THREADPOOL_TICKET;
}
示例#2
0
		bool CClientSock::Connect(char*ip,int port)
		{
			WSAData wsaData;
			if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
			{
				return false;
			}

			sockaddr_in addr;
			addr.sin_family = AF_INET;
			addr.sin_addr.S_un.S_addr = inet_addr(ip);
			addr.sin_port = htons(port);

			m_sock = socket(AF_INET,SOCK_STREAM,0);

			DisableNagle(m_sock);

			int sz = sizeof(addr);

			if (connect(m_sock,(sockaddr*)&addr,sz) == SOCKET_ERROR)
			{
				return false;
			}

			LINGER lingerStruct;
			lingerStruct.l_onoff = 1;
			lingerStruct.l_linger = 0;
			setsockopt(m_sock,SOL_SOCKET,SO_DONTLINGER,(const char*)(&lingerStruct),sizeof(lingerStruct));

			m_running = true;

			DWORD dwThreadID;
			HANDLE h = CreateThread(NULL,NULL,SendFunc,this,NULL,&dwThreadID);
			if (!h)
			{
				m_running = false;
				return false;
			}
			h = CreateThread(NULL,NULL,RecvFunc,this,NULL,&dwThreadID);
			if (!h)
			{
				m_running = false;
				return false;
			}
			printf("clientSock is running...\n");
			return true;
		}
bool CClientThread::ProcessPacket(CRData *data)
{
	uchar id;
	if( data->getUChar(&id)==true )
	{
		switch(id)
		{
		case ID_GET_GAMELIST:
			{	
#ifdef CHECK_IDENT
				std::string ident;
				data->getStr(&ident);
				if(!FileServ::checkIdentity(ident))
				{
					Log("Identity check failed -1", LL_DEBUG);
					return false;
				}
#endif

				hFile=0;
				std::vector<std::wstring> games=get_maps();


				Log("Sending game list", LL_DEBUG);

				EnableNagle();

				CWData data;
				data.addUChar( ID_GAMELIST );
				data.addUInt( (unsigned int)games.size() );

				stack.Send(clientpipe, data);

				for(size_t i=0;i<games.size();++i)
				{
					std::string version;
					std::wstring udir;
					version=getFile(wnarrow(map_file(games[i]+L"\\version.uri",true,&udir)));

					if( udir!=L"" )
						games[i]+=L"|"+udir;

					std::string game=Server->ConvertToUTF8(games[i]);
					

					stack.Send(clientpipe, (char*)game.c_str(), game.size() );					
					stack.Send(clientpipe, (char*)version.c_str(), version.size() );
				}
				
				Log("done.", LL_DEBUG);

				DisableNagle();
			}break;
		case ID_GET_FILE_RESUME:
		case ID_GET_FILE:
		case ID_GET_FILE_RESUME_HASH:
			{
				std::string s_filename;
				if(data->getStr(&s_filename)==false)
					break;

#ifdef CHECK_IDENT
				std::string ident;
				data->getStr(&ident);
				if(!FileServ::checkIdentity(ident))
				{
					Log("Identity check failed -2", LL_DEBUG);
					return false;
				}
#endif

				std::wstring o_filename=Server->ConvertToUnicode(s_filename);

				_i64 start_offset=0;
				bool offset_set=data->getInt64(&start_offset);

				Log("Sending file "+Server->ConvertToUTF8(o_filename), LL_DEBUG);

				std::wstring filename=map_file(o_filename);

				Log("Mapped name: "+Server->ConvertToUTF8(filename), LL_DEBUG);

				if(filename.empty())
				{
					char ch=ID_BASE_DIR_LOST;
					int rc=SendInt(&ch, 1);

					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: Send BASE_DIR_LOST -1", LL_DEBUG);
						return false;
					}
					Log("Info: Base dir lost -1", LL_DEBUG);
					break;
				}

				cmd_id=id;

				if( id==ID_GET_FILE_RESUME_HASH )
				{
					hash_func.init();
				}

#ifdef _WIN32
				if(filename.size()<2 || (filename[0]!='\\' && filename[1]!='\\' ) )
				{
					filename=L"\\\\?\\"+filename;			
				}

				if(bufmgr==NULL)
				{
					bufmgr=new CBufMgr(NBUFFERS,READSIZE);
				}
#endif
				
#ifndef LINUX
#ifndef BACKUP_SEM
				hFile=CreateFileW(filename.c_str(), FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
#else
				hFile=CreateFileW(filename.c_str(), FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
#endif

				if(hFile == INVALID_HANDLE_VALUE)
				{
					hFile=NULL;
#ifdef CHECK_BASE_PATH
					std::wstring basePath=map_file(getuntil(L"/",o_filename)+L"/");
					if(!isDirectory(basePath))
					{
						char ch=ID_BASE_DIR_LOST;
						int rc=SendInt(&ch, 1);
						if(rc==SOCKET_ERROR)
						{
							Log("Error: Socket Error - DBG: Send BASE_DIR_LOST", LL_DEBUG);
							return false;
						}
						Log("Info: Base dir lost", LL_DEBUG);
						break;
					}
#endif
					
					char ch=ID_COULDNT_OPEN;
					int rc=SendInt(&ch, 1);
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: Send COULDNT OPEN", LL_DEBUG);
						return false;
					}
					Log("Info: Couldn't open file", LL_DEBUG);
					break;
				}

				currfilepart=0;
				sendfilepart=0;
				sent_bytes=start_offset;

				LARGE_INTEGER filesize;
				GetFileSizeEx(hFile, &filesize);

				curr_filesize=filesize.QuadPart;

				next_checkpoint=start_offset+c_checkpoint_dist;
				if(next_checkpoint>curr_filesize)
					next_checkpoint=curr_filesize;

				if( offset_set==false || id==ID_GET_FILE_RESUME || id==ID_GET_FILE_RESUME_HASH )
				{
					CWData data;
					data.addUChar(ID_FILESIZE);
					data.addUInt64(filesize.QuadPart);

					int rc=SendInt(data.getDataPtr(), data.getDataSize());
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: SendSize", LL_DEBUG);
						CloseHandle(hFile);
						hFile=NULL;
						return false;
					}
				}

				if(filesize.QuadPart==0)
				{
					CloseHandle(hFile);
					hFile=NULL;
					break;
				}

				for(_i64 i=start_offset;i<filesize.QuadPart && stopped==false;i+=READSIZE)
				{
					bool last;
					if(i+READSIZE<filesize.QuadPart)
						last=false;
					else
					{
						last=true;
						Log("Reading last file part", LL_DEBUG);
					}

					while(bufmgr->nfreeBufffer()==0 && stopped==false)
					{
						int rc;
						SleepEx(0,true);
						rc=SendData();
						if(rc==-1)
						{
							Log("Error: Send failed in file loop -1", LL_DEBUG);
							CloseThread(hFile);
						}
						else if(rc==0)
							SleepEx(1,true);
					}

					if( stopped==false )
						ReadFilePart(hFile, i, last);

					if(FileServ::isPause() )
					{
						DWORD starttime=GetTickCount();
						while(GetTickCount()-starttime<5000)
						{
							SleepEx(500,true);

							int rc=SendData();
							if(rc==-1)
							{
								Log("Error: Send failed in file pause loop -2", LL_DEBUG);
								CloseThread(hFile);
							}
						}
					}
				}

				while(bufmgr->nfreeBufffer()!=NBUFFERS && stopped==false)
				{
					SleepEx(0,true);
					int rc;
					rc=SendData();
					
					if( rc==2 && bufmgr->nfreeBufffer()!=NBUFFERS )
					{
						Log("Error: File end and not all Buffers are free!-1", LL_WARNING);
					}

					if(rc==-1)
					{
						Log("Error: Send failed in off file loop -3", LL_DEBUG);
						CloseHandle(hFile);
						hFile=NULL;
						break;
					}
					else if(rc==0)
						SleepEx(1,true);
				}

				if( stopped==false )
				{
					Log("Closed file.", LL_DEBUG);
					CloseHandle(hFile);
					hFile=NULL;
				}
#else //LINUX
				hFile=open64(Server->ConvertToUTF8(filename).c_str(), O_RDONLY|O_LARGEFILE);
				
				if(hFile == INVALID_HANDLE_VALUE)
				{
#ifdef CHECK_BASE_PATH
					std::wstring basePath=map_file(getuntil(L"/",o_filename)+L"/");
					if(!isDirectory(basePath))
					{
						char ch=ID_BASE_DIR_LOST;
						int rc=SendInt(&ch, 1);
						if(rc==SOCKET_ERROR)
						{
							Log("Error: Socket Error - DBG: Send BASE_DIR_LOST", LL_DEBUG);
							return false;
						}
						Log("Info: Base dir lost", LL_DEBUG);
						break;
					}
#endif
					hFile=0;
					char ch=ID_COULDNT_OPEN;
					int rc=SendInt(&ch, 1);
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: Send COULDNT OPEN", LL_DEBUG);
						return false;
					}
					Log("Info: Couldn't open file", LL_DEBUG);
					break;
				}
				
				currfilepart=0;
				sendfilepart=0;
				
				struct stat64 stat_buf;
				fstat64(hFile, &stat_buf);
				
				off64_t filesize=stat_buf.st_size;
				curr_filesize=filesize;
				
				if( offset_set==false || id==ID_GET_FILE_RESUME || id==ID_GET_FILE_RESUME_HASH )
				{
					CWData data;
					data.addUChar(ID_FILESIZE);
					data.addUInt64(filesize);

					int rc=SendInt(data.getDataPtr(), data.getDataSize() );	
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: SendSize", LL_DEBUG);
						CloseHandle(hFile);
						hFile=0;
						return false;
					}
				}
				
				if(filesize==0)
				{
					CloseHandle(hFile);
					hFile=0;
					break;
				}
				
				off64_t foffset=start_offset;

				unsigned int s_bsize=8192;

				if(id==ID_GET_FILE || id==ID_GET_FILE_RESUME )
				{
					s_bsize=32768;
					next_checkpoint=curr_filesize;
				}
				else
				{
					next_checkpoint=start_offset+c_checkpoint_dist;
					if(next_checkpoint>curr_filesize)
					    next_checkpoint=curr_filesize;
				}

				char *buf=new char[s_bsize];

				bool has_error=false;
				
				while( foffset < filesize )
				{
					size_t count=(std::min)((size_t)s_bsize, (size_t)(next_checkpoint-foffset));
					if( clientpipe==NULL && ( id==ID_GET_FILE || id==ID_GET_FILE_RESUME ) )
					{
						ssize_t rc=sendfile64(int_socket, hFile, &foffset, count);
						if(rc>0)
						{
							foffset+=rc;
						}
						else
						{
							Log("Error: Reading and sending from file failed", LL_DEBUG);
							CloseHandle(hFile);
							delete []buf;
							return false;
						}
					}
					else
					{
						ssize_t rc=read(hFile, buf, count);
						if(rc>0)
						{
							rc=SendInt(buf, rc);
							if(rc==SOCKET_ERROR)
							{
								Log("Error: Sending data failed");
								CloseHandle(hFile);
								delete []buf;
								return false;
							}
							else if(id==ID_GET_FILE_RESUME_HASH)
							{
								hash_func.update((unsigned char*)buf, rc);
							}
							
							foffset+=rc;
						}
						else
						{
							Log("Error: Reading from file failed", LL_DEBUG);
							CloseHandle(hFile);
							delete []buf;
							return false;
						}
						
						if(id==ID_GET_FILE_RESUME_HASH && foffset==next_checkpoint)
						{
							hash_func.finalize();
							SendInt((char*)hash_func.raw_digest_int(), 16);
							next_checkpoint+=c_checkpoint_dist;
							if(next_checkpoint>curr_filesize)
								next_checkpoint=curr_filesize;
							
							hash_func.init();
						}
					}
					if(FileServ::isPause() )
					{
						Sleep(500);
					}
				}
				
				CloseHandle(hFile);
				delete []buf;
				hFile=0;
#endif

			}break;
		case ID_GET_FILE_BLOCKDIFF:
			{
				bool b=GetFileBlockdiff(data);
				if(!b)
					return false;
			}break;
		case ID_BLOCK_REQUEST:
			{
				if(state==CS_BLOCKHASH)
				{
					Handle_ID_BLOCK_REQUEST(data);
				}
			}break;
		}
	}
	if( stopped==true )
		return false;
	else
		return true;
}