mirror of
https://github.com/wiiu-env/ftpiiu_plugin.git
synced 2024-11-22 20:59:18 +01:00
Improve FTP throughput
This commit is contained in:
parent
d70cc5a238
commit
1c5084e08e
@ -33,7 +33,7 @@ DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
APP_TITLE := ftBRONY
|
||||
APP_DESCRIPTION := Like ftPONY but magical.
|
||||
APP_DESCRIPTION := ftBRONY v1.2
|
||||
APP_AUTHOR := mtheall
|
||||
ICON := ftbrony.png
|
||||
|
||||
@ -44,7 +44,7 @@ ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O3 -mword-relocations \
|
||||
$(ARCH) \
|
||||
-DSTATUS_STRING="\"ftbrony v1.1\""
|
||||
-DSTATUS_STRING="\"ftbrony v1.2\""
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
|
@ -3,7 +3,7 @@ TARGET := $(notdir $(CURDIR))
|
||||
CFILES := $(wildcard source/*.c)
|
||||
OFILES := $(patsubst source/%,build.linux/%,$(CFILES:.c=.o))
|
||||
|
||||
CFLAGS := -g -Wall -Iinclude -DSTATUS_STRING="\"ftpd v1.0\""
|
||||
CFLAGS := -g -Wall -Iinclude -DSTATUS_STRING="\"ftpd v1.2\""
|
||||
LDFLAGS :=
|
||||
|
||||
.PHONY: all clean
|
||||
|
140
source/ftp.c
140
source/ftp.c
@ -22,10 +22,12 @@
|
||||
|
||||
#define POLL_UNKNOWN (~(POLLIN|POLLOUT))
|
||||
|
||||
#define XFER_BUFFERSIZE 4096
|
||||
#define XFER_BUFFERSIZE 32768
|
||||
#define SOCK_BUFFERSIZE 32768
|
||||
#define FILE_BUFFERSIZE 65536
|
||||
#define CMD_BUFFERSIZE 1024
|
||||
#define SOC_ALIGN 0x1000
|
||||
#define SOC_BUFFERSIZE 0x100000
|
||||
#define SOCU_ALIGN 0x1000
|
||||
#define SOCU_BUFFERSIZE 0x100000
|
||||
#define LISTEN_PORT 5000
|
||||
#ifdef _3DS
|
||||
#define DATA_PORT (LISTEN_PORT+1)
|
||||
@ -99,16 +101,18 @@ struct ftp_session_t
|
||||
ftp_session_t *next; /*!< link to next session */
|
||||
ftp_session_t *prev; /*!< link to prev session */
|
||||
|
||||
int (*transfer)(ftp_session_t*); /*! data transfer callback */
|
||||
char buffer[XFER_BUFFERSIZE]; /*! persistent data between callbacks */
|
||||
size_t bufferpos; /*! persistent buffer position between callbacks */
|
||||
size_t buffersize; /*! persistent buffer size between callbacks */
|
||||
uint64_t filepos; /*! persistent file position between callbacks */
|
||||
uint64_t filesize; /*! persistent file size between callbacks */
|
||||
int (*transfer)(ftp_session_t*); /*! data transfer callback */
|
||||
char buffer[XFER_BUFFERSIZE]; /*! persistent data between callbacks */
|
||||
char tmp_buffer[XFER_BUFFERSIZE]; /*! persistent data between callbacks */
|
||||
char file_buffer[FILE_BUFFERSIZE]; /*! stdio file buffer */
|
||||
size_t bufferpos; /*! persistent buffer position between callbacks */
|
||||
size_t buffersize; /*! persistent buffer size between callbacks */
|
||||
uint64_t filepos; /*! persistent file position between callbacks */
|
||||
uint64_t filesize; /*! persistent file size between callbacks */
|
||||
union
|
||||
{
|
||||
DIR *dp; /*! persistent open directory pointer between callbacks */
|
||||
int fd; /*! persistent open file descriptor between callbacks */
|
||||
DIR *dp; /*! persistent open directory pointer between callbacks */
|
||||
FILE *fp; /*! persistent open file pointer between callbacks */
|
||||
};
|
||||
};
|
||||
|
||||
@ -181,17 +185,21 @@ ftp_command_cmp(const void *p1,
|
||||
|
||||
#ifdef _3DS
|
||||
/*! SOC service buffer */
|
||||
static u32 *SOC_buffer = NULL;
|
||||
static u32 *SOCU_buffer = NULL;
|
||||
#endif
|
||||
|
||||
/*! server listen address */
|
||||
static struct sockaddr_in serv_addr;
|
||||
/*! listen file descriptor */
|
||||
static int listenfd = -1;
|
||||
#ifdef _3DS
|
||||
/*! current data port */
|
||||
static in_port_t data_port = DATA_PORT;
|
||||
#endif
|
||||
/*! list of ftp sessions */
|
||||
static ftp_session_t *sessions = NULL;
|
||||
/*! socket buffersize */
|
||||
static int sock_buffersize = SOCK_BUFFERSIZE;
|
||||
|
||||
/*! Allocate a new data port
|
||||
*
|
||||
@ -237,6 +245,32 @@ ftp_set_socket_nonblocking(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! set socket options
|
||||
*
|
||||
* @param[in] fd socket
|
||||
*/
|
||||
static void
|
||||
ftp_set_socket_options(int fd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* it's okay if this fails */
|
||||
rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
|
||||
&sock_buffersize, sizeof(sock_buffersize));
|
||||
if(rc != 0)
|
||||
{
|
||||
console_print(RED "setsockopt: %d %s\n" RESET, errno, strerror(errno));
|
||||
}
|
||||
|
||||
/* it's okay if this fails */
|
||||
rc = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
|
||||
&sock_buffersize, sizeof(sock_buffersize));
|
||||
if(rc != 0)
|
||||
{
|
||||
console_print(RED "setsockopt: %d %s\n" RESET, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*! close a socket
|
||||
*
|
||||
* @param[in] fd socket to close
|
||||
@ -325,10 +359,10 @@ ftp_session_close_file(ftp_session_t *session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = close(session->fd);
|
||||
rc = fclose(session->fp);
|
||||
if(rc != 0)
|
||||
console_print(RED "close: %d %s\n" RESET, errno, strerror(errno));
|
||||
session->fd = -1;
|
||||
console_print(RED "fclose: %d %s\n" RESET, errno, strerror(errno));
|
||||
session->fp = NULL;
|
||||
}
|
||||
|
||||
/*! open file for reading for ftp session
|
||||
@ -344,15 +378,23 @@ ftp_session_open_file_read(ftp_session_t *session)
|
||||
struct stat st;
|
||||
|
||||
/* open file in read mode */
|
||||
session->fd = open(session->buffer, O_RDONLY);
|
||||
if(session->fd < 0)
|
||||
session->fp = fopen(session->buffer, "rb");
|
||||
if(session->fp == NULL)
|
||||
{
|
||||
console_print(RED "open '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
|
||||
console_print(RED "fopen '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* it's okay if this fails */
|
||||
errno = 0;
|
||||
rc = setvbuf(session->fp, session->file_buffer, _IOFBF, FILE_BUFFERSIZE);
|
||||
if(rc != 0)
|
||||
{
|
||||
console_print(RED "setvbuf: %d %s\n" RESET, errno, strerror(errno));
|
||||
}
|
||||
|
||||
/* get the file size */
|
||||
rc = fstat(session->fd, &st);
|
||||
rc = fstat(fileno(session->fp), &st);
|
||||
if(rc != 0)
|
||||
{
|
||||
console_print(RED "fstat '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
|
||||
@ -380,10 +422,10 @@ ftp_session_read_file(ftp_session_t *session)
|
||||
ssize_t rc;
|
||||
|
||||
/* read file at current position */
|
||||
rc = read(session->fd, session->buffer, sizeof(session->buffer));
|
||||
rc = fread(session->buffer, 1, sizeof(session->buffer), session->fp);
|
||||
if(rc < 0)
|
||||
{
|
||||
console_print(RED "read: %d %s\n" RESET, errno, strerror(errno));
|
||||
console_print(RED "fread: %d %s\n" RESET, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -404,14 +446,24 @@ ftp_session_read_file(ftp_session_t *session)
|
||||
static int
|
||||
ftp_session_open_file_write(ftp_session_t *session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* open file in write and create mode with truncation */
|
||||
session->fd = open(session->buffer, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
if(session->fd < 0)
|
||||
session->fp = fopen(session->buffer, "wb");
|
||||
if(session->fp == NULL)
|
||||
{
|
||||
console_print(RED "open '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
|
||||
console_print(RED "fopen '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* it's okay if this fails */
|
||||
errno = 0;
|
||||
rc = setvbuf(session->fp, session->file_buffer, _IOFBF, FILE_BUFFERSIZE);
|
||||
if(rc != 0)
|
||||
{
|
||||
console_print(RED "setvbuf: %d %s\n" RESET, errno, strerror(errno));
|
||||
}
|
||||
|
||||
/* reset file position */
|
||||
/* TODO: support REST command */
|
||||
session->filepos = 0;
|
||||
@ -431,15 +483,16 @@ ftp_session_write_file(ftp_session_t *session)
|
||||
ssize_t rc;
|
||||
|
||||
/* write to file at current position */
|
||||
rc = write(session->fd, session->buffer + session->bufferpos,
|
||||
session->buffersize - session->bufferpos);
|
||||
rc = fwrite(session->buffer + session->bufferpos,
|
||||
1, session->buffersize - session->bufferpos,
|
||||
session->fp);
|
||||
if(rc < 0)
|
||||
{
|
||||
console_print(RED "write: %d %s\n" RESET, errno, strerror(errno));
|
||||
console_print(RED "fwrite: %d %s\n" RESET, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if(rc == 0)
|
||||
console_print(RED "write: wrote 0 bytes\n" RESET);
|
||||
console_print(RED "fwrite: wrote 0 bytes\n" RESET);
|
||||
|
||||
/* adjust file position */
|
||||
session->filepos += rc;
|
||||
@ -766,6 +819,9 @@ ftp_session_connect(ftp_session_t *session)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set socket options */
|
||||
ftp_set_socket_options(session->data_fd);
|
||||
|
||||
/* connect to peer */
|
||||
rc = connect(session->data_fd, (struct sockaddr*)&session->peer_addr,
|
||||
sizeof(session->peer_addr));
|
||||
@ -986,18 +1042,18 @@ ftp_init(void)
|
||||
#endif
|
||||
|
||||
/* allocate buffer for SOC service */
|
||||
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
|
||||
if(SOC_buffer == NULL)
|
||||
SOCU_buffer = (u32*)memalign(SOCU_ALIGN, SOCU_BUFFERSIZE);
|
||||
if(SOCU_buffer == NULL)
|
||||
{
|
||||
console_print(RED "memalign: failed to allocate\n" RESET);
|
||||
goto memalign_fail;
|
||||
}
|
||||
|
||||
/* initialize SOC service */
|
||||
ret = socInit(SOC_buffer, SOC_BUFFERSIZE);
|
||||
ret = socInit(SOCU_buffer, SOCU_BUFFERSIZE);
|
||||
if(ret != 0)
|
||||
{
|
||||
console_print(RED "SOC_Initialize: 0x%08X\n" RESET, (unsigned int)ret);
|
||||
console_print(RED "socInit: 0x%08X\n" RESET, (unsigned int)ret);
|
||||
goto soc_fail;
|
||||
}
|
||||
#endif
|
||||
@ -1011,6 +1067,9 @@ ftp_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set socket options */
|
||||
ftp_set_socket_options(listenfd);
|
||||
|
||||
/* get address to listen on */
|
||||
serv_addr.sin_family = AF_INET;
|
||||
#ifdef _3DS
|
||||
@ -1019,6 +1078,7 @@ ftp_init(void)
|
||||
#else
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr.sin_port = htons(LISTEN_PORT);
|
||||
#endif
|
||||
|
||||
/* reuse address */
|
||||
{
|
||||
@ -1031,7 +1091,6 @@ ftp_init(void)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* bind socket to listen address */
|
||||
rc = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
|
||||
@ -1092,7 +1151,7 @@ ftp_init(void)
|
||||
|
||||
#ifdef _3DS
|
||||
soc_fail:
|
||||
free(SOC_buffer);
|
||||
free(SOCU_buffer);
|
||||
|
||||
memalign_fail:
|
||||
#ifdef ENABLE_LOGGING
|
||||
@ -1127,8 +1186,8 @@ ftp_exit(void)
|
||||
/* deinitialize SOC service */
|
||||
ret = socExit();
|
||||
if(ret != 0)
|
||||
console_print(RED "SOC_Shutdown: 0x%08X\n" RESET, (unsigned int)ret);
|
||||
free(SOC_buffer);
|
||||
console_print(RED "socExit: 0x%08X\n" RESET, (unsigned int)ret);
|
||||
free(SOCU_buffer);
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
/* close log file */
|
||||
@ -1671,6 +1730,8 @@ FTP_DECLARE(PASV)
|
||||
return ftp_send_response(session, 451, "\r\n");
|
||||
}
|
||||
|
||||
ftp_set_socket_options(session->pasv_fd);
|
||||
|
||||
session->pasv_addr.sin_port = htons(next_data_port());
|
||||
|
||||
#ifdef _3DS
|
||||
@ -1946,8 +2007,7 @@ FTP_DECLARE(RNFR)
|
||||
|
||||
FTP_DECLARE(RNTO)
|
||||
{
|
||||
int rc;
|
||||
char buffer[XFER_BUFFERSIZE];
|
||||
int rc;
|
||||
|
||||
console_print(CYAN "%s %s\n" RESET, __func__, args ? args : "");
|
||||
|
||||
@ -1958,12 +2018,12 @@ FTP_DECLARE(RNTO)
|
||||
|
||||
session->flags &= ~SESSION_RENAME;
|
||||
|
||||
memcpy(buffer, session->buffer, XFER_BUFFERSIZE);
|
||||
memcpy(session->tmp_buffer, session->buffer, XFER_BUFFERSIZE);
|
||||
|
||||
if(build_path(session, args) != 0)
|
||||
return ftp_send_response(session, 554, "%s\r\n", strerror(errno));
|
||||
|
||||
rc = rename(buffer, session->buffer);
|
||||
rc = rename(session->tmp_buffer, session->buffer);
|
||||
if(rc != 0)
|
||||
{
|
||||
console_print(RED "rename: %d %s\n" RESET, errno, strerror(errno));
|
||||
|
@ -65,6 +65,7 @@ main(int argc,
|
||||
/* initialize needed 3DS services */
|
||||
gfxInitDefault();
|
||||
gfxSet3D(false);
|
||||
sdmcWriteSafe(false);
|
||||
#endif
|
||||
|
||||
/* initialize console subsystem */
|
||||
|
Loading…
Reference in New Issue
Block a user