📄 ftpdlib.c
字号:
if (ftpdWindowSize < 0 || ftpdWindowSize > 65536) ftpdWindowSize = FTPD_WINDOW_SIZE; /* set the window size */ if (setsockopt(newSock, SOL_SOCKET, SO_SNDBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); if (setsockopt(newSock, SOL_SOCKET, SO_RCVBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); /* replace the dataSock with our new connection */ (void) close (pSlot->dataSock); pSlot->dataSock = newSock; /* N.B.: we stay passive */ if (ftpdCmdSend (pSlot, pSlot->cmdSock, 150, "Opening %s mode data connection", pSlot->status & FTPD_ASCII_TYPE ? (int) "ASCII" : (int) "BINARY", 0, 0, 0, 0, 0) == ERROR) { (void) close (pSlot->dataSock); return (ERROR); } return (OK); } else { /* reuse the old connection -- it's still useful */ if (ftpdCmdSend (pSlot, pSlot->cmdSock, 125, "Using existing data connection", 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } return (OK); } } else { /* Determine address for local end of connection. */ addrLen = sizeof (struct sockaddr); if (getsockname (pSlot->cmdSock, (struct sockaddr *) &addr, &addrLen) < 0) { return (ERROR); } /* Replace control port with default data port. */ addr.sin_port = htons (FTP_DATA_PORT); /* open a new data socket */ if ((pSlot->dataSock = socket (AF_INET, SOCK_STREAM, 0)) < 0) { return (ERROR); } if (setsockopt (pSlot->dataSock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0 || bind (pSlot->dataSock, (struct sockaddr *) &addr, sizeof (addr)) < 0) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } /* Set socket address to PORT command values or default. */ bcopy ( (char *)&pSlot->dataAddr, (char *)&addr, sizeof (struct sockaddr_in)); /* try until we get a connection to the client's port */ while (connect (pSlot->dataSock, (struct sockaddr *) &addr, sizeof (addr)) < 0) { if ((errno & 0xffff) == EADDRINUSE && retry < FTPD_WAIT_MAX) { taskDelay (FTPD_WAIT_INTERVAL * sysClkRateGet ()); retry += FTPD_WAIT_INTERVAL; continue; } /* timeout -- we give up */ ftpdCmdSend (pSlot, pSlot->cmdSock, 425, "Can't build data connection", 0, 0, 0, 0, 0, 0); ftpdSockFree (&pSlot->dataSock); return (ERROR); } /* * Enable the keep alive option to prevent misbehaving clients * from locking the secondary task during file transfers. */ if (setsockopt (pSlot->dataSock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof (on)) != 0) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } /* Check for window size validity */ if (ftpdWindowSize < 0 || ftpdWindowSize > 65536) ftpdWindowSize = FTPD_WINDOW_SIZE; /* set the window size */ if (setsockopt(pSlot->dataSock, SOL_SOCKET, SO_SNDBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); if (setsockopt(pSlot->dataSock, SOL_SOCKET, SO_RCVBUF, (char *)&ftpdWindowSize, sizeof (ftpdWindowSize))) printf("Couldn't set the Send Window to 10k\n"); if (ftpdCmdSend (pSlot, pSlot->cmdSock, 150, "Opening %s mode data connection", pSlot->status & FTPD_ASCII_TYPE ? (int) "ASCII" : (int) "BINARY", 0, 0, 0, 0, 0) == ERROR) { ftpdSockFree (&pSlot->dataSock); return (ERROR); } } return (OK); }/********************************************************************************* ftpdDataStreamSend - send FTP data over data connection** When our FTP client does a "RETR" (send me a file) and we find an existing* file, ftpdWorkTask() will call us to perform the actual shipment of the* file in question over the data connection.** We do the initialization of the new data connection ourselves here* and make sure that everything is fine and dandy before shipping the* contents of the file. Special attention is given to the type of* the file representation -- ASCII or BINARY. If it's binary, we* don't perform the prepending of "\r" character in front of each* "\n" character. Otherwise, we have to do this for the ASCII files.** SEE ALSO:* ftpdDataStreamReceive which is symmetric to this function.*/LOCAL void ftpdDataStreamSend ( FTPD_SESSION_DATA *pSlot, /* pointer to our session slot */ FILE *inStream /* pointer to the input file stream */ ) { FAST char *pBuf; /* pointer to the session buffer */ FAST int netFd; /* output socket */ FAST int fileFd; /* input file descriptor */ FAST char ch; /* character holder */ FAST int cnt; /* number of chars read/written */ FAST FILE *outStream; /* buffered output socket stream */ int retval = 0; /* get a fresh connection or reuse the old one */ if (ftpdDataConnGet (pSlot) == ERROR) { dataError (pSlot); return; } pBuf = &pSlot->buf [0]; if (pSlot->status & FTPD_ASCII_TYPE) { /* ASCII representation */ /* get a buffered I/O stream for this output data socket */ if ((outStream = fdopen (pSlot->dataSock, "w")) == NULL) { dataError (pSlot); return; } /* write out the contents of the file and do the '\r' prepending */ while ((ch = getc (inStream)) != (char) EOF) { pSlot->byteCount++; /* if '\n' is encountered, we prepend a '\r' */ if (ch == '\n') { if (ferror (outStream)) { dataError (pSlot); fclose (outStream); return; } if (putc ('\r', outStream) == EOF) { dataError (pSlot); fclose (outStream); return; } } if (putc (ch, outStream) == EOF) { dataError (pSlot); fclose (outStream); return; } /* Abort the file transfer if a shutdown is in progress. */ if (ch == '\n' && ftpsShutdownFlag) { dataError (pSlot); fclose (outStream); return; } } /* flush it out */ (void) fflush (outStream); if (ferror (inStream)) { /* error in reading the file */ fileError (pSlot); fclose (outStream); return; } if (ferror (outStream)) { /* error in sending the file */ dataError (pSlot); fclose (outStream); return; } fclose (outStream); /* everything is okay */ transferOkay (pSlot); } else if (pSlot->status & FTPD_BINARY_TYPE) { /* BINARY representation */ netFd = pSlot->dataSock; /* get a raw descriptor for this input file */ fileFd = fileno (inStream); /* unbuffered block I/O between file and network */ while ((cnt = read (fileFd, pBuf, BUFSIZE)) > 0 && (retval = write (netFd, pBuf, cnt)) == cnt) { pSlot->byteCount += cnt; if (ftpsShutdownFlag) { /* Abort the file transfer if a shutdown is in progress. */ cnt = 1; break; } } /* cnt should be zero if the transfer ended normally */ if (cnt != 0) { if (cnt < 0) { fileError (pSlot); return; } ftpdDebugMsg ("read %d bytes, wrote %d bytes\n", cnt, retval,0,0); dataError (pSlot); return; } transferOkay (pSlot); } else unImplementedType (pSlot); /* invalide representation type */ }/********************************************************************************* ftpdDataStreamReceive - receive FTP data over data connection** When our FTP client requests "STOR" command and we were able to* create a file requested, ftpdWorkTask() will call ftpdDataStreamReceive* to actually carry out the request -- receiving the contents of the* named file and storing it in the new file created.** We do the initialization of the new data connection ourselves here* and make sure that everything is fine and dandy before receiving the* contents of the file. Special attention is given to the type of* the file representation -- ASCII or BINARY. If it's binary, we* don't perform the handling of '\r' character in front of each* '\n' character. Otherwise, we have to do this for the ASCII files.** SEE ALSO:* ftpdDataStreamSend which is symmetric to this function.*/LOCAL void ftpdDataStreamReceive ( FTPD_SESSION_DATA *pSlot, FILE *outStream ) { FAST char *pBuf; /* pointer to the session buffer */ FAST char ch; /* character holder */ FAST FILE *inStream; /* buffered input file stream for data socket */ FAST int fileFd; /* output file descriptor */ FAST int netFd; /* network file descriptor */ FAST BOOL dontPutc; /* flag to prevent bogus chars */ FAST int cnt; /* number of chars read/written */ /* get a fresh data connection or reuse the old one */ if (ftpdDataConnGet (pSlot) == ERROR) { dataError (pSlot); return; } pBuf = &pSlot->buf [0]; if (pSlot->status & FTPD_ASCII_TYPE) { /* ASCII representation */ /* get a buffer I/O stream for the input data socket connection */ if ((inStream = fdopen (pSlot->dataSock, "r")) == NULL) { dataError (pSlot); return; } /* read in the contents of the file while doing the '\r' handling */ while ((ch = getc (inStream)) != (char) EOF) { dontPutc = FALSE; pSlot->byteCount++; /* a rather strange handling of sequences of '\r' chars */ while (ch == '\r') { if (ferror (outStream)) { dataError (pSlot); fclose (inStream); return; } /* replace bogus chars between '\r' and '\n' chars with '\r' */ if ((ch = getc (inStream)) != '\n') { (void) putc ('\r', outStream); if (ch == '\0' || ch == (char) EOF) { dontPutc = TRUE; break; } } } if (dontPutc == FALSE) (void) putc (ch, outStream); /* Abort file transfer if a shutdown is in progress. */ if (ch == '\n' && ftpsShutdownFlag) { dataError (pSlot); fclose (inStream); return; } } /* flush out to the file */ (void) fflush (outStream); if (ferror (inStream)) { /* network input error */ dataError (pSlot); fclose (inStream); return; } if (ferror (outStream)) { /* file output error */ fileError (pSlot); fclose (inStream); retur
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -