diff --git a/headers/client.h b/headers/client.h index a1079f1bff15ed3d2ea5d35f2f7758a434f62f4f..bf547f40ad17fe6d4a5b5aebf8afa1eb5a3140bc 100644 --- a/headers/client.h +++ b/headers/client.h @@ -16,15 +16,13 @@ #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/types.h> - +#include <sys/stat.h> #include <arpa/inet.h> // include local #include "conexao.h" #include "frame.h" -#define NUM_RETRIES 100 - vector<string> CMD_HELP = {"H", "help", "-h", "HELP", "Help", "-H", "ajuda", "Ajuda", "AJUDA"}; vector<string> CMD_EXIT = {"exit", "-e", "EXIT", "Exit", @@ -51,7 +49,13 @@ private: char string_cmd(string str); void print_help(); bool verify_ack(frame *received, frame *sent); + frame *receive_ack(frame *f); vector<frame *> create_frames(vector<char> data, int type); + int send_frame_socket(frame *f); + int start_transmission(); + int end_transmission(); + string calc_file_size(string fileName); + vector<char> read_file(string fileName); public: // --------- Dados ---------- // @@ -66,6 +70,86 @@ public: // ------------------------------ PRIVATE --------------------------------- // +// Verifica se recebeu um ack valido +frame *client::receive_ack(frame *f) +{ + frame *ack_res = NULL; + + // se recebemos algo, e NÃO ẽ o ACK que estamos + // esperando, continuamos tentando receber + do { + ack_res = socket->receive_frame(); + if (ack_res->get_tipo() == ERRO) + { + cout << "Espaco insulficiente no destino\n"; + return NULL; + } + + } while ( + ack_res && + !(verify_ack(ack_res, f) && + ack_res->get_dado()[0] == f->get_seq()) + ); + + return ack_res; +} + +// Solicita ao socket que envie um frame +int client::send_frame_socket(frame *f) +{ + // Fica tentando enviar o frame até receber o ack + frame* ack_res = NULL; + int retries = 0; + do { + // envia um frame da fila + socket->send_frame(f); + ack_res = receive_ack(f); + retries++; + + } while (ack_res == NULL && retries < NUM_RETRIES); + + if (ack_res == NULL && retries == NUM_RETRIES) { + cout << "Desisti de enviar\n"; + return 0; + } + + cout << "\tACK recebido:\n"; + ack_res->imprime(HEX); + return 1; +} + +// Inicia a transmissao com o servidor +int client::start_transmission() +{ + cout << "\tIniciando transmissao\n"; + frame *ini = new frame(INIT, 0, vector<char>(1,0)); + int enviado = send_frame_socket(ini); + if ( !enviado ) + { + cout << "\tFalha ao iniciar a transmissao\n"; + return 0; + } + + cout << "\tTransmissao iniciada com sucesso\n"; + return 1; +} + +// Encerra a transmissao com o servidor +int client::end_transmission() +{ + cout << "\tEncerrando a transmissao\n"; + frame *end= new frame(FIMT, 0, vector<char>(1,0)); + int enviado = send_frame_socket(end); + if ( !enviado ) + { + cout << "\tFalha ao encerrar a transmissao\n"; + return 0; + } + + cout << "\tTransmissao encerrada com sucesso\n"; + return 1; +} + /** * @brief Send a list of frames through the socket * @@ -73,6 +157,7 @@ public: * @return int */ int client::send_frames(vector<frame *> frames) { + if ( !start_transmission() ) { return 0; } // Envia um frame por vez for (size_t i = 0; i < frames.size(); i++) { @@ -80,35 +165,18 @@ int client::send_frames(vector<frame *> frames) { cout << "\tEnviando frame\n"; frames[i]->imprime(DEC); - int retries = 0; - - // Fica tentando enviar o frame até receber o ack - frame* ack_res = NULL; - do { - // envia um frame da fila - socket->send_frame(frames[i]); - retries++; - - // se recebemos algo, e NÃO ẽ o ACK que estamos - // esperando, continuamos tentando receber - do { - ack_res = socket->receive_frame(); - } while ( - ack_res && - !(verify_ack(ack_res, frames[i]) && - ack_res->get_seq() == frames[i]->get_seq()) - ); - } while (ack_res == NULL && retries < NUM_RETRIES); - - if (ack_res == NULL && retries == NUM_RETRIES) { - cout << "Desisti de enviar\n"; + int enviado = send_frame_socket(frames[i]); + if ( !enviado ) + { + cout << "\tFalha ao enviar o frame\n"; return 0; } cout << "\tFrame enviado com sucesso\n"; } - cout << "Terminou de enviar todos os frames\n"; + if ( !end_transmission() ) { return 0; } + cout << "\tTerminou de enviar todos os frames\n"; return 1; } @@ -122,15 +190,7 @@ int client::send_frames(vector<frame *> frames) { * @return false */ bool client::verify_ack(frame *received, frame *sent) { - - cout << "Verificando ack\nReceived:\n"; - received->imprime(HEX); - cout << "Sent:\n"; - sent->imprime(HEX); - - return ( - received->get_tipo() == ACK && - received->chk_crc8()); + return ( received->get_tipo() == ACK && received->chk_crc8()); } /** @@ -148,18 +208,75 @@ int client::send_message(vector<char> data, int type) { return send_frames(frames); } +string client::calc_file_size(string fileName) +{ + struct stat buffer; + stat(fileName.c_str(), &buffer); + int fileSize = buffer.st_size; + + return to_string(fileSize); +} + +vector<char> client::read_file(string fileName) +{ + fstream file; + file.open(fileName, ios::in); + + if (!file) { + cout << "Arquivo inexistente. Operacao abortada\n"; + return vector<char>(); + } + + string teste; + vector<char> fileData; + char c; + while ( (file.get(c), file.eof() == false) ) + { + fileData.push_back(c); + teste.push_back(c); + } + + file.close(); + cout << "vetor criado: " << teste << "\n"; + return fileData; +} + /** * @brief Send a file through the socket * */ void client::send_file() { - cout << "Enviando arquivo\n"; string fileName; - cout << "Digite o nome do arquivo:\n"; - getline(cin, fileName); + do { + cout << "Digite o nome do arquivo(maximo de " << TAM_DADOS << " char):\n"; + getline(cin, fileName); + } while ( fileName.size() > TAM_DADOS ); + + // Envia o primeiro frame com o tamanho do arquivo + string fileSize = calc_file_size(fileName); + cout << "Tamanho do arquivo: " << fileSize << "\n"; + cout << "Enviando tamanho do arquivo\n"; + if (!send_message(vector<char>(fileSize.begin(), fileSize.end()), MIDIA)) + { + cout << "Limite de timout, arquivo nao foi enviado\n"; + return; + } + // Envia o segundo frame com o nome do arquivo + cout << "Enviando nome do arquivo\n"; if (!send_message(vector<char>(fileName.begin(), fileName.end()), MIDIA)) + { cout << "Limite de timout, arquivo nao foi enviado\n"; + return; + } + + cout << "Enviando arquivo\n"; + vector<char> file = read_file(fileName); + if (file.empty() || !send_message(file, DADOS)) + { + cout << "Limite de timout, arquivo nao foi enviado\n"; + return; + } else cout << "Arquivo enviado com sucesso\n"; diff --git a/headers/conexao.h b/headers/conexao.h index 7be294023ab5a1edf028a5bf12610ee722d6d9db..f736ce341e23eb6cd32d51f1397d6882a89c79ba 100644 --- a/headers/conexao.h +++ b/headers/conexao.h @@ -24,6 +24,7 @@ using namespace std; #define BYTE "%02x" +#define NUM_RETRIES 100 class conexao { private: diff --git a/headers/server.h b/headers/server.h index 6a38d155940c027c65a90a67d6becc3663a3b760..085a75334f38e38269221604ec3b8ce024d972e5 100644 --- a/headers/server.h +++ b/headers/server.h @@ -38,6 +38,11 @@ private: // ---------- Funcoes -------- // int send_nack(frame *fReceive); int send_ack(frame *fReceive); + void send_confirm(frame *fReceive); + void receive_text(frame *f); + frame *receive_frame_socket(); + int receive_valid_frame(frame **f); + void start_receveing_message(); public: // ------- Construtores ------ // @@ -59,8 +64,9 @@ int server::send_ack(frame *fReceive) { frame *ack = new frame(); ack->set_tipo(ACK); - ack->set_dado(vector<char>(fReceive->get_dado(), fReceive->get_dado()+fReceive->get_tam())); - ack->set_seq(fReceive->get_seq()); + vector<char> seq; + seq.push_back(char(fReceive->get_seq())); + ack->set_dado(seq); int ackSent = 0; ackSent = socket->send_frame(ack); @@ -81,8 +87,9 @@ int server::send_nack(frame *fReceive) { frame *nack = new frame(); nack->set_tipo(NACK); - nack->set_dado(vector<char>(fReceive->get_dado(), fReceive->get_dado()+fReceive->get_tam())); - nack->set_seq(fReceive->get_seq()); + vector<char> seq; + seq.push_back(char(fReceive->get_seq())); + nack->set_dado(seq); int nackSent = 0; nackSent = socket->send_frame(nack); @@ -92,37 +99,112 @@ int server::send_nack(frame *fReceive) { return nackSent; } +// Recebe uma mensagem em forma de texto +void server::receive_text(frame *f) +{ + string textoReceive; + textoReceive.append(f->get_dado()); + int lastSeq = f->get_seq(); + + do { + if ( !receive_valid_frame(&f) ) { continue; } + if ( f->get_tipo() != TEXTO ) { continue; } + if ( f->get_seq() == lastSeq) { continue; } + + lastSeq = f->get_seq(); + textoReceive.append(f->get_dado()); + + } while ( f->get_tipo() != FIMT ); + + cout << "Mensagem recebida: " << textoReceive << "\n"; +} -// ------------------------------- PUBLIC --------------------------------- // +// Recebe o primeiro frame do cliente +frame *server::receive_frame_socket() +{ + frame *fReceive; + int retries = 0; -/** - * @brief function that runs the server thread and receives the frames - * - */ + do + { + retries++; + if ( ! (fReceive = socket->receive_frame()) ) { continue; } + } while ( fReceive == NULL && retries < NUM_RETRIES ); -// lock the thread with mutex -void server::run() { + if ( fReceive == NULL && retries == NUM_RETRIES ) { + cout << "Desisti de receber o frame\n"; + return NULL; + } + + return fReceive; +} + +int server::receive_valid_frame(frame **f) +{ + int crc8; + + do { + // Se nao conseguir receber o frame, mata a comunicacao + *f = receive_frame_socket(); + if ( *f == NULL ) { return 0; } + + // Avisa o cliente se nao conseguiu receber o frame + crc8 = (*f)->chk_crc8(); + if ( crc8 ) { send_ack(*f); break; } + send_nack(*f); + } while ( !crc8 ); + + return 1; +} + +void server::start_receveing_message() +{ + int endTransmission = 0; + + do { + frame *f = receive_frame_socket(); + if ( !f ) { return; } + int frameType = f->get_tipo(); + + switch (frameType) + { + case TEXTO: + receive_text(f); + endTransmission = 1; + break; + + case MIDIA: + break; + + default: + break; + } + } while ( !endTransmission ); +} + + +// ------------------------------- PUBLIC --------------------------------- // + +void server::run() { while (true) { - frame *fReceive; /*-- listening local ip and waiting for messages --*/ /*-- ignore if the package is not valid --*/ + frame *fReceive; if ( ! (fReceive = socket->receive_frame()) ) { continue; } + cout << "Frame recebido:" << endl; fReceive->imprime(HEX); - /*-- if frame is an ACK or NACK, it ignores it --*/ - bool sendAck = fReceive->chk_crc8() && (fReceive->get_tipo() != ACK) && - (fReceive->get_tipo() != NACK); - bool sendNack = !fReceive->chk_crc8() && fReceive->get_tipo() != ACK && - fReceive->get_tipo() != NACK; - - /*-- checking crc and sending ack or nack --*/ - if (sendAck) - send_ack(fReceive); - else if (sendNack) - send_nack(fReceive); + // Verifica se o frame eh de inicio de transmissao e se nao veio com erro + int frameType = fReceive->get_tipo(); + if ( frameType != INIT ) { continue; } + + if ( !fReceive->chk_crc8() ) { send_nack(fReceive); continue; } + + send_ack(fReceive); + start_receveing_message(); } } diff --git a/src/exemplo.cpp b/src/exemplo.cpp index 400e8f3500a799bd32d26c6ac90ab73255600dc0..cbad342a25a068ad22e2a1c52c767a21a506eeb9 100644 --- a/src/exemplo.cpp +++ b/src/exemplo.cpp @@ -25,13 +25,9 @@ int get_status( char *argv ) int main(int argc, char *argv[]) { gen_crc8_table(); -<<<<<<< HEAD:exemplo.cpp char* device = argv[2]; cout << "Device: " << device << endl; conexao socket(device); -======= - conexao socket((char *)argv[2]); ->>>>>>> 80e7f477d4253b6d77bf36c80fb004480000a16a:src/exemplo.cpp int status = get_status(argv[1]); switch ( status ) diff --git a/todo.txt b/todo.txt index d702e4fbe5ffd0a6a6f3c1d7aa288eb65eb90a00..f1653f25511af31b9fa71c051f565ea5eb8bf7cd 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,8 @@ -> Ver se os frames que estao vindo sao arquivos e juntar eles no arquivo --> Juntar todos os frames num so para mensagens de mais de dois frames +-> Testar tamanho antes de enviar o arquivo --> Fazer o close_connection +-> Arrumar a interface -> Merge correcao de erro -> Enviar arquivo correcao de erros @@ -14,14 +14,8 @@ -> Merge log --> Organizar header/src diretorios - -> Adicionar coisas no log --> Testar tamanho antes de enviar o arquivo - --> Arrumar a interface - -> Polling para enviar/receber (encerrar comunicacao/esperar/trocar) -> Relatorio