/* retorna o tipo de frame verificando o campo de controlo */ char * verifyFrameType(char * frame) { switch(frame[2]) { case C_SET: return "set"; break; case C_DISC: return "disc"; break; case C_UA: return "ua"; break; case RR(1): return "rr1"; break; case RR(0): return "rr0"; break; case REJ(0): return "rej0"; break; case REJ(1): return "rej1"; break; case C_I0: return "I0"; break; case C_I1: return "I1"; break; } }
/* Cria e envia uma trama do tipo type (Não funcional para tipo I) */ int buildFrame(int flag, char * type) { info->frameSend[0] = F; if (type == "set") info->frameSend[2] = C_SET; else if (type == "ua") info->frameSend[2] = C_UA; else if (type == "disc") info->frameSend[2] = C_DISC; else if (!strcmp(type, "rr1")) info->frameSend[2] = RR(1); else if (!strcmp(type,"rr0")) info->frameSend[2] = RR(0); else if (!strcmp(type,"rej0")) info->frameSend[2] = REJ(0); else if (!strcmp(type,"rej1")) info->frameSend[2] = REJ(0); else return 0; info->frameSend[1] = campo_endereco(info->flag, info->frameSend[2]); info->frameSend[3] = info->frameSend[1]^info->frameSend[2]; info->frameSend[4] = F; info->frameSendLength = 5; //printf("Trama composta %s: 0x%x 0x%x 0x%x 0x%x 0x%x \n", type, info->frameSend[0], info->frameSend[1], info->frameSend[2], info->frameSend[3], info->frameSend[4]); return 1; }
int llwrite(int fd, unsigned char* buffer, int length){ //printf("entrei no llwrite\n"); char *bufferStuffed; char header[] = { FLAG, 0x03, I(ll.sequenceNumber), header[1]^header[2] }; char dataBCC = generateBCC((char*)buffer, length); char* toStuff = malloc(length+1); memcpy(toStuff, buffer, length); toStuff[length] = dataBCC; int n= byteStuffing(toStuff, length+1, &bufferStuffed); //int k; //puts(""); //for (k=0;k<n;k++){ //printf("\n%d\n", bufferStuffed[k]); //} // puts(""); char* message = (char*) malloc(n+6); memcpy(message, header, 4); memcpy(message+4, bufferStuffed, n); message[n+4] = FLAG; int wrote = 0; while(!wrote) wrote = write(fd, message, n+5); stats.dataFramesTransmitted++; //puts("message sent\n"); free(message); free(bufferStuffed); alarm(ll.timeOut); Command command = receiveCommand(fd); //was asked for new frame if (command.command == RR(!ll.sequenceNumber)){ ll.sequenceNumber = (!ll.sequenceNumber); retries = 0; //puts("fui confirmado"); alarm(0); return length; } //frame was rejected, resend if (command.command == REJ(ll.sequenceNumber) || (command.command == NONE && ll.numTransmissions > retries)){ if (command.command == NONE){ stats.timeouts++; //printf("\nNumber of retries: %d\n", retries); alarm(0); } //puts("byte was rejected,resending or no response\n"); stats.rejs++; return llwrite(fd, buffer, length); } else{ //puts("eu esperei mas o reader nao me quis responder :("); return -1; } return length; }
int llread(int fd, unsigned char **buffer){ //printf("preparing to read frame\n"); Command command = receiveCommand(fd); //puts("llread:received command"); int repeated; if (command.command == I(ll.sequenceNumber)) repeated = 0; else if (command.command == I(!ll.sequenceNumber)) repeated = 1; else if (command.command == DISC){ //printf("llread: disconnecting\n"); while(!sendByte(fd, 0x01, DISC)){} //puts("llread: disc confirmation sent\n"); command = receiveCommand(fd); if (command.command != UA){ //puts("llread: didnt receive UA after disc confirmation\n"); return E_GENERIC; } else{ //puts("llread: connection successfully closed\n"); return E_CLOSED; } } if (command.command == I(0) || command.command == I(1)){ //puts("llread: received a data frame\n"); //if we never saw this frame before, consider it stats.dataFramesTransmitted++; if(!repeated){ //puts("llread: new data frame\n"); int length = byteDeStuffing(&(command.data), command.size); //puts("llread: destuffing succeeded\n"); int bccOK = verifyBCC(command.data, length, command.data[length-1]); if(getRand() < RANDOM_REJ_CHANCE){ bccOK = 0; // puts("\n randomly rejecting good packet"); } //Reject frames with wrong BCC if(!bccOK){ //puts("llread: frame was damaged, rejecting and rereading\n"); stats.rejs++; while(!sendByte(fd, 0x03, REJ(ll.sequenceNumber) )){} return llread(fd, buffer); } //accept the frame and confirm it //puts("llread: frame bcc ok, accepting\n"); *buffer = (unsigned char*) malloc(length); memcpy(*buffer, command.data, length); while(!sendByte(fd,0x03, RR(!ll.sequenceNumber))){} //puts("llread: receiver ready sent, message confirmed\n"); ll.sequenceNumber = !ll.sequenceNumber; free(command.data); //printf("%d length\n", length); return length; } //this frame is repeated. Confirm it and ask for the new frame else{ //puts("llread: message repeated"); while(!sendByte(fd, 0x03, RR(ll.sequenceNumber))){} return E_GENERIC; } } else{ //printf("received unexpected command 0x%02x\n",command.command); return E_GENERIC; } return 0; }
void state_machine(int state, char signal, char * type) { if (state == START) { if (signal == F) { state = FLAG; SET2[0]=signal; } } else if (state == FLAG) { if (signal == F) state = FLAG; else if ((signal == campo_endereco(!info->flag, C_SET) && type == "set") || (signal == campo_endereco(!info->flag, C_UA) && type == "ua") || (signal == campo_endereco(!info->flag, C_DISC) && type == "disc") || (signal == campo_endereco(!info->flag, RR(1)) && type == "rr1") || (signal == campo_endereco(!info->flag, RR(0)) && type == "rr0") || (signal == campo_endereco(!info->flag, REJ(1)) && type == "rej1") || (signal == campo_endereco(!info->flag, REJ(0)) && type == "rej0") || (signal == campo_endereco(!info->flag, C_I0) && type == "I0") || (signal == campo_endereco(!info->flag, C_I1) && type == "I1")) { state = A_STATE; SET2[1]=signal; } else state = START; } else if (state == A_STATE) { if (signal == F) { state = FLAG; } else if ((signal == C_SET && type == "set") || (signal == C_UA && type == "ua") || (signal == C_DISC && type == "disc") || (signal == RR(1) && type == "rr1") || (signal == RR(0) && type == "rr0") || (signal == REJ(1) && type == "rej1") || (signal == REJ(0) && type == "rej0") || (signal == C_I0 && type == "I0") || (signal == C_I1 && type == "I1")) { state = C; SET2[2]=signal; } else state = START; } else if (state == C) { if (signal == F) state = FLAG; else if (signal == (SET2[1]^SET2[2])) { state = BCC_STATE; SET2[3]=signal; } else state = START; } else if (state == BCC_STATE) { if (signal == F) { state = STOP2; SET2[4]=signal; } else state = START; } estado = state; //printf("estado: %d \n", estado); }