commit 631cd83280c0dbd6766bae1f8675b88af631c0c2
parent 2c08011fa094be52c4d95d950ac72c267764bd4f
Author: Remy Noulin <loader2x@gmail.com>
Date: Sun, 14 Aug 2022 10:37:00 -0400
add comments
NOTES.md | 14 +++++++++++-
README.md | 3 +++
makeHeader.c | 25 +++++++++++++++++++++
sclient.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
sserver.c | 39 +++++++++++++++++++++++++++++++--
5 files changed, 146 insertions(+), 6 deletions(-)
Diffstat:
5 files changed, 146 insertions(+), 6 deletions(-)
diff --git a/NOTES.md b/NOTES.md
@@ -1,7 +1,19 @@
+- create packages
+- tls
+- reduce repeated code: create macros and functions
+- check inputs, add limits
+- add rate limiter, ban wrong token for 15minutes
+- create tests
+- send errors from server to client
+- make daemon
+
+
+Speed (no tls)
158MB
tuyau 2.744s
scp 3.896s
+
# to root path
x./sclient.c NOTES.md dev
x./sclient.c ~/notes.txt dev
@@ -65,7 +77,7 @@ port 1032
token: QE123123
root: /home/rlp/tmp/
port: 1022
-serverConfig.yml
+~/.tuyau/serverConfig.yml
---
port: 1023 // optional
user:
diff --git a/README.md b/README.md
@@ -8,3 +8,6 @@ Commits:
2 - send files and directories recursively
3 - receive a single file
4 - receive files and directories recursively
+
+The send code in the client is similar to the send code in the server.
+The receive code in the server is similar to the receive code in the client.
diff --git a/makeHeader.c b/makeHeader.c
@@ -1,6 +1,31 @@
#include "libsheepyObject.h"
#include "shpPackages/short/short.h"
+/*
+packet structures:
+0 - send file
+ u8 command = 0
+ u8 token[8]
+ u16 filenameLength
+ <filename>
+ u16 filemode
+ u16 pathLength
+ <path>
+ u64 filesize
+ <filedata>
+1 - mkdir
+ u8 command = 0
+ u8 token[8]
+ u16 filemode
+ u16 pathLength
+ <path>
+2 - download/receive files
+ u8 command = 0
+ u8 token[8]
+ u16 pathLength
+ <path>
+*/
+
void makeHeader(u8 *buf, u32 *bufip, u8 command, smallDictt *svrInfo, char *sendFile, char *destPath, u64 **filesize) {
// command
diff --git a/sclient.c b/sclient.c
@@ -1,7 +1,27 @@
#! /usr/bin/env sheepy
/* or direct path to sheepy: #! /usr/local/bin/sheepy */
-
/* Libsheepy documentation: https://spartatek.se/libsheepy/ */
+
+/*
+usage
+- create server config
+- start server
+- create client config
+- run client
+
+Upload files:
+./sclient.c files serverName
+./sclient.c files serverName:path/
+./sclient.c file serverName:path/newfilename
+
+Downdload files:
+./sclient.c serverName:path/files
+ >> downloads to current directory
+./sclient.c serverName:path/files path/
+./sclient.c serverName:path/file path/newfilename
+
+*/
+
#include "libsheepyObject.h"
#include <netdb.h>
#include <netinet/in.h>
@@ -20,6 +40,10 @@
#define CONFIG "~/.tuyau/config.yml"
+/* enable/disable logging */
+/* #undef pLog */
+/* #define pLog(...) */
+
bool saveReceivedData(void *receiveB, size_t sz, void *context);
int main(int ARGC, char** ARGV) {
@@ -27,6 +51,17 @@ int main(int ARGC, char** ARGV) {
initLibsheepy(ARGV[0]);
setLogMode(LOG_FUNC);
+ // Steps
+ //
+ // load configuration
+ // check if there is a server name in argv 1
+ // search for server name in last argument
+ // if receive and 2 args, arg 2 must be a valid path in client
+ // open connection to server
+ // receive files in receivePath
+ // send files
+
+ // load configuration
cleanCharP(config) = expandHome(CONFIG);
cleanAllocateSmallJson(cfg);
readFileG(cfg, config);
@@ -36,6 +71,13 @@ int main(int ARGC, char** ARGV) {
ret 1;
}
+ // check if there is a server name in argv 1
+ // if yes, the user wants to receive data from the server
+ // destPath is the path in the server to download from
+ // set server name
+ // if no, the user wants to upload to the server
+
+ // send or receive data to/from server
bool isReceive = no;
const char *serverName = null;
char *destPath = null;
@@ -52,6 +94,7 @@ int main(int ARGC, char** ARGV) {
}
if (not isReceive) {
+ // search for server name in last argument
if (ARGC == 2) {
logE("Missing arguments");
ret 1;
@@ -81,7 +124,7 @@ int main(int ARGC, char** ARGV) {
} // not isReceive
elif (ARGC > 2) {
// receive
- // arg 2 must be a path in client
+ // arg 2 must be a valid path in client
receivePath = ARGV[2];
cleanCharP(localPath) = normalizePathG(ARGV[2]);
if (not isEmptyG(localPath)/*ignore "." -> ""*/) {
@@ -109,6 +152,7 @@ int main(int ARGC, char** ARGV) {
lv(svrInfo);
+ // open connection to server
int sock;
struct sockaddr_in server;
struct hostent *hp;
@@ -140,6 +184,7 @@ int main(int ARGC, char** ARGV) {
XFailure;
}
+ // buffer for network packets
u8 buf[1024*1024] = init0Var;
if (isReceive) {
@@ -161,6 +206,7 @@ int main(int ARGC, char** ARGV) {
cleanAllocateSmallArray(pathToSend);
+ // verify that paths in client are valid
rangeFrom(i, 1, ARGC-1) {
if (not isPath(ARGV[i])) {
logE("Incorrect path: "BLD YLW"%s"RST,ARGV[i]);
@@ -171,10 +217,14 @@ int main(int ARGC, char** ARGV) {
cleanAllocateSmallDict(recusive);
+ // send files in command line arguments
+
iter(pathToSend, P) {
castS(p, P);
char *sendFile = ssGet(P);
+ // create local directory in server
+ // add files from local directory to recusive dict, the last element is the local path
if (isDirG(p)) {
logD("mkdir in server");
@@ -190,6 +240,7 @@ int main(int ARGC, char** ARGV) {
var dir = readDirAllG(rtSmallArrayt, p);
//lv(dir);
if (not isEmptyG(dir)) {
+ // save local path in last element
pushG(dir, ssGet(p));
setNFreeG(recusive, dirname, dir);
}
@@ -203,11 +254,13 @@ int main(int ARGC, char** ARGV) {
makeHeader(buf, &bufi, 0 /* command */, svrInfo, sendFile, destPath, &filesize);
if (*filesize < (sizeof(buf) - bufi)) {
+ // the file is smaller than the network buffer, send all in one go
pError0(bReadFile(sendFile, buf + bufi));
o(netframe,send , sock, buf, bufi + *filesize);
}
else {
logD("big file");
+ // loop to send big file in chunks
u64 szToSend = *filesize;
u8 *b = buf + bufi;
u64 bSz = sizeof(buf) - bufi;
@@ -234,7 +287,10 @@ int main(int ARGC, char** ARGV) {
} // loop on arguments
- // Send files recursively
+ // send files recursively
+ // each key is a path in server corresponding to a local directory
+ // the element is the list of files in the directory
+ // it is similar to the iter(pathToSend, P) loop
iter(recusive, A) {
cast(smallArrayt*,a,A);
@@ -244,6 +300,8 @@ int main(int ARGC, char** ARGV) {
castS(p, P);
char *sendFile = ssGet(P);
+ // create local directory in server
+ // add files from local directory to recusive dict, the last element is the local path
cleanCharP(localp) = catS(localPath, "/", ssGet(p));
if (isDirG(localp)) {
logD("mkdir in server");
@@ -259,6 +317,7 @@ int main(int ARGC, char** ARGV) {
var dir = readDirAllG(rtSmallArrayt, localp);
lv(dir);
if (not isEmptyG(dir)) {
+ // save local path in last element
pushG(dir, localp);
setNFreeG(recusive, dirname, dir);
}
@@ -274,11 +333,13 @@ int main(int ARGC, char** ARGV) {
makeHeader(buf, &bufi, 0 /* command */, svrInfo, localp, dest, &filesize);
if (*filesize < (sizeof(buf) - bufi)) {
+ // the file is smaller than the network buffer, send all in one go
pError0(bReadFile(localp, buf + bufi));
o(netframe,send , sock, buf, bufi + *filesize);
}
else {
logD("big file");
+ // loop to send big file in chunks
u64 szToSend = *filesize;
u8 *b = buf + bufi;
u64 bSz = sizeof(buf) - bufi;
@@ -323,6 +384,7 @@ u64 transferSz = 0;
bool saveReceivedData(void *receiveB, size_t sz, void *context) {
logVarG(sz);
if (packetCount == 0) {
+ // receive a new command
// header
u8 *command = (u8*) receiveB;
@@ -354,6 +416,7 @@ bool saveReceivedData(void *receiveB, size_t sz, void *context) {
logD("bufi %d fsz %d + %d, filename %s, root %s, destPath %s",bufi, *filesize, bufi + *filesize, filename, root,destPath);
+ // local filename
cleanCharP(path) = null;
if (not root) {
@@ -377,11 +440,13 @@ bool saveReceivedData(void *receiveB, size_t sz, void *context) {
lv(path);
if (*filesize <= sz - bufi) {
+ // the file is smaller than the network buffer, the complete file is already here
pError0(writeFile(path, receiveB + bufi, *filesize));
pError0(fileChmod(path, *filemode));
}
else {
logD("open fd");
+ // increase packetCount to receive big file in chunks
inc packetCount;
fd = open(path, O_WRONLY | O_CREAT, *filemode);
if (fd == -1) {
diff --git a/sserver.c b/sserver.c
@@ -29,6 +29,10 @@ int mysock = 0;
smallJsont *tokens = null;
+/* enable/disable logging */
+/* #undef pLog */
+/* #define pLog(...) */
+
void saveReceivedData(void *receiveB, size_t sz);
bool cb(void *buf, size_t size, void *context) {
@@ -41,10 +45,18 @@ int main(int ARGC, char** ARGV) {
initLibsheepy(ARGV[0]);
setLogMode(LOG_FUNC);
+ // Steps
+ // load configuration
+ // create tokens dict
+ // open listen socket
+ // start event loop
+
+ // load configuration
cleanCharP(config) = expandHome(CONFIG);
cleanAllocateSmallJson(cfg);
readFileG(cfg, config);
+ // create tokens dict
tokens = allocG(rtSmallJsont);
iter(cfg, D) {
@@ -54,6 +66,7 @@ int main(int ARGC, char** ARGV) {
lv(tokens);
+ // open listen socket
int sock;
struct sockaddr_in server;
int rval;
@@ -66,7 +79,7 @@ int main(int ARGC, char** ARGV) {
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons(1032);
+ server.sin_port = htons(1032); // TODO allow changing port
if (bind(sock, (struct sockaddr *) &server, sizeof(server))){
perror("bind failed");
@@ -77,6 +90,7 @@ int main(int ARGC, char** ARGV) {
o(netframe, setCallback, cb, NULL /*context*/);
+ // start event loop
listen(sock, 5);
forever {
mysock = accept(sock, (struct sockaddr *)0, 0);
@@ -94,6 +108,7 @@ int main(int ARGC, char** ARGV) {
void saveReceivedData(void *receiveB, size_t sz) {
logVarG(sz);
if (packetCount == 0) {
+ // receive a new command
// header
u8 *command = (u8*) receiveB;
u8 *token = (u8*) (receiveB + 1);
@@ -133,11 +148,13 @@ void saveReceivedData(void *receiveB, size_t sz) {
logD("bufi %d fsz %d + %d, filename %s, destPath %s",bufi, *filesize, bufi + *filesize, filename, destPath);
+ // local filename
char *path = catS(root, "/", nS(destPath));
pErrorNULL(normalizePathG(&path));
pErrorNULL(trimG(&path));
cleanCharP(nroot) = normalizePathG(root);
//lv(path);
+ // make sure path is inside root
if (not startsWithG(path, nroot)) {
logE("Incorrect path");
ret;
@@ -164,11 +181,13 @@ void saveReceivedData(void *receiveB, size_t sz) {
lv(path);
if (*filesize <= sz - bufi) {
+ // the file is smaller than the network buffer, the complete file is already here
pError0(writeFile(path, receiveB + bufi, *filesize));
pError0(fileChmod(path, *filemode));
}
else {
logD("open fd");
+ // increase packetCount to receive big file in chunks
inc packetCount;
fd = open(path, O_WRONLY | O_CREAT, *filemode);
if (fd == -1) {
@@ -216,6 +235,8 @@ void saveReceivedData(void *receiveB, size_t sz) {
ret;
}
+ // send a file or glob
+
cleanAllocateSmallArray(pathToSend);
if (isPath(sendFile)) {
@@ -237,6 +258,7 @@ void saveReceivedData(void *receiveB, size_t sz) {
cleanAllocateNetFrame(netframe);
+ // network buffer
u8 buf[1024*1024] = init0Var;
cleanAllocateSmallDict(recusive);
@@ -245,6 +267,8 @@ void saveReceivedData(void *receiveB, size_t sz) {
castS(p, P);
char *sendFile = ssGet(P);
+ // create local directory in client
+ // add files from local directory to recusive dict, the last element is the local path
if (isDirG(p)) {
logD("mkdir in client");
@@ -259,6 +283,7 @@ void saveReceivedData(void *receiveB, size_t sz) {
var dir = readDirAllG(rtSmallArrayt, p);
//lv(dir);
if (not isEmptyG(dir)) {
+ // save local path in last element
pushG(dir, ssGet(p));
setNFreeG(recusive, dirname, dir);
}
@@ -272,11 +297,13 @@ void saveReceivedData(void *receiveB, size_t sz) {
makeHeader(buf, &bufi, 0 /* command */, null/*svrInfo no need to authenticate the client*/, sendFile, null/*destPath is already selected in client*/, &filesize);
if (*filesize < (sizeof(buf) - bufi)) {
+ // the file is smaller than the network buffer, send all in one go
pError0(bReadFile(sendFile, buf + bufi));
o(netframe,send , mysock, buf, bufi + *filesize);
}
else {
logD("big file");
+ // loop to send big file in chunks
u64 szToSend = *filesize;
u8 *b = buf + bufi;
u64 bSz = sizeof(buf) - bufi;
@@ -302,7 +329,10 @@ void saveReceivedData(void *receiveB, size_t sz) {
}
} // sendFile or globbing
- // Send files recursively
+ // send files recursively
+ // each key is a path in server corresponding to a local directory
+ // the element is the list of files in the directory
+ // it is similar to the iter(pathToSend, P) loop
iter(recusive, A) {
cast(smallArrayt*,a,A);
@@ -312,6 +342,8 @@ void saveReceivedData(void *receiveB, size_t sz) {
castS(p, P);
char *sendFile = ssGet(P);
+ // create local directory in server
+ // add files from local directory to recusive dict, the last element is the local path
cleanCharP(localp) = catS(localPath, "/", ssGet(p));
if (isDirG(localp)) {
logD("mkdir in client");
@@ -326,6 +358,7 @@ void saveReceivedData(void *receiveB, size_t sz) {
var dir = readDirAllG(rtSmallArrayt, localp);
lv(dir);
if (not isEmptyG(dir)) {
+ // save local path in last element
pushG(dir, localp);
setNFreeG(recusive, dirname, dir);
}
@@ -340,11 +373,13 @@ void saveReceivedData(void *receiveB, size_t sz) {
makeHeader(buf, &bufi, 0 /* command */, null/*svrInfo no need to authenticate the client*/, localp, (char*)iK(recusive) /*dest*/, &filesize);
if (*filesize < (sizeof(buf) - bufi)) {
+ // the file is smaller than the network buffer, send all in one go
pError0(bReadFile(localp, buf + bufi));
o(netframe,send , mysock, buf, bufi + *filesize);
}
else {
logD("big file");
+ // loop to send big file in chunks
u64 szToSend = *filesize;
u8 *b = buf + bufi;
u64 bSz = sizeof(buf) - bufi;