Files
Datakom2_Lab3/s_stub.c
2026-03-05 13:35:06 +01:00

214 lines
6.9 KiB
C

/* ***************************************** */
/* Laboration 2 i Datakommunikation 2 */
/* RPC-lib */
/* ***************************************** */
/* s_stub.c */
/* Ansvarar för att operationer utförs */
/* utförs på rätt sätt i servern */
/* ***************************************** */
/* Christian Ohlsson, di7chro@cse.kau.se */
/* Stefan Sonesson, di7stes@cse.kau.se */
/* ***************************************** */
#include "header.h"
/* Globala variabler */
int data_sockfd; /* Den socket som data färdas på */
msg myMsg; /* Meddelandet som funktionerna fyller i */
/* ==============================================
printsin()
Skriver ut information om klienten
============================================== */
printsin(struct sockaddr_in *sin, char *m1, char *m2 ) {
struct hostent *gethostbyaddr(), *h;
printf ("%s %s\n", m1, m2);
printf ("Family %d addr %x port %d\n", sin -> sin_family,
ntohl(sin -> sin_addr.s_addr), ntohs(sin -> sin_port));
h = gethostbyaddr((char *)&sin->sin_addr, sizeof(int), AF_INET);
printf ("Symbolic host name <%s>\n",h->h_name);
}
/* ==============================================
rem_open()
Öppnar en fil och fyller i data såsom
längd och fildeskriptor i strukten.
============================================== */
void rem_open() {
int fd;
struct stat st;
if((fd = open(myMsg.path, O_CREAT|O_RDWR|O_APPEND, PERMS)) < 0) {
myMsg.op = OPN; /* Skicka fel till klient */
return;
}
fstat(fd, &st);
myMsg.length = st.st_size;
myMsg.op = OPP; /* Operationen gick bra */
myMsg.fd = fd;
}
/* ==============================================
rem_read()
Läser data ur en fil tills EOF tecknet nås och
dessa tecken stoppas i en buffer, som slutligen
returneras
============================================== */
char *rem_read() {
char *buf;
int fd;
lseek(myMsg.fd, 0, SEEK_SET);
buf = (char*)malloc(myMsg.length);
if((read(myMsg.fd, buf, myMsg.length)) < 0)
myMsg.op = RDN; /* Skicka fel till klient */
else
myMsg.op = RDP; /* Operationen gick bra */
return buf;
}
/* ==============================================
rem_write()
Skriver tecken till fil
============================================== */
void rem_write() {
if((write(myMsg.fd, myMsg.data, myMsg.length)) < 0)
myMsg.op = WRN; /* Skicka fel till klient */
else
myMsg.op = WRP; /* Operationen gick bra */
}
/* ==============================================
rem_delete()
Tar bort en fil mha unlink, som egentligen
räknar ner antalet länkar till en fil
============================================== */
int rem_delete() {
if((unlink(myMsg.path)) < 0) {
myMsg.op = DLN; /* Skicka fel till klient */
return 0;
}
else {
myMsg.op = DLP; /* Operationen gick bra */
return 1;
}
}
/* ==============================================
rem_close()
Stänger en fil.
Returnerar svar om hur det gick
============================================== */
int rem_close() {
if((close(myMsg.fd)) < 0) {
myMsg.op = CLN; /* Skicka fel till klient */
return 0;
}
else {
myMsg.op = CLP; /* Operationen gick bra */
return 1;
}
}
/* ==============================================
rem_exit()
Stänger datasocketen vid fel.
Avslutar programmet
============================================== */
void rem_exit() {
puts("Quitting");
close(data_sockfd);
exit(0);
}
/* ==============================================
main()
Sköter uppkoppling och lyssnar efter klienter
============================================== */
main() {
int listener, client_length, length, val, again;
char *bytes;
struct sockaddr_in srvr_addr, client_addr;
signal(SIGCHLD, SIG_IGN);
signal(SIGINT, rem_exit);
/* Skapa en socket som lyssnar efter uppkopplingar */
if((listener = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
perror("server: can't open stream socket");
exit(0);
}
/* Nolla ut strukten */
bzero((char *) &srvr_addr, sizeof(srvr_addr));
srvr_addr.sin_family = AF_INET;
srvr_addr.sin_addr.s_addr = htons(INADDR_ANY);
srvr_addr.sin_port = PORT;
/* Bind ett namn till socketen */
if(bind(listener, (struct sockaddr *)&srvr_addr, sizeof(srvr_addr)) < 0) {
perror("server: can't bind local address");
exit(0);
}
length = sizeof(srvr_addr);
while(TRUE) {
/* Hämta namnet på socketen */
if(getsockname(listener, (struct sockaddr *)&srvr_addr, &length) < 0) {
perror("server: can't get sockname");
exit(0);
}
printf("Port number %d\n", ntohs(srvr_addr.sin_port));
/* Lyssna efter uppkopplingar */
listen(listener, MAXCONNECTED);
client_length = sizeof(client_addr);
/* Acceptera den nya uppkopplingen */
if ((data_sockfd=accept(listener,
(struct sockaddr *)&client_addr, &length)) < 0) {
perror("server: accept error");
exit(0);
}
/*printsin(&client_addr,"\nRSTREAM", "accepted connection from");*/
again=1;
while(again) {
/* Läs data från socketen */
if((read(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
switch(myMsg.op) {
case OP: /* Klienten vill öppna en fil */
rem_open();
if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
break;
case RD: /* Klienten vill läsa från en fil */
bytes = rem_read();
if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
if((write(data_sockfd, bytes, myMsg.length)) < 0)
rem_exit();
break;
case WR: /* Klienten vill skriva till en fil */
if((myMsg.data = (char*)malloc(myMsg.length)) == NULL) {
myMsg.op = WRN; /* Om minne inte kunde allokeras */
if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
}
if((read(data_sockfd, myMsg.data, myMsg.length)) < 0)
rem_exit();
rem_write();
if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
free(myMsg.data);
break;
case DEL:/* Klienten vill ta bort en fil */
val = rem_delete();
if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
if(val == 1) { close(data_sockfd); again=0; }
break;
case CL: /* Klienten vill stänga en fil */
val = rem_close();
if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0)
rem_exit();
if(val == 1) { close(data_sockfd); again=0; }
break;
default: break;
}
}
}
}