www.pudn.com > ftpd.rar > ftpd.c
/* FTP server example for DSock, copyright (C) 2002 by DM&P. This is a simple FTP server for demo. You can improve it to support multi-user and support more commands. */ #include "..\dsock.h" #include#include #include #include #include #include #define FTP_PORT 21 #define FTP_TIME_OUT 30 BOOL FtpServer(SOCKET s); int main() { DWORD dwIp; char szBuf[1024]; SOCKET s; char *sz = "-\\|/"; uint nCnt = 0; printf("\nDM&P DSock FTP Server Example\n"); /* Open DSock library */ if(DSock_Open() == FALSE) { printf("Unable to initialize socket library\n"); return 1; } /* Load network setup from config file */ DSock_LoadConfigFile("dsock.cfg"); /* Show server IP */ dwIp = DSock_GetHostIp(); inet_ntoa(szBuf, dwIp); printf("FTP Server IP : %s\n", szBuf); /* Ceate socket for FTP server */ s = SocketCreate(TCP_SOCKET); if(s == INVALID_SOCKET) { printf("SocketCreate() error\n"); DSock_Close(); return 1; } if(SocketBind(s, 0L, FTP_PORT) == FALSE) { printf("SocketBind() error\n"); SocketDestory(s); DSock_Close(); return 1; } if(SocketListen(s) == FALSE) { printf("SocketListen() error\n"); SocketDestory(s); DSock_Close(); return 1; } /* We change FtpServer() to non-blocking function for programmer to check FTP connection. You can add HTTP or TELNET server checking routine into checking loop to support multiple services. */ while(TRUE) { printf("%c\r", sz[nCnt++ / 500 % 4]); if(kbhit()) /* Press any key to break */ break; FtpServer(s); } /* Destory FTP server socket */ SocketDestory(s); /* Close DSock library */ DSock_Close(); return 0; } BOOL FtpServer(SOCKET s) { char szBuf[1024]; static BOOL bConnected = FALSE; /* Because FtpServer() will immediately return when it process FTP command, we should save IP and port in PORT command. */ static DWORD dwIp; static WORD wPort; static clock_t clk; /* For time out checking */ char *p, *p2; /* Listen when socket is not connected */ if(bConnected == FALSE) { if(SocketAccept(s, &dwIp) == FALSE) return TRUE; else { SocketPutString(s, "220 DSock FTP Server, service ready.\r\n"); inet_ntoa(szBuf, dwIp); printf("FTP: Accepting connection from %s\n", szBuf); bConnected = TRUE; clk = clock(); } } /* Socket already connected but ... */ if(SocketIsConnected(s) == FALSE) { bConnected = FALSE; printf("FTP: Remote disconected.\n"); SocketClose(s); SocketBind(s, 0L, FTP_PORT); SocketListen(s); return TRUE; } /* Is idle time out ? */ if((clock() - clk) >= 18.2 * FTP_TIME_OUT) { bConnected = FALSE; printf("FTP: User idled %d seconds, disconnect.\n", FTP_TIME_OUT); SocketClose(s); SocketBind(s, 0L, FTP_PORT); SocketListen(s); return TRUE; } /* Is any data available ? */ if(SocketDataReady(s) == FALSE) return TRUE; /* Reset timer when user send command */ clk = clock(); SocketGetString(s, szBuf, 1024); /* Debug information */ printf("FTP: %s\n", szBuf); p = szBuf; while(*p != ' ' && *p != NULL) p++; if(p) { *p = NULL; p2 = p + 1; } /* p2 point to the second parameter */ /*** Process FTP commands ***/ /* You should save user name for password checking. We accept all user name here. */ if(stricmp("user", szBuf) == 0) { SocketPutString(s, "331 Password required for %s.\r\n", p2); } /* You can load user names and passwords from password file */ else if(stricmp("pass", szBuf) == 0) { if(stricmp("dmp", p2) != 0) /* default password for all user */ { SocketPutString(s, "530 Login incorrect.\r\n"); SocketClose(s); SocketBind(s, 0L, FTP_PORT); SocketListen(s); bConnected = FALSE; } SocketPutString(s, "230 Logged in okay.\r\n"); } #define MakeLong(high, low) \ ((long)(((WORD) (low)) | (((DWORD) ((WORD) (high))) << 16))) #define MakeWord(high, low) \ ((WORD) (((BYTE) (low)) | (((WORD) ((BYTE) (high))) << 8))) /* Port command for data connection. */ else if(stricmp("port", szBuf) == 0) { char c[6]; int i[2]; sscanf(p2, "%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5]); i[0] = MakeWord(c[0], c[1]); i[1] = MakeWord(c[2], c[3]); wPort = MakeWord(c[4], c[5]); dwIp = MakeLong(i[0], i[1]); SocketPutString(s, "200 PORT command successful.\r\n"); } /* We use binary mode for all commands */ else if(stricmp("type", szBuf) == 0) { SocketPutString(s, "200 Type set to %s.\r\n", p2); } /* Client uplaod file */ else if(stricmp("stor", szBuf) == 0) { SOCKET s2; FILE *fp = fopen(p2, "wb"); SocketPutString(s, "150 Opening BINARY mode data connection.\r\n"); s2 = SocketCreate(TCP_SOCKET); SocketConnect(s2, dwIp, wPort); if(fp == NULL) { SocketPutString(s, "550 Unable to create file.\r\n"); } else { long lSize = 0; int nLen; while(TRUE) { nLen = SocketRecv(s2, (uchar *)szBuf, 1024); lSize += nLen; printf("FTP: %lu bytes received\r", lSize); fwrite(szBuf, nLen, 1, fp); if(nLen < 1024) break; } printf("\n"); fclose(fp); SocketPutString(s, "226 Transfer complete.\r\n"); } SocketClose(s2); SocketDestory(s2); } /* Client download file */ else if(stricmp("retr", szBuf) == 0) { SOCKET s2; FILE *fp = fopen(p2, "rb"); SocketPutString(s, "150 Opening BINARY mode data connection.\r\n"); s2 = SocketCreate(TCP_SOCKET); SocketConnect(s2, dwIp, wPort); if(fp == NULL) { SocketPutString(s, "550 No such file or directory.\r\n"); } else { long lSize = 0; int nLen; while(TRUE) { nLen = fread(szBuf, 1, 1024, fp); if(SocketSend(s2, (uchar *)szBuf, nLen) == 0) { printf("Unable to send data."); break; } /* error handle is ignored */ lSize += nLen; printf("FTP: %lu bytes sent\r", lSize); if(nLen < 1024) break; } printf("\n"); fclose(fp); SocketPutString(s, "226 Transfer complete.\r\n"); } SocketClose(s2); SocketDestory(s2); } /* Change work directory */ else if(stricmp("cwd", szBuf) == 0) { if(chdir(p2) != 0) SocketPutString(s, "550 No such file or directory.\r\n"); else SocketPutString(s, "250 CWD command sucessful.\r\n"); } /* Make directory */ else if(stricmp("mkd", szBuf) == 0 || stricmp("xmkd", szBuf) == 0) { if(mkdir(p2) != 0) SocketPutString(s, "550 Path or file function not found.\r\n"); else SocketPutString(s, "257 New directory created.\r\n"); } /* Remove direcory */ else if(stricmp("rmd", szBuf) == 0 || stricmp("xrmd", szBuf) == 0) { if(rmdir(p2) != 0) SocketPutString(s, "550 Path or file not found.\r\n"); else SocketPutString(s, "257 Command successful.\r\n"); } /* Delete file */ else if(stricmp("dele", szBuf) == 0) { if(remove(p2) != 0) SocketPutString(s, "550 No such file or directory.\r\n"); else SocketPutString(s, "257 Command successful.\r\n"); } else if(stricmp("cdup", szBuf) == 0) { if(chdir("..") != 0) SocketPutString(s, "550 No such file or directory.\r\n"); else SocketPutString(s, "250 CDUP command sucessful.\r\n"); } /* Print work directory */ else if(stricmp("pwd", szBuf) == 0 || stricmp("xpwd", szBuf) == 0) { char szBuf2[256]; getcwd(szBuf2, 256); p = szBuf2; while(*p) { if(*p == '\\') *p = '/'; p++; } p = szBuf2; while(*p != ':') p++; sprintf(szBuf, "257 \"%s\" is current directory.\r\n", p + 1); SocketPutString(s, szBuf); } /* Directory list */ else if(stricmp("list", szBuf) == 0 || stricmp("nlst", szBuf) == 0) { SOCKET s2; struct ffblk ffblk; int nCode; char *szAttr = "-rwxr--r--"; static char *szMonth[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; SocketPutString(s, "150 Opening ASCII mode data connection for directory listing.\r\n"); s2 = SocketCreate(TCP_SOCKET); SocketConnect(s2, dwIp, wPort); nCode = findfirst("*.*", &ffblk, 0xff); while(!nCode) { szAttr[0] = ffblk.ff_attrib & FA_DIREC ? 'd' : '-'; SocketPutString(s2, "%10s 1 501 501 %10lu %3s %2d %4d %s\r\n", szAttr, ffblk.ff_fsize, szMonth[((ffblk.ff_fdate & 0x01e0) >> 5) - 1], ffblk.ff_fdate & 0x001f, 1980 + (ffblk.ff_fdate >> 9), ffblk.ff_name); nCode = findnext(&ffblk); } SocketClose(s2); SocketDestory(s2); SocketPutString(s, "226 Transfer complete.\r\n"); } else if(stricmp("quit", szBuf) == 0) { SocketPutString(s, "221 Bye!\r\n"); SocketClose(s); SocketBind(s, 0L, FTP_PORT); SocketListen(s); bConnected = FALSE; } else { SocketPutString(s, "500 Command not understood.\r\n"); } return TRUE; }