void CTransferSocket::OnConnect(int nErrorCode) { if (nErrorCode) { if (m_hFile!=INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } Close(); if (!m_bSentClose) { m_bSentClose = TRUE; m_status = 2; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } #ifndef NOLAYERS if (m_pGssLayer) VERIFY(AddLayer(m_pGssLayer)); #endif if (!m_bStarted) InitTransfer(FALSE); CAsyncSocketEx::OnConnect(nErrorCode); }
void CTransferSocket::OnAccept(int nErrorCode) { CAsyncSocketEx tmp; Accept(tmp); SOCKET socket=tmp.Detach(); Close(); Attach(socket); bAccepted=TRUE; #ifndef NOLAYERS if (m_pGssLayer) VERIFY(AddLayer(m_pGssLayer)); #endif if (m_bReady) if (!m_bStarted) InitTransfer(FALSE); CAsyncSocketEx::OnAccept(nErrorCode); }
void CTransferSocket::OnReceive(int nErrorCode) { CAsyncSocketEx::OnReceive(nErrorCode); if (nErrorCode) { Close(); if (m_hFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } if (!m_bSentClose) { m_bSentClose=TRUE; m_status=3; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } GetSystemTime(&m_LastActiveTime); if (m_nMode==TRANSFERMODE_RECEIVE) { if (!m_bStarted) if (!InitTransfer(FALSE)) return; if (m_hFile == INVALID_HANDLE_VALUE) { ASSERT(m_Filename!=""); #if defined(_XBOX) // this to handle fat-x limitations if (g_guiSettings.GetBool("servers.ftpautofatx")) { /*CUtil::ShortenFileName(m_Filename); // change! addme to new ports CStdString strFilename = CUtil::GetFileName(m_Filename); CStdString strPath; CUtil::GetDirectory(m_Filename,strPath); vector<CStdString> tokens; CUtil::Tokenize(strPath,tokens,"\\/"); strPath = tokens.front(); for (vector<CStdString>::iterator iter=tokens.begin()+1; iter != tokens.end(); ++iter) { CUtil::ShortenFileName(*iter); CUtil::RemoveIllegalChars(*iter); strPath += "\\"+*iter; } CUtil::RemoveIllegalChars(strFilename); m_Filename = strPath+"\\"+strFilename;*/ CUtil::GetFatXQualifiedPath(m_Filename); } m_hFile = CreateFile(m_Filename, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); #else m_hFile = CreateFile(m_Filename, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0); #endif if (m_hFile == INVALID_HANDLE_VALUE) { Close(); if (!m_bSentClose) { m_bSentClose=TRUE; m_status=3; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } #if defined(_XBOX) LARGE_INTEGER size; size.QuadPart = m_nRest; VERIFY(SetFilePointerEx(m_hFile, size, NULL, FILE_BEGIN)); SetEndOfFile(m_hFile); m_nBufferPos = 0; m_nAlign = (4096 - (m_nRest & 4095)) & 4095; if (m_pBuffer) free(m_pBuffer); // Xbox writes ide data in 128k blocks, so always try to write 128k of data at a time. // Uses a 160k buffer so there's a bit of overrun as it's more efficient to always try and read 32k+ from the socket. // Also allows realignment to page alignment when restarting. m_nBufSize = 160*1024; m_pBuffer = (char*)malloc(m_nBufSize); if (!m_pBuffer) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; Close(); if (!m_bSentClose) { m_bSentClose=TRUE; m_status=6; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } } m_nPreAlloc = 0; } int len = m_nBufSize - m_nBufferPos; #else DWORD low=(DWORD)(m_nRest&0xFFFFFFFF); LONG high=(LONG)(m_nRest>>32); VERIFY(SetFilePointer(m_hFile, low, &high, FILE_BEGIN)!=0xFFFFFFFF || GetLastError()==NO_ERROR); SetEndOfFile(m_hFile); } if (!m_pBuffer) m_pBuffer = new char[m_nBufSize]; int len = m_nBufSize; #endif int nLimit = -1; if (GetState() != closed) { nLimit = m_pOwner->GetSpeedLimit(1); if (nLimit != -1 && GetState() != aborted && len > nLimit) len = nLimit; } if (!len) return; #if defined(_XBOX) int numread = Receive(m_pBuffer + m_nBufferPos, len); #else int numread = Receive(m_pBuffer, len); #endif if (numread==SOCKET_ERROR) { if (GetLastError()!=WSAEWOULDBLOCK) { if (m_hFile!=INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } Close(); if (!m_bSentClose) { m_bSentClose=TRUE; m_status=1; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } } Sleep(0); return; } if (!numread) { if (m_hFile != INVALID_HANDLE_VALUE) { #if defined(_XBOX) if (m_nBufferPos) { DWORD numwritten; WriteFile(m_hFile, m_pBuffer, m_nBufferPos, &numwritten, 0); } FlushFileBuffers(m_hFile); SetEndOfFile(m_hFile); #endif CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } Close(); if (!m_bSentClose) { m_bSentClose=TRUE; m_status=0; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } ((CServerThread *)m_pOwner->m_pOwner)->IncRecvCount(numread); if (nLimit != -1 && GetState() != aborted) m_pOwner->m_SlQuota.nUploaded += numread; #if defined(_XBOX) m_nBufferPos += numread; if (m_nBufferPos >= 128*1024 + m_nAlign) { if (!m_nPreAlloc) { // pre alloc the file on disk - makes writing much faster due to less FAT updates SetFilePointer(m_hFile, 32*1024*1024, 0, FILE_CURRENT); SetEndOfFile(m_hFile); SetFilePointer(m_hFile, -32*1024*1024, 0, FILE_CURRENT); m_nPreAlloc = 32*1024*1024 / (128*1024); } DWORD numwritten; if (!WriteFile(m_hFile, m_pBuffer, 128*1024 + m_nAlign, &numwritten, 0) || numwritten != 128*1024 + m_nAlign) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; Close(); if (!m_bSentClose) { m_bSentClose=TRUE; m_status=3; //TODO: Better reason m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } else { if (m_nBufferPos > numwritten) { memmove(m_pBuffer, m_pBuffer + numwritten, m_nBufferPos - numwritten); } m_nBufferPos -= numwritten; --m_nPreAlloc; m_nAlign = 0; } } #else DWORD numwritten; if (!WriteFile(m_hFile, m_pBuffer, numread, &numwritten, 0) || numwritten!=(unsigned int)numread) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; Close(); if (!m_bSentClose) { m_bSentClose=TRUE; m_status=3; //TODO: Better reason m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } #endif }
void CTransferSocket::OnSend(int nErrorCode) { CAsyncSocketEx::OnSend(nErrorCode); if (nErrorCode) { if (m_hFile != INVALID_HANDLE_VALUE) CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; m_status=1; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); Close(); return; } if (m_nMode==TRANSFERMODE_LIST || m_nMode==TRANSFERMODE_NLST) { //Send directory listing if (!m_bStarted) if (!InitTransfer(TRUE)) return; while (m_pDirListing && m_pDirListing->len) { int numsend = m_nBufSize; if ((m_pDirListing->len - m_nBufferPos) < m_nBufSize) numsend = m_pDirListing->len - m_nBufferPos; int nLimit = m_pOwner->GetSpeedLimit(0); if (nLimit != -1 && GetState() != aborted && numsend > nLimit) numsend = nLimit; if (!numsend) return; int numsent = Send(m_pDirListing->buffer + m_nBufferPos, numsend); if (numsent==SOCKET_ERROR) { if (GetLastError()!=WSAEWOULDBLOCK) { Close(); m_status=1; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } return; } if (nLimit != -1 && GetState() != aborted) m_pOwner->m_SlQuota.nDownloaded += numsent; ((CServerThread *)m_pOwner->m_pOwner)->IncSendCount(numsent); GetSystemTime(&m_LastActiveTime); if (numsent < numsend) m_nBufferPos += numsent; else m_nBufferPos += numsend; ASSERT(m_nBufferPos <= m_pDirListing->len); if (m_nBufferPos == m_pDirListing->len) { t_dirlisting *pPrev = m_pDirListing; m_pDirListing = m_pDirListing->pNext; delete pPrev; m_nBufferPos = 0; if (!m_pDirListing) break; } //Check if there are other commands in the command queue. MSG msg; if (PeekMessage(&msg,0, 0, 0, PM_NOREMOVE)) { TriggerEvent(FD_WRITE); return; } } #ifndef NOLAYERS if (m_pGssLayer) if (!ShutDown() && GetLastError() == WSAEWOULDBLOCK) return; #endif Close(); m_status = 0; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); } else if (m_nMode==TRANSFERMODE_SEND) { //Send file if (!m_bStarted) if (!InitTransfer(TRUE)) return; int count=0; while (m_hFile!=INVALID_HANDLE_VALUE || m_nBufferPos) { count++; DWORD numread; if (m_nBufSize-m_nBufferPos && m_hFile!=INVALID_HANDLE_VALUE) { if (!ReadFile(m_hFile, m_pBuffer+m_nBufferPos, m_nBufSize-m_nBufferPos, &numread, 0)) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; Close(); m_status=3; //TODO: Better reason m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); return; } if (!numread) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; if (!m_nBufferPos) { // only close if we've actually finished! m_status=0; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); Close(); return; } } numread+=m_nBufferPos; m_nBufferPos=0; } else numread=m_nBufferPos; m_nBufferPos=0; if (numread<m_nBufSize) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } int numsend = numread; int nLimit = m_pOwner->GetSpeedLimit(0); if (nLimit != -1 && GetState() != aborted && numsend > nLimit) numsend = nLimit; if (!numsend) { m_nBufferPos = numread; return; } int numsent=Send(m_pBuffer, numsend); if (numsent==SOCKET_ERROR) { if (GetLastError()!=WSAEWOULDBLOCK) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; m_status=1; m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); Close(); return; } m_nBufferPos=numread; return; } else if ((unsigned int)numsent<numread) { memmove(m_pBuffer, m_pBuffer+numsent, numread-numsent); m_nBufferPos=numread-numsent; } if (nLimit != -1 && GetState() != aborted) m_pOwner->m_SlQuota.nDownloaded += numsent; ((CServerThread *)m_pOwner->m_pOwner)->IncSendCount(numsent); GetSystemTime(&m_LastActiveTime); //Check if there are other commands in the command queue. MSG msg; if (PeekMessage(&msg,0, 0, 0, PM_NOREMOVE)) { TriggerEvent(FD_WRITE); return; } } #ifndef NOLAYERS if (m_pGssLayer) if (!ShutDown() && GetLastError() == WSAEWOULDBLOCK) return; #endif m_status=0; Sleep(0); //Give the system the possibility to relay the data //If not using Sleep(0), GetRight for example can't receive the last chunk. m_pOwner->m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_TRANSFERMSG, m_pOwner->m_userid); Close(); } }
void PerfSocket::Client_Recv_TCP(void) { // terminate loop nicely on user interupts sInterupted = false; //my_signal( SIGINT, Sig_Interupt ); //my_signal( SIGPIPE, Sig_Interupt ); #ifndef WIN32 signal (SIGPIPE, SIG_IGN); #endif int currLen; InitTransfer(); double fract = 0.0; mStartTime.setnow(); long endSize = get_tcp_windowsize(mSock), startSize=endSize, loopLen =0, prevLen =0; Timestamp prevTime; prevTime.setnow(); /* Periodic reporting is done here in the loop itself, if Suggest Window Size option is set*/ mPReporting = false; /* Send the first packet indicating that the server has to send data */ mBuf[0] = 'a'; currLen = write( mSock, mBuf, mSettings->mBufLen ); if ( currLen < 0 ) { WARN_errno( currLen < 0, "write" ); return; } do { // perform read currLen = read( mSock, mBuf, mSettings->mBufLen ); mPacketTime.setnow(); if ( currLen < 0 ) { WARN_errno( currLen < 0, "read" ); break; } mTotalLen += currLen; loopLen +=currLen; // periodically report bandwidths ReportPeriodicBW(); double nFract = mStartTime.fraction(mPacketTime,mEndTime); if ( nFract > (fract + 0.1) ) { printf(seperator_line); ReportWindowSize(); sReporting.Lock(); ReportBW( loopLen, prevTime.subSec(mStartTime), mPacketTime.subSec( mStartTime)); sReporting.Unlock(); fract +=0.1; if ( startSize != endSize ) { /* Change the window size only if the data transfer has changed at least by 5% */ if ( loopLen < prevLen ) { if ( ( ((double)(prevLen - loopLen)) / ((double)prevLen)) > 0.05 ) { endSize = startSize + (endSize - startSize)/2; } } else { if ( ( ((double)(loopLen - prevLen)) / ((double)prevLen) ) > 0.05 ) { startSize = endSize; endSize = endSize*2; prevLen = loopLen; } } } else { endSize = endSize*2; prevLen = loopLen; } /** Reset the variables after setting new window size */ prevTime.setnow(); loopLen = 0 ; //shutdown(mSock,SHUT_RDWR); close(mSock); mSock = -1; Connect( mSettings->mHost, mSettings->mLocalhost ); mBuf[0] = 'a'; if ( set_tcp_windowsize(mSock,endSize) == -1 ) { printf(unable_to_change_win); } if ( get_tcp_windowsize(mSock) != endSize ) { printf(unable_to_change_win); } write( mSock, mBuf, mSettings->mBufLen ); } } while ( ! (sInterupted || (mMode_time && mPacketTime.after( mEndTime )) || (!mMode_time && mTotalLen >= mAmount)) ); printf( seperator_line ); ReportWindowSize(); sReporting.Lock(); ReportBW( loopLen, prevTime.subSec(mStartTime), mPacketTime.subSec( mStartTime)); sReporting.Unlock(); printf( seperator_line); printf( opt_estimate); if ( loopLen > prevLen ) set_tcp_windowsize(mSock,endSize); else set_tcp_windowsize(mSock,startSize); ReportWindowSize(); printf( seperator_line ); // stop timing mEndTime.setnow(); sReporting.Lock(); ReportBW( mTotalLen, 0.0, mEndTime.subSec( mStartTime )); sReporting.Unlock(); if ( mSettings->mPrintMSS ) { // read the socket option for MSS (maximum segment size) ReportMSS( getsock_tcp_mss( mSock )); } //close(mSock); //mSock = -1; }
void PerfSocket::Recv_TCP( void ) { extern Mutex clients_mutex; extern Iperf_ListEntry *clients; // get the remote address and remove it later from the set of clients SocketAddr remote = getRemoteAddress(); iperf_sockaddr peer = *(iperf_sockaddr *) (remote.get_sockaddr()); // keep track of read sizes -> gives some indication of MTU size // on SGI this must be dynamically allocated to avoid seg faults int currLen; int *readLenCnt = new int[ mSettings->mBufLen+1 ]; for ( int i = 0; i <= mSettings->mBufLen; i++ ) { readLenCnt[ i ] = 0; } InitTransfer(); #ifndef WIN32 signal (SIGPIPE, SIG_IGN); #endif do { // perform read currLen = read( mSock, mBuf, mSettings->mBufLen ); if ( false ) { DELETE_ARRAY( readLenCnt ); Server_Send_TCP(); return; } mPacketTime.setnow(); // periodically report bandwidths ReportPeriodicBW(); mTotalLen += currLen; // count number of reads of each size if ( currLen <= mSettings->mBufLen ) { readLenCnt[ currLen ]++; } } while ( currLen > 0 && sInterupted == false ); // stop timing mEndTime.setnow(); sReporting.Lock(); ReportBW( mTotalLen, 0.0, mEndTime.subSec( mStartTime )); sReporting.Unlock(); if ( mSettings->mPrintMSS ) { // read the socket option for MSS (maximum segment size) ReportMSS( getsock_tcp_mss( mSock )); // on WANs the most common read length is often the MSS // on fast LANs it is much harder to detect int totalReads = 0; for ( currLen = 0; currLen < mSettings->mBufLen+1; currLen++ ) { totalReads += readLenCnt[ currLen ]; } // print each read length that occured > 5% of reads int thresh = (int) (0.05 * totalReads); printf( report_read_lengths, mSock ); for ( currLen = 0; currLen < mSettings->mBufLen+1; currLen++ ) { if ( readLenCnt[ currLen ] > thresh ) { printf( report_read_length_times, mSock, (int) currLen, readLenCnt[ currLen ], (100.0 * readLenCnt[ currLen ]) / totalReads ); } } } DELETE_ARRAY( readLenCnt ); clients_mutex.Lock(); Iperf_delete ( &peer, &clients ); clients_mutex.Unlock(); }
void PerfSocket::Send_TCP( void ) { if ( false ) { Client_Recv_TCP(); return; } // terminate loop nicely on user interupts sInterupted = false; SigfuncPtr oldINT = my_signal( SIGINT, Sig_Interupt ); SigfuncPtr oldPIPE = my_signal( SIGPIPE, Sig_Interupt ); int currLen; bool canRead; InitTransfer(); do { // If the input is from a // file, fill the buffer with // data from the file if ( mSettings->mFileInput ) { extractor->getNextDataBlock(mBuf); // If the first character is 'a' // change if to '0' so that the // server does not mistake it for // a Window Suggest option if ( mBuf[0] == 'a' ) mBuf[0] = '0'; canRead = extractor->canRead(); } else canRead = true; // perform write currLen = write( mSock, mBuf, mSettings->mBufLen ); mPacketTime.setnow(); if ( currLen < 0 ) { WARN_errno( currLen < 0, "write" ); break; } // periodically report bandwidths ReportPeriodicBW(); mTotalLen += currLen; } while ( ! (sInterupted || (mMode_time && mPacketTime.after( mEndTime )) || (!mMode_time && mTotalLen >= mAmount)) && canRead ); if ( oldINT != Sig_Interupt ) { // Return signal handlers to previous handlers my_signal( SIGINT, oldINT ); my_signal( SIGPIPE, oldPIPE ); } // shutdown sending connection and wait (read) // for the other side to shutdown shutdown( mSock, SHUT_WR ); currLen = read( mSock, mBuf, mSettings->mBufLen ); WARN_errno( currLen == SOCKET_ERROR, "read on server close" ); WARN( currLen > 0, "server sent unexpected data" ); // stop timing mEndTime.setnow(); sReporting.Lock(); ReportBW( mTotalLen, 0.0, mEndTime.subSec( mStartTime )); sReporting.Unlock(); if ( mSettings->mPrintMSS ) { // read the socket option for MSS (maximum segment size) ReportMSS( getsock_tcp_mss( mSock )); } }