-
Notifications
You must be signed in to change notification settings - Fork 0
/
ftserver.c
125 lines (99 loc) · 4.35 KB
/
ftserver.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/******************************************************************************
** VS-FTP (Very Simple File Transfer Protocol)
** Server Software
** Author: Daniel Green, [email protected]
** Last Modified: 2 June 2019
** Description: starts a ftp server that accepts list and get commands.
*** Usage requires the ftclient program to be running on either localhost
*** or remote location. The server program will transfer to client any file
*** type, including binary, of any size.
*** The server will remain listening for connections until SIGINT is recieved.
***
** DEMO: To demonstrate the program, first start ftserver, then start ftclient.
** Transfer big.txt, a 6.2 MB file, and compare downloaded byte size to client
** reported byte count. Then transfer cvector, a binary file, give it execute
** permissions and execute. It is simple program that allocates a large array
** on the heap and displays the size of the array.
******************************************************************************/
/*
sources: https://linux.die.net/man/,
https://docs.python.org/3.7/library/socket.html
https://beej.us/guide/bgnet/
*/
#include "ft.h"
int main(int argc, char *argv[])
{
int sock, cmdSock, dataSock, dataPort;
char buffer[MAX_BUF],
dd_addr_buff[ADDR_LEN],
status[MAX_BUF],
cmd[CMD_LEN];
socklen_t clientLen;
struct sockaddr_in csa_cmd;
if (argc < 2) { fprintf(stderr," ***ERROR usage: %s PORT=<port>", "make server"); exit(1); } // Check usage & args
start_server(&sock, atoi(argv[1]));
// Enter server main loop
while(1){
// Get the size of the address for the client that will connect
clientLen = sizeof(csa_cmd);
// Accept a connection, blocking if one is not available until one connects
if((cmdSock = accept(sock, (SA*)&csa_cmd, &clientLen)) > -1){
// save client address as string
inet_ntop(AF_INET, &csa_cmd.sin_addr, dd_addr_buff, clientLen);
// acknowledge the client has connected, print the address and port
printlnStr("SERVER: accepted connection from %s ", dd_addr_buff);
// send success status greeting to client
ctrl_send("220", cmdSock);
while (1)
{
// memset(buffer, '\0', MAX_BUF);
memset(status, '\0', MAX_BUF);
// recv command from client on cmd port
ctrl_recieve(cmdSock, buffer);
printlnStr("Recieved from client: %s", buffer);
// Only accept legal commands
if (strcmp(buffer, "-l") == 0 || strcmp(buffer, "-g") == 0)
{
// save command
strcpy(cmd, buffer);
// send client the "pending further information" status
ctrl_send("350", cmdSock);
// recieve data port from client
ctrl_recieve(cmdSock, buffer);
dataPort = atoi(buffer);
// after recieving data port, inform client more info is needed
ctrl_send("350", cmdSock);
//recieve OK ready for connection status from client
ctrl_recieve(cmdSock, buffer);
// data_connect: establishes data connection on dataPort
data_connect(&dataSock, &csa_cmd, dataPort);
// handle_cmd: execs command, sends data, and closes dataSocket
handle_cmd(cmd, &cmdSock, &dataSock);
}
else
{
// This should never be encountered, but in case the client allows an invalid command,
// send the client status code 502 and close the connection.
ctrl_send("502", cmdSock);
close(cmdSock);
memset(buffer, '\0', MAX_BUF);
puts("Connection closed by server");
break;
}
}
}
}
puts("closing listen socket\n");
close(sock); // Close the listening socket
return 0;
}
void error(const char *msg) { perror(msg); exit(1); } // Error function used for reporting issues
// scratch code
// struct sigaction sigact;
// sigemptyset(&sigact.sa_mask);
// sigact.sa_flags = SA_RESTART;
// sigact.sa_handler = grimReaper;
// if (sigaction(SIGCHLD, &sigact, NULL) == -1) {
// error("SERVER: Error from sigaction()");
// exit(EXIT_FAILURE);
// }