#include "../include/headdef.h"
// initialize the server sockets and listen for incomming connections
static void init(void);
// establish connection with clients and fork off a child to serve
static void run_server(void);
// check for clients identity and set fd to and open fd pointing to the
// file on disk to sasve, nbytes to number of bytes to receive, cipher to
// which cipher algorithm to use for decryption and key to key being used
// by cipher
static void check_client(int *fd, size_t *nbytes, int *cipher, char *key);
// use the fd return by analyse and store data
static void store_file(int fd, size_t nbytes, int cipher, char *key);
static int sd_me, sd_other;
static struct sockaddr_in sa_me, sa_other;
// will be set while receiving data from a client to not let others disturbe
int main(void)
{
init();
run_server();
return EXIT_SUCCESS;
}
static void init(void)
{
et_neg1(sd_me = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
// my socket address info
memset(&sa_me, sizeof sa_me, '\0');
sa_me.sin_family = AF_INET;
sa_me.sin_port = htons(atoi(S_PORT));
sa_me.sin_addr.s_addr = htonl(INADDR_ANY);
// check to reuse the port if already in use
int yes = 1;
et_neg1(setsockopt(sd_me, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes));
// bind my socket address to the socket for receiving
et_neg1(bind(sd_me, (const struct sockaddr *)&sa_me, sizeof(struct sockaddr)));
// listen for incomming connections
et_neg1(listen(sd_me, BACKLOG));
}
static void run_server(void)
{
while (1) {
int sd_other;
socklen_t othadd_len = sizeof sa_other;
ec_neg1(sd_other = accept(sd_me, (struct sockaddr *)&sa_other, &othadd_len));
// fork a child to serve the client
pid_t pid;
ec_neg1(pid = fork());
// child part
if (! pid) {
close(sd_me);
int fd, cipher;
size_t nbytes;
char key[MAX_KEY_SIZE];
printf("socket %d", sd_other);
check_client(&fd, &nbytes, &cipher, key);
// if everything's fine, then save the file
if (-1 != fd) {
store_file(fd, nbytes, cipher, key);
}
exit(EXIT_SUCCESS);
}
// parent part again
// child will die until this moment
ec_neg1(wait(0));
close(sd_other);
}
}
static void check_client(int *fd, size_t *nbytes, int *cipher, char *key)
{
struct nego_pack nego;
ssize_t nread;
ec_neg1(nread = read_all(sd_other, (char *)&nego, sizeof nego));
// if this is true, then the package is a negotiation package
if (! strcmp(HELLO, nego.hello)) {
ec_neg1(*fd = open(nego.filename, O_WRONLY
| O_CREAT
| O_EXCL));
ec_neg1(fchmod(*fd, S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR));
*nbytes = nego.nbytes;
*cipher = nego.cipher;
strcpy(key, nego.key);
}
}
static void store_file(int fd, size_t nbytes, int cipher, char *key)
{
// while not achived nbytes, read from socket and write to file
while (nbytes > 0) {
char buf[BUFFER_SIZE];
ssize_t nread;
ec_neg1(nread = read_all(sd_other, buf, BUFFER_SIZE));
// TODO: decrypt data here
ec_neg1(write_all(fd, buf, nread));
nbytes -= nread;
}
ec_nzero(close(fd));
}