Last active
May 30, 2017 14:13
-
-
Save EV21/2e48d69c381d8e655c2c9ae65f46c859 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <sys/stat.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <netdb.h> | |
#include <string.h> /* memset */ | |
#include <unistd.h> /* close */ | |
#include <time.h> | |
#include <dirent.h> | |
#define DEF_PORT 10258 | |
#define MSG_LEN 512 | |
#define CMND_LEN 4 | |
#define LIST "List" | |
#define GET "Get " | |
#define PUT "Put " | |
#define QUIT "Quit" | |
//int listHandler(void); | |
char buffer[MSG_LEN]; | |
struct sockaddr_storage their_addr; //client addr info | |
struct addrinfo *result, *p; | |
char ipstr[100]; | |
int cport; | |
int main(int argc, char *args[]) | |
{ | |
int s_tcp; /* socket descriptor (listener)*/ | |
int messenger; /* socket descriptor (send and recv)*/ | |
char *port = "10258"; | |
struct addrinfo hints; | |
int n; | |
int yes = 1; | |
socklen_t sin_size; | |
int recv_ready; | |
char msg[MSG_LEN]; | |
//char buffer[MSG_LEN]; | |
if (argc == 2) { | |
port = args[1]; | |
} else if (argc == 1) { | |
port = DEF_PORT; | |
} else { | |
perror("incorrect parameters"); | |
return 1; | |
} | |
memset(&hints, 0, sizeof(hints)); | |
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever | |
hints.ai_socktype = SOCK_STREAM; | |
hints.ai_flags = AI_PASSIVE; | |
//prepare struct addrinfo | |
if (getaddrinfo(NULL, port, &hints, &result) != 0) | |
{ | |
perror("getaddrdinfo failed"); | |
return 1; | |
} | |
//try to connect | |
for (p = result; p != NULL; p = p->ai_next) | |
{ | |
//create socket descriptor | |
if ((s_tcp = socket(p->ai_family, p->ai_socktype, | |
p->ai_protocol)) == -1) | |
{ | |
perror("server: socket"); | |
continue; | |
} | |
// set socket option; indicates that the rules used in validating adresses supplied in a bind() call | |
// should allow reuse of local addresses | |
if (setsockopt(s_tcp, SOL_SOCKET, SO_REUSEADDR, &yes, | |
sizeof(int)) == -1) | |
{ | |
perror("setsockopt"); | |
continue; | |
} | |
// bind socket with ip and port | |
if (bind(s_tcp, p->ai_addr, p->ai_addrlen) == -1) | |
{ | |
close(s_tcp); | |
perror("server: bind"); | |
continue; | |
} | |
break; | |
} | |
if (p == NULL) | |
{ | |
fprintf(stderr, "server: failed to bind\n"); | |
return 2; | |
} | |
// server ip | |
void *addr; | |
if (p->ai_family == AF_INET) | |
{ | |
struct sockaddr_in *ip = (struct sockaddr_in *)p->ai_addr; | |
addr = &(ip->sin_addr); | |
cport = &(ip->sin_port); | |
} | |
else | |
{ | |
struct sockaddr_in6 *ip = (struct sockaddr_in6 *)p->ai_addr; | |
addr = &(ip->sin6_addr); | |
cport = &(ip->sin6_port); | |
} | |
inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr)); | |
// frees address information | |
freeaddrinfo(result); | |
// socket listening for incoming connections | |
if (listen(s_tcp, 5) < 0) | |
{ | |
perror("listen"); | |
close(s_tcp); | |
return 1; | |
} | |
printf("Waiting for TCP connections ... \n"); | |
while (1) | |
{ | |
sin_size = sizeof their_addr; | |
if ((messenger = accept(s_tcp, (struct sockaddr *)&their_addr, &sin_size)) == -1) | |
{ | |
perror("accept"); | |
continue; | |
} | |
recv_ready = 1; | |
while (recv_ready) | |
{ | |
if (n = (recv(messenger, msg, MSG_LEN, 0)) <= 0) | |
{ | |
recv_ready = 0; | |
printf("Recv nothing ... \n"); | |
//s_tcp delete? | |
break; | |
} | |
else | |
{ | |
buffer[n] = '\0'; | |
printf("Messege recived : \n%s", buffer); | |
if ((strncmp(msg, GET, CMND_LEN) == 0)) | |
{ | |
getHandler(msg); | |
} | |
else if ((strncmp(msg, PUT, CMND_LEN) == 0)) | |
{ | |
putHandler(msg); | |
} | |
else if ((strncmp(msg, LIST, CMND_LEN) == 0)) | |
{ | |
listHandler(); | |
} | |
else | |
{ | |
printf("wrong command\n"); | |
wrongCmd(msg); | |
} | |
if (send(messenger, buffer, strlen(buffer), 0) > 0) | |
{ | |
printf("sent\n"); | |
} | |
} | |
memset(buffer, 0, strlen(buffer)); | |
memset(msg, 0, strlen(msg)); | |
} | |
} | |
close(s_tcp); | |
} | |
/* | |
* Handler for command "LIST" | |
* List will prepare a message with the Serverhostname, the used IP-Address, the local time | |
* and the server directory contents | |
*/ | |
int listHandler(void) | |
{ | |
DIR *dir; | |
struct dirent *ent; | |
char list_string[MSG_LEN]; | |
if ((dir = opendir(".")) != NULL) | |
{ | |
//empty the string | |
memset(list_string, 0, strlen(list_string)); | |
while ((ent = readdir(dir)) != NULL) | |
{ | |
//save every entry of the direction in list_string | |
strncat(list_string, ent->d_name, sizeof(list_string)); | |
strncat(list_string, " \n ", sizeof(list_string)); | |
} | |
closedir(dir); | |
} | |
else | |
{ | |
perror("opendir failed"); | |
return 1; | |
} | |
char host_name[100]; | |
int host; | |
if (host = gethostname(host_name, sizeof(host_name))) | |
{ | |
perror("Error getting Hostname gethostname()"); | |
sprintf(host_name, "Unknown Hostname"); | |
} | |
//get servers locatime | |
char times_string[24]; | |
time_t now = time(0); | |
strftime(times_string, sizeof(times_string), "%d.%m.%Y %H:%M:%S", localtime(&now)); | |
//fill send-buffer with directory, time, host_name and IP-address | |
sprintf(buffer, " [Server]: %s from %s\n [Date]: %s \n [Directory]:\n %s ", | |
host_name, (ipstr), times_string, list_string); | |
} | |
/* | |
* Handler for command "GET" | |
* The textfile contents at the local server directory will be prepared for sending to the client. | |
*/ | |
int getHandler(char *cmd) | |
{ | |
char *fname; | |
FILE *fp; | |
struct stat attrib; | |
int fc; | |
char str[10]; | |
char tmp[MSG_LEN]; | |
int c; | |
fname = strtok(cmd, " "); | |
fname = strtok(NULL, "\n"); | |
stat(fname, &attrib); | |
sprintf(tmp, "File: %s \nLast modification: %sSize: %d Bytes\nContents: \n", | |
fname, ctime(&attrib.st_mtim), (int)attrib.st_size); | |
if ((int)(attrib.st_size) > MSG_LEN) | |
{ | |
//warning info | |
char warn[50] = "===Warning:File cant be received completely!==="; | |
strncat(tmp, warn, sizeof(tmp)); | |
} | |
fp = fopen(fname, "r"); | |
if (fp == NULL) | |
{ | |
perror("error file"); | |
} | |
else | |
{ | |
while ((c = fgetc(fp)) != EOF) | |
{ | |
sprintf(str, "%c", c); | |
strncat(tmp, str, sizeof(tmp)); | |
} | |
fclose(fp); | |
} | |
//fille send buffer | |
sprintf(buffer, "%s", tmp); | |
} | |
/* | |
* wrong command handler | |
* The incorrect message and a help message for correct usage will be prepared | |
*/ | |
int wrongCmd(char *cmd) | |
{ | |
char *output; | |
sprintf(buffer, "%s - command entered incorrectly or not supported.\nList of available commands:\n’List’\n’Get <filename>’\n’Put <filename>’\n’Quit’\n", strncpy(output, cmd, strlen(cmd) - 1)); | |
} | |
/* | |
* putHandler handles a push-operation | |
* the client is sending a textfile | |
* the server does a console output an saves the file | |
*/ | |
int putHandler(char *cmd) | |
{ | |
FILE *fp; | |
char cname[100]; | |
char *filecontent, *filename; | |
size_t filesize; | |
if (getnameinfo((struct sockaddr *)&their_addr, sizeof((struct sockaddr *)&their_addr), cname, 100, NULL, 0, 0) != 0) | |
{ | |
perror(("Cannot resolve adress\n")); | |
} | |
filename = strtok(cmd, " "); | |
filename = strtok(NULL, " "); | |
filecontent = strtok(NULL, EOF); | |
filesize = strlen(filecontent); | |
fp = fopen(filename, "w"); | |
fwrite(filecontent, 1, filesize, fp); | |
fclose(fp); | |
sprintf(buffer, " OK %s:%d \n ", cname, cport); | |
} | |
############# | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/stat.h> | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <time.h> | |
#include <dirent.h> | |
//Constants avoiding magic numbers | |
#define WHITESPACE " " | |
#define EOF_STR "\0" | |
#define EOL_STR "\n" | |
#define TRUE 1 | |
#define FALSE 0 | |
#define NAME_LEN 2048 | |
#define MSG_LEN 2048 | |
#define SHORT_LEN 24 //backlog argument max length of queue for pending connections to socket(s_tcp) | |
#define CMD_LEN_SHRT 3 //length of short commands | |
#define LONG_CMD_LEN 4 //length long commands command | |
#define READBUFFSIZE 256 //Size of read buffer | |
#define DEFAULT_PORT "10258" | |
//Pototypes | |
void FreeSocket(); | |
void acceptClient(); | |
void handleListCmd(); | |
void handleGetCmd(); | |
void handlePutCmd(); | |
void sendHelpMsg(); | |
void handleKillCmd(); | |
//Globals | |
/* host socket descriptor*/ | |
int socketFD; | |
/* Connection socket descriptor*/ | |
int connectFD; | |
/* port used for chanel */ | |
int chanelPort; | |
/* local name of the host/server */ | |
char host_name[NAME_LEN]; | |
/* buffer for receiveing messages */ | |
char receive_buff[MSG_LEN]; | |
/* buffer to hold answer-messages */ | |
char send_buff[MSG_LEN]; | |
/* connected client IP-adress */ | |
char ip_addr[NAME_LEN]; | |
/* server info */ | |
struct addrinfo *result, *p; | |
/* client socket */ | |
struct sockaddr_storage sock_addr_stor; | |
/* size of socket information */ | |
socklen_t sock_addr_len = sizeof (struct sockaddr_storage); | |
/* port used for Socket */ | |
char *port; | |
int main(int argc, char *argv[]) { | |
if (argc == 2) { | |
port = argv[1]; | |
} else { | |
printf("Default port: 10258\n"); | |
port = DEFAULT_PORT; | |
} | |
struct addrinfo hints; | |
memset(&hints, 0, sizeof (hints)); | |
hints.ai_family = AF_INET6; | |
hints.ai_socktype = SOCK_STREAM; | |
hints.ai_flags = AI_PASSIVE; | |
/* | |
* extract the hosts name (Server) | |
*/ | |
if (gethostname(host_name, sizeof (host_name))) { | |
perror("gethostname failed: "); | |
} | |
//prepare struct addrinfo | |
if (getaddrinfo(NULL, port, &hints, &result) != 0) { | |
perror("getaddrinfo failed: "); | |
exit(EXIT_FAILURE); | |
} | |
//try to connect | |
for (p = result; p != NULL; p = p->ai_next) { | |
//create socket descriptor | |
socketFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol); | |
if (socketFD == -1) { | |
perror("serveer: socket"); | |
continue; | |
} | |
// bind socket with ip and port | |
if (bind(socketFD, p->ai_addr, p->ai_addrlen) == 0) { | |
break; | |
} | |
close(socketFD); | |
} | |
if (p == NULL) { | |
fprintf(stderr, "could not bind\n"); | |
exit(EXIT_FAILURE); | |
} | |
/* | |
* Free addrinfo structure AI including associated storage. | |
*/ | |
freeaddrinfo(result); | |
//Sets Port to listening | |
if (listen(socketFD, MSG_LEN) == -1) { | |
perror("accept failed"); | |
puts("closing socket\n"); | |
close(socketFD); | |
exit(EXIT_FAILURE); | |
} | |
printf("Set socket to listen: success\n"); | |
printf("Waiting for TCP connections ... \n"); | |
while (TRUE) { | |
//get message, reconnect if receive fails | |
if (recv(connectFD, receive_buff, MSG_LEN, 0) <= 0) { | |
acceptClient(); | |
} else { //evaluate messages | |
//Proccessing List command | |
if (strncmp(receive_buff, "List", LONG_CMD_LEN) == 0) { | |
handleListCmd(); | |
//Processing Get <file> | |
} else if (strncmp(receive_buff, "Get", CMD_LEN_SHRT) == 0) { | |
handleGetCmd(); | |
//Process Put <file> | |
} else if (strncmp(receive_buff, "Put", CMD_LEN_SHRT) == 0) { | |
handlePutCmd(); | |
//procecing Quit | |
} else if (strncmp(receive_buff, "Kill", LONG_CMD_LEN) == 0) { | |
handleKillCmd(); | |
//unknown command | |
} else { | |
sendHelpMsg(); | |
} | |
} | |
} | |
} | |
/** | |
* Initializes Socket and extracts info | |
*/ | |
void initSocket() { | |
} | |
/** | |
* Accept connection to Client and extract info | |
*/ | |
void acceptClient() { | |
//try accepting connection | |
if ((connectFD = accept(socketFD, (struct sockaddr*) &sock_addr_stor, | |
&sock_addr_len)) < 0) { | |
perror("accepting connection: "); | |
close(socketFD); | |
exit(EXIT_FAILURE); | |
} | |
//get client's IP-address | |
/* for storing IP and Port of connected client */ | |
void *ip_addr_bin; | |
puts("Connection established: using IPv4 mode\n"); | |
chanelPort = ((struct sockaddr_in*) &sock_addr_stor)->sin_port; | |
ip_addr_bin = &((struct sockaddr_in*) &sock_addr_stor)->sin_addr; | |
// } | |
puts("Client connected established\n"); | |
/* | |
* Convert a Internet address in binary network format for interface | |
* adress family in buffer starting at CP to presentation form and place | |
* result in buffer of length astarting at buffer. | |
*/ | |
if (((struct sockaddr*) &sock_addr_stor)->sa_family == AF_INET6) { | |
inet_ntop(((struct sockaddr*) &sock_addr_stor)->sa_family, | |
&((struct sockaddr_in6*) &sock_addr_stor)->sin6_addr, | |
ip_addr, sizeof (ip_addr)); | |
} else { | |
inet_ntop(((struct sockaddr*) &sock_addr_stor)->sa_family, ip_addr_bin, | |
ip_addr, sizeof (ip_addr)); | |
} | |
} | |
/** | |
* Handles Request for display of directory | |
*/ | |
void handleListCmd() { | |
/* Stream for listing dir */ | |
DIR *directory; | |
/* dirctory entry */ | |
struct dirent *dir_entry; | |
/* buffer for dirlist */ | |
char dir_list_buf[MSG_LEN]; | |
/* timestamp */ | |
time_t currenttime; | |
/* for the time string */ | |
char time_str[SHORT_LEN]; | |
//Open directory on server | |
if ((directory = opendir(".")) != NULL) { | |
//reset string | |
memset(dir_list_buf, 0, strlen(dir_list_buf)); | |
//put all entries in the same string | |
while ((dir_entry = readdir(directory)) != NULL) { | |
strncat(dir_list_buf, dir_entry->d_name, sizeof (dir_list_buf)); | |
strncat(dir_list_buf, " \n ", sizeof (dir_list_buf)); | |
} | |
closedir(directory); | |
} else { | |
perror("openening directory failed"); | |
exit(EXIT_FAILURE); | |
} | |
//getlocaltime | |
currenttime = time(NULL); | |
strftime(time_str, sizeof (time_str), "%d.%m.%Y - %H:%M:%S", | |
localtime(¤ttime)); | |
//write directory, time, host_name and IP-address to send-buffer | |
sprintf(send_buff, | |
" [Server]: %s from %s\n [Date]: %s \n [Directory]:\n %s ", | |
host_name, (ip_addr), time_str, dir_list_buf); | |
//send buffer to client | |
if (send(connectFD, send_buff, strlen(send_buff), 0) > 0) { | |
puts("Sending buff to client\n"); | |
} | |
} | |
/** | |
* Handles request for display of specific File | |
*/ | |
void handleGetCmd() { | |
//holds file attributes | |
struct stat fileAttrBuf; | |
//for splitting strings | |
char file_string[MSG_LEN]; | |
//filepointer | |
FILE *pFile; | |
//separated from command filename to get | |
char *filename; | |
//goto start of filename | |
filename = strtok(receive_buff, WHITESPACE); | |
//extract filename | |
filename = strtok(NULL, EOL_STR); | |
//Get file attributes for FILE and put them in buffer. | |
stat(filename, &fileAttrBuf); | |
//Write to outgoing string | |
sprintf(file_string, | |
"[File]: %s \n [Last modification]: %s [Size]: %d Bytes\n [Contents]: \n", | |
filename, ctime((const time_t *) &fileAttrBuf.st_mtim), | |
(int) fileAttrBuf.st_size); | |
//access filecontent | |
char content[READBUFFSIZE]; | |
char readbuf[READBUFFSIZE]; | |
pFile = fopen(filename, "r"); | |
if (pFile == NULL) { | |
perror("error opening file"); | |
} else { | |
while (feof(pFile) == FALSE) { | |
if (fgets(readbuf, READBUFFSIZE, pFile) != NULL) { | |
sprintf(content, "%s", readbuf); | |
strncat(file_string, content, sizeof (file_string)); | |
printf("content: %s \n",content); | |
} | |
} | |
fclose(pFile); | |
} | |
//Write to output buffer | |
sprintf(send_buff, " Server: %s from %s \n %s", host_name, ip_addr, | |
file_string); | |
//send buffer to client | |
if (send(connectFD, send_buff, strlen(send_buff), 0) > 0) { | |
printf("%s ... sent\n", send_buff); | |
} | |
} | |
/** | |
* Handles Request to write incoming stream to file | |
*/ | |
void handlePutCmd() { | |
/* host adress*/ | |
struct sockaddr *hostAddr; | |
/* local name of the client */ | |
char client_name[NAME_LEN]; | |
hostAddr = (struct sockaddr*) &sock_addr_stor; | |
//get client address | |
if (getnameinfo(hostAddr, sizeof (hostAddr), client_name, NAME_LEN, NULL, 0, | |
0) != 0) { | |
perror(("resolve adress: ")); | |
sprintf(client_name, "%s", ip_addr); | |
} | |
/* name of file to be processed */ | |
char *filename; | |
/* content of received file */ | |
char *filecontent; | |
/* size */ | |
size_t filesize; | |
//goto start of filename | |
filename = strtok(receive_buff, WHITESPACE); | |
//extract filename | |
filename = strtok(NULL, WHITESPACE); | |
//extract filecontetent | |
filecontent = strtok(NULL, EOF_STR); | |
filesize = strlen(filecontent); | |
//create and write to file | |
FILE * rcv_fileptr; | |
rcv_fileptr = fopen(filename, "w"); | |
fwrite(filecontent, 1, filesize, rcv_fileptr); | |
fclose(rcv_fileptr); | |
sprintf(send_buff, " OK %s: %d \n ", client_name, chanelPort); | |
//send buffer | |
if (send(connectFD, send_buff, strlen(send_buff), 0) > 0) { | |
printf("%s ... sent\n", send_buff); | |
} | |
} | |
/** | |
* Handles request to close socket | |
**/ | |
void handleKillCmd() { | |
FreeSocket(); | |
exit(EXIT_SUCCESS); | |
} | |
/** | |
* Sends help message if command not recognised | |
*/ | |
void sendHelpMsg() { | |
printf("Command %s is unknown\n", receive_buff); | |
sprintf(send_buff, | |
"Commando %s not recognised\n Use 'List', 'Get', 'Put' or 'Quit'.\n", | |
receive_buff); | |
if (send(connectFD, send_buff, strlen(send_buff), 0) > 0) { | |
printf("%s sent...\n", send_buff); | |
} | |
} | |
/** | |
* Frees ressources | |
*/ | |
void FreeSocket() { | |
puts("Terminating Server\n"); | |
close(connectFD); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment