update ftpserver

This commit is contained in:
ambrumf 2023-10-13 12:57:17 +08:00
parent ffbf276607
commit f5589fbaa4
1 changed files with 198 additions and 66 deletions

View File

@ -25,13 +25,18 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <pthread.h>
#define CMD_PORT 9970
#define CMD_PORT 9971
#define BACKLOG_LEN 128
#define MAX_USERS 100
#define MAX_CONNECTION 100
#define UNLOGED_IN 0
#define LOGED_IN 1
int off = 0;
int fd_map[200];
struct User {
char username[50];
char password[50];
@ -41,34 +46,82 @@ struct LoginStatus {
char *addr;
char username[50];
char password[50];
int login_status;//登录状态0代表未登录 1代表已登录
int login_status;
};
struct User users[MAX_USERS];
struct LoginStatus login_list[MAX_CONNECTION];
void GetFullAddress(char *client_id, char *client_ip, int client_port) {
void StartNewConnection(int data_fd,struct sockaddr_in client_addr);
void GetFullAddress(char* client_id, char* client_ip, int client_port) {
memset(client_id, 0, sizeof(client_id));
sprintf(client_id, "%s:%d", client_ip, client_port);
}
int CheckPassword(int it){
for(int i=0;i<MAX_USERS;i++){
if(strcmp(login_list[it].username,users[i].username) == 0 && strcmp(login_list[it].password,users[i].password) == 0)return 1;
int CheckPassword(int it) {
for (int i = 0;i < MAX_USERS;i++) {
if (strcmp(login_list[it].username, users[i].username) == 0 && strcmp(login_list[it].password, users[i].password) == 0)return 1;
}
return 0;
}
void StartDataConnection(int data_fd,struct sockaddr_in client_addr)
{
char *GetRespond(char *buf,int it) {
char * cmd=malloc(100);
char * data=malloc(100);
char * respond=malloc(100);
sscanf(buf,"%s %s",cmd,data);
}
void *CreateDataSockt(void *arg) {
int *data = arg;
int port = data[0];
int cmd_fd = data[1];
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
printf("Failed to create socket\n");
return NULL;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
int ret = bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0) {
printf("%d\n", ret);
printf("Failed to bind socket\n");
return NULL;
}
while (1) {
listen(fd, BACKLOG_LEN);
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int data_fd = accept(fd, (struct sockaddr *)&client_addr, &len);
fd_map[cmd_fd] = data_fd;
StartDataConnection(data_fd, client_addr);
}
close(fd);
return NULL;
}
char* GetRespond(char* buf, int it,int *ret,int cmd_fd) {
char * cmd = malloc(100);
char * data = malloc(100);
char* respond = malloc(100);
printf("%s\n", buf);
sscanf(buf, "%s %s", cmd, data);
if(strcmp(cmd,"USER")==0){
login_list[it].login_status=LOGED_IN;
strcpy(login_list[it].username,data);
sprintf(respond,"331 %s login ok, send your password\n",data);
strcpy(login_list[it].username, data);
sprintf(respond, "331 %s login ok, send your password\n", data);
}
else if(strcmp(cmd,"PASS")==0){
login_list[it].login_status=LOGED_IN;
strcpy(login_list[it].password, data);
if(CheckPassword(it)){
sprintf(respond,"230 access granted, restrictions apply\n");
}
@ -77,16 +130,66 @@ char *GetRespond(char *buf,int it) {
}
}
else if(strcmp(cmd,"SIZE")==0){
struct stat file_stat;
if (stat(data, &file_stat) == 0) {
int size = file_stat.st_size;
sprintf(respond, "213 %d", size);
}
else sprintf(respond, "550 file not found");
}
else if(strcmp(cmd,"PASV")==0){
else if (strcmp(cmd, "PASV") == 0) {
off = (off + 1) % 15;
int port = 9980 + off;
sprintf(respond, "227 enter passive mode (8.140.53.225,%d,%d)", port / 256, port % 256);
pthread_t thread;
int arg[2];
arg[0] = port;
arg[1] = cmd_fd;
pthread_create(&thread, NULL, CreateDataSockt, arg);
*ret = 227;
}
else if(strcmp(cmd,"RETR")==0){
else if (strcmp(cmd, "RETR") == 0) {
char* dir=malloc(100);
sprintf(dir, "/home/xiuos/wojiuguaji/%s", data);
FILE* file = fopen(dir, "rb");
if (file == NULL) {
sprintf(respond, "550 failed to open file\n");
}
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
fseek(file, 0, SEEK_SET);
char* buff = (char*)malloc(file_size);
fread(buf, 1, file_size, file);
write(fd_map[cmd_fd], buff, strlen(buff));
fclose(file);
free(buff);
free(dir);
}
else if(strcmp(cmd,"STOR")==0){
else if (strcmp(cmd, "STOR") == 0) {
char* dir=malloc(100);
sprintf(dir, "/home/xiuos/wojiuguaji/%s", data);
FILE* file = fopen(dir, "wb");
if (file == NULL) {
sprintf(respond, "550 failed to open file\n");
}
char* buff = (char*)malloc(5000);
read(fd_map[cmd_fd], buff, sizeof(buff));
fwrite(buff, 1, strlen(buff), file);
fclose(file);
free(buff);
free(dir);
}
else if(strcmp(cmd,"QUIT")==0){
sprintf(respond, "221 connection close");
*ret = 221;
}
else {
respond = "500 syntax error\n";
@ -94,9 +197,75 @@ char *GetRespond(char *buf,int it) {
return respond;
}
void *RecvSend(void *arg)
{
int* data = arg;
int cmd_fd = data[0];
int it = data[1];
while (1)
{
char buf[100];
memset(buf, 0, sizeof(buf));
int size;
size = read(cmd_fd, buf, sizeof(buf));
if (size < 0) {
printf("Failed to read or client closed\n");
return NULL;
}
int* ret = malloc(sizeof(int));
char* respond = GetRespond(buf, it,ret,cmd_fd);
write(cmd_fd, respond, strlen(respond));
}
return NULL;
}
void StartNewConnection(int cmd_fd, struct sockaddr_in client_addr)
{
char client_ip[INET_ADDRSTRLEN];
int client_port;
inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, sizeof(client_ip));
client_port = ntohs(client_addr.sin_port);
printf("Client %s:%d connected.\n", client_ip, client_port);
int it = -1;
char client_id[50];
for (int i = 0;i < MAX_CONNECTION;i++) {
GetFullAddress(client_id, client_ip, client_port);
if (strcmp(client_id, login_list[i].addr) == 0) {
it=i;
break;
}
}
if (it == -1) {
for(int i=0;i<MAX_CONNECTION;i++){
if(login_list[i].login_status==0){
it = i;
strcpy(login_list[i].addr, client_id);
break;
}
}
if(it==-1){
const char limit_exceeded[] = "530 connection limit exceeded.";
write(cmd_fd, limit_exceeded, strlen(limit_exceeded));
return;
}
}
if(login_list[it].login_status == UNLOGED_IN){
const char welcome[] = "220 welcome.";
write(cmd_fd, welcome, strlen(welcome));
}
pthread_t thread;
int arg[2];
arg[0] = cmd_fd;
arg[1] = it;
pthread_create(&thread, NULL, RecvSend, arg);
}
int Init() {
memset(login_list,0,sizeof(login_list));
memset(users,0,sizeof(users));
for (int i = 0;i < MAX_CONNECTION;i++) {
login_list[i].addr = (char*)malloc(50);
strcpy(login_list[i].addr, "");
@ -118,60 +287,21 @@ int Init() {
return 0;
}
listen(fd, BACKLOG_LEN);
printf("Socket created, binding to port 9970\n");
printf("Socket created, binding to port 9971\n");
while (1) {
listen(fd, BACKLOG_LEN);
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int cmd_fd = accept(fd, (struct sockaddr *)&client_addr, &len);
char client_ip[INET_ADDRSTRLEN];
int client_port;
inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, sizeof(client_ip));
client_port = ntohs(client_addr.sin_port);
printf("Client %s:%d connected.\n", client_ip, client_port);
StartNewConnection(cmd_fd, client_addr);
int it = -1;
char client_id[50];
for (int i = 0;i < MAX_CONNECTION;i++) {
GetFullAddress(client_id, client_ip, client_port);
printf("%s\n", client_id);
if (strcmp(client_id, login_list[it].addr) == 0) {
it=i;
break;
}
}
if (it==-1){
for(int i=0;i<MAX_CONNECTION;i++){
if(login_list[i].login_status==0){
it = i;
strcpy(login_list[i].addr, client_id);
break;
}
}
if(it==-1){
const char limit_exceeded[] = "530 connection limit exceeded.";
write(cmd_fd, limit_exceeded, strlen(limit_exceeded));
continue;
}
}
if(login_list[it].login_status == UNLOGED_IN){
const char welcome[] = "220 welcome.";
write(cmd_fd, welcome, strlen(welcome));
}
char buf[1024];
int size;
size = read(cmd_fd, buf, sizeof(buf));
if (size < 0) {
printf("Failed to read or client closed\n");
}
char *respond = GetRespond(buf, it);
write(cmd_fd, respond, strlen(respond));
}
close(fd);
}
void InsertUser(char * username,char * password)
@ -184,8 +314,10 @@ void InsertUser(char * username,char * password)
}
}
}
int main() {
InsertUser("frank","114514");
memset(users,0,sizeof(users));
InsertUser("frank", "114514");
Init();
return 0;
}