Files
Datakomm_1/link.cpp
2026-03-05 13:37:25 +01:00

690 lines
14 KiB
C++

#include "physlayer.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#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;
}