runtime split original file into chunks
No need to split the original file on the server side.master
parent
e39f7f8e3c
commit
324fdcfd58
|
@ -471,6 +471,7 @@ void tip_server_accept_cb(struct ev_loop *loop, struct ev_io *io, int events)
|
||||||
}
|
}
|
||||||
memcpy(&cli->addr, &client_addr, sizeof(client_addr));
|
memcpy(&cli->addr, &client_addr, sizeof(client_addr));
|
||||||
cli->fd = -1;
|
cli->fd = -1;
|
||||||
|
cli->chunk = -1;
|
||||||
|
|
||||||
syslog(LOG_ERR, "accepting client connection from %s:%hu",
|
syslog(LOG_ERR, "accepting client connection from %s:%hu",
|
||||||
inet_ntoa(cli->addr.sin_addr), htons(cli->addr.sin_port));
|
inet_ntoa(cli->addr.sin_addr), htons(cli->addr.sin_port));
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#define MAX_CHUNKS 4
|
||||||
|
|
||||||
#define TIP_MSG_REQUEST_MAXLEN 131072
|
#define TIP_MSG_REQUEST_MAXLEN 131072
|
||||||
|
|
||||||
extern const char *root;
|
extern const char *root;
|
||||||
|
@ -48,7 +50,9 @@ struct tip_client {
|
||||||
enum tip_http_method method;
|
enum tip_http_method method;
|
||||||
const char *uri;
|
const char *uri;
|
||||||
const char *path;
|
const char *path;
|
||||||
|
uint32_t chunk;
|
||||||
off_t size;
|
off_t size;
|
||||||
|
off_t left;
|
||||||
int fd;
|
int fd;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ int tip_client_state_process_payload(struct tip_client *cli)
|
||||||
char _uri[32], *uri = _uri;
|
char _uri[32], *uri = _uri;
|
||||||
char allow_redirect_str[5];
|
char allow_redirect_str[5];
|
||||||
char path[PATH_MAX + 1];
|
char path[PATH_MAX + 1];
|
||||||
|
char *chunk = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -93,14 +94,37 @@ int tip_client_state_process_payload(struct tip_client *cli)
|
||||||
if (!sanitize(uri))
|
if (!sanitize(uri))
|
||||||
return tip_client_method_not_found(cli);
|
return tip_client_method_not_found(cli);
|
||||||
|
|
||||||
|
/* skip initial / */
|
||||||
|
uri++;
|
||||||
|
|
||||||
|
switch (cli->method) {
|
||||||
|
case TIP_METHOD_GET:
|
||||||
|
case TIP_METHOD_POST:
|
||||||
|
/* get chunk number from file extension, e.g. FILE.0 */
|
||||||
|
chunk = strchr(uri, '.');
|
||||||
|
if (chunk) {
|
||||||
|
*chunk = '\0';
|
||||||
|
chunk++;
|
||||||
|
cli->chunk = atoi(chunk);
|
||||||
|
if (cli->chunk >= MAX_CHUNKS)
|
||||||
|
return tip_client_file_not_found(cli);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TIP_METHOD_HEAD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(path, PATH_MAX, "%s/%s", root, uri);
|
snprintf(path, PATH_MAX, "%s/%s", root, uri);
|
||||||
|
|
||||||
err = stat(path, &st);
|
err = stat(path, &st);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return tip_client_file_not_found(cli);
|
return tip_client_file_not_found(cli);
|
||||||
|
|
||||||
/* skip initial / */
|
/* restore the original uri that was mangled. */
|
||||||
uri++;
|
if (chunk) {
|
||||||
|
chunk--;
|
||||||
|
*chunk = '.';
|
||||||
|
}
|
||||||
|
|
||||||
cli->uri = strdup(uri);
|
cli->uri = strdup(uri);
|
||||||
cli->path = strdup(path);
|
cli->path = strdup(path);
|
||||||
|
@ -139,6 +163,8 @@ int tip_client_state_process_payload(struct tip_client *cli)
|
||||||
|
|
||||||
int tip_client_state_process_payload_reply(struct tip_client *cli)
|
int tip_client_state_process_payload_reply(struct tip_client *cli)
|
||||||
{
|
{
|
||||||
|
uint64_t chunk_size;
|
||||||
|
off_t chunk_offset;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -156,8 +182,35 @@ int tip_client_state_process_payload_reply(struct tip_client *cli)
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return tip_client_file_not_found(cli);
|
return tip_client_file_not_found(cli);
|
||||||
|
|
||||||
if (cli->method == TIP_METHOD_POST)
|
switch (cli->method) {
|
||||||
|
case TIP_METHOD_GET:
|
||||||
|
if (cli->chunk < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
chunk_size = cli->size / MAX_CHUNKS;
|
||||||
|
if (cli->size % MAX_CHUNKS) {
|
||||||
|
if (cli->chunk < MAX_CHUNKS - 1) {
|
||||||
|
chunk_size++;
|
||||||
|
chunk_offset = chunk_size * cli->chunk;
|
||||||
|
} else {
|
||||||
|
chunk_offset = chunk_size * cli->chunk;
|
||||||
|
chunk_offset += MAX_CHUNKS - 1;
|
||||||
|
chunk_size--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chunk_offset = chunk_size * cli->chunk;
|
||||||
|
}
|
||||||
|
cli->size = chunk_size;
|
||||||
|
cli->offset = chunk_offset;
|
||||||
|
break;
|
||||||
|
case TIP_METHOD_POST:
|
||||||
cli->size = 0;
|
cli->size = 0;
|
||||||
|
break;
|
||||||
|
case TIP_METHOD_HEAD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cli->left = cli->size;
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
snprintf(buf, sizeof(buf),
|
||||||
"HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n",
|
"HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n",
|
||||||
|
@ -181,10 +234,21 @@ int tip_client_state_process_payload_reply(struct tip_client *cli)
|
||||||
|
|
||||||
int tip_client_state_process_payload_bulk(struct tip_client *cli)
|
int tip_client_state_process_payload_bulk(struct tip_client *cli)
|
||||||
{
|
{
|
||||||
if (sendfile(tip_client_socket(cli), cli->fd, &cli->offset, BLOCK) < 0)
|
uint32_t bytes;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (cli->left < BLOCK)
|
||||||
|
bytes = cli->left;
|
||||||
|
else
|
||||||
|
bytes = BLOCK;
|
||||||
|
|
||||||
|
ret = sendfile(tip_client_socket(cli), cli->fd, &cli->offset, bytes);
|
||||||
|
if (ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (cli->offset >= cli->size) {
|
cli->left -= ret;
|
||||||
|
|
||||||
|
if (cli->left <= 0) {
|
||||||
cli->state = TIP_CLIENT_CLOSE_WAIT;
|
cli->state = TIP_CLIENT_CLOSE_WAIT;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue