Select Git revision
messages.cpp
-
Victor Perszel authoredVictor Perszel authored
messages.cpp 22.54 KiB
// Implementado por: Eduardo Machado e Victor Perszel
// 2015
#include "messages.h"
//######################### MÉTODOS DA CLASSE Message #########################
int Message::sendCD(unsigned char* dirName){
int error, success = 0, garbage, rv;
char *receiptMessage = (char*)malloc(sizeof(char*)*64);
struct pollfd ufds[1]; // usado para timeout em recv
SubMessage changeDir, answer;
ufds[0].fd = soquete;
ufds[0].events = POLLIN;
changeDir.setData(dirName,3,0);
while(!success){
error = send(soquete, changeDir.objToString(), changeDir.getSize()+4, 0);
if (error == -1){
cout << "Erro ao tentar mudar de diretório (messages.cpp::sendCD)" << endl;
}
garbage = 0;
while((garbage < 10) && (!success)){
// vetor de pollfd, numero de buffers observados, timeout(ms)
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendCD)" << endl;
return -1;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
success = 1;
if(answer.getType() == 8){ // 8 = OK
// Tá ok para mudar de Diretório
return 0; // YAY
} else if(answer.getType() == 0){ // 0 = NACK
// NACK
success = 0; // reenvia pedido
} else if(answer.getType() == 14){ //14 = 0xE --> Erro
// ERRO
if(answer.getData()[0] == '0'){
cout << "Diretório Inexistente\n" << endl;
return -1;
} else if (answer.getData()[0] == '1'){
cout << "Sem permissão para acessar o diretório\n" << endl;
return -1;
} else {
success = 0; // reenvia pedido
}
}
}
}
} else{
cout << "Tempo limite de resposta excedido :c\n" << endl;
cout << "TIMEOUT ATINGIDO (messages.cpp::sendData)" << endl;
}
garbage++;
}
}
}
int Message::sendLS(unsigned char* options){
int error, success = 0, garbage, rv;
char *receiptMessage = (char*)malloc(sizeof(char*)*64);
struct pollfd ufds[1]; // usado para timeout em recv
char* listagem;
SubMessage listDir, answer, ack, nack;
ufds[0].fd = soquete;
ufds[0].events = POLLIN;
listDir.setData(options,4,0);
while(!success){
error = send(soquete, listDir.objToString(), listDir.getSize()+4, 0);
if (error == -1){
cout << "Erro ao tentar listar diretorio (messages.cpp::sendLS)" << endl;
}
garbage = 0;
while((garbage < 10) && (!success)){
// vetor de pollfd, numero de buffers observados, timeout(ms)
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendLS)" << endl;
return -1;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
success = 1;
if(answer.getType() == 10){ // 10 = 0xA --> (A)mostra
// Mostra as mensagens
if(answer.checkParity()){ // Caso a paridade dê errado
nack.setData((unsigned char*)answer.getSeq(),0,0); // Manda um nack
send(soquete,nack.objToString(),nack.getSize()+4, 0);
success = 0;
} else {
strcat(listagem,(char*)answer.getData()); // Põe o valor recebido em "listagem"
success = 0;
while(!success){
rv = poll(ufds, 1, 500); // Observa por novas mensagens
if(rv){
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
if(answer.getStartMessage() == 0x7E){
if(answer.getType() == 10){ // 10 = 0xA --> (A)mostra
if(answer.checkParity()){ // Caso a paridade dê errado
nack.setData((unsigned char*)answer.getSeq(),0,0); // Manda um nack
send(soquete,nack.objToString(),nack.getSize()+4, 0);
success = 0;
} else {
strcat(listagem,(char*)answer.getData()); // Põe em "listagem"
ack.setData((unsigned char*)answer.getSeq(),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
}
} else if (answer.getType() == 15) { // Se for FIM
ack.setData((unsigned char*)answer.getSeq(),1,0);
success = 1;
}
}
} else {
cout << "TIMEOUT DO LS (messages.cpp::sendLS)" << endl;
}
}
}
cout << listagem << endl;
return 0; // YAY
} else if(answer.getType() == 0){ // 0 = NACK
// NACK
success = 0; // reenvia pedido
} else if(answer.getType() == 14){ //14 = 0xE --> Erro
// ERRO
if(answer.getData()[0] == '0'){
cout << "Opção inválida, por favor tente -l, -a ou -la\n" << endl;
return -1;
} else {
success = 0; // reenvia pedido
}
}
}
}
} else{
cout << "Tempo limite de resposta excedido :c\n" << endl;
cout << "TIMEOUT ATINGIDO (messages.cpp::sendData)" << endl;
}
garbage++;
}
}
}
int Message::sendPUT(unsigned char* fileName){
int error, success = 0, garbage, rv;
char *receiptMessage = (char*)malloc(sizeof(char*)*64);
string temp, fileData;
struct pollfd ufds[1]; // usado para timeout em recv
SubMessage put, answer, size;
ifstream fileIn;
ufds[0].fd = soquete;
ufds[0].events = POLLIN;
put.setData(fileName,5,0);
fileIn.open((char*)fileName, ios::in);
fileIn.seekg(0);
while(getline(fileIn, temp)) {
fileData += temp + "\n";
}
while(!success){
error = send(soquete, put.objToString(), put.getSize()+4, 0);
if (error == -1){
cout << "Erro ao enviar arquivo (messages.cpp::sendPUT)" << endl;
}
garbage = 0;
while((garbage < 10) && (!success)){
// vetor de pollfd, numero de buffers observados, timeout(ms)
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendPUT)" << endl;
return -1;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
success = 1;
if(answer.getType() == 8){ // 8 = OK
// OK, mandar tamanho
size.setData((unsigned char*)fileData.size(),9,0);
send(soquete, size.objToString(), size.getSize()+4, 0);
success = 0;
while(!success){
rv = poll(ufds, 1, 500);
if (rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendPUT)" << endl;
return -1;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
if(answer.getType() == 8){
success = 1;
if(sendData((unsigned char*)fileData.c_str())){
cout << "Erro ao mandar dados (messages.cpp::sendPUT)" << endl;
return -1;
}
} else if (answer.getType() == 0){
success = 0;
} else if (answer.getType() == 15){ // 15 = 0xE --> Erro
if(answer.getData()[0] == '2'){
cout << "Não tem espaço para mandar o arquivo" << endl;
return -1;
} else {
success = 0;
}
}
}
}
}
}
} else if(answer.getType() == 0){ // 0 = NACK
// NACK
success = 0; // reenvia pedido
}
}
}
} else{
cout << "Tempo limite de resposta excedido :c\n" << endl;
cout << "TIMEOUT ATINGIDO (messages.cpp::sendPUT)" << endl;
}
garbage++;
}
}
}
int Message::sendGET(unsigned char* fileName){
int error, success = 0, garbage, rv;
char *receiptMessage = (char*)malloc(sizeof(char*)*64);
string temp, fileData;
struct pollfd ufds[1]; // usado para timeout em recv
SubMessage get, answer, ack, nack, err, ok;
ofstream fileOut;
ufds[0].fd = soquete;
ufds[0].events = POLLIN;
get.setData(fileName,6,0);
while(!success){
error = send(soquete, get.objToString(), get.getSize()+4, 0);
if (error == -1){
cout << "Erro ao receber arquivo (messages.cpp::sendGET)" << endl;
}
garbage = 0;
while((garbage < 10) && (!success)){
// vetor de pollfd, numero de buffers observados, timeout(ms)
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendGET)" << endl;
return -1;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
if(answer.getType() == 0){
success = 0;
} else if (answer.getType() == 15){ // Erro
if(answer.getData()[0] == '0'){
cout << "Arquivo Inexistente" << endl;
ack.setData((unsigned char*)answer.getSeq(),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
return -1;
} else if (answer.getData()[0] == '1'){
cout << "Sem permissão para baixar o arquivo" << endl;
ack.setData((unsigned char*)answer.getSeq(),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
return -1;
} else {
success = 0;
}
} else if (answer.getType() == 9){ // Tamanho
if(testaSeTamanhoEhInvalido()){
err.setData((unsigned char*)answer.getSeq(),1,0);
send(soquete, err.objToString(), err.getSize()+4, 0); // Erro
return -1;
} else if(answer.checkParity()){
nack.setData((unsigned char*)answer.getSeq(),0,0); // Manda um nack
send(soquete,nack.objToString(),nack.getSize()+4, 0);
return -1;
} else {
ok.setData((unsigned char*)answer.getSeq(),8,0); // Manda um ok
send(soquete,ok.objToString(),ok.getSize()+4, 0);
if(receiveData(fileName,atoi((char*)answer.getData())) == -1){
cout << "Erro no recebimento de dados (messages.cpp::sendGET)" << endl;
return -1;
} else{
cout << "Arquivo transferido com sucesso" << endl;
return 0;
}
}
}
}
}
}
}
}
}
int Message::sendData(unsigned char* stringMessage){
int numberOfMessages, sizeLastMessage, size=0;
int i, j, k, garbage, error, rv, success = 0;
unsigned char* subData; // a parte da mensagem que vai em cada sequencia
char *receiptMessage = (char*)malloc(sizeof(char*)*64);
char *erro1, *erro2, *sucesso, *buffer;
struct pollfd ufds[1]; // usado para timeout em recv
SubMessage answer, end;
ufds[0].fd = soquete;
ufds[0].events = POLLIN;
// Calcula o tamanho da msg
while( stringMessage[size] != '\0'){
size++;
}
// Verifica quantas mensagens serao necessarias
if (size%64){
numberOfMessages = (size/64) + 1;
} else {
numberOfMessages = (size/64);
}
sizeLastMessage = size%64;
numberOfMessages++; // +1 = Mensagem de FIM
// Cria as sub mensagens
SubMessage subMensagem[numberOfMessages];
// string usada para dividir a mensagem de entrada e colocar na parte de data das SubMessages
subData = (unsigned char*) malloc(sizeof(unsigned char) * 64);
int tipo = 13; // 13 = 0xD --> Dados
// Divide a mensagem
k = 0; // k é a numero da sequencia na submensagem
for(i = 0; i < numberOfMessages-1; ++i){
for(j = 0; j < 64; ++j){
subData[j] = stringMessage[(i*64)+j];
}
subMensagem[i].setData(subData, tipo, k);
++k;
if(k == 64){ // Caso estoure o número de bits de sequencia
k = 0;
}
}
if (sizeLastMessage){
// Caso a última mensagem não seja completa realoca subData para o tamanho da última mensagem
subData = (unsigned char*) realloc(subData, sizeof(unsigned char) * sizeLastMessage);
for(j = 0; j < sizeLastMessage; ++j){
subData[j] = stringMessage[(i*64)+j];
}
subMensagem[i].setData(subData, tipo, k);
++k;
}else{
// Caso contrario continua com o tamanho maior
for(j = 0; j < 64; ++j){
subData[j] = stringMessage[(i*64)+j];
}
subMensagem[i].setData(subData, tipo, k);
++k;
}
// Seta mensagem de FIM
i++;
subMensagem[i].setData((unsigned char*)"FIM", 15, k); // Dados = "FIM", tipo = 0xF, sequencia = proxima
// Caso haja só uma ou duas mensagens
if (numberOfMessages < 4){
while(!success){
if(numberOfMessages < 1) {
cout << "Algo parece estranho, sua mensagem contém conteúdo?\n" << endl;
cout << "Erro: Mensagem nula (messages.cpp::sendData)" << endl;
return -1;
}
// manda a primeira msg
error = send(soquete, subMensagem[0].objToString() , subMensagem[i].getSize()+4, 0);
if(numberOfMessages > 1) // Se forem 2 ou 3 msgs, manda a segunda
error = send(soquete, subMensagem[1].objToString() , subMensagem[i].getSize()+4, 0);
if(numberOfMessages > 2) // Se forem 3 msgs, manda a terceira
error = send(soquete, subMensagem[2].objToString() , subMensagem[i].getSize()+4, 0);
if(error == -1){
cout << "Problema com o envio da mensagem (messages.cpp::sendData)" << endl;
}
// vetor de pollfd, numero de buffers observados, timeout(ms)
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendData)" << endl;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
if(numberOfMessages == 1){
if(answer.getType() == 1){ //ACK
success = 1; // YAY
} else {
cout << "Mensagem entregue com erro (messages.cpp::sendData)" << endl;
}
} else if (numberOfMessages == 2){ // numero de mensagens = 2
if((answer.getType() == 1) && (answer.getData() == (unsigned char*)'1') ){ // aceitou ambas as msgs
success = 1; // YAY
} else {
cout << "Mensagem entregue com erro (messages.cpp::sendData)" << endl;
}
} else { // numbero de mensagens = 3
if((answer.getType() == 1) && (answer.getData() == (unsigned char*)'2') ){ // aceitou ambas as msgs
success = 1; // YAY
} else {
cout << "Mensagem entregue com erro (messages.cpp::sendData)" << endl;
}
}
}
}
} else {
cout << "Tempo limite de resposta excedido :c\n" << endl;
cout << "TIMEOUT ATINGIDO (messages.cpp::sendData)" << endl;
}
}
success = 0;
} else if (numberOfMessages > 3){
i = 0;
while (i < numberOfMessages - 2){
error = send(soquete, subMensagem[i].objToString() , subMensagem[i].getSize()+4, 0);
if(i < numberOfMessages - 1)
error = send(soquete, subMensagem[i+1].objToString() , subMensagem[i].getSize()+4, 0);
if(i < numberOfMessages)
error = send(soquete, subMensagem[i+2].objToString() , subMensagem[i].getSize()+4, 0);
success = 0;
garbage = 0;
while((garbage < 10) && (!success)){ // Tenta 10 vezes para evitar reenviar a mensagem quando recebe lixo
// vetor de pollfd, numero de buffers observados, timeout(ms)
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento de resposta (messages.cpp::sendData)" << endl;
return -1;
} else {
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
success = 1;
if(answer.getType() == 1) {
sprintf(erro1, "%d", i);
sprintf(erro2, "%d", i+1);
sprintf(sucesso, "%d", i+2);
if(answer.getData() == (unsigned char*)erro1){
i += 1;
} else if (answer.getData() == (unsigned char*)erro2){
i += 2;
} else if (answer.getData() == (unsigned char*)sucesso){
i += 3;
} else {
success = 0;
}
} else if (answer.getType() == 0){
success = 0; // NACK
}
}
}
} else {
cout << "Tempo limite de resposta excedido :c\n" << endl;
cout << "TIMEOUT ATINGIDO (messages.cpp::sendData)" << endl;
}
garbage++;
}
}
}
return 0;
}
//################# MÉTODOS DA CLASSE Message --> Recebimento #################
int Message::receiveCD(unsigned char* intendedDirectory){
int errorTest;
SubMessage resposta;
errorTest = chdir((char*) intendedDirectory);
if(errno = ENOENT){
if(errno = EPERM){
if (errorTest == -1){
resposta.setData((unsigned char*)'0',0,0); // Manda um Nack
send(soquete,resposta.objToString(),resposta.getSize()+4, 0);
} else {
resposta.setData((unsigned char*)'0',8,0); // Manda um OK
send(soquete,resposta.objToString(),resposta.getSize()+4, 0);
}
} else { // Não há permissão para acessar o diretorio
resposta.setData((unsigned char*)'1',14,0); // Manda um Erro
send(soquete,resposta.objToString(),resposta.getSize()+4, 0);
}
} else { // Diretorio não existe
resposta.setData((unsigned char*)'0',14,0); // Manda um Erro
send(soquete,resposta.objToString(),resposta.getSize()+4, 0);
}
}
//
int Message::receiveData(unsigned char* fileName, int size){
int numberOfMessages, messagesCounter = 0, seqCounter;
int i, garbage, error, rv, success = 0, greaterSeq = 0;
unsigned char *subData;
char *receiptMessage = (char*)malloc(sizeof(char*)*64);
struct pollfd ufds[1];
SubMessage nack, ack, answer;
ofstream fileOut;
map<int,string> subMensagem;
string finalMessage;
ufds[0].fd = soquete;
ufds[0].events = POLLIN;
// Verifica quantas mensagens serao necessarias
if (size%64){
numberOfMessages = (size/64) + 1;
}else{
numberOfMessages = (size/64);
}
numberOfMessages++; // +1 = Mensagem de FIM
while(!success){
rv = poll(ufds, 1, 500);
if(rv){
if(rv == -1){
cout << "Erro no recebimento dos dados (messages.cpp::receiveData)" << endl;
return -1;
}else{
recv(soquete, receiptMessage, 68*sizeof(char), 0);
answer.stringToObj((unsigned char*)receiptMessage);
// Lê começo da mensagem e vê se tem o delimitador de início
if(answer.getStartMessage() == 0x7E){ // 0x7E = 01111110
if(answer.checkParity()){
if(messagesCounter == 0){ // Se a primeira mensagem tiver erro
nack.setData((unsigned char*)answer.getSeq(),0,0); // Manda um nack
send(soquete,nack.objToString(),nack.getSize()+4, 0);
}else{
ack.setData((unsigned char*)((answer.getSeq()-1)%64),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
messagesCounter = 0;
}
}else{
if(answer.getType() == 13){
if(subMensagem[answer.getSeq()+(seqCounter*64)] == ""){
if(answer.getSeq() == 63){
seqCounter++;
}
subMensagem[answer.getSeq()+(seqCounter*64)] = (char*)answer.getData();
messagesCounter++;
if(answer.getSeq()+(seqCounter*64) > greaterSeq){
greaterSeq = answer.getSeq()+(seqCounter*64);
}
if(messagesCounter > 2){
ack.setData((unsigned char*)(greaterSeq%64),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
messagesCounter = 0;
}
}else{
ack.setData((unsigned char*)answer.getSeq(),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
messagesCounter = 0;
}
}else if(answer.getType() == 15){
success = 1;
ack.setData((unsigned char*)((greaterSeq%64)+1),1,0);
send(soquete, ack.objToString(), ack.getSize()+4, 0); // Manda um ACK
}
}
}
}
}else{
cout << "Tempo limite de resposta excedido :c\n" << endl;
cout << "TIMEOUT ATINGIDO (messages.cpp::receiveData)" << endl;
}
}
for(i = 0; i < greaterSeq; ++i){
finalMessage += subMensagem[i];
}
// Escrita no arquivo de saída.
fileOut.open((char *)fileName, ios::out);
fileOut << finalMessage;
return 0;
}