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));
|
||||
cli->fd = -1;
|
||||
cli->chunk = -1;
|
||||
|
||||
syslog(LOG_ERR, "accepting client connection from %s:%hu",
|
||||
inet_ntoa(cli->addr.sin_addr), htons(cli->addr.sin_port));
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <stdbool.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define MAX_CHUNKS 4
|
||||
|
||||
#define TIP_MSG_REQUEST_MAXLEN 131072
|
||||
|
||||
extern const char *root;
|
||||
|
@ -48,7 +50,9 @@ struct tip_client {
|
|||
enum tip_http_method method;
|
||||
const char *uri;
|
||||
const char *path;
|
||||
uint32_t chunk;
|
||||
off_t size;
|
||||
off_t left;
|
||||
int fd;
|
||||
off_t offset;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ int tip_client_state_process_payload(struct tip_client *cli)
|
|||
char _uri[32], *uri = _uri;
|
||||
char allow_redirect_str[5];
|
||||
char path[PATH_MAX + 1];
|
||||
char *chunk = NULL;
|
||||
struct stat st;
|
||||
int err;
|
||||
|
||||
|
@ -93,14 +94,37 @@ int tip_client_state_process_payload(struct tip_client *cli)
|
|||
if (!sanitize(uri))
|
||||
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);
|
||||
|
||||
err = stat(path, &st);
|
||||
if (err < 0)
|
||||
return tip_client_file_not_found(cli);
|
||||
|
||||
/* skip initial / */
|
||||
uri++;
|
||||
/* restore the original uri that was mangled. */
|
||||
if (chunk) {
|
||||
chunk--;
|
||||
*chunk = '.';
|
||||
}
|
||||
|
||||
cli->uri = strdup(uri);
|
||||
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)
|
||||
{
|
||||
uint64_t chunk_size;
|
||||
off_t chunk_offset;
|
||||
char buf[1024];
|
||||
int fd;
|
||||
|
||||
|
@ -156,8 +182,35 @@ int tip_client_state_process_payload_reply(struct tip_client *cli)
|
|||
if (fd < 0)
|
||||
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;
|
||||
break;
|
||||
case TIP_METHOD_HEAD:
|
||||
break;
|
||||
}
|
||||
|
||||
cli->left = cli->size;
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (cli->offset >= cli->size) {
|
||||
cli->left -= ret;
|
||||
|
||||
if (cli->left <= 0) {
|
||||
cli->state = TIP_CLIENT_CLOSE_WAIT;
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue