Skip to content

Instantly share code, notes, and snippets.

@EV21
Last active May 30, 2017 14:13
Show Gist options
  • Save EV21/2e48d69c381d8e655c2c9ae65f46c859 to your computer and use it in GitHub Desktop.
Save EV21/2e48d69c381d8e655c2c9ae65f46c859 to your computer and use it in GitHub Desktop.
#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(&currenttime));
//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