Merge branch 'master' of https://github.com/Agorise/c-ipfs
This commit is contained in:
commit
5678a14eb3
1 changed files with 78 additions and 35 deletions
115
core/api.c
115
core/api.c
|
@ -8,6 +8,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "libp2p/net/p2pnet.h"
|
#include "libp2p/net/p2pnet.h"
|
||||||
#include "libp2p/utils/logger.h"
|
#include "libp2p/utils/logger.h"
|
||||||
#include "ipfs/core/api.h"
|
#include "ipfs/core/api.h"
|
||||||
|
@ -56,23 +58,25 @@ int find_chunk(char *buf, const size_t buf_size, size_t *pos, size_t *size)
|
||||||
int read_chunked(int fd, struct s_request *req, char *already, size_t already_size)
|
int read_chunked(int fd, struct s_request *req, char *already, size_t already_size)
|
||||||
{
|
{
|
||||||
char buf[MAX_READ], *p;
|
char buf[MAX_READ], *p;
|
||||||
size_t pos, nsize;
|
size_t pos, nsize, buf_size = 0, r;
|
||||||
|
|
||||||
while (already_size > 0) {
|
if (already_size > 0) {
|
||||||
if (already_size < 10 &&
|
if (already_size <= sizeof(buf)) {
|
||||||
(already < buf || already > (buf + already_size))) {
|
|
||||||
memcpy(buf, already, already_size);
|
memcpy(buf, already, already_size);
|
||||||
already = buf;
|
buf_size += already_size;
|
||||||
if (socket_read_select4(fd, 5) <= 0) {
|
already_size = 0;
|
||||||
libp2p_logger_error("api", "socket timeout.\n");
|
} else {
|
||||||
break;
|
memcpy(buf, already, sizeof(buf));
|
||||||
}
|
already += sizeof(buf);
|
||||||
nsize = read(fd, buf+already_size, sizeof(buf) - already_size);
|
buf_size += sizeof(buf);
|
||||||
if (nsize > 0) {
|
already_size -= sizeof(buf);
|
||||||
already_size += nsize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!find_chunk(already, already_size, &pos, &nsize)) {
|
|
||||||
|
while(buf_size) {
|
||||||
|
if (!find_chunk(buf, buf_size, &pos, &nsize)) {
|
||||||
|
libp2p_logger_error("api", "fail find_chunk.\n");
|
||||||
|
libp2p_logger_error("api", "nsize = %d.\n", nsize);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (nsize == 0) {
|
if (nsize == 0) {
|
||||||
|
@ -80,37 +84,61 @@ int read_chunked(int fd, struct s_request *req, char *already, size_t already_si
|
||||||
}
|
}
|
||||||
p = realloc(req->buf, req->size + nsize);
|
p = realloc(req->buf, req->size + nsize);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
libp2p_logger_error("api", "fail realloc.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
req->buf = p;
|
req->buf = p;
|
||||||
req->size += nsize;
|
req->size += nsize;
|
||||||
already += pos;
|
|
||||||
already_size -= pos;
|
CPCHUNK:
|
||||||
while (nsize > already_size) {
|
r = nsize;
|
||||||
memcpy(req->buf + req->body + req->body_size, already, already_size);
|
buf_size -= pos;
|
||||||
req->body_size += already_size;
|
if (r > buf_size) {
|
||||||
nsize -= already_size;
|
r = buf_size;
|
||||||
already = buf;
|
}
|
||||||
if (socket_read_select4(fd, 5) <= 0) {
|
memcpy(req->buf + req->body + req->body_size, buf + pos, r);
|
||||||
libp2p_logger_error("api", "socket timeout.\n");
|
req->body_size += r;
|
||||||
|
nsize -= r;
|
||||||
|
buf_size -= r;
|
||||||
|
if (buf_size > 0) {
|
||||||
|
memmove(buf, buf + pos + r, buf_size);
|
||||||
|
}
|
||||||
|
pos = 0;
|
||||||
|
if (already_size > 0) {
|
||||||
|
r = sizeof(buf) - buf_size;
|
||||||
|
if (already_size <= r) {
|
||||||
|
memcpy(buf, already, already_size);
|
||||||
|
buf_size += already_size;
|
||||||
|
already_size = 0;
|
||||||
|
} else {
|
||||||
|
memcpy(buf, already, r);
|
||||||
|
already += r;
|
||||||
|
buf_size += r;
|
||||||
|
already_size -= r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket_read_select4(fd, 5) > 0) {
|
||||||
|
r = sizeof(buf) - buf_size;
|
||||||
|
r = read(fd, buf+buf_size, r);
|
||||||
|
buf_size += r;
|
||||||
|
if (r == 0 && nsize == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
already_size = read(fd, buf, sizeof buf);
|
|
||||||
if (nsize <= 0) {
|
if (r <= 0) {
|
||||||
libp2p_logger_error("api", "read fail.\n");
|
libp2p_logger_error("api", "read fail.\n");
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nsize) {
|
|
||||||
memcpy(req->buf + req->body + req->body_size, already, nsize);
|
|
||||||
req->body_size += nsize;
|
|
||||||
already += nsize;
|
|
||||||
}
|
|
||||||
if (memcmp (already, "\r\n", 2)!=0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
already += 2;
|
}
|
||||||
already_size -= 2;
|
|
||||||
|
if (nsize > 0)
|
||||||
|
goto CPCHUNK; // still have data to transfer on current chunk.
|
||||||
|
|
||||||
|
if (memcmp (buf, "\r\n", 2)!=0) {
|
||||||
|
libp2p_logger_error("api", "fail CRLF.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +187,7 @@ void *api_connection_thread (void *ptr)
|
||||||
{
|
{
|
||||||
int timeout, s, r;
|
int timeout, s, r;
|
||||||
const INT_TYPE i = (INT_TYPE) ptr;
|
const INT_TYPE i = (INT_TYPE) ptr;
|
||||||
char buf[MAX_READ+1], *p, *body;
|
char resp[MAX_READ+1], buf[MAX_READ+1], *p, *body;
|
||||||
char client[INET_ADDRSTRLEN];
|
char client[INET_ADDRSTRLEN];
|
||||||
struct s_request req;
|
struct s_request req;
|
||||||
int (*read_func)(int, struct s_request*, char*, size_t) = read_all;
|
int (*read_func)(int, struct s_request*, char*, size_t) = read_all;
|
||||||
|
@ -201,6 +229,7 @@ void *api_connection_thread (void *ptr)
|
||||||
req.method = 0;
|
req.method = 0;
|
||||||
p = strchr(req.buf + req.method, ' ');
|
p = strchr(req.buf + req.method, ' ');
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
libp2p_logger_error("api", "fail looking for space on method '%s'.\n", req.buf + req.method);
|
||||||
write_cstr (s, HTTP_400);
|
write_cstr (s, HTTP_400);
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
@ -208,6 +237,7 @@ void *api_connection_thread (void *ptr)
|
||||||
req.path = p - req.buf;
|
req.path = p - req.buf;
|
||||||
p = strchr(p, ' ');
|
p = strchr(p, ' ');
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
libp2p_logger_error("api", "fail looking for space on path '%s'.\n", req.buf + req.path);
|
||||||
write_cstr (s, HTTP_400);
|
write_cstr (s, HTTP_400);
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
@ -215,6 +245,7 @@ void *api_connection_thread (void *ptr)
|
||||||
req.http_ver = p - req.buf;
|
req.http_ver = p - req.buf;
|
||||||
p = strchr(req.buf + req.http_ver, '\r');
|
p = strchr(req.buf + req.http_ver, '\r');
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
libp2p_logger_error("api", "fail looking for CR on http_ver '%s'.\n", req.buf + req.http_ver);
|
||||||
write_cstr (s, HTTP_400);
|
write_cstr (s, HTTP_400);
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
@ -234,10 +265,12 @@ void *api_connection_thread (void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!read_func(s, &req, body, r - (body - buf))) {
|
if (!read_func(s, &req, body, r - (body - buf))) {
|
||||||
|
libp2p_logger_error("api", "fail read_func.\n");
|
||||||
write_cstr (s, HTTP_500);
|
write_cstr (s, HTTP_500);
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = strstr(req.buf + req.header, "Accept-Encoding:");
|
||||||
libp2p_logger_error("api", "method = '%s'\n"
|
libp2p_logger_error("api", "method = '%s'\n"
|
||||||
"path = '%s'\n"
|
"path = '%s'\n"
|
||||||
"http_ver = '%s'\n"
|
"http_ver = '%s'\n"
|
||||||
|
@ -246,6 +279,15 @@ void *api_connection_thread (void *ptr)
|
||||||
req.buf+req.method, req.buf+req.path, req.buf+req.http_ver,
|
req.buf+req.method, req.buf+req.path, req.buf+req.http_ver,
|
||||||
req.buf+req.header, req.body_size);
|
req.buf+req.header, req.body_size);
|
||||||
|
|
||||||
|
snprintf(resp, sizeof(resp), "%s 200 OK\r\n" \
|
||||||
|
"Content-Type: application/json\r\n"
|
||||||
|
"Server: c-ipfs/0.0.0-dev\r\n"
|
||||||
|
"X-Chunked-Output: 1\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n\r\n", req.buf + req.http_ver);
|
||||||
|
write_str (s, resp);
|
||||||
|
libp2p_logger_error("api", "resp = {\n%s\n}\n", resp);
|
||||||
|
|
||||||
if (strcmp(req.buf + req.method, "GET")==0) {
|
if (strcmp(req.buf + req.method, "GET")==0) {
|
||||||
// just an error message, because it's not used.
|
// just an error message, because it's not used.
|
||||||
write_dual (s, req.buf + req.http_ver, strchr (HTTP_404, ' '));
|
write_dual (s, req.buf + req.http_ver, strchr (HTTP_404, ' '));
|
||||||
|
@ -253,6 +295,7 @@ void *api_connection_thread (void *ptr)
|
||||||
// TODO: Handle chunked/gzip/form-data/json POST requests.
|
// TODO: Handle chunked/gzip/form-data/json POST requests.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
libp2p_logger_error("api", "fail looking for body.\n");
|
||||||
write_cstr (s, HTTP_400);
|
write_cstr (s, HTTP_400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue