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; 
}