/*************************************************************************** Windows Sockets Client Application Support Module Written by: John A. Junod Internet: 267 Hillwood Street Martinez, GA 30907 Compuserve: 72321,366 This program executable and all source code is released into the public domain. It would be nice (but is not required) to give me a little credit for any use of this code. THE INFORMATION AND CODE PROVIDED IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL JOHN A. JUNOD BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF JOHN A. JUNOD HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *****************************************************************************/ #include "ws_glob.h" #include "ws_ftp.h" #include #include #include #include #include #include #include #include // atoi() extern int errno; extern int nHostType; extern BOOL bAborted; // timer routine may set this BOOLEAN globalsucceed = FALSE; int iMultiLine=0; extern volatile BOOLEAN aborttimerexpired; // lgk new globals so we can close open files on an abort or close BOOLEAN sendingfile = FALSE; BOOLEAN receivingfile = FALSE; int sendingfilehandle = -1; int receivefilehandle = -1; // lgk timer messages do not work for use because we have mult. threads // so create a timer proc. extern BOOLEAN check_busy(); extern void set_busy(); void closefilesonabort(rwasopen,swasopen) BOOLEAN *rwasopen; BOOLEAN *swasopen; { *rwasopen = FALSE; *swasopen = FALSE; if (receivingfile) { *rwasopen = TRUE; _lclose(receivefilehandle); receivingfile = FALSE; receivefilehandle = -1; } if (sendingfile) { *swasopen = TRUE; _lclose(sendingfilehandle); sendingfile = FALSE; sendingfilehandle = -1; } } // lgk new routine to wait for 550 message after closesocket DWORD waitfor550(SOCKET ctrl_skt) { int iRetCode = 0; BOOLEAN aborttimerexpired = FALSE; while((iRetCode != 550) && (aborttimerexpired == FALSE)) { iRetCode = ReadDisplayLine(ctrl_skt); // some servers return message 226 or ok so if we get 2 set it to 550 if (iRetCode = 2) iRetCode = 550; DoPrintf("Got abort response = %d \n",iRetCode); } if (aborttimerexpired) { DoPrintf("Abort Timeout has Expired\n"); DoPrintf("Abort Failed... Recommend you close/reconnect\n"); set_busy(FALSE); bCmdInProgress = 0; } return 0; } VOID CALLBACK mytimerproc(wind,msg,idevent,systime) HWND wind; UINT msg; UINT idevent; DWORD systime; { DoPrintf("Timer has Expired\n"); if(idevent ==10) { KillTimer(wind,10); if(WSAIsBlocking()) { // lgk if we are blocking in another thread here we need to kill // it also if (check_busy()) { DoPrintf("Timer cancelled blocking call\n"); bAborted=TRUE; WSACancelBlockingCall(); TerminateThread(threadhandle,1); set_busy(FALSE); } else { DoPrintf("Timer cancelled blocking call\n"); bAborted=TRUE; WSACancelBlockingCall(); } } } } /* // send a message on the control socket, read and display the resulting // message and return the result value */ int getreply(SOCKET ctrl_skt,LPSTR cmdstring) { int iRetCode=0; iCode=0; if(strncmp(cmdstring,"PASS ",5)==0) DoAddLine("PASS xxxxxx"); else DoAddLine(cmdstring); if(ctrl_skt==INVALID_SOCKET) { DoAddLine("Not connected"); } else { if(SendPacket(ctrl_skt,cmdstring)!=-1) iRetCode=ReadDisplayLine(ctrl_skt); } return(iRetCode); // 0 - 5 } int command(SOCKET ctrl_skt, char *fmt,...) { va_list args; char szBuf[90]; // int iRetCode; va_start(args,fmt); vsprintf(szBuf,fmt,args); va_end(args); return(getreply(ctrl_skt,szBuf)); } int qcommand(SOCKET ctrl_skt, char *fmt,...) { va_list args; char szBuf[90]; // int iRetCode; va_start(args,fmt); vsprintf(szBuf,fmt,args); va_end(args); command(ctrl_skt,szBuf); return iCode ; } // return a string pointer to ON or OFF based on the flag char *onoff(BOOL flag) { if(flag) return("ON"); else return("OFF"); } // process CWD int DoCWD(SOCKET ctrl_skt,LPSTR path) { if(command(ctrl_skt,"CWD %s",path)==FTP_ERROR && iCode==500) { command(ctrl_skt,"XCWD %s",path); } return(iCode/100); } // proces PWD int DoPWD(SOCKET ctrl_skt) { if(command(ctrl_skt,"PWD")==FTP_ERROR && iCode==500) { command(ctrl_skt,"XPWD"); } return(iCode/100); } // process MKD int DoMKD(SOCKET ctrl_skt,LPSTR pathname) { if(command(ctrl_skt,"MKD %s",pathname)==FTP_ERROR && iCode==500) { command(ctrl_skt,"XMKD %s",pathname); } if (iCode != 550) return(iCode/100); else return iCode; } // process RMD int DoRMD(SOCKET ctrl_skt,LPSTR pathname) { if(command(ctrl_skt,"RMD %s",pathname)==FTP_ERROR && iCode==500) command(ctrl_skt,"XRMD %s",pathname); return(iCode/100); } // process DELE int DoDELE(SOCKET ctrl_skt,LPSTR pathname) { command(ctrl_skt,"DELE %s",pathname); return(iCode/100); } // process user command int DoQUOTE(SOCKET ctrl_skt,LPSTR string) { if(strncmp(string,"LIST",4)==0 || strncmp(string,"NLST",4)==0) DoDirList(ctrl_skt,string); else command(ctrl_skt,string); return(iCode/100); } // process chmod int DoCHMOD(SOCKET ctrl_skt,LPSTR modes,LPSTR filename) { return(command(ctrl_skt,"SITE CHMOD %s %s",modes,filename)); } extern BOOL bHELP; // initial connection volatile SOCKET DoConnect2(LPSTR ftp_host) { int iLength,iRetCode; int iFlag=1; char host[80] ; volatile SOCKET ctrl_skt; if(bConnected) { DoAddLine("Already connected!"); return(INVALID_SOCKET); } // let other routines know that we are busy bCmdInProgress++; // DoPrintf("host name in doconnect is %s\n",ftp_host); bHELP=FALSE; if(use_gateway) strcpy(host, szGateHost) ; else strcpy(host, ftp_host) ; // create a connected socket if((ctrl_skt=connectTCP(host,"ftp"))==INVALID_SOCKET) { //DoAddLine("connection failed"); DoPrintf("Connection to %s failed",host) ; bCmdInProgress--; return(INVALID_SOCKET); } // get information about local end of the connection iLength = sizeof (saCtrlAddr); if (getsockname(ctrl_skt,(struct sockaddr *)&saCtrlAddr, &iLength) ==SOCKET_ERROR) { ReportWSError("getsockname",WSAGetLastError()); bCmdInProgress--; DoClose(ctrl_skt); return(INVALID_SOCKET); } // show remote end address DoPrintf("[%u] from %s port %u",ctrl_skt, inet_ntoa(saCtrlAddr.sin_addr), ntohs(saCtrlAddr.sin_port)); // get initial message from remote end // lgk need to set the global control_socket to ctrl_skt here since // it will be returned but abort does not work unless it is set here ctrl_socket = ctrl_skt; iMultiLine = 0; iCode = 0; while((iRetCode=ReadDisplayLine(ctrl_skt))==FTP_PRELIM && !bAborted) // 93.12.04 if(nHostType==HOST_TYPE_AUTO) { if(strstr(szMsgBuf,"(EXOS")!=NULL) nHostType=HOST_TYPE_U5000; } // if it succeeded if(iRetCode==FTP_COMPLETE) { if(nHostType==HOST_TYPE_AUTO) { if(strstr(szMsgBuf,"(EXOS")!=NULL) nHostType=HOST_TYPE_U5000; } if (setsockopt(ctrl_skt, SOL_SOCKET, SO_OOBINLINE, (LPSTR)&iFlag, sizeof(iFlag))==SOCKET_ERROR) { ReportWSError("setsockopt",WSAGetLastError()); } // have to reset this so "command" will work bCmdInProgress--; if(use_gateway) { // send our userid if((iRetCode=command(ctrl_skt,"USER %s",szGateUserID))==FTP_CONTINUE) { // if the remote system requires a password, send it. iRetCode=command(ctrl_skt,"PASS %s",szGatePassWord); } if(iRetCode!=FTP_COMPLETE) { // if we failed to successfully log on DoAddLine("Gateway logon failure, so quitting"); DoClose((SOCKET)ctrl_skt); return(INVALID_SOCKET); } if((iRetCode=qcommand(ctrl_skt,"site %s",ftp_host))==FTP_ERROR) { DoAddLine("Connect to final destination failed, so quitting"); DoClose((SOCKET)ctrl_skt); bConnected=0; return(INVALID_SOCKET); } bConnected=1; // lgk now that we are connected enable the close button and disable the // open button EnableWindow(hBtnClose,TRUE); EnableWindow(hBtnConnect,FALSE); } // end of gateway connect // send our userid to the ftp_host if((iRetCode=command(ctrl_skt,"USER %s",szUserID))==FTP_CONTINUE) // || 1) { while(szPassWord[0]==0) { StdInputPassword(szPassWord,"Need a password:"); } // if the remote system requires a password, send it. if((iRetCode=command(ctrl_skt,"PASS %s",szPassWord))==FTP_CONTINUE) { // if the remote system requires an account, send it. StdInput(NULL,"Need an account:"); iRetCode=command(ctrl_skt,"ACCT %s",szDlgEdit); } } // if we are successfully logged on,..... if(iRetCode!=FTP_COMPLETE) // || 0) { DoAddLine("logon failure, so quitting"); DoClose((SOCKET)ctrl_skt); bConnected=0; EnableWindow(hBtnClose,FALSE); EnableWindow(hBtnConnect,TRUE); return(INVALID_SOCKET); } bConnected=1; EnableWindow(hBtnClose,TRUE); EnableWindow(hBtnConnect,FALSE); } else { DoPrintf("unk open msg \"%s\" %u",szMsgBuf,iCode); // allow other processes to work bCmdInProgress--; DoClose((SOCKET)ctrl_skt); bConnected = 0; EnableWindow(hBtnClose,TRUE); EnableWindow(hBtnConnect,FALSE); return(INVALID_SOCKET); } wsprintf(szString,"WS_FTP32 %s",szRemoteHost); SetWindowText(hWndMain,szString); return (ctrl_skt); } // lgk new connect routine that retires // initial connection volatile SOCKET DoConnect(LPSTR ftp_host) { int tries = 0; volatile SOCKET rval = 0; BOOLEAN done = FALSE; while (done == FALSE) { rval=DoConnect2(ftp_host); if (rval == INVALID_SOCKET) { // we failed so check if we want to retry if (uiRetries > tries) { DoPrintf("Connection failed...Retrying (%d of %d)",++tries,uiRetries); } else done = TRUE; } else done = TRUE; } // end of loop if (rval != INVALID_SOCKET) { if (bBell == 1) MessageBeep(MB_ICONASTERISK); } else if (uiRetries > 0) { DoPrintf("All %d Retries failed...Connection to %s Failed.",uiRetries,ftp_host); if (bBell == 1) MessageBeep(MB_ICONEXCLAMATION); } return (rval); } int DoDirList(SOCKET ctrl_skt,LPSTR szCMD) { int nRC,nBell; nBell=bBell; bBell=0; nRC=RetrieveFile(ctrl_skt,szCMD,szTmpFile,szTmpFile,TYPE_A); bBell=nBell; return(nRC); } int SendFile(SOCKET ctrl_skt,LPSTR szCMD,LPSTR localfile,char stype) { int iRetCode; int iLength; int iFlag = 1; iCode=0; // if we don't have a valid control socket, can't do anything if(ctrl_skt==INVALID_SOCKET) { DoAddLine("no ctrl_skt, ignored"); return(0); } // if we are doing something, don't try to do this if(bCmdInProgress) { DoAddLine("command in process, ignored"); return(0); } // if the requested type is not the same as the default type if(cType!=stype) { if(stype==TYPE_L) command(ctrl_skt,"TYPE L 8"); else command(ctrl_skt,"TYPE %c",stype); cType=stype; } // create a listener socket, if it is successful if((listen_socket=GetFTPListenSocket(ctrl_skt))!=INVALID_SOCKET) { // send command to see the result of this all iRetCode=command((SOCKET)ctrl_skt,szCMD); // read the control channel (should return 1xx if it worked) if(iRetCode==FTP_PRELIM) { // wait for connection back to us on the listen socket SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc); // get our data connection iLength=sizeof(saSockAddr1); data_socket=accept(listen_socket,(struct sockaddr far *)&saSockAddr1, (int far *)&iLength); // turn off the timeout timer KillTimer(hWndMain,10); // if it failed, we have to quit this if(data_socket==INVALID_SOCKET) { ReportWSError("accept",WSAGetLastError()); listen_socket=DoClose(listen_socket); if(bBell) MessageBeep(MB_ICONEXCLAMATION); iRetCode=0; } else { // lgk set for reuse if(setsockopt(data_socket,SOL_SOCKET,SO_REUSEADDR, (char *)&iFlag,sizeof(iFlag))==SOCKET_ERROR) { ReportWSError("setsockopt",WSAGetLastError()); closesocket(data_socket); if(bBell) MessageBeep(MB_ICONEXCLAMATION); iRetCode =0; } else { // we don't need the listener socket anymore listen_socket=DoClose(listen_socket); // inform user of the connection DoPrintf("[%u] accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr),ntohs(saSockAddr1.sin_port)); // copy the file iRetCode=SendMass(data_socket,localfile,stype==TYPE_I); // close the socket data_socket=DoClose(data_socket); // read the close control message (should return 2xx) iRetCode=ReadDisplayLine(ctrl_skt); } // ok setsock } // ok open } else { listen_socket=DoClose(listen_socket); iRetCode=0; if(bBell) MessageBeep(MB_ICONEXCLAMATION); } } // get listen socket failed else { listen_socket=DoClose(listen_socket); iRetCode=0; if(bBell) MessageBeep(MB_ICONEXCLAMATION); } return(iRetCode); } int RetrieveFile(SOCKET ctrl_skt,LPSTR szCMD,LPSTR localfile, LPSTR shortname,char rtype) { int iRetCode; int iLength; int iFlag = 1; iCode=0; iMultiLine = 0; // if we don't have a valid control socket, can't do anything if(ctrl_skt==INVALID_SOCKET) { DoAddLine("no ctrl_skt, ignored"); return(0); } // if we are doing something, don't try to do this if(bCmdInProgress) { DoAddLine("command in process, ignored"); return(0); } // if the requested type is not the same as the default type if(cType!=rtype) { if(rtype==TYPE_L) command(ctrl_skt,"TYPE L 8"); else command(ctrl_skt,"TYPE %c",rtype); cType=rtype; } // create a listener socket, if it is successful if((listen_socket=GetFTPListenSocket(ctrl_skt))!=INVALID_SOCKET) { // send command to see the result of this all iRetCode=command((SOCKET)ctrl_skt,szCMD); // read the control channel (should return 1xx if it worked) if(iRetCode==FTP_PRELIM) { // wait for connection back to us on the listen socket SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc); // get our data connection iLength=sizeof(saSockAddr1); data_socket=accept(listen_socket,(struct sockaddr far *)&saSockAddr1, (int far *)&iLength); // lgk check for error case here if (data_socket == INVALID_SOCKET) { ReportWSError("accept for retrieve",WSAGetLastError()); data_socket=DoClose(data_socket); return 0; } if(setsockopt(data_socket,SOL_SOCKET,SO_REUSEADDR, (char *)&iFlag,sizeof(iFlag))==SOCKET_ERROR) { ReportWSError("setsockopt",WSAGetLastError()); closesocket(data_socket); return(INVALID_SOCKET); } // turn off the timeout timer KillTimer(hWndMain,10); // if it failed, we have to quit this if(data_socket==INVALID_SOCKET) { ReportWSError("accept",WSAGetLastError()); listen_socket=DoClose(listen_socket); iRetCode=0; } else { // we don't need the listener socket anymore listen_socket=DoClose(listen_socket); // inform user of the connection DoPrintf("[%u] accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr),ntohs(saSockAddr1.sin_port)); // copy the file iRetCode=ReadMass(data_socket,localfile,shortname,rtype==TYPE_I); // shut the data socket down if(shutdown(data_socket,2)!=0) ReportWSError("shutdown",WSAGetLastError()); // close the data socket data_socket=DoClose(data_socket); // read the close control message (should return 2xx) iRetCode=ReadDisplayLine(ctrl_skt); } } else { listen_socket=DoClose(listen_socket); iRetCode=0; if(bBell) MessageBeep(MB_ICONEXCLAMATION); } } else { listen_socket=DoClose(listen_socket); iRetCode=0; if(bBell) MessageBeep(MB_ICONEXCLAMATION); } return(iRetCode); } // user close routine volatile SOCKET DoClose(SOCKET sockfd) { LINGER ntlinger; if(sockfd!=INVALID_SOCKET) { if(WSAIsBlocking()) { DoPrintf("(%u) Cancelled blocking call",sockfd); WSACancelBlockingCall(); bAborted=TRUE; } // dont report error here since shutdown does not work on non data sockets // if(shutdown(sockfd,2)==SOCKET_ERROR) // ReportWSError("shutdown",WSAGetLastError()); shutdown(sockfd,2); // 93.12.04 - so Lanera Winsock Works ntlinger.l_onoff = (u_short)TRUE; ntlinger.l_linger = (u_short)0; setsockopt(sockfd,SOL_SOCKET,SO_LINGER, (LPSTR)&ntlinger,sizeof(ntlinger) ); if(closesocket(sockfd)==SOCKET_ERROR) ReportWSError("closesocket",WSAGetLastError()); else { DoPrintf("[%u] Socket closed.",sockfd); sockfd=INVALID_SOCKET; } } if(sockfd!=INVALID_SOCKET) DoPrintf("%u Failed to close socket.",sockfd); return(sockfd); } int SendPacket(SOCKET sockfd,LPSTR msg) { int i; if(sockfd==INVALID_SOCKET) return(-1); if(bCmdInProgress) { DoAddLine("command in progress, ignored"); return (-1); } bCmdInProgress++; i=strlen(msg); strcpy(szSendPkt,msg); // append a CRLF to the end of outgoing messages szSendPkt[i++]='\r'; szSendPkt[i++]='\n'; szSendPkt[i]=0; i=sendstr(sockfd,szSendPkt,i); bCmdInProgress--; return (i); } // read a reply (may be multi line) and display in debug window int ReadDisplayLine(SOCKET sockfd) { int iRetCode; int iContinue; // char *s; // char c; // can't do anything if we don't have a socket if(sockfd==INVALID_SOCKET) return(0); // let other routine know that we are doing something right now. bCmdInProgress++; // count the lines in the response iMultiLine++; // initialize some variables iContinue=0; // go read the line iRetCode=ReadLine(sockfd); // if it wasn't a valid value or the 4th char was a hyphen // lgk check for error here and return if so if (iRetCode == SOCKET_ERROR) { return iRetCode; } // lgk bug here when iretcode == 0 does not mean continue if(((iRetCode<100) && (iRetCode > 0)) || iRetCode>599 || szMsgBuf[3]=='-') // then it is a continuation line iContinue=1; // lgk do not add blank lines to the window if (strlen(szMsgBuf) != 0) // send the line we read to our user/debug window DoAddLine((LPSTR)&szMsgBuf[0]); // DoPrintf("iRetCode=%u, =%u",iRetCode,iContinue); // if the timer killed it if(bAborted) { iCode=iRetCode=421; iContinue=0; } // we only want to set the real return code in certain situations if((iMultiLine==1 || iCode==0) && iRetCode>99 && iRetCode<600) iCode=iRetCode; // handle continuation lines // dont do this if we have a null line if(iContinue==1 || (iCode>0 && iMultiLine>1 && iRetCode!=iCode)) ReadDisplayLine(sockfd); // count back down our multiline reponses iMultiLine--; // allow other processes to run bCmdInProgress--; // return only the first char of return code // lgk special case here to return 550 not first char if (iCode==550) return iCode; if(iCode>99 && iCode<600) return (iCode/100); else return 0; } // read a reply line back in from the sockfd and return the // value at the beginning of the first line. int ReadLine(SOCKET sockfd) { LPSTR szBuf; int nIndex; int iNumBytes,iN1,iN2; //.iN3; int iBytesRead; int iRetCode; int i; // char *s; char c; // can't do anything if we don't have a socket if(sockfd==INVALID_SOCKET) return(0); // let other routines know that we are doing something right now. bCmdInProgress++; // make sure we don't mistakenly think we timed out KillTimer(hWndMain,10); bAborted=FALSE; // zero our receive buffer memset(szMsgBuf,0,4096); // initialize some variables szBuf=szMsgBuf; iBytesRead=0; iRetCode=0; // set our timeout SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc); // this routine is a little better as it read 80 characters at a time // (if it works:-) Here we PEEK at what is available, find the LF etc... // lgk here we have a bug and it puts the system in an endless loop // we don't check for a socket error but one happens fix this iNumBytes=recv(sockfd,(LPSTR)szBuf,82,MSG_PEEK); if (iNumBytes == SOCKET_ERROR) { ReportWSError("socket recv (peek)",WSAGetLastError()); return (SOCKET_ERROR); } while(iBytesRead<4000 && (iNumBytes > 0)) { // Trumpet WinSock Alpha 15 always returns the len (82) from a recv // with MSG_PEEK. I suppose this is an error??? The spec doesn't say // that MSG_PEEK returns something different than normal. KillTimer(hWndMain,10); iN1=iNumBytes; // must terminate the string so strchr doesn't go wild. szBuf[iNumBytes]=0; // find a LF in the input if it exists // for(nIndex=0;nIndex80 && nHostType==HOST_TYPE_U5000) for(nIndex=0;nIndex2 && (szMsgBuf[i-1]==0x0a || szMsgBuf[i-1]==0x0d || szMsgBuf[i-1]==' ')) szMsgBuf[i-1]=0; // unmark our progress bCmdInProgress--; return(iRetCode); } // based on WINTEL (ftp.c) and BSD (ftp.c) volatile SOCKET GetFTPListenSocket(SOCKET ctrl_skt) { SOCKET listen_skt; int iLength; int iRetCode; char *a,*p; int iFlag=1; // create a data socket if((listen_skt=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET) { ReportWSError("socket create",WSAGetLastError()); return (INVALID_SOCKET); } // let system pick an unused port. we tell remote end with PORT cmd DoPrintf("[%u] going to listen %s port %u",listen_skt, inet_ntoa(saCtrlAddr.sin_addr),ntohs(saCtrlAddr.sin_port)); if(bSendPort) { saCtrlAddr.sin_port=htons(0); saCtrlAddr.sin_family=AF_INET; saCtrlAddr.sin_addr.s_addr=0; } else // otherwise we attempt to reuse our ctrl_skt if(setsockopt(listen_skt,SOL_SOCKET,SO_REUSEADDR, (char *)&iFlag,sizeof(iFlag))==SOCKET_ERROR) { ReportWSError("setsockopt",WSAGetLastError()); closesocket(listen_skt); return(INVALID_SOCKET); } // Bind name to socket if( bind((SOCKET)listen_skt,(LPSOCKADDR)&saCtrlAddr, (int)sizeof(struct sockaddr))==SOCKET_ERROR) { ReportWSError("bind",WSAGetLastError()); closesocket(listen_skt); return (INVALID_SOCKET); } // get the port name that we got for later transmission in PORT cmd iLength=sizeof(saCtrlAddr); if(getsockname(listen_skt,(struct sockaddr *)&saCtrlAddr,&iLength)<0) { ReportWSError("getsockname",WSAGetLastError()); closesocket(listen_skt); return(INVALID_SOCKET); } // invoke listener if(listen(listen_skt,1)!=0) { ReportWSError("listen",WSAGetLastError()); closesocket(listen_skt); return(INVALID_SOCKET); } // inform remote end about our port that we created. if(bSendPort) { struct sockaddr_in saTmpAddr; int iLength; iLength = sizeof (saTmpAddr); if (getsockname(ctrl_skt,(LPSOCKADDR)&saTmpAddr, &iLength) ==SOCKET_ERROR) { ReportWSError("getsockname",WSAGetLastError()); } a = (char *)&saTmpAddr.sin_addr; p = (char *)&saCtrlAddr.sin_port; #define UC(b) (((int)b)&0xff) if((iRetCode=command(ctrl_skt,"PORT %d,%d,%d,%d,%d,%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])))!=FTP_COMPLETE) { DoPrintf("[%u] remote end didn't understand our port command.",listen_skt); return(listen_skt); } } DoPrintf("[%u] listener %s port %u",listen_skt, inet_ntoa(saCtrlAddr.sin_addr),ntohs(saCtrlAddr.sin_port)); return(listen_skt); } // send a file through the data socket int SendMass(SOCKET sockfd,LPSTR filename,BOOL binaryflag) { int iNumBytes; int iRetCode; int iFileHandle; long lBytesWritten; time_t ttStart,ttStop,ttDiff; iRetCode=0; // if we don't have a socket, return an error if(sockfd==INVALID_SOCKET || !(bConnected)) return 0; // turn on a flag so other routines know we have a command in progress bCmdInProgress++; // initialize some vars lBytesWritten=0l; iRetCode=0; // at the moment we are ignoring the fact that the local destination file // may not open correctly. if((iFileHandle=_lopen(filename,OF_READ))== -1) { DoPrintf("failed to open file %s (%u)",filename,errno); if(bBell) MessageBeep(MB_ICONEXCLAMATION); } else { sendingfilehandle = iFileHandle; sendingfile = TRUE; // get the start time ttStart=time(NULL); // loop to send output to remote end while((iNumBytes=_lread(iFileHandle,szMsgBuf,512))>0) { // this forces binary mode at the moment iRetCode=sendstr(sockfd,szMsgBuf,iNumBytes); // count the characters that we received lBytesWritten+=iNumBytes; wsprintf(szString,"%lu",lBytesWritten); SendMessage(hTxtLBytes,WM_SETTEXT,0,(LPARAM)szString); } // get the finish time ttStop=time(NULL); // if the output file is open, close it _lclose(iFileHandle); sendingfile = FALSE; sendingfilehandle = -1; // show the user how we did SendMessage(hTxtLBytes,WM_SETTEXT,0,(LPARAM)NULL); ttDiff=ttStop-ttStart; if(ttDiff==0l) ttDiff=1l; // lgk fix to convert bps to k/sec if bps > 1024 if (lBytesWritten > 1024) { DoPrintf("%ld bytes transmitted in %.2f seconds, (%3.2fKbytes/sec), transfer %s", lBytesWritten,(float)ttDiff,(float)lBytesWritten/1024.000/(float)ttDiff, (iFileHandle==-1)?"failed":"succeeded"); if (iFileHandle != -1) { totalbytestransfered = totalbytestransfered + lBytesWritten; totaltimefortransfer = totaltimefortransfer + ttDiff; ++totalfilestransfered; } } else { DoPrintf("Transmitted %ld bytes in %ld secs, %ld bps, transfer %s", lBytesWritten,(long)ttDiff, lBytesWritten*8l/(long)(ttDiff), (iFileHandle==-1)?"failed":"succeeded"); if (iFileHandle != -1) { totalbytestransfered = totalbytestransfered + lBytesWritten; totaltimefortransfer = totaltimefortransfer + ttDiff; ++totalfilestransfered; } } iRetCode=TRUE; if(bBell) MessageBeep(MB_ICONASTERISK); } // turn off our command in progress flag bCmdInProgress--; return (iRetCode); } // read information from the data socket into a file. int ReadMass(SOCKET sockfd,LPSTR filename, LPSTR shortname, BOOL binaryflag) { int iNumBytes; int iRetCode; int iFileHandle; long lBytesRead; time_t ttStart,ttStop,ttDiff; // if we don't have a socket, return an error if(sockfd==INVALID_SOCKET || !(bConnected)) return 0; // turn on a flag so other routines know we have a command in progress bCmdInProgress++; // make sure we don't mistakenly think we timed out KillTimer(hWndMain,10); bAborted=FALSE; // initialize some vars lBytesRead=0l; iRetCode=0; // at the moment we are ignoring the fact that the local destination file // may not open correctly. if((iFileHandle=_lcreat(filename,0))== -1) { DoPrintf("failed to open file %s (%u)",filename,errno); DoPrintf("Trying shorting name %s ",shortname); if ((iFileHandle=_lcreat(shortname,0)) == -1) DoPrintf("Still failed to open file %s (%u)",shortname,errno); } // here if the name was too long than may be an ntfs partition so try the shorter name receivefilehandle = iFileHandle; receivingfile = TRUE; // get the start time ttStart=time(NULL); // loop to receive input from remote end while(!bAborted && (iNumBytes=recv(sockfd,(LPSTR)szMsgBuf,4000,0))>0) { // write what we received if the file is open if(iFileHandle!= -1) _lwrite(iFileHandle,szMsgBuf,iNumBytes); // count the characters that we received lBytesRead+=iNumBytes; // update screen wsprintf(szString,"%lu",lBytesRead); SendMessage(hTxtRBytes,WM_SETTEXT,0,(LPARAM)szString); } // get the finish time ttStop=time(NULL); // if the output file is open, close it if(iFileHandle != -1) { _lclose(iFileHandle); receivingfile = FALSE; receivefilehandle = -1; } // if we had a recv error, let us know about it if(iNumBytes==SOCKET_ERROR) { ReportWSError("recv",WSAGetLastError()); if(lBytesRead==0l) { if(bBell) MessageBeep(MB_ICONEXCLAMATION); bCmdInProgress--; return(FALSE); } } SendMessage(hTxtRBytes,WM_SETTEXT,0,(LPARAM)NULL); ttDiff=ttStop-ttStart; if(ttDiff==0l) ttDiff=1l; // show the user how we did if (lBytesRead > 1024) { DoPrintf("%ld bytes received in %.2f seconds, (%3.2fKbytes/sec), transfer %s", lBytesRead,(float)ttDiff,(float)lBytesRead/1024.000/(float)ttDiff, (iFileHandle==-1 || bAborted)?"failed":"succeeded"); if (iFileHandle != -1) { totalbytestransfered = totalbytestransfered + lBytesRead; totaltimefortransfer = totaltimefortransfer + ttDiff; ++totalfilestransfered; } // lgk set global variable so that we know it succeeded so we will // close window globalsucceed = TRUE; if (iFileHandle == -1) globalsucceed = FALSE; } else { DoPrintf("Received %ld bytes in %ld secs, %ld bps, transfer %s", lBytesRead,(long)ttDiff, lBytesRead*8l/(long)ttDiff, (iFileHandle==-1 || bAborted)?"failed":"succeeded"); if (iFileHandle != -1) { totalbytestransfered = totalbytestransfered + lBytesRead; totaltimefortransfer = totaltimefortransfer + ttDiff; ++totalfilestransfered; } } // lgk set global variable so that we know it succeeded so we will // close window globalsucceed = TRUE; if (iFileHandle == -1) globalsucceed = FALSE; // DoPrintf("Bell = %d \n",bBell); if(bBell > 0) MessageBeep(MB_ICONASTERISK); // turn off our command in progress flag bCmdInProgress--; return (TRUE); }