You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.6 KiB
109 lines
3.6 KiB
/*
|
|
** Copyright (C) 2020 Johannes Kepler University Linz, Institute of Networks and Security
|
|
** Copyright (C) 2020 CDL Digidow <https://www.digidow.eu/>
|
|
**
|
|
** Licensed under the EUPL, Version 1.2 or – as soon they will be approved by
|
|
** the European Commission - subsequent versions of the EUPL (the "Licence").
|
|
** You may not use this work except in compliance with the Licence.
|
|
**
|
|
** You should have received a copy of the European Union Public License along
|
|
** with this program. If not, you may obtain a copy of the Licence at:
|
|
** <https://joinup.ec.europa.eu/software/page/eupl>
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the Licence is distributed on an "AS IS" basis,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the Licence for the specific language governing permissions and
|
|
** limitations under the Licence.
|
|
**
|
|
*/
|
|
|
|
#include "server.h"
|
|
|
|
int server_open(int16_t port) {
|
|
struct sockaddr_in servaddr;
|
|
int connfd = 0;
|
|
|
|
connfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (-1 == connfd) {
|
|
printf("server_open: failed to create endpoint.\n");
|
|
return -1;
|
|
}
|
|
servaddr.sin_family = AF_INET;
|
|
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
servaddr.sin_port = htons(port);
|
|
|
|
if (0 != bind(connfd, (const struct sockaddr *) &servaddr, sizeof(servaddr))) {
|
|
printf("server_open: failed to bind socket\n");
|
|
close(connfd);
|
|
return -1;
|
|
}
|
|
return connfd;
|
|
}
|
|
|
|
int server_start(conn_handler handler, int16_t port) {
|
|
struct sockaddr_in client;
|
|
unsigned int client_len = 0;
|
|
int connfd = 0;
|
|
int clientfd = 0;
|
|
int len = 0;
|
|
int ret = 0; //<0 .. failure, 0 .. continue, 1 .. exit, 2 .. shutdown
|
|
char buffer[MAX_BUFSIZE];
|
|
|
|
if(NULL == handler) {
|
|
printf("server_start: received empty handler, stopping\n");
|
|
return -1;
|
|
}
|
|
connfd = server_open(port);
|
|
if(-1 == connfd) {
|
|
printf("server_start: could not open port, stopping\n");
|
|
return -1;
|
|
}
|
|
if (0 != listen(connfd, MAX_CLIENTS)) {
|
|
printf("server_start: listen failed, stopping\n");
|
|
return -1;
|
|
}
|
|
printf("server_start: listening\n");
|
|
for(ret = 1; 1 == ret;) {
|
|
client_len = sizeof(client);
|
|
clientfd = accept(connfd, (struct sockaddr *) &client, &client_len);
|
|
if (0 >= clientfd) {
|
|
printf("server_start: connection to client failed\n");
|
|
ret = -1;
|
|
} else {
|
|
for(ret = 0; 0 == ret;) {
|
|
bzero(buffer, MAX_BUFSIZE);
|
|
len = 0;
|
|
do {
|
|
ret = read(clientfd, &buffer[len], sizeof(buffer)-len);
|
|
len += ret;
|
|
} while(0 < ret && buffer[len-1] != '\n');
|
|
|
|
if (0 > ret) {
|
|
printf("server_start: cannot read from socket\n");
|
|
ret = -1;
|
|
} else if(0 == ret) {
|
|
printf("server_start: client closed connection\n");
|
|
ret = 1;
|
|
} else {
|
|
ret = handler(buffer);
|
|
}
|
|
|
|
if (0 == ret && 0 >= write(clientfd, buffer, strlen(buffer))) {
|
|
printf("server_start: cannot write to socket\n");
|
|
ret = 1;
|
|
}
|
|
}
|
|
if (0 != close(clientfd)) {
|
|
printf("server_start: failed to close client connection properly\n");
|
|
ret = -1;
|
|
}
|
|
}
|
|
}
|
|
printf("server_start: closing connection\n");
|
|
if (0 != close(connfd)) {
|
|
printf("server_start: failed to close server port properly\n");
|
|
ret = -1;
|
|
}
|
|
return ret;
|
|
}
|
|
|