214 lines
6.9 KiB
C
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|