├── example1.txt.txt ├── syst_info.txt.txt ├── MyServer.exe ├── .gitattributes ├── .gitignore └── MyServer.c /example1.txt.txt: -------------------------------------------------------------------------------- 1 | blahblahblah 2 | durpdurpdurp -------------------------------------------------------------------------------- /syst_info.txt.txt: -------------------------------------------------------------------------------- 1 | system information 2 | blahblahblah -------------------------------------------------------------------------------- /MyServer.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bysz71/Simple-ftp-server/HEAD/MyServer.exe -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /MyServer.c: -------------------------------------------------------------------------------- 1 | //159.334 assignment1 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #define WSVERS MAKEWORD(2,0) 11 | //for wsastartup() use only, make 2 byte -> 16bit word 12 | WSADATA wsadata; 13 | 14 | 15 | #define BUFFERSIZE 200 16 | #define SEGMENTSIZE 198 17 | 18 | static const char USER[] = "admin"; 19 | static const char PW[] = "admin"; 20 | void str_cut(char* output_string, const char* input_string, int start, int end); 21 | int recv_msg(char* receive_buffer,int ns); 22 | char rfc[20][4]; 23 | 24 | 25 | 26 | main(int argc, char *argv[]){ 27 | strcpy(rfc[0],"SYST"); 28 | strcpy(rfc[1],"USER"); 29 | strcpy(rfc[2],"PASS"); 30 | strcpy(rfc[3],"QUIT"); 31 | 32 | const char username[] = "admin"; 33 | const char password[] = "admin"; 34 | const int cport = 1234; 35 | struct sockaddr_in localaddr,remoteaddr,data_addr_act; 36 | SOCKET s, ns, s_data_act; 37 | 38 | char send_buffer[BUFFERSIZE],receive_buffer[BUFFERSIZE]; 39 | char temp[BUFFERSIZE]; 40 | char bool; 41 | memset(&send_buffer,0,BUFFERSIZE); 42 | memset(&receive_buffer,0,BUFFERSIZE); //init buffers 43 | 44 | int n,bytes,addrlen; 45 | memset(&localaddr,0,sizeof(localaddr)); 46 | memset(&remoteaddr,0,sizeof(remoteaddr)); //init local and remote addresses 47 | 48 | 49 | 50 | 51 | //winsock init 52 | printf("\nSERVER : Initialising Winsock ...\n"); 53 | if(WSAStartup(WSVERS, &wsadata) != 0){ 54 | WSACleanup(); 55 | printf("WSAStartup failed. Error Code : %d", WSAGetLastError()); 56 | exit(1); 57 | } 58 | printf("SERVER : Initialised.\n"); 59 | 60 | //SOCKET 61 | s = socket(PF_INET, SOCK_STREAM, 0); //init s socket(A/P family[PF_INET for tcp] , transport[SOCK_STREAM for tcp] , protocol specified [0 for no specification]) 62 | if (s < 0) { 63 | printf("SERVER : socket failed\n"); 64 | exit(1); 65 | } 66 | localaddr.sin_family = AF_INET; //address family set for tcp 67 | if (argc == 2) { //decision on using specified port or default port 68 | localaddr.sin_port = htons((u_short)atoi(argv[1])); 69 | printf("SERVER : Communication port is specified to %s. \n",argv[1]); 70 | }else{ 71 | localaddr.sin_port = htons(cport); 72 | printf("SERVER : No port specified, use default port %d.\n",cport); 73 | } 74 | localaddr.sin_addr.s_addr = INADDR_ANY; //s_addr, 32 bit unsigned long IP addr, INADDR_ANY -> 0,0,0,0 local 75 | 76 | //BIND: bind socket with local address 77 | if (bind(s,(struct sockaddr *)(&localaddr),sizeof(localaddr))!=0){ 78 | printf("SERVER : Bind failed!\n"); 79 | exit(0); 80 | } 81 | printf("SERVER : binding succeeded.\n"); 82 | 83 | //LISTEN 84 | listen(s,5); 85 | printf("SERVER : Listening...\n"); 86 | 87 | //infinite loop 88 | while(1){ 89 | addrlen = sizeof(remoteaddr); 90 | ns = accept(s,(struct sockaddr *)(&remoteaddr),&addrlen); 91 | if (ns < 0){ 92 | sprintf(send_buffer,"421 Service not available, closing control connection\r\n"); 93 | break; 94 | } 95 | printf("SERVER : accepted a connection from client IP %s port %d \n",inet_ntoa(remoteaddr.sin_addr),ntohs(localaddr.sin_port)); 96 | //inet_ntoa converts Ipv4 address into ASCII string in internet standard dotted-decimal format 97 | //ntohs converts a u_short from TCP/IP network byte order to host byte order (format conversion blah blah) 98 | 99 | //system info feed if 421 not happen 100 | sprintf(send_buffer,"220 Microsoft FTP service\r\n"); 101 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 102 | if(bytes<0)break; 103 | 104 | while(1){ 105 | memset(&receive_buffer,0,BUFFERSIZE); 106 | bytes = recv_msg(receive_buffer,ns); 107 | if(bytes < 0)break; 108 | memset(&send_buffer,0,BUFFERSIZE); 109 | 110 | if(strncmp(receive_buffer,"USER",4) && strncmp(receive_buffer,"PASS",4) && strncmp(receive_buffer,"SYST",4) 111 | &&strncmp(receive_buffer,"PORT",4) && strncmp(receive_buffer,"STOR",4) && strncmp(receive_buffer,"RETR",4) 112 | &&strncmp(receive_buffer,"LIST",4) && strncmp(receive_buffer,"QUIT",4)){ 113 | sprintf(send_buffer,"202 Command not implemented, superfluous at this site. \r\n"); 114 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 115 | } 116 | 117 | if(strncmp(receive_buffer,"USER",4) == 0){ 118 | sprintf(send_buffer,"331 password required\r\n"); 119 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 120 | if(bytes < 0)break; 121 | } 122 | 123 | if(strncmp(receive_buffer,"PASS",4) == 0){ 124 | sprintf(send_buffer,"230 logged in\r\n"); 125 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 126 | if(bytes < 0)break; 127 | } 128 | 129 | if(strncmp(receive_buffer,"QUIT",4) == 0){ 130 | sprintf(send_buffer,"221 Service closing control connection\r\n"); 131 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 132 | if(bytes < 0)break; 133 | exit(1); 134 | } 135 | 136 | if(strncmp(receive_buffer,"PORT",4) == 0){ 137 | int act_ip[6], port_dec, connect_result; 138 | unsigned char act_port[2]; 139 | char data_addr[20]; 140 | 141 | sscanf(receive_buffer,"PORT %d,%d,%d,%d,%d,%d",&act_ip[0],&act_ip[1],&act_ip[2],&act_ip[3],&act_port[0],&act_port[1]); 142 | sscanf(receive_buffer,"PORT %d,%d,%d,%d,%d,%d",&act_ip[0],&act_ip[1],&act_ip[2],&act_ip[3],&act_ip[4],&act_ip[5]); 143 | sprintf(data_addr,"%d.%d.%d.%d",act_ip[0],act_ip[1],act_ip[2],act_ip[3]); 144 | port_dec = (act_port[0] << 8) + act_port[1]; 145 | data_addr_act.sin_port = htons(port_dec); 146 | data_addr_act.sin_addr.s_addr = inet_addr(data_addr); 147 | data_addr_act.sin_family = AF_INET; 148 | s_data_act = socket(AF_INET, SOCK_STREAM, 0); 149 | if(s_data_act == INVALID_SOCKET){ 150 | printf("SERVER : socket function failed with error:%d \n",WSAGetLastError()); 151 | WSACleanup(); 152 | return 1; 153 | } 154 | connect_result = connect(s_data_act, (struct sockaddr *) & data_addr_act, sizeof(data_addr_act)); 155 | if(connect_result == SOCKET_ERROR){ 156 | printf("SERVER : connect function failed with error:%d \n",WSAGetLastError()); 157 | connect_result == closesocket(s_data_act); 158 | if(connect_result == SOCKET_ERROR) 159 | printf("SERVER : close socket function failed with error:%d \n",WSAGetLastError()); 160 | WSACleanup(); 161 | return 1; 162 | } 163 | printf("SERVER : data connection established.\n"); 164 | sprintf(send_buffer,"200 PORT command successful\n"); 165 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 166 | if(bytes < 0) break; 167 | } 168 | 169 | if(strncmp(receive_buffer,"LIST",4) == 0){ 170 | DIR *dp; 171 | struct dirent *ep; 172 | sprintf(send_buffer,"125 data connection already open, transfer starting\r\n"); 173 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 174 | if(bytes < 0) break; 175 | dp = opendir("./"); 176 | if(dp != NULL){ 177 | while(ep = readdir(dp)){ 178 | //puts(ep->d_name); 179 | sprintf(temp,"200\t"); 180 | strcat(temp,ep->d_name); 181 | strcat(temp,"\r\n"); 182 | sprintf(send_buffer,temp); 183 | bytes = send(s_data_act, send_buffer,strlen(send_buffer),0); 184 | if(bytes < 0) break; 185 | } 186 | (void) closedir (dp); 187 | }else 188 | perror("SERVER : couldn't open the directory."); 189 | closesocket(s_data_act); 190 | sprintf(send_buffer,"226 closing data connection. Requested file action successful.\r\n"); 191 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 192 | if(bytes < 0) break; 193 | } 194 | 195 | if(strncmp(receive_buffer,"STOR",4) == 0){ 196 | char filename[100]; 197 | char data_buffer[BUFFERSIZE]; 198 | FILE *fout; 199 | sprintf(send_buffer,"125 data connection already open, transfer starting\r\n"); 200 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 201 | str_cut(filename,receive_buffer,5,strlen(receive_buffer)); 202 | fout=fopen(filename,"w"); 203 | while(1){ 204 | bytes = recv_msg(data_buffer,s_data_act); 205 | printf("%s\n",data_buffer); 206 | if(bytes<=0)break; 207 | fprintf(fout,"%s\r\n",data_buffer); 208 | } 209 | fclose(fout); 210 | closesocket(s_data_act); 211 | sprintf(send_buffer,"226 file uploaded.\r\n"); 212 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 213 | if(bytes<0)break; 214 | } 215 | 216 | if(strncmp(receive_buffer,"RETR",4) == 0){ 217 | char filename[100]; 218 | char data_buffer[BUFFERSIZE]; 219 | FILE *fin; 220 | sprintf(send_buffer,"125 data connection already open, transfer starting\r\n"); 221 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 222 | if(bytes<0)break; 223 | str_cut(filename,receive_buffer,5,strlen(receive_buffer)); 224 | fin = fopen(filename,"r"); 225 | if(fin == NULL){ 226 | printf("Server: cannot open %s",filename); 227 | break; 228 | } 229 | //while(fscanf(fin, " %s ", data_buffer) != EOF){ 230 | while(fgets(data_buffer,BUFFERSIZE,fin)!=NULL){ 231 | //fscanf(fin,"%s\r\n",data_buffer); 232 | //fgets(data_buffer,BUFFERSIZE,fin); 233 | //printf(data_buffer); 234 | sprintf(send_buffer,"%s\n",data_buffer); 235 | bytes = send(s_data_act,send_buffer,strlen(send_buffer),0); 236 | if(bytes<=0) break; 237 | } 238 | fclose(fin); 239 | closesocket(s_data_act); 240 | sprintf(send_buffer,"226 file downloaded.\r\n"); 241 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 242 | if(bytes < 0)break; 243 | 244 | } 245 | 246 | if(strncmp(receive_buffer,"SYST",4 == 0)){ 247 | char filename[] = "syst_info.txt"; 248 | FILE *fin; 249 | char data_buffer[BUFFERSIZE]; 250 | sprintf(send_buffer,"125 data connection already open, transfer starting\r\n"); 251 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 252 | if(bytes<0)break; 253 | fin = fopen (filename,"r"); 254 | if(fin == NULL){ 255 | printf("Server: cannot open %s",filename); 256 | break; 257 | } 258 | while(fgets(data_buffer,BUFFERSIZE,fin)!=NULL){ 259 | //printf(data_buffer); 260 | bytes = send(s_data_act,send_buffer,strlen(send_buffer),0); 261 | if(bytes<0) break; 262 | } 263 | fclose(fin); 264 | closesocket(s_data_act); 265 | sprintf(send_buffer,"226 system info done.\r\n"); 266 | bytes = send(ns,send_buffer,strlen(send_buffer),0); 267 | if(bytes<0)break; 268 | } 269 | 270 | 271 | } 272 | 273 | 274 | 275 | closesocket(ns); 276 | printf("SERVER : disconnected from %s \r\n", inet_ntoa(remoteaddr.sin_addr)); 277 | printf("SERVER : exit?(y/n)"); 278 | bool = getchar(); 279 | if(bool=='y')exit(1); 280 | 281 | } 282 | closesocket(s); 283 | return 0; 284 | } 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | void str_cut(char* output_string, const char* input_string, int start, int end){ 300 | int i = 0; 301 | int j = 0; 302 | for(j = start; j <= end; j++){ 303 | output_string[i] = input_string[j]; 304 | i++; 305 | } 306 | } 307 | 308 | int recv_msg(char* receive_buffer,int ns){ 309 | int n = 0; 310 | int bytes = 0; 311 | while(1){ 312 | bytes = recv(ns,&receive_buffer[n],1,0); 313 | if(bytes<=0) break; 314 | if(receive_buffer[n] == '\n'){ 315 | receive_buffer[n] = '\0'; 316 | break; 317 | } 318 | if(receive_buffer[n] != '\r') n++; 319 | } 320 | //if(bytes <= 0) break; 321 | printf("-->Debug: message reads from client <%s>\r\n", receive_buffer); 322 | return bytes; 323 | } --------------------------------------------------------------------------------