update ftpserver
This commit is contained in:
parent
ffbf276607
commit
f5589fbaa4
|
@ -25,13 +25,18 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.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 BACKLOG_LEN 128
|
||||||
#define MAX_USERS 100
|
#define MAX_USERS 100
|
||||||
#define MAX_CONNECTION 100
|
#define MAX_CONNECTION 100
|
||||||
#define UNLOGED_IN 0
|
#define UNLOGED_IN 0
|
||||||
#define LOGED_IN 1
|
#define LOGED_IN 1
|
||||||
|
|
||||||
|
int off = 0;
|
||||||
|
int fd_map[200];
|
||||||
struct User {
|
struct User {
|
||||||
char username[50];
|
char username[50];
|
||||||
char password[50];
|
char password[50];
|
||||||
|
@ -41,26 +46,74 @@ struct LoginStatus {
|
||||||
char *addr;
|
char *addr;
|
||||||
char username[50];
|
char username[50];
|
||||||
char password[50];
|
char password[50];
|
||||||
int login_status;//登录状态,0代表未登录 1代表已登录
|
int login_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct User users[MAX_USERS];
|
struct User users[MAX_USERS];
|
||||||
struct LoginStatus login_list[MAX_CONNECTION];
|
struct LoginStatus login_list[MAX_CONNECTION];
|
||||||
|
|
||||||
|
void StartNewConnection(int data_fd,struct sockaddr_in client_addr);
|
||||||
|
|
||||||
void GetFullAddress(char* client_id, char* client_ip, int client_port) {
|
void GetFullAddress(char* client_id, char* client_ip, int client_port) {
|
||||||
memset(client_id, 0, sizeof(client_id));
|
memset(client_id, 0, sizeof(client_id));
|
||||||
sprintf(client_id, "%s:%d", client_ip, client_port);
|
sprintf(client_id, "%s:%d", client_ip, client_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CheckPassword(int it) {
|
int CheckPassword(int it) {
|
||||||
for (int i = 0;i < MAX_USERS;i++) {
|
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;
|
if (strcmp(login_list[it].username, users[i].username) == 0 && strcmp(login_list[it].password, users[i].password) == 0)return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
void StartDataConnection(int data_fd,struct sockaddr_in client_addr)
|
||||||
|
{
|
||||||
|
|
||||||
char *GetRespond(char *buf,int it) {
|
}
|
||||||
|
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 * cmd = malloc(100);
|
||||||
char * data = malloc(100);
|
char * data = malloc(100);
|
||||||
char* respond = malloc(100);
|
char* respond = malloc(100);
|
||||||
|
printf("%s\n", buf);
|
||||||
sscanf(buf, "%s %s", cmd, data);
|
sscanf(buf, "%s %s", cmd, data);
|
||||||
if(strcmp(cmd,"USER")==0){
|
if(strcmp(cmd,"USER")==0){
|
||||||
login_list[it].login_status=LOGED_IN;
|
login_list[it].login_status=LOGED_IN;
|
||||||
|
@ -68,7 +121,7 @@ char *GetRespond(char *buf,int it) {
|
||||||
sprintf(respond, "331 %s login ok, send your password\n", data);
|
sprintf(respond, "331 %s login ok, send your password\n", data);
|
||||||
}
|
}
|
||||||
else if(strcmp(cmd,"PASS")==0){
|
else if(strcmp(cmd,"PASS")==0){
|
||||||
login_list[it].login_status=LOGED_IN;
|
strcpy(login_list[it].password, data);
|
||||||
if(CheckPassword(it)){
|
if(CheckPassword(it)){
|
||||||
sprintf(respond,"230 access granted, restrictions apply\n");
|
sprintf(respond,"230 access granted, restrictions apply\n");
|
||||||
}
|
}
|
||||||
|
@ -77,16 +130,66 @@ char *GetRespond(char *buf,int it) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(strcmp(cmd,"SIZE")==0){
|
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 {
|
else {
|
||||||
respond = "500 syntax error\n";
|
respond = "500 syntax error\n";
|
||||||
|
@ -94,9 +197,75 @@ char *GetRespond(char *buf,int it) {
|
||||||
return respond;
|
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() {
|
int Init() {
|
||||||
memset(login_list,0,sizeof(login_list));
|
memset(login_list,0,sizeof(login_list));
|
||||||
memset(users,0,sizeof(users));
|
|
||||||
for (int i = 0;i < MAX_CONNECTION;i++) {
|
for (int i = 0;i < MAX_CONNECTION;i++) {
|
||||||
login_list[i].addr = (char*)malloc(50);
|
login_list[i].addr = (char*)malloc(50);
|
||||||
strcpy(login_list[i].addr, "");
|
strcpy(login_list[i].addr, "");
|
||||||
|
@ -118,60 +287,21 @@ int Init() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(fd, BACKLOG_LEN);
|
|
||||||
printf("Socket created, binding to port 9970\n");
|
printf("Socket created, binding to port 9971\n");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
listen(fd, BACKLOG_LEN);
|
||||||
|
|
||||||
struct sockaddr_in client_addr;
|
struct sockaddr_in client_addr;
|
||||||
socklen_t len = sizeof(client_addr);
|
socklen_t len = sizeof(client_addr);
|
||||||
int cmd_fd = accept(fd, (struct sockaddr *)&client_addr, &len);
|
int cmd_fd = accept(fd, (struct sockaddr *)&client_addr, &len);
|
||||||
|
|
||||||
char client_ip[INET_ADDRSTRLEN];
|
StartNewConnection(cmd_fd, client_addr);
|
||||||
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);
|
|
||||||
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)
|
void InsertUser(char * username,char * password)
|
||||||
|
@ -184,7 +314,9 @@ void InsertUser(char * username,char * password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
memset(users,0,sizeof(users));
|
||||||
InsertUser("frank", "114514");
|
InsertUser("frank", "114514");
|
||||||
Init();
|
Init();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue