commit 7b369dafb749ba6bf6442e7440146b834a8b9600
parent 3f5d85a450d7748e9ad5d3b165db9c10e8f8750c
Author: Remy Noulin <loader2x@gmail.com>
Date: Sat, 13 Aug 2022 11:38:06 -0400
add receive single file from server
Move makeHeader to own file because this function is shared between
client and server
NOTES.md | 15 ++-
makeHeader.c | 81 ++++++++++++
makeHeader.h | 3 +
sclient.c | 424 +++++++++++++++++++++++++++++++++++------------------------
sserver.c | 68 +++++++++-
5 files changed, 416 insertions(+), 175 deletions(-)
Diffstat:
| M | NOTES.md | | | 15 | +++++++++++---- |
| A | makeHeader.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | makeHeader.h | | | 3 | +++ |
| M | sclient.c | | | 424 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
| M | sserver.c | | | 68 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
5 files changed, 416 insertions(+), 175 deletions(-)
diff --git a/NOTES.md b/NOTES.md
@@ -7,12 +7,13 @@ x./sclient.c NOTES.md dev:tuyauTest/
x./sclient.c NOTES.md dev:tuyauTest/ger.md
## receive
-./sclient.c dev:NOTES.md
-./sclient.c dev:NOTES.md ../
+x./sclient.c dev:NOTES.md
+x./sclient.c dev:NOTES.md ../
+x./sclient.c dev:NOTES.md test.txt
cp file tuyau://ip/path
-frame send file:
+0 frame send file:
1 byte command
8 bytes token
2 bytes file name length
@@ -24,13 +25,19 @@ frame send file:
8 bytes data size
<data>
-frame mkdir
+1 frame mkdir
1 byte command
8 bytes token
2 bytes file mode/permissions
2 bytes path length
<path>
+2 frame receive file:
+1 byte command
+8 bytes token
+2 bytes path in server length
+<path in server>
+
> client/server requests
client > command
diff --git a/makeHeader.c b/makeHeader.c
@@ -0,0 +1,81 @@
+#include "libsheepyObject.h"
+#include "shpPackages/short/short.h"
+
+void makeHeader(u8 *buf, u32 *bufip, u8 command, smallDictt *svrInfo, char *sendFile, char *destPath, u64 **filesize) {
+
+ // command
+ // token
+ // file name max 8k
+ // file mode
+ // dest path
+
+ lv(sendFile);
+ lv(destPath);
+
+ // command
+ buf[0] = command;
+ // token
+ if (svrInfo)
+ memcpy(buf + 1, $(svrInfo, "token"), 8);
+ else
+ // used for downloading files from server to client
+ pError0(zeroBuf(buf + 1, 8));
+
+ u32 bufi = 0;
+ if (command == 0) {
+ // send file
+ // file name max 8k
+ u16 *filenameLength = (u16*)(buf + 9);
+ char *filename = basename(sendFile);
+ *filenameLength = lenG(filename);
+ memcpy(buf + 11, filename, lenG(filename));
+ bufi = 11 + lenG(filename);
+ // file mode
+ u16 *filemode = (u16*)(buf + bufi);
+ struct stat st;
+ if(stat(sendFile, &st) != 0){
+ logE("Can't access %s", sendFile);
+ XFailure;
+ }
+ *filemode = st.st_mode & 0xFFF;
+ bufi += 2;
+ // dest path
+ u16 *pathLength = (u16*)(buf + bufi);
+ *pathLength = lenG(destPath);
+ bufi += 2;
+ if (destPath) {
+ memcpy(buf + bufi, destPath, *pathLength);
+ bufi += *pathLength;
+ }
+ // file size
+ *filesize = (u64*)(buf + bufi);
+ **filesize = fileSizeG(sendFile);
+ bufi += 8;
+ }
+ elif (command == 1) {
+ // mkdir
+ u16 *filemode = (u16*)(buf + 9);
+ struct stat st;
+ if(stat(sendFile, &st) != 0){
+ logE("Can't access %s", sendFile);
+ XFailure;
+ }
+ *filemode = st.st_mode & 0xFFF;
+ // dest path
+ u16 *pathLength = (u16*)(buf + 11);
+ *pathLength = lenG(destPath);
+ memcpy(buf + 13, destPath, *pathLength);
+ bufi = 13 + lenG(destPath);
+ }
+ elif (command == 2) {
+ // download/receive files
+ // path in server
+ u16 *pathLength = (u16*)(buf + 9);
+ *pathLength = lenG(destPath);
+ memcpy(buf + 11, destPath, *pathLength);
+ bufi = 11 + lenG(destPath);
+ }
+
+ *bufip = bufi;
+}
+// vim: set expandtab ts=2 sw=2:
diff --git a/makeHeader.h b/makeHeader.h
@@ -0,0 +1,3 @@
+#include "libsheepyObject.h"
+void makeHeader(u8 *buf, u32 *bufip, u8 command, smallDictt *svrInfo, char *sendFile, char *destPath, u64 **filesize);
+// vim: set expandtab ts=2 sw=2:
diff --git a/sclient.c b/sclient.c
@@ -16,74 +16,11 @@
#include "netFrame.h"
#include "shpPackages/short/short.h"
+#include "makeHeader.h"
#define CONFIG "~/.tuyau/config.yml"
-void makeHeader(u8 *buf, u32 *bufip, u8 command, smallDictt *svrInfo, char *sendFile, char *destPath, u64 **filesize) {
-
- // command
- // token
- // file name max 8k
- // file mode
- // dest path
-
- lv(sendFile);
- lv(destPath);
-
- // command
- buf[0] = command;
- // token
- memcpy(buf + 1, $(svrInfo, "token"), 8);
-
- u32 bufi = 0;
- if (command == 0) {
- // send file
- // file name max 8k
- u16 *filenameLength = (u16*)(buf + 9);
- char *filename = basename(sendFile);
- *filenameLength = lenG(filename);
- memcpy(buf + 11, filename, lenG(filename));
- bufi = 11 + lenG(filename);
- // file mode
- u16 *filemode = (u16*)(buf + bufi);
- struct stat st;
- if(stat(sendFile, &st) != 0){
- logE("Can't access %s", sendFile);
- XFailure;
- }
- *filemode = st.st_mode & 0xFFF;
- bufi += 2;
- // dest path
- u16 *pathLength = (u16*)(buf + bufi);
- *pathLength = lenG(destPath);
- bufi += 2;
- if (destPath) {
- memcpy(buf + bufi, destPath, *pathLength);
- bufi += *pathLength;
- }
- // file size
- *filesize = (u64*)(buf + bufi);
- **filesize = fileSizeG(sendFile);
- bufi += 8;
- }
- elif (command == 1) {
- // mkdir
- u16 *filemode = (u16*)(buf + 9);
- struct stat st;
- if(stat(sendFile, &st) != 0){
- logE("Can't access %s", sendFile);
- XFailure;
- }
- *filemode = st.st_mode & 0xFFF;
- // dest path
- u16 *pathLength = (u16*)(buf + 11);
- *pathLength = lenG(destPath);
- memcpy(buf + 13, destPath, *pathLength);
- bufi = 13 + lenG(destPath);
- }
-
- *bufip = bufi;
-}
+bool saveReceivedData(void *receiveB, size_t sz, void *context);
int main(int ARGC, char** ARGV) {
@@ -99,30 +36,26 @@ int main(int ARGC, char** ARGV) {
ret 1;
}
- // check args
- if (ARGC == 2) {
- TODO("check that a server is selected and store files in current path");
- }
-
- if (ARGC < 3) {
- logE("Missing arguments");
- ret 1;
- }
-
bool isReceive = no;
+ const char *serverName = null;
+ char *destPath = null;
+ char *receivePath = null;
iter(cfg, D) {
cast(smallDictt*,d,D);
//lv(d);
if (startsWithG(ARGV[1], iK(cfg)) and ARGV[1][lenG(iK(cfg))] == ':' and ARGV[1][lenG(iK(cfg))+1] != 0) {
- TODO("arg 2 must be a path in client");
- isReceive = yes;
+ serverName = iK(cfg);
+ destPath = ARGV[1] + lenG(iK(cfg)) + 1;
+ isReceive = yes;
break;
}
}
- const char *serverName = null;
- char *destPath = null;
if (not isReceive) {
+ if (ARGC == 2) {
+ logE("Missing arguments");
+ ret 1;
+ }
logD("path in client");
// check last arg
bool foundDest = no;
@@ -146,6 +79,26 @@ int main(int ARGC, char** ARGV) {
}
}
} // not isReceive
+ elif (ARGC > 2) {
+ // receive
+ // arg 2 must be a path in client
+ receivePath = ARGV[2];
+ cleanCharP(localPath) = normalizePathG(ARGV[2]);
+ if (not isEmptyG(localPath)/*ignore "." -> ""*/) {
+ logD("check if receivePath is dir or dir with filename");
+ if (not isPath(localPath)) {
+ if (endsWithG(receivePath,'/')) {
+ logE("Directory doesn't exist %s", localPath);
+ ret 1;
+ }
+ cleanCharP(dir) = shDirname(localPath);
+ if (not isPath(dir)) {
+ logE("Directory doesn't exist %s", dir);
+ ret 1;
+ }
+ }
+ }
+ }
if (not serverName) {
logE("server name not found");
@@ -159,7 +112,6 @@ int main(int ARGC, char** ARGV) {
int sock;
struct sockaddr_in server;
struct hostent *hp;
- int mysock;
int rval;
cleanAllocateNetFrame(netframe);
@@ -190,122 +142,68 @@ int main(int ARGC, char** ARGV) {
u8 buf[1024*1024] = init0Var;
- cleanAllocateSmallArray(pathToSend);
+ if (isReceive) {
+ // receive files in receivePath
- rangeFrom(i, 1, ARGC-1) {
- if (not isPath(ARGV[i])) {
- logE("Incorrect path: "BLD YLW"%s"RST,ARGV[i]);
- continue;
- }
- pushG(pathToSend, ARGV[i]);
- }
-
- cleanAllocateSmallDict(recusive);
+ u32 bufi = 0;
+ makeHeader(buf, &bufi, 2 /* command */, svrInfo, null /*sendFile*/, destPath, null /*filesize*/);
- iter(pathToSend, P) {
- castS(p, P);
- char *sendFile = ssGet(P);
+ o(netframe,send , sock, buf, bufi);
- if (isDirG(p)) {
- logD("mkdir in server");
+ o(netframe, setCallback, saveReceivedData, receivePath /*context*/);
- char *dirname = basename(ssGet(p));
- cleanCharP(dest) = catS(destPath, "/", dirname);
+ var r = o(netframe,receive, sock);
+ logVarG(r);
- u32 bufi = 0;
- u64 *filesize = null;
- makeHeader(buf, &bufi, 1 /* command */, svrInfo, ssGet(p), dest, &filesize);
+ }
+ else {
+ // send files
- o(netframe,send , sock, buf, bufi);
+ cleanAllocateSmallArray(pathToSend);
- var dir = readDirAllG(rtSmallArrayt, p);
- //lv(dir);
- if (not isEmptyG(dir)) {
- pushG(dir, ssGet(p));
- setNFreeG(recusive, dirname, dir);
+ rangeFrom(i, 1, ARGC-1) {
+ if (not isPath(ARGV[i])) {
+ logE("Incorrect path: "BLD YLW"%s"RST,ARGV[i]);
+ continue;
}
- lv(recusive);
- continue;
+ pushG(pathToSend, ARGV[i]);
}
- // send
- u32 bufi = 0;
- u64 *filesize = null;
- makeHeader(buf, &bufi, 0 /* command */, svrInfo, sendFile, destPath, &filesize);
+ cleanAllocateSmallDict(recusive);
- if (*filesize < (sizeof(buf) - bufi)) {
- pError0(bReadFile(sendFile, buf + bufi));
- o(netframe,send , sock, buf, bufi + *filesize);
- }
- else {
- logD("big file");
- u64 szToSend = *filesize;
- u8 *b = buf + bufi;
- u64 bSz = sizeof(buf) - bufi;
- int fd = open(sendFile, O_RDONLY);
- do {
- if (szToSend <= bSz) {
- read(fd, b, szToSend);
- o(netframe,send , sock, b, szToSend);
- szToSend = 0;
- }
- else {
- read(fd, b, bSz);
- if (szToSend == *filesize) {
- o(netframe,send , sock, buf, bufi + bSz);
- }
- else {
- o(netframe,send , sock, b, bSz);
- }
- szToSend -= bSz;
- }
- } while(szToSend);
- close(fd);
- }
- } // loop on arguments
-
-
- // Send files recursively
-
- iter(recusive, A) {
- cast(smallArrayt*,a,A);
- cleanCharP(localPath) = cropElemG(a, rtChar, -1);
- lv(localPath);
- iter(a, P) {
+ iter(pathToSend, P) {
castS(p, P);
char *sendFile = ssGet(P);
- cleanCharP(localp) = catS(localPath, "/", ssGet(p));
- if (isDirG(localp)) {
+ if (isDirG(p)) {
logD("mkdir in server");
- cleanCharP(dirname) = catS(iK(recusive), "/", ssGet(p));
+
+ char *dirname = basename(ssGet(p));
cleanCharP(dest) = catS(destPath, "/", dirname);
u32 bufi = 0;
u64 *filesize = null;
- makeHeader(buf, &bufi, 1 /* command */, svrInfo, localp, dest, &filesize);
+ makeHeader(buf, &bufi, 1 /* command */, svrInfo, ssGet(p), dest, &filesize);
o(netframe,send , sock, buf, bufi);
- var dir = readDirAllG(rtSmallArrayt, localp);
- lv(dir);
+ var dir = readDirAllG(rtSmallArrayt, p);
+ //lv(dir);
if (not isEmptyG(dir)) {
- pushG(dir, localp);
+ pushG(dir, ssGet(p));
setNFreeG(recusive, dirname, dir);
}
- //lv(recusive);
+ lv(recusive);
continue;
}
- logD("Send files from localPath/p to destPath/iK(recusive)/");
// send
- cleanCharP(dest) = catS(destPath, "/", iK(recusive));
- u32 bufi = 0;
- u64 *filesize = null;
- makeHeader(buf, &bufi, 0 /* command */, svrInfo, localp, dest, &filesize);
+ u32 bufi = 0;
+ u64 *filesize = null;
+ makeHeader(buf, &bufi, 0 /* command */, svrInfo, sendFile, destPath, &filesize);
if (*filesize < (sizeof(buf) - bufi)) {
- pError0(bReadFile(localp, buf + bufi));
+ pError0(bReadFile(sendFile, buf + bufi));
o(netframe,send , sock, buf, bufi + *filesize);
}
else {
@@ -313,7 +211,7 @@ int main(int ARGC, char** ARGV) {
u64 szToSend = *filesize;
u8 *b = buf + bufi;
u64 bSz = sizeof(buf) - bufi;
- int fd = open(localp, O_RDONLY);
+ int fd = open(sendFile, O_RDONLY);
do {
if (szToSend <= bSz) {
read(fd, b, szToSend);
@@ -333,14 +231,200 @@ int main(int ARGC, char** ARGV) {
} while(szToSend);
close(fd);
}
+ } // loop on arguments
+
+
+ // Send files recursively
+
+ iter(recusive, A) {
+ cast(smallArrayt*,a,A);
+ cleanCharP(localPath) = cropElemG(a, rtChar, -1);
+ lv(localPath);
+ iter(a, P) {
+ castS(p, P);
+ char *sendFile = ssGet(P);
+
+ cleanCharP(localp) = catS(localPath, "/", ssGet(p));
+ if (isDirG(localp)) {
+ logD("mkdir in server");
+ cleanCharP(dirname) = catS(iK(recusive), "/", ssGet(p));
+ cleanCharP(dest) = catS(destPath, "/", dirname);
+
+ u32 bufi = 0;
+ u64 *filesize = null;
+ makeHeader(buf, &bufi, 1 /* command */, svrInfo, localp, dest, &filesize);
+
+ o(netframe,send , sock, buf, bufi);
+
+ var dir = readDirAllG(rtSmallArrayt, localp);
+ lv(dir);
+ if (not isEmptyG(dir)) {
+ pushG(dir, localp);
+ setNFreeG(recusive, dirname, dir);
+ }
+ //lv(recusive);
+ continue;
+ }
+
+ logD("Send files from localPath/p to destPath/iK(recusive)/");
+ // send
+ cleanCharP(dest) = catS(destPath, "/", iK(recusive));
+ u32 bufi = 0;
+ u64 *filesize = null;
+ makeHeader(buf, &bufi, 0 /* command */, svrInfo, localp, dest, &filesize);
+
+ if (*filesize < (sizeof(buf) - bufi)) {
+ pError0(bReadFile(localp, buf + bufi));
+ o(netframe,send , sock, buf, bufi + *filesize);
+ }
+ else {
+ logD("big file");
+ u64 szToSend = *filesize;
+ u8 *b = buf + bufi;
+ u64 bSz = sizeof(buf) - bufi;
+ int fd = open(localp, O_RDONLY);
+ do {
+ if (szToSend <= bSz) {
+ read(fd, b, szToSend);
+ o(netframe,send , sock, b, szToSend);
+ szToSend = 0;
+ }
+ else {
+ read(fd, b, bSz);
+ if (szToSend == *filesize) {
+ o(netframe,send , sock, buf, bufi + bSz);
+ }
+ else {
+ o(netframe,send , sock, b, bSz);
+ }
+ szToSend -= bSz;
+ }
+ } while(szToSend);
+ close(fd);
+ }
+ }
}
- }
- lv(recusive);
+ lv(recusive);
+
+ // last frame size 0
+ o(netframe,end, sock);
- // last frame size 0
- o(netframe,end, sock);
+ } // isReceive
close(sock);
}
+
+
+int packetCount = 0;
+int fd = -1;
+u64 transferSz = 0;
+
+bool saveReceivedData(void *receiveB, size_t sz, void *context) {
+ logVarG(sz);
+ if (packetCount == 0) {
+ // header
+ u8 *command = (u8*) receiveB;
+
+ char *root = context;
+
+ if (*command == 0) {
+ // receive file
+
+ u16 *filenameLength = (u16*)(receiveB + 9);
+ // receiveB + 11 = filename
+ cleanCharP(filename) = malloc(*filenameLength + 1);
+ filename[*filenameLength] = 0;
+ memcpy(filename, receiveB + 11, *filenameLength);
+ u32 bufi = 11 + *filenameLength;
+ u16 *filemode = (u16*)(receiveB + bufi);
+ bufi += 2;
+ u16 *pathLength = (u16*)(receiveB + bufi);
+ bufi += 2;
+ cleanCharP(destPath) = null;
+ if (*pathLength) {
+ destPath = malloc(*pathLength + 1);
+ memcpy(destPath, receiveB + bufi, *pathLength);
+ destPath[*pathLength] = 0;
+ bufi += *pathLength;
+ }
+ // file size
+ u64 *filesize = (u64*)(receiveB + bufi);
+ bufi += 8;
+
+ logD("bufi %d fsz %d + %d, filename %s, root %s, destPath %s",bufi, *filesize, bufi + *filesize, filename, root,destPath);
+
+ cleanCharP(path) = null;
+
+ if (not root) {
+ // save file in current directory
+ path = strdup(filename);
+ }
+ elif (isDir(root)) {
+ path = catS(root, "/", filename);
+ }
+ else {
+ // root has a filename
+ path = strdup(root);
+ }
+
+ pErrorNULL(normalizePathG(&path));
+ lv(path);
+
+ if (*filesize <= sz - bufi) {
+ pError0(writeFile(path, receiveB + bufi, *filesize));
+ pError0(fileChmod(path, *filemode));
+ }
+ else {
+ logD("open fd");
+ inc packetCount;
+ fd = open(path, O_WRONLY | O_CREAT, *filemode);
+ if (fd == -1) {
+ logE("cant open %s", path);
+ ret yes;
+ }
+ int r = write(fd, receiveB + bufi, sz - bufi);
+ if (r == -1) {
+ logE("cant write %s", path);
+ ret yes;
+ }
+ transferSz = *filesize - (sz - bufi);
+ }
+ }
+ elif (*command == 1) {
+ // mkdir
+ TODO("mkdir");
+ u16 *filemode = (u16*)(receiveB + 9);
+ u16 *pathLength = (u16*)(receiveB + 11);
+ cleanCharP(destPath) = malloc(*pathLength + 1);
+ memcpy(destPath, receiveB + 13, *pathLength);
+ destPath[*pathLength] = 0;
+ char *path = catS(root, "/", destPath);
+ pErrorNULL(normalizePathG(&path));
+ pErrorNULL(trimG(&path));
+ logD(BLD GRN"mkdir" RST);
+ lv(path);
+ pError0(mkdirParents(path));
+ pError0(fileChmod(path, *filemode));
+ }
+ }
+ else {
+ // receive large files packetCount > 0
+ if (fd == -1) ret yes;
+ // big file
+ int r = write(fd, receiveB, sz);
+ if (r == -1) {
+ logE("cant write");
+ ret yes;
+ }
+ if (transferSz <= sz) {
+ transferSz = 0;
+ close(fd);
+ fd = -1;
+ packetCount = 0;
+ }
+ else transferSz -= sz;
+ }
+ ret yes;
+}
// vim: set expandtab ts=2 sw=2:
diff --git a/sserver.c b/sserver.c
@@ -15,12 +15,15 @@
#include "netFrame.h"
#include "shpPackages/short/short.h"
+#include "makeHeader.h"
#define CONFIG "~/.tuyau/serverConfig.yml"
int packetCount = 0;
int fd = -1;
u64 transferSz = 0;
+// client socket
+int mysock = 0;
smallJsont *tokens = null;
@@ -51,7 +54,6 @@ int main(int ARGC, char** ARGV) {
int sock;
struct sockaddr_in server;
- int mysock;
int rval;
sock = socket(AF_INET, SOCK_STREAM, 0);
@@ -194,6 +196,70 @@ void saveReceivedData(void *receiveB, size_t sz) {
pError0(mkdirParents(path));
pError0(fileChmod(path, *filemode));
}
+ elif (*command == 2) {
+ TODO("send files to client, send back sendFile basename");
+ u16 *sendFileLength = (u16*)(receiveB + 9);
+ cleanCharP(sendFile) = malloc(*sendFileLength + 1);
+ memcpy(sendFile, receiveB + 11, *sendFileLength);
+ sendFile[*sendFileLength] = 0;
+ pErrorNULL(prependG(&sendFile, '/'));
+ pErrorNULL(prependG(&sendFile, root));
+ pErrorNULL(normalizePathG(&sendFile));
+ pErrorNULL(trimG(&sendFile));
+ lv(sendFile);
+ cleanCharP(nroot) = normalizePathG(root);
+ if (not startsWithG(sendFile, nroot)) {
+ logE("Incorrect path, outside home directory: "BLD YLW"%s"RST,sendFile);
+ ret;
+ }
+ if (not isPath(sendFile)) {
+ logE("Incorrect path: "BLD YLW"%s"RST,sendFile);
+ ret;
+ }
+
+ cleanAllocateNetFrame(netframe);
+
+ u8 buf[1024*1024] = init0Var;
+
+ // send
+ u32 bufi = 0;
+ u64 *filesize = null;
+ 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)) {
+ pError0(bReadFile(sendFile, buf + bufi));
+ o(netframe,send , mysock, buf, bufi + *filesize);
+ }
+ else {
+ logD("big file");
+ u64 szToSend = *filesize;
+ u8 *b = buf + bufi;
+ u64 bSz = sizeof(buf) - bufi;
+ int fd = open(sendFile, O_RDONLY);
+ do {
+ if (szToSend <= bSz) {
+ read(fd, b, szToSend);
+ o(netframe,send , mysock, b, szToSend);
+ szToSend = 0;
+ }
+ else {
+ read(fd, b, bSz);
+ if (szToSend == *filesize) {
+ o(netframe,send , mysock, buf, bufi + bSz);
+ }
+ else {
+ o(netframe,send , mysock, b, bSz);
+ }
+ szToSend -= bSz;
+ }
+ } while(szToSend);
+ close(fd);
+ }
+
+ // last frame size 0
+ // close connection
+ o(netframe,end, mysock);
+ }
}
else {
// receive large files packetCount > 0