diff --git a/Makefile b/Makefile index b76d9812bd4615d9d6eea2e56b60bb0da1ae0947..a2a739a296e3a295ac46b79f11d491082b5ec9f1 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,15 @@ -CFLAGS= -g -Wall -O2 +CFLAGS= -w -g -Wall -O2 CC=g++ -OBJ=Protocol.o +OBJ=Protocol.o Message.o + +all: cacoclient cacoserver %.o: %.cpp $(CC) $(CFLAGS) $^ -c -o $@ cacoclient: client.cpp $(OBJ) $(CC) $(CFLAGS) $^ -o $@ -# cacoserver: $(OBJ) client.cpp -# $(CC) $(CFLAGS) $^ -o $@ +cacoserver: server.cpp $(OBJ) + $(CC) $(CFLAGS) $^ -o $@ clean: rm -f *.o caco* diff --git a/Message.cpp b/Message.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca83b764cb679e6f5b6b641abf1e8bfdf2a64760 --- /dev/null +++ b/Message.cpp @@ -0,0 +1,28 @@ +#include "Message.h" +#include "definitions.h" + +BYTE Message::calcParity() { + char parity = 0x00; + char *m = this->header.c_ctrl.begin + this->header.c_ctrl.sizeSeq + this->header.c_ctrl.seqType + (char *)(&data[0]); + for(int i=0; i < strlen(m); ++i) { + parity = parity^m[i]; + } + this->header.c_ctrl.parity = parity; + return parity; +} + +bool Message::checkParity() { + BYTE parity = this->calcParity(); + return (parity == this->header.c_ctrl.parity); +} + +string Message::getSendData() { + calcParity(); + string s(data.begin(), data.end()); + string d = header.c_ctrl.begin + header.c_ctrl.sizeSeq + header.c_ctrl.seqType + s.c_str() + header.c_ctrl.parity; + return d; +} + +Message::Message() { + this->header.c_ctrl.begin = BEGIN; +} diff --git a/Message.h b/Message.h new file mode 100644 index 0000000000000000000000000000000000000000..071f1956829095c0fc3a72bef1c21ae6db2494c4 --- /dev/null +++ b/Message.h @@ -0,0 +1,16 @@ +#ifndef __MESSAGE__ +#define __MESSAGE__ +#include "definitions.h" + +class Message { + +public: + Header header; + vector<BYTE> data; + BYTE calcParity(); + bool checkParity(); + string getSendData(); + + Message(); +}; +#endif diff --git a/Protocol.cpp b/Protocol.cpp index cb2fd145f95bcff4fc484fd878beec25b6df6d96..4ad3707ab0a96cb4334ec810eceb66dcf96ea6f8 100644 --- a/Protocol.cpp +++ b/Protocol.cpp @@ -1,33 +1,112 @@ +#include <sys/socket.h> #include "Protocol.h" #include "definitions.h" -Message Protocol::getMessage(){ - return message; +vector<Message> Protocol::getMessages(){ + return messages; } -void Protocol::setMessage(Message message){ - this->message = message; +void Protocol::setMessages(vector<Message> messages){ + this->messages = messages; } -bool Protocol::send(int socket) { +bool Protocol::send(int socket, int window) { + for(int i=0; i < messages.size(); ++i) { + string data = messages[i].getSendData(); + } return true; } -char Protocol::calcParity() { - char parity = 0x00; - char *m = this->message.c_ctrl.begin + this->message.c_ctrl.size + this->message.c_ctrl.seqType + (&data[0]); - for(int i=0; i < strlen(m); ++i) { - parity = parity^m[i]; +vector<BYTE> Protocol::getData(){ + vector<BYTE> fullData; + for (int i=0; i < messages.size(); ++i){ + fullData.insert(fullData.end(), messages[i].data.begin(), messages[i].data.end()); + } + return fullData; +} + +string Protocol::getDataAsString(){ + vector<BYTE> fullData = getData(); + string str(fullData.begin(), fullData.end()); + return str; +} + +void Protocol::setData(vector<BYTE> data, int type){ + vector<BYTE>::const_iterator first, last; + int i; + for (i=0; i <= data.size()-MAXSIZE; i+=MAXSIZE){ + Message msg; + msg.header.i_ctrl.begin = BEGIN; + msg.header.i_ctrl.size = MAXSIZE; + msg.header.i_ctrl.sequence = messages.size()%(MAXSIZE+1); + msg.header.i_ctrl.type = type; + first = data.begin()+i; + last = data.begin()+i+MAXSIZE+1; + vector<BYTE> subvector(first, last); + msg.data = subvector; + //TODO: Set parity + messages.push_back(msg); + } + if(i < data.size()){ + Message msg; + msg.header.i_ctrl.begin = BEGIN; + msg.header.i_ctrl.sequence = messages.size()%(MAXSIZE+1); + msg.header.i_ctrl.type = type; + int size = data.size()-i; + first = data.begin()+i; + last = data.begin()+size+1; + vector<BYTE> subvector(first, last); + msg.data = subvector; + if(size < MINSIZE){ + size = MINSIZE; + msg.data.insert(msg.data.begin(), MINSIZE-size, 0x0); + } + msg.header.i_ctrl.size = size; + //TODO: Set parity + messages.push_back(msg); + } +} + +int Protocol::recvMessage(int sockt){ + BYTE dataRec[MAXSIZE+4]; + recv(sockt, dataRec, MAXSIZE, 0); + Message msg; + msg.header.c_ctrl.begin = dataRec[0]; + if(msg.header.i_ctrl.begin != BEGIN){ + return NOISE; + } + msg.header.c_ctrl.sizeSeq = dataRec[1]; + msg.header.c_ctrl.seqType = dataRec[2]; + if(msg.header.i_ctrl.sequence != ((messages.back().header.i_ctrl.sequence+1)%(MAXSIZE+1))){ + return SEQ_MISS; } - this->message.c_ctrl.parity = parity; - return parity; + msg.header.c_ctrl.parity = dataRec[3+msg.header.i_ctrl.size]; + // TODO: Check parity + if(msg.header.i_ctrl.type == ENDTX){ + return ENDTX; + } + + BYTE msgData[msg.header.i_ctrl.size]; + memcpy(msgData,dataRec+3,msg.header.i_ctrl.size); + msg.data.insert(msg.data.end(), msgData, msgData+msg.header.i_ctrl.size); + messages.push_back(msg); + return msg.header.i_ctrl.type; } -bool Protocol::checkParity() { - char parity = this->calcParity(); - return (parity == this->message.c_ctrl.parity); +// void Protocol::recvWholeData(int sockt, int window){ +// int status; +// while((status=this->recvMessage(sockt)) != ENDTX){ +// if(status > 0){ +// if(messages.back().header.i_ctrl.sequence % window == 0){ +// //TODO: send ACK +// } +// } +// } +// } + +void Protocol::addMessage(Message msg) { + messages.push_back(msg); } Protocol::Protocol(){ - this->message.c_ctrl.begin = 0x7E; } diff --git a/Protocol.h b/Protocol.h index adcc99425e29dc545298746f5871a209636bdca0..040f6d9fb1cb33f97a7ba44bd33d69bfb8b157b1 100644 --- a/Protocol.h +++ b/Protocol.h @@ -1,19 +1,22 @@ #ifndef __PROTOCOL__ #define __PROTOCOL__ #include "definitions.h" +#include "Message.h" class Protocol{ private: - Message message; - vector<char> data; + vector<Message> messages; + int timeout; public: - - Message getMessage(); - void setMessage(Message message); - bool send(int socket); - char calcParity(); - bool checkParity(); + bool send(int socket, int window); + vector<Message> getMessages(); + void setMessages(vector<Message> messages); + vector<BYTE> getData(); + void setData(vector<BYTE> data, int type); + string getDataAsString(); + int recvMessage(int sockt); + void addMessage(Message msg); Protocol(); }; diff --git a/client.cpp b/client.cpp index febcc73f0af06f7951e6da9e6bce9af3bf26fc53..9d7a6e043569d721bd17cb1a9ee245dd79504b6c 100644 --- a/client.cpp +++ b/client.cpp @@ -1,32 +1,69 @@ +#include <stdexcept> #include "definitions.h" #include "dirFunctions.h" #include "ConexaoRawSocket.c" +#include "Protocol.h" -int main(){ +void printCommandsList(); - int socket = ConexaoRawSocket(DEVICE); - +int main(){ + int pos, sockt = ConexaoRawSocket(DEVICE); + string line, command, args; + Protocol protocol = Protocol(); + printCommandsList(); while(true){ - string command, path; cout << endl << "Entre com o comando:" << endl; - cin >> command; - if(command == "quit"){ - break; + getline(cin,line); + pos = line.find_first_of(" "); + if(pos == string::npos){ + pos = line.size(); } - cin >> path; - if(command == "cd"){ - cd(path); - }else if(command == "ls"){ - ls(path); - }else if(command == "cdr"){ - //TODO - }else if(command == "lsr"){ - //TODO - }else if(command == "put"){ - //TODO - }else if(command == "get"){ - //TODO + command = line.substr(0,pos); + try{ + if(command == "quit"){ + break; + } + if(command == "cd"){ + args = line.substr(pos+1, line.size()); + cd(args); + }else if(command == "ls"){ + cout << ls(line); + }else if(command == "cdr"){ + //TODO + }else if(command == "lsr"){ + Message msg = Message(); + msg.header.i_ctrl.type = LS; + msg.data = vector<BYTE>(line.begin(), line.end()); + protocol.addMessage(msg); + protocol.send(sockt, WAIT_STOP); + // TODO: imprimir resposta + }else if(command == "put"){ + //TODO + }else if(command == "get"){ + + }else if(command == "help"){ + printCommandsList(); + }else{ + cout << "Comando inexistente." << endl; + printCommandsList(); + } + }catch(char const* strException){ + cerr<<"Error: "<< strException << endl; + }catch(out_of_range e){ + cerr<<"Error: Esse comando requer argumentos."<<endl; } } return 0; -} \ No newline at end of file +} + +void printCommandsList(){ + cout << "Os comandos suportados são:"<< endl; + cout << "cd - Mudar de diretório local"<< endl; + cout << "ls - Visualizar arquivos no diretório local"<< endl; + cout << "cdr - Mudar de diretório remoto"<< endl; + cout << "lsr - Visualizar arquivos no diretório remoto"<< endl; + cout << "put - Enviar arquivo para diretório remoto"<< endl; + cout << "get - Pegar arquivo do diretório remoto"<< endl; + cout << "help - Lista de comandos"<< endl; + cout << "quit - Sair"<< endl; +} diff --git a/definitions.h b/definitions.h index 41172491abff370859092b839caa2404ced9e754..8269b16c18fc86321eaf8a3db16dbd77378880a5 100644 --- a/definitions.h +++ b/definitions.h @@ -7,7 +7,15 @@ using namespace std; +//Maximum and minimum of bytes in data field +#define MAXSIZE 63 +#define MINSIZE 60 + +//Delimiter indicating beginning of a message +#define BEGIN 0x7E +//Socket device #define DEVICE "lo" +//Message types #define NACK 0 #define ACK 1 #define CD 3 @@ -15,10 +23,28 @@ using namespace std; #define PUT 5 #define GET 6 #define OK 8 -#define TAM 9 -#define TELA 10 -#define ERRO 14 -#define FIM 15 +#define SIZE 9 +#define OUTPUT 10 +#define DATA 13 +#define ERROR 14 +#define ENDTX 15 + +//Windows +#define WAIT_STOP 1 +#define SLIDING 3 + +//Values of data for ERROR messages +#define DIR_ERR '0' +#define PERM_ERR '1' +#define SPACE_ERR '2' + +//recvMessage errors +#define NOISE -1 +#define SEQ_MISS -2 +#define INCONSISTENT -3 + +//Data types +#define BYTE unsigned char typedef struct{ int begin : 8, @@ -29,13 +55,12 @@ typedef struct{ }i_Control; typedef struct{ - char begin,size,seqType,parity; + char begin,sizeSeq,seqType,parity; }c_Control; typedef union { c_Control c_ctrl; i_Control i_ctrl; -}Message; - +}Header; -#endif \ No newline at end of file +#endif diff --git a/dirFunctions.cpp b/dirFunctions.cpp index 078e39c86c8e4134e08d493d9a79043593ddaba9..bb8964a28e48d098d6051a59ce72882a376d9752 100644 --- a/dirFunctions.cpp +++ b/dirFunctions.cpp @@ -1,8 +1,9 @@ #include <iostream> #include <errno.h> #include <unistd.h> -#include <dirent.h> #include <string.h> +#include <vector> +#include <stdio.h> //popen using namespace std; @@ -13,16 +14,16 @@ void cd(string path){ } } -void ls(string path){ - //TODO: #1 - struct dirent *entry; - DIR *dir = opendir(path.c_str()); - if(dir != NULL){ - while((entry=readdir(dir)) != NULL){ - cout << entry->d_name << endl; - } - closedir(dir); - }else{ - cout<<"Error: could not open directory."<<endl; +string ls(string args){ + string output; + FILE *lsOut = popen(args.c_str(), "r"); + if(!lsOut){ + throw "Couldn't execute ls"; } + char buffer[1024]; + while(fgets(buffer, sizeof(buffer), lsOut)!=NULL){ + output += buffer; + } + pclose(lsOut); + return output; } \ No newline at end of file diff --git a/dirFunctions.h b/dirFunctions.h index 1cb22424a70c1b679ffde53db571a39f89c614b8..fe120405bd8f732f027633b8b0ad3107c3d8b0a0 100644 --- a/dirFunctions.h +++ b/dirFunctions.h @@ -7,6 +7,6 @@ using namespace std; void cd(string path); -void ls(string path); +string ls(string path); #endif \ No newline at end of file diff --git a/server.cpp b/server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a21d9460a73e5309a73276cbc9a625fce0b3f4e --- /dev/null +++ b/server.cpp @@ -0,0 +1,28 @@ +#include "definitions.h" +#include "Protocol.h" +#include "dirFunctions.h" +#include "ConexaoRawSocket.c" + +int main(){ + int sockt = ConexaoRawSocket(DEVICE); + Protocol protocol; + while(true){ + int status = protocol.recvMessage(sockt); + if(status > 0){ + if(status == ENDTX){ + protocol = Protocol(); + //TODO: send ACK + }else if(status == CD){ + cd(protocol.getDataAsString()); + }else if(status == LS){ + string output = ls(protocol.getDataAsString()); + //TODO: send output back + }else if(status == PUT){ + //TODO + }else if(status == GET){ + //TODO + } + } + } + return 0; +} \ No newline at end of file