#include "physlayer.h" #include #include #include #include "link_signal.h" #include "link.h" #include "student.h" const CONTROL_FRAME_SIZE = 14; int PSOCK_FD; int USOCK_FD; typedef enum state{IDLE, UICON, UOCON, DATA, UIDCON, UODCON}state; state LINK_STATE = IDLE; static action ALIST[] = { { L_DATA_REQUEST , DataRequest }, { L_DATA_INDICATION , DataIndication }, { L_CONNECT_REQUEST , ConnectRequest }, { L_CONNECT_INDICATION , ConnectIndication }, { L_CONNECT_RESPONSE , ConnectResponse }, { L_CONNECT_CONFIRM , ConnectConfirm }, { L_DISCONNECT_REQUEST , DisconnectRequest }, { L_DISCONNECT_INDICATION , DisconnectIndication }, { L_DISCONNECT_RESPONSE , DisconnectResponse }, { L_DISCONNECT_CONFIRM , DisconnectConfirm }, { L_ABORT_REQUEST , AbortRequest }, { L_ABORT_INDICATION , AbortIndication }, { SYSTEM_FAILURE , SystemError }, { DEFAULT , Default }, }; int incoming_frame_status = 0, incoming_frame_index = 0; // global! int incoming_frame_length = 0; struct Frame { char start_header[6]; short control; short length; short cc; char *data; char end_header[6]; }; Frame incoming_frame; // global! (tillfälligt). int ConnectRequest(void) { int return_value; if(LINK_STATE == IDLE) { return_value = WriteSignaltoSocket(PSOCK_FD, F_CONNECT_REQUEST, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = UOCON; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int ConnectIndication(void) { int return_value; if(LINK_STATE == IDLE) { return_value = WriteSignaltoSocket(PSOCK_FD, F_CONNECT_RESPONSE, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = UICON; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int ConnectConfirm(void) { Frame frame; int return_value, frame_length; if(LINK_STATE == IDLE) { return_value = Abort(SP); if(return_value < 0) return SYSTEM_FAILURE; } else if(LINK_STATE == UOCON) { frame_length = PutDataInFrame("", 0, &frame, SABM); if(frame_length == -10) return SYSTEM_FAILURE; return_value = SendFrame(&frame, PSOCK_FD); if(return_value < 0) return SYSTEM_FAILURE; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int ConnectResponse(void) { Frame frame; int return_value, frame_length; if(LINK_STATE == IDLE) { return_value = Abort(SU); if(return_value < 0) return SYSTEM_FAILURE; } else if(LINK_STATE == UICON) { frame_length = PutDataInFrame("", 0, &frame, UA); if(frame_length == -10) return SYSTEM_FAILURE; return_value = SendFrame(&frame, PSOCK_FD); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = DATA; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int DisconnectRequest(void) { Frame frame; int return_value, frame_length; if(LINK_STATE == IDLE) { return_value = Abort(SU); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = IDLE; } else if(LINK_STATE == DATA) { frame_length = PutDataInFrame("", 0, &frame, DISC); if(frame_length == -10) return SYSTEM_FAILURE; return_value = SendFrame(&frame, PSOCK_FD); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = UODCON; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int DisconnectIndication(void) { int return_value; if(LINK_STATE == IDLE) { return_value = Abort(SP); if(return_value < 0) return SYSTEM_FAILURE; } else if(LINK_STATE == UIDCON) { return_value = WriteSignaltoSocket(PSOCK_FD, F_DISCONNECT_RESPONSE, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = IDLE; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int DisconnectResponse(void) { Frame frame; int return_value, frame_length; if(LINK_STATE == IDLE) { return_value = Abort(SU); if(return_value < 0) return SYSTEM_FAILURE; LINK_STATE = IDLE; } else if(LINK_STATE == UIDCON) { frame_length = PutDataInFrame("", 0, &frame, UA); if(frame_length == -10) return SYSTEM_FAILURE; return_value = SendFrame(&frame, PSOCK_FD); if(return_value < 0) return SYSTEM_FAILURE; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int DisconnectConfirm(void) { int return_value; if(LINK_STATE == IDLE) { return_value = Abort(SP); if(return_value < 0) return SYSTEM_FAILURE; } else if(LINK_STATE == UODCON) LINK_STATE = IDLE; else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int AbortRequest(void) { int return_value; if(LINK_STATE == IDLE) // Do nothing. ; else { return_value = Abort(SP); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int AbortIndication(void) { int return_value; if(LINK_STATE == IDLE) ;// Do nothing. else { return_value = Abort(SU); if(return_value < 0) return SYSTEM_FAILURE; } return SUCCESS; } int Status(void) { int return_value; char frame_status; frame_status = CheckFrame(&incoming_frame); return_value = WriteSignaltoSocket(USOCK_FD, L_STATUS, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; return_value = WriteDatatoSocket(USOCK_FD, &frame_status, sizeof(char)); if(return_value < 0) return SYSTEM_FAILURE; return SUCCESS; } int Abort(short who) { int return_value; if((who == SU) || (who == BO)) { return_value = WriteSignaltoSocket(USOCK_FD, L_ABORT_INDICATION, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; } if((who == SP) || (who == BO)) { return_value = WriteSignaltoSocket(PSOCK_FD, F_ABORT_REQUEST, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; } LINK_STATE = IDLE; return SUCCESS; } int Checksum(int data_length) { int sum; // Vet ej varför, men det står i laborationshäftet. sum = data_length % 128; return sum; } int PutDataInFrame(char *data, short data_length, Frame *frame, short control) { int frame_length, cc = 0; strcat(frame->start_header, "DLEST"); frame->start_header[5] = 'X'; frame->control = control; frame->length = data_length; if(control == I) cc = Checksum(data_length); else { frame->cc = cc; data_length = sizeof(frame->data); } frame->data = data; strcat(frame->start_header, "DLEET"); frame->end_header[5] = 'X'; frame_length = 6 + 6 + 2 + 2 + 2 + data_length; return frame_length; } int ClearFrame(Frame *frame) { frame->start_header[0] = 0; frame->end_header[0] = 0; frame->control = 0; frame->length = 0; frame->cc = 0; if(frame->data != NULL) { delete[] frame->data; frame->data = NULL; } incoming_frame_status = 0; // Global variabel. incoming_frame_index = 0; // Global variabel. } int FillInFrame(Frame *frame, char data, char *charframe) { int status; if(CheckFrame(frame) == -1) return FRAME_ERROR; if(incoming_frame_status) return FRAME_IS_FULL; if(incoming_frame_index == 12) { if(frame->control == I) { frame->data = new char[frame->length]; if(frame->data == NULL) return SYSTEM_FAILURE; charframe[incoming_frame_index] = data; incoming_frame_index++; } } else { charframe[incoming_frame_index] = data; incoming_frame_index++; } return CheckFrame(frame); } int CheckFrame(Frame *frame) { int start, end, cc; if(incoming_frame_index == 10) // HEADER_LENGTH = 22 incoming_frame_length = HEADER_LENGTH + frame->length; if(incoming_frame_index >= 10) { if(incoming_frame_index == incoming_frame_length) { start = CheckStartHeader((char*)frame); end = CheckEndHeader((char*)frame); cc = CheckCC(frame); FixFrameData(frame); // tar bort de onödiga DLE om det behövs. if(start == 0 && end == 0 && cc == 0) { incoming_frame_status = 1; return FRAME_IS_FULL; // frame_is_full = 1 } else return FRAME_ERROR; // frame_error = -1 } } return FRAME_NOT_READY; // frame_not_ready = 0 } int CheckStartHeader(char *frame) { int index; char start[7]; start[7] = '\0'; for(index = 0; index < 6; index++) start[index] = (char)frame[index]; return strcmp(start, "DLESTX"); } int CheckEndHeader(char *frame) { if(incoming_frame_status != 1) return FRAME_ERROR; int index; char start[7]; start[7] = '\0'; for(index = 0; index < 6; index++) start[index] = (char)frame[incoming_frame_index - 5 + index]; return strcmp(start, "DLEETX"); } int CheckCC(Frame *frame) { int cc; cc = Checksum(frame->length); if(cc == frame->cc) return 0; return FRAME_ERROR; } int FixFrameData(Frame *frame) { char *tmp; int length, index, tmpindex, before = 0; length = frame->length; for(index = 0; index < frame->length; index++) { if(frame->data[index] == 'D' && frame->data[index+1] == 'L' && frame->data[index+2] == 'E') { if(before == 1) { length--; before = 0; } else before = 1; } } if(length == frame->length) return SUCCESS; tmp = new char[length]; if(tmp == NULL) return SYSTEM_FAILURE; for(index = 0, tmpindex = 0; index < frame->length; index++, tmpindex++) { if(frame->data[index] == 'D' && frame->data[index+1] == 'L' && frame->data[index+2] == 'E') { if(before == 1) { before = 0; index += 3; } else before = 1; } if(index < frame->length) tmp[tmpindex]; } delete[] frame->data; frame->data = tmp; frame->length = length; return SUCCESS; } int SendFrame(Frame *frame, int socket_id) { int frame_length, index = 0, return_value; frame_length = GetFrameLength(frame); if(socket_id == USOCK_FD) { return_value = WriteSignaltoSocket(USOCK_FD, L_DATA_INDICATION, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; return_value = WriteDatatoSocket(USOCK_FD, frame->data, frame->length); if(return_value < 0) return SYSTEM_FAILURE; } else if(socket_id == PSOCK_FD) { for(index = 0; index < frame_length; index++) { return_value = WriteSignaltoSocket(PSOCK_FD, F_DATA_REQUEST, SIG_LEN); if(return_value < 0) return SYSTEM_FAILURE; return_value = WriteDatatoSocket(PSOCK_FD, (char *)&frame[index], sizeof(char)); if(return_value < 0) return SYSTEM_FAILURE; } } else return SYSTEM_FAILURE; return SUCCESS; } int DataIndication(void) { /*Frame *frame; char temp = 'a'; int return_value, frame_length; if(LINK_STATE == IDLE) Abort(SP); else if(LINK_STATE == UICON) { return_value = ReadDatafromSocket(PSOCK_FD, &temp, TWO_BYTES); if(return_value < 0) return SYSTEM_FAILURE; return_value = ReadDatafromSocket(PSOCK_FD, temp, BYTE_LEN); if(return_value < 0) return SYSTEM_FAILURE; } else { return_value = Abort(BO); if(return_value < 0) return SYSTEM_FAILURE; } if(frame != NULL) delete[] frame; */ return SUCCESS; } void main(int argc, char *argv[]) { int tmp_fd1, PSOCK; printf("LINK_LAYER har startat...\n"); if((PSOCK = CreateUnixClientSocket(UPATH)) < 0) { fprintf(stderr, "Can't create unix client signal socket 111\n"); exit(1); } printf("LINK_LAYER har skapat FTP_LAYER Socket...\n"); if((tmp_fd1 = CreateUnixServerSocket(PPATH)) < 0) { fprintf(stderr, "Can't create unix server signal socket.\n"); exit(1); } printf("LINK_LAYER har skapat PHYS_LAYER Socket...\n"); switch(fork()) { case -1: fprintf(stderr, "Fork failed.\n"); case 0: printf("Fuck you\n\n"); close(PSOCK_FD); close(USOCK_FD); execv("./phys_layer", argv); exit(1); default: if((PSOCK = AcceptConnection(tmp_fd1)) < 0) { fprintf(stderr, "Can't accept unix client signal socket.\n"); exit(1); } MainLoop(); exit(1); } } void MainLoop(void) { int return_value; do { return_value = PollSocket(PSOCK_FD, USOCK_FD, NULL); if(return_value < 0) return; return_value = ReadSignalfromSocket(return_value - 1, SIG_LEN); return_value = (* FindAction(return_value, ALIST))(); if(return_value < 0) return ; } while(return_value >= 0); } int DataRequest(void) { return 10; } int Default(void) { return 10; } int GetFrameLength(Frame *frame) { return frame->length; } int SystemError(void) { return 108; }