To send simple message was working correctly in this program.
But it has some problem when I send a file.
There are another socket which has different port.
I made another socket.
But after binding, When listen method was called in server,
it just halt.
And client occurs connect error.
please let me know how can I fix it.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/_default_fcntl.h>
#include <sys/reent.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>
#include <grp.h>
#include <dirent.h>
#include <pwd.h>
void error_handling(char *message);
void inst_list();
void inst_pwd();
void inst_cwd(char *target);
void inst_nlst();
void inst_dele();
void inst_mkd(char *target);
void inst_handling();
void inst_rmd(char *target);
void inst_retr(char *target);
char sendMsg[500] = "";
char workingPath[500]="/";
char homePath[500]="../../usr/ftp";
struct sockaddr_in clnt_adr;
int clnt_sock;
int main(int argc, char *argv[])
{
int serv_sock, data_sock, clnt_dataSock;
char message[BUF_SIZE];
int str_len, i;
char dataPort[] = "13000";
char welcomeMsg[30] = "Hello dataPort: ";
char dataConnectMsg[30] = "Data Connected!";
char method[10] = "";
char target[100] = "";
struct sockaddr_in serv_adr;
struct sockaddr_in data_adr;
struct sockaddr_in datcl_adr;
socklen_t clnt_adr_sz;//
socklen_t datcl_adr_sz;//
if(argc!=2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
data_sock = socket(PF_INET, SOCK_STREAM,0);
if(serv_sock==-1)
error_handling("socket() error");
if(data_sock == -1)
error_handling("Data socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
memset(&data_adr, 0, sizeof(data_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
data_adr.sin_family = AF_INET;
data_adr.sin_addr.s_addr=htonl(INADDR_ANY);
data_adr.sin_port=htons(13230);
if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("bind() error");
// if(bind(data_sock, (struct sockaddr*)&data_adr, sizeof(data_adr))==-1)
// error_handling("data bind() error");
if(listen(serv_sock, 5)==-1)
error_handling("listen() error");
// if(listen(data_sock, 5)==-1)
// error_handling("listen() error");
clnt_adr_sz=sizeof(clnt_adr);
// datcl_adr_sz=sizeof(datcl_adr);
for(i=0; i<5; i++)
{
clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
if(clnt_sock==-1)
error_handling("accept() error");
else
printf("Connected client %d \n", i+1);
strcat(welcomeMsg , dataPort);
write(clnt_sock, welcomeMsg, strlen(welcomeMsg));
while((str_len=read(clnt_sock, message, BUF_SIZE))!=0)
{
message[str_len] = 0;
sscanf(message, "%s %s",method, target);
if(strcmp(method, "QUIT") == 0)
{
strcat(sendMsg, "Disconnected");
write(clnt_sock, sendMsg, strlen(sendMsg));
close(clnt_sock);
}
inst_handling(method, target);
write(clnt_sock, sendMsg, strlen(sendMsg));
memset(method, 0 , sizeof(char)*10);
memset(target, 0 , sizeof(char)*100);
memset(sendMsg, 0, sizeof(char)*500);
}
}
close(serv_sock);
return 0;
}
void inst_handling(char *method, char *target)
{
char cpyMessage[2048] = "";
char *token;
char protocol[100];
char host[200];
if(strcmp(method,"PWD") == 0)//작업 디렉토리 표시
inst_pwd();
else if(strcmp(method, "CWD") == 0)//작업 디렉토리 변경
inst_cwd(target);
else if(strcmp(method, "LIST") == 0)//원격지 파일 목록 보기
inst_list();
else if(strcmp(method, "NLST") == 0)///원격지 디렉토리 목록 보기
inst_nlst();
// else if(strcmp(method, "STOR") == 0)//원격지에 파일 저장
// inst_put(target,body);
else if(strcmp(method, "RETR") == 0)//원격지 파일 가져오기
inst_retr(target);
else if(strcmp(method, "DELE") == 0)//원격지 파일 삭제
inst_dele(target);
else if(strcmp(method, "MKD") == 0)//원격지 디렉토리 생성
inst_mkd(target);
else if(strcmp(method, "RMD") == 0)//원격지 디렉토리 제거
inst_rmd(target);
else
{
fputs("\n\n nowhere", stderr);
fputc('\n', stderr);
strcat(sendMsg, "Wrong Message");
}
}
void inst_pwd()
{
strcat(sendMsg,"Working Directory : ");
strcat(sendMsg, workingPath);
return;
}
void inst_cwd(char *target)
{
char fullPath[500] = "";
strcat(fullPath, homePath);
strcat(fullPath, target);
DIR *dir_ptr;
if ( ( dir_ptr = opendir( fullPath ) ) == NULL )
{
strcat(sendMsg, "Please enter correct path");
return;
}
memset(workingPath, 0 , sizeof(char)*500);
strcat(workingPath, target);
strcat(sendMsg, workingPath);
return;
}
void inst_list()
{
char fileList[200] = "";
char fullPath[500] = "";
strcat(fullPath, homePath);
strcat(fullPath, workingPath);
DIR *dir_ptr;
struct dirent *direntp; /* each entry */
struct stat info;
if ( ( dir_ptr = opendir( fullPath ) ) == NULL )
printf("ls1: cannot open %s\n", fullPath);
else
{
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
{
if( stat(fullPath, &info) != -1 )
{
if(direntp->d_type != DT_DIR)
{
strcat(fileList, direntp->d_name);
strcat(fileList, "\n");
}
}
}
closedir(dir_ptr);
}
strcat(sendMsg,"File List : \n");
strcat(sendMsg,fileList);
return;
}
void inst_nlst()
{
char fileList[200] = "";
char fullPath[500] = "";
strcat(fullPath, homePath);
strcat(fullPath, workingPath);
DIR *dir_ptr;
struct dirent *direntp; /* each entry */
struct stat info;
if ( ( dir_ptr = opendir( fullPath ) ) == NULL )
printf("ls1: cannot open %s\n", fullPath);
else
{
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
{
if( stat(fullPath, &info) != -1 )
{
if(direntp->d_type == DT_DIR)
{
strcat(fileList, direntp->d_name);
strcat(fileList, "\n");
}
}
}
closedir(dir_ptr);
}
strcat(sendMsg,"Directory List : \n");
strcat(sendMsg,fileList);
return;
}
void inst_dele(char *target)
{
char inst[1024] = "";
char path[1024] = "";
FILE *file = NULL;
mode_t file_mode;
struct stat file_info;
strcat(path, homePath);
strcat(path, target);
if(stat(path,&file_info) == -1)
{
strcat(sendMsg, "No such a file\n");
return;
}
file_mode = file_info.st_mode;
if (S_ISDIR(file_mode))
{//디렉토리 파일인 경우
strcat(sendMsg, "Error: The target is Directory\n");
return;
}
else if (S_ISREG(file_mode))
{//일반 파일인 경우
strcat(inst, "rm ");
strcat(inst, path);
if( system(inst) != -1 )
strcat(sendMsg, "The file is removed");
else
strcat(sendMsg, "Fail to remove the file\n");
return;
}
}
void inst_rmd(char *target)
{
char inst[1024] = "";
char path[1024] = "";
FILE *file = NULL;
mode_t file_mode;
struct stat file_info;
strcat(path, homePath);
strcat(path, target);
if(stat(path,&file_info) == -1)
{
strcat(sendMsg, "No such a file\n");
return;
}
file_mode = file_info.st_mode;
if (S_ISDIR(file_mode))//디렉토리 파일인 경우
{
int n=0;
struct dirent* d;
DIR* dir = opendir(path);
while((d = readdir(dir))!=NULL) n++;
if(n>2)
{
strcat(sendMsg, "The Directory is not empty\n");
return;
}
closedir(dir);
strcat(inst, "rmdir ");
strcat(inst, path);
if( system(inst) != -1 )
strcat(sendMsg, "The directory is removed");
else
strcat(sendMsg, "Fail to remove the Directory\n");
return;
}
else if (S_ISREG(file_mode))
{//일반 파일인 경우
strcat(sendMsg, "Error: The target is File\n");
return;
}
}
void inst_mkd(char *target)
{
char path[100] = "";
char inst[200] = "";
strcat(path, homePath);
strcat(path, target);//home path와 사용자가 입력한 path를 더해준다
strcat(inst, "mkdir -p ");//중간 폴더까지 모두 생성하도록 -p 옵션 사용
strcat(inst, path);
if(system(inst) != -1)
{
strcat(sendMsg, "The Directory is created");
}
return;
}
void inst_retr(char *target)
{
int read_cnt;
char buf[BUF_SIZE];
FILE * fp;
fp=fopen("../../usr/ftp/test.c", "rb");
while(1)
{
read_cnt=fread((void*)buf, 1, BUF_SIZE, fp);
if(read_cnt<BUF_SIZE)
{
write(clnt_sock, buf, read_cnt);
break;
}
write(clnt_sock, buf, BUF_SIZE);
}
puts("fin file data");
fclose(fp);
strcat(sendMsg,"END");
}
//int inst_delete(char *target)
//{
// char inst[1024] = "";
// char path[1024] = "../../usr/http";
// FILE *file = NULL;
// mode_t file_mode;
// struct stat file_info;
//
// strcat(path, target);
//
// if(stat(path,&file_info) == -1)
// {
// strcat(sendMessage, "HTTP/1.1 404 Not Found\n");
// return 0;
// }
//
// file_mode = file_info.st_mode;
// if (S_ISDIR(file_mode))
// {//디렉토리 파일인 경우
// strcat(inst, "rm -rf ");
// strcat(inst, path);
// system(inst);
// strcat(sendMessage, "HTTP/1.1 200 OK\n");
// return 0;
// }
// else if (S_ISREG(file_mode))
// {//일반 파일인 경우
// strcat(inst, "rm -f ");
// strcat(inst, "/usr/http");
// strcat(inst, path);
// system(inst);
// strcat(sendMessage, "HTTP/1.1 200 OK\n");
// return 0;
// }
//}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
module for File Transfer
void inst_retr(char *target)
{
data_sock = socket(PF_INET, SOCK_STREAM,0);
if(data_sock == -1)
error_handling("Data socket() error");
memset(&data_adr, 0, sizeof(data_adr));
data_adr.sin_family = AF_INET;
data_adr.sin_addr.s_addr=htonl(INADDR_ANY);
data_adr.sin_port=htons(12501);
if(bind(data_sock, (struct sockaddr*)&data_adr, sizeof(data_adr))==-1)
error_handling("data bind() error");
else
error_handling("bind ok");
if(listen(data_sock, 5)==-1)
error_handling("listen() error");
datcl_adr_sz=sizeof(datcl_adr);
clnt_sock=accept(data_sock, (struct sockaddr*)&datcl_adr, &datcl_adr_sz);
if(clnt_sock==-1)
error_handling("accept() error");
else
printf("Connected data client \n");
int read_cnt;
char buf[BUF_SIZE];
char eof = EOF;
FILE * fp;
fp=fopen("../../usr/ftp/test.c", "rb");
while(1)
{
read_cnt=fread((void*)buf, 1, BUF_SIZE, fp);
if(read_cnt<BUF_SIZE)
{
write(clnt_sock, buf, read_cnt);
break;
}
write(clnt_sock, buf, BUF_SIZE);
puts("file data");
}
shutdown(clnt_sock, SHUT_WR);
puts("fin file data");
fclose(fp);
strcat(sendMsg,"END");
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 1024
void error_handling(char *message);
void inst_retr();
int sock;
int main(int argc, char *argv[])
{
int datasock;
char message[BUF_SIZE];
char tmp[BUF_SIZE];
char dataMsg[BUF_SIZE];
char method[BUF_SIZE];
char target[BUF_SIZE];
int str_len;
struct sockaddr_in serv_adr, data_adr;
if(argc!=3) {
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
sock=socket(PF_INET, SOCK_STREAM, 0);
datasock=socket(PF_INET, SOCK_STREAM, 0);
if(sock==-1)
error_handling("socket() error");
if(datasock==-1)
error_handling("Data socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
memset(&data_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
serv_adr.sin_port=htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("connect() error!");
else
puts("Connected...........");
// data_adr.sin_family=AF_INET;
// data_adr.sin_addr.s_addr=htons(atoi(argv[1]));
// data_adr.sin_port=htons(13230);
//
// if(connect(datasock, (struct sockaddr*)&data_adr, sizeof(data_adr)) == -1)
// error_handling("data connect() error!");
// else
// puts("Connected.....data...");
str_len=read(sock, message, BUF_SIZE-1);
message[str_len]=0;
printf("%s\n", message);
while(1)
{
fputs("Input message(Q to quit): ", stdout);
fgets(message, BUF_SIZE, stdin);
message[strlen(message)-1] = 0;
if(strcmp(message,"QUIT") == 0)
break;
strcpy(tmp,message);
sscanf(tmp, "%s %s",method, target);
if(strcmp(method, "RETR") == 0)
{
write(sock, message, strlen(message));
inst_retr();
str_len=read(sock, message, BUF_SIZE-1);
message[str_len]=0;
printf("Message from server: %s\n", message);
memset(message, 0, sizeof(char)*BUF_SIZE);
memset(method, 0, sizeof(char)*BUF_SIZE);
memset(target, 0, sizeof(char)*BUF_SIZE);
continue;
}
// if(strcmp(message,"data") == 0)
// {
// write(sock, message, strlen(message));
//
//
// str_len=read(datasock, message, BUF_SIZE-1);
// message[str_len]=0;
// printf("Message from server: %s", message);
//
//
// }
write(sock, message, strlen(message));
str_len=read(sock, message, BUF_SIZE-1);
message[str_len]=0;
printf("Message from server: %s\n", message);
memset(message, 0, sizeof(char)*BUF_SIZE);
memset(method, 0, sizeof(char)*BUF_SIZE);
memset(target, 0, sizeof(char)*BUF_SIZE);
}
close(sock);
return 0;
}
void inst_retr()
{
char buf[BUF_SIZE];
int read_cnt;
FILE *fp;
fp=fopen("../../usr/ftp/receive.dat", "wb");
while((read_cnt=read(sock, buf, BUF_SIZE ))!=0)
fwrite((void*)buf, 1, read_cnt, fp);
puts("Received file data");
fclose(fp);
return;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
module for file Recieving
void inst_retr()
{
datasock=socket(PF_INET, SOCK_STREAM, 0);
if(datasock==-1)
error_handling("Data socket() error");
if(connect(datasock, (struct sockaddr*)&data_adr, sizeof(data_adr)) == -1)
error_handling("data connect() error!");
else
puts("Connected.....data...");
char buf[BUF_SIZE];
int read_cnt;
FILE *fp;
fp=fopen("../../usr/ftp/receive.dat", "wb");
while((read_cnt=read(sock, buf, BUF_SIZE ))!=0)
fwrite((void*)buf, 1, read_cnt, fp);
puts("Received file data");
fclose(fp);
return;
}
Related
I've read all the related answers but could not find the reason why this is happening. I've tried replacing close() to shutdown and then close and more but still the same.
All I need is to be able to browse to my server and when asking a file it'll return its content and when asking a directory it will return a list of whats in it. this all WORKS, except for the RST packet.
Can anyone help?
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#define HTTP_BAD_REQUEST "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>File Not Found</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_GOOD_REQUEST "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Results</TITLE>\n</HEAD>\n<BODY>\n"
#define HTTP_ERROR "HTTP/1.1 500 Internal Server Error\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Internal Server Error!</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_NOT_IMPLEMENTED "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Method Not Implemented</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_END "<br/></BODY></HTML>\n\0"
#define MAX_REQUEST_SIZE 1024
int send_response(int fd, char* filepath)
{
struct stat statbuf;
int iofd;
int check = 1;
char buf[1024];
if ( stat(filepath,&statbuf) < 0 )
{
printf("Path not found\n");
send(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST), 0);
return -1;
}
else
{
if(S_ISDIR(statbuf.st_mode))
{
//directory
DIR *dp;
struct dirent *ep;
dp = opendir (filepath);
if (dp == NULL)
{
printf("Error opening directory\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
ep = readdir (dp);
while (ep != NULL)
{
send(fd, ep->d_name, strlen(ep->d_name), 0);
send(fd, "<br/>", strlen("<br/>"), 0);
ep = readdir (dp);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
(void) closedir (dp);
return 0;
}
else if (S_ISREG(statbuf.st_mode))
{
//regular file
iofd = open(filepath, O_RDONLY);
if( iofd < 0 )
{
printf("Error opening file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
while ( check > 0)
{
check = read(iofd,buf,sizeof(buf));
if (check < 0)
{
printf("Error reading file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(iofd);
return -1;
}
else if (check == 0)
break;
else
send(fd, buf, strlen(buf), 0);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
close(iofd);
return 0;
}
}
}
int process(int fd, char* header)
{
char npath[MAX_REQUEST_SIZE];
char *eol = strchr(header, '\r');
// split header to get path and method
char *method = strtok(header, " ");
char *path = strtok(NULL, " ");
char *http = strtok(NULL, " ");
if( eol != NULL )
*eol = '\0';
if( strcmp(method, "GET") || (strcmp(method, "POST")))
{
if( path[0] == '/' && path[1] == '\0' )
{
path ="/";
}
else if( path[0] == '/' )
{
snprintf(npath, MAX_REQUEST_SIZE, "%s", path);
path = npath;
}
return send_response(fd, path);
}
else
{
send(fd, HTTP_NOT_IMPLEMENTED, strlen(HTTP_NOT_IMPLEMENTED), 0);
return -1;
}
}
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
int n;
while ((i < size - 1) && (c != '\n'))
{
n = recv(sock, &c, 1, 0);
if (n > 0)
{
if (c == '\r')
{
n = recv(sock, &c, 1, MSG_PEEK);
if ((n > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
}
buf[i] = c;
i++;
}
else
c = '\n';
}
buf[i] = '\0';
return(i);
}
int service(int fd)
{
char buffer[MAX_REQUEST_SIZE];
if (get_line(fd, buffer, MAX_REQUEST_SIZE) <= 0)
{
printf("Error reading from socket");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
return process(fd, buffer);
}
void cleanup( int signal )
{
int pid;
while(1)
{
pid = waitpid(-1, NULL, WNOHANG);
if( pid < 0 )
break;
else if( pid == 0 )
break;
}
exit(0);
}
int main(int argc, char *argv[])
{
int port = 80;
int max_requests;
struct sigaction finish;
finish.sa_handler = &cleanup;
sigaction( SIGINT, &finish, NULL );
if ((argc == 1) || (argc > 3))
{
printf("Usage Error: wrong amount of arguments to main");
return -1;
}
else if (argc == 3)
{
max_requests = strtol(argv[1], NULL, 0);
port = strtol(argv[2], NULL, 0);
}
else
max_requests = strtol(argv[1], NULL, 0);
struct sockaddr_in servaddr;
int serversock = socket(AF_INET, SOCK_STREAM, 0);
int on = 1;
if( serversock < 0 )
{
printf("Error creating socket: %s\n", strerror(errno));
return 1;
}
if( setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
printf("Error tweaking socket options: %s\n", strerror(errno));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if( bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
printf("Error binding to server address: %s\n", strerror(errno));
return 1;
}
if( listen(serversock, max_requests) < 0 )
{
printf("Error using listen(): %s\n", strerror(errno));
return 1;
}
while(1)
{
int clientsock, pid, childstatus;
//server shall now wait for a new connection
clientsock = accept(serversock, NULL, NULL);
if( clientsock < 0 )
{
printf("Error using accept(): %s\n", strerror(errno));
return 1;
}
pid = fork();
if( pid < 0 )
{
printf("Error using fork(): %s\n", strerror(errno));
send(clientsock, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(clientsock);
continue;
}
else if( pid == 0 )
{
shutdown(serversock, 2);
if (service(clientsock) != 0 )
printf("error in service\n");
if (shutdown(clientsock, SHUT_WR) != 0)
{
printf("Error shutting the socket down: %s\n", strerror(errno));
return -1;
}
close(clientsock);
return 0;
}
pid = waitpid(-1, NULL, WNOHANG);
if( pid < 0 )
{
printf("Error using waitpid(): %s\n", strerror(errno));
break;
}
close(clientsock);
}
return 999;
}
the following code:
cleanly compiles
properly outputs error messages to stderr
properly outputs a 'usage' message when not correct number of command line parameters
'should' operate correctly with connections after the first
caveat: not thoroughly tested.
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#define HTTP_BAD_REQUEST "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>File Not Found</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_GOOD_REQUEST "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Results</TITLE>\n</HEAD>\n<BODY>\n"
#define HTTP_ERROR "HTTP/1.1 500 Internal Server Error\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Internal Server Error!</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_NOT_IMPLEMENTED "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Method Not Implemented</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_END "<br/></BODY></HTML>\n\0"
#define MAX_REQUEST_SIZE 1024
int send_response(int fd, char* filepath)
{
struct stat statbuf;
int iofd; // file descriptor
ssize_t readStatus = 1;
char buf[ MAX_REQUEST_SIZE ];
if ( stat(filepath,&statbuf) < 0 )
{
perror( "stat for file failed" );
//printf("Path not found\n");
send(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST), 0);
return -1;
}
else
{ // path found
if(S_ISDIR(statbuf.st_mode))
{
//directory
DIR *dp;
struct dirent *ep;
dp = opendir (filepath);
if (dp == NULL)
{
fprintf( stderr, "Error opening directory\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
// implied else, opendir successful
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
ep = readdir (dp);
while (ep != NULL)
{
send(fd, ep->d_name, strlen(ep->d_name), 0);
send(fd, "<br />", strlen("<br />"), 0);
ep = readdir (dp);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
closedir (dp);
return 0;
}
else if (S_ISREG(statbuf.st_mode))
{ //regular file
iofd = open(filepath, O_RDONLY);
if( iofd < 0 )
{
//fprintf(stderr, "Error opening file\n");
perror( "open failed" );
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
// implied else, open successful
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
while ( readStatus > 0)
{
readStatus = read(iofd,buf,sizeof(buf));
if (readStatus < 0)
{
perror( "read of file failed");
//printf("Error reading file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(iofd);
return -1;
}
else if (readStatus == 0) // EOF or signal
break;
else // transmit line from file
send(fd, buf, strlen(buf), 0);
} // end while
send(fd, HTTP_END, strlen(HTTP_END), 0);
close(iofd);
return 0;
}
}
return -2;
}
int process(int fd, char* header)
{
// split header to get path and method
char *method = strtok(header, " ");
char *path = strtok(NULL, " ");
//char *http = strtok(NULL, " ");
// if trailing newline, replace with NUL byte
char *eol = NULL;
if( NULL == (eol = strchr(header, '\r') ) )
*eol = '\0';
if( strcmp(method, "GET") || (strcmp(method, "POST")))
{
return send_response(fd, path);
}
else
{
send(fd, HTTP_NOT_IMPLEMENTED, strlen(HTTP_NOT_IMPLEMENTED), 0);
return -1;
}
} // end function: process
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
ssize_t recvStatus;
while ( (i < (size - 1)) && (c != '\n') )
{
recvStatus = recv(sock, &c, 1, 0);
if ( recvStatus > 0)
{ // then some bytes read
if (c == '\r')
{
recvStatus = recv(sock, &c, 1, MSG_PEEK);
if ((recvStatus > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
} // endif
buf[i] = c;
i++;
}
else
{
c = '\n';
} // endif
} // end while
// terminate the char array
buf[i] = '\0';
return(i);
} // end function: get_line
int service(int fd)
{
char buffer[MAX_REQUEST_SIZE];
if (get_line(fd, buffer, MAX_REQUEST_SIZE) <= 0)
{
fprintf( stderr, "Error reading from socket");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
return process(fd, buffer);
} // end function: service
void cleanup( int signal )
{
(void)signal;
pid_t pid;
while(1)
{
pid = waitpid(-1, NULL, WNOHANG);
if( pid <= 0 )
break;
}
exit(0);
} // end function: cleanup
int main(int argc, char *argv[])
{
uint16_t port = 80;
int max_requests;
struct sigaction finish;
finish.sa_handler = &cleanup;
sigaction( SIGINT, &finish, NULL );
if ( (argc != 3) && (argc != 2) )
{
fprintf( stderr, "USAGE: %s <maxConnections> [<portToUse>]\n", argv[0]);
//printf("Usage Error: wrong amount of arguments to main");
return -1;
}
max_requests = (int)strtol(argv[1], NULL, 0);
if( 3 == argc )
{
port = (uint16_t)strtol(argv[2], NULL, 0);
}
int serversock = socket(AF_INET, SOCK_STREAM, 0);
if( serversock < 0 )
{
printf("Error creating socket: %s\n", strerror(errno));
return 1;
}
int on = 1;
if( setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
{
perror( "setsockopt for SO_REUSEADDR failed" );
//printf("Error tweaking socket options: %s\n", strerror(errno));
}
if( setsockopt(serversock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0 )
{
perror( "setsockopt for SO_KEEPALIVE failed" );
//printf("Error tweaking socket options: %s\n", strerror(errno));
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if( bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
perror( "bind failed" );
//printf("Error binding to server address: %s\n", strerror(errno));
return 1;
}
if( listen(serversock, max_requests) < 0 )
{
perror( "listen failed" );
//printf("Error using listen(): %s\n", strerror(errno));
return 1;
}
while(1)
{
int clientsock;
pid_t pid;
//int childstatus;
//server shall now wait for a new connection
clientsock = accept(serversock, NULL, NULL);
if( clientsock < 0 )
{
perror( "accept failed" );
//printf("Error using accept(): %s\n", strerror(errno));
close( serversock );
return 1;
}
pid = fork();
switch( pid )
{
case -1: // fork failed
fprintf(stderr, "Error using fork(): %s\n", strerror(errno));
send(clientsock, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(clientsock);
break;
case 0: // in child process
//shutdown(serversock, 2);
if (service(clientsock) != 0 )
{
fprintf( stderr, "error in service\n");
}
close(clientsock);
return 0;
break;
default: // in parent process
pid = waitpid( -1, NULL, WNOHANG);
close(clientsock);
break;
} // end switch
} // end while
return 0;
} // end function: main
The goal of this server is to transfer small files, in a relatively simple manner. I have finished the code and it all compiles without error, and when I try to run it, the server side has no problems, but the client side gives an error in the socket binding and a segmentation fault. I was wondering what in the code was causing these problems.
Server:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
#include <crypt.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <netinet/ip.h>
void timestamp_ss()
{
time_t current_time;
char* log_time;
log_time = ctime(¤t_time);
log_file_ss(log_time);
}
send_data(int sockfd, char info_to_send)
{
char eof_buffer[4] = "\EOF";
int sent_data, data_to_send;
data_to_send = strlen(&info_to_send);
while(data_to_send > 0)
{
sent_data = send(sockfd, &info_to_send, data_to_send, 0);
if(sent_data == -1)
perror("There was a problem in the sending of data!");
data_to_send -= sent_data;
info_to_send += sent_data;
}
send(sockfd, eof_buffer, 4, 0);
}
int recv_data(int sockfd, char *dest_buffer)
{
#define EoF "\EOF"
unsigned char *buffer;
int eof_match = 0, eof_size = 2;
buffer = dest_buffer;
while(recv(sockfd, buffer, 1, 0) == 1)
{
if(*buffer == EoF[eof_match])
{
eof_match++;
if(eof_match = eof_size)
{
*(buffer+1-eof_size) = '\0';
return strlen(dest_buffer);
}
else
{
eof_match = 0;
}
}
buffer++;
}
return 0;
}
int password_ss(char *password_attempt, char *password_actual)
{
char key[] = { "ZjQXStSi" };
char ivec[] = {"7eNP3U1b" };
char des_dec[] = { "DES_DECRYPT" };
char des_hw[] = { "DES_HW" };
int l, i;
l = strlen(password_attempt);
i = cbc_crypt(key, password_attempt, l, *des_dec | *des_hw, ivec);
if(i < 0)
error_escape("In decryption");
if(password_attempt == password_actual)
return 1;
else
return 0;
}
int log_file_ss(char *log_message)
{
char logfile[]= "/Server/log/C-File-Transfer-Server-Log";
int log_fd, len;
log_fd = open(logfile, O_WRONLY | O_APPEND | O_CREAT);
len = strlen(log_message);
write(log_fd, log_message, len);
}
void file_to_client_ss(int sockfd, struct sockaddr_in *client_addr_ptr)
{
char file_req_c[128];
char buffer[10000];
char files[256];
char pass_attempt[128];
char *error_403[20] = { "Error 403: Forbidden" };
char *error_404[25] = { "Error 404: File Not Found" };
char *pass_path[20] = { "/server/log/PASSWORD" };
char *pass_req[50] = { "This File Requires A Password, Please Enter It Now" };
char *no_pass[37] = { "This File Does Not Require A Password" };
char *username;
char *file_s;
char *string;
char *file1_path[26] = { "/server/received_files/r_w" };
char *file2_path[24] = { "/server/received_files/r" };
char *file3_path[24] = { "/server/received_files/n" };
char file_data;
FILE *cs, *ps;
int file1, file2, file3, file_test, pass;
cs = fopen(file_req_c, "r");
recv_data(sockfd, username);
chdir("/server/log/PASSWORD");
ps = fopen(username, "r");
fread(files, 1, file_size(ps), ps);
chdir("/server");
recv_data(sockfd, file_req_c);
file_test = file_exist(file1_path, file_req_c);
if(file_test = -1)
{
file_test = file_exist(file2_path, file_req_c);
if(file_test = -1)
{
file_test = file_exist(file3_path, file_req_c);
if(file_test = -1)
{
error_escape("Opening file request from client");
}
else
{
send_data(sockfd, **pass_req);
recv_data(sockfd, pass_attempt);
pass = password_ss(pass_attempt, files);
if(pass == 0)
{
send_data(sockfd, **error_403);
error_escape("Wrong Password");
}
else
{
if(file_exist(pass_path, username) == 0)
send_data(sockfd, *file_req_c);
else
errror_escape("Error in sending file");
}
}
}
else
{
chdir(*file2_path);
file_data = fread(buffer, 1, file_size(cs), cs);
send_data(sockfd, **no_pass);
send_data(sockfd, file_data);
}
}
else
{
chdir(*file1_path);
file_data = fread(buffer, 1, file_size(cs), cs);
send_data(sockfd, **no_pass);
send_data(sockfd, file_data);
}
}
int file_size(FILE *stream)
{
off_t file_len;
fseek(stream, 0, SEEK_END);
file_len = ftell(stream);
fclose(stream);
return file_len;
}
int file_exist(char *file_path, char *file_name)
{
DIR *dp;
FILE *fc;
struct dirent *ep;
dp = opendir(file_path);
if(dp == NULL)
perror("Opening path");
else
chdir(file_path);
closedir(dp);
fc = fopen(file_name, "r");
if(fc == NULL)
{
perror("Opening file");
return(-1);
}
else {
return(0);
}
}
error_escape(char *problem)
{
char error_message[256];
strcpy(error_message, "! There Has Been An Error !");
strncat(error_message, problem, 173);
perror("Error: ");
log_file_ss(error_message);
timestamp_ss();
exit(-1);
}
void file_accept_ss(int sockfd, struct sockaddr_in *client_addr_ptr)
{
char client_request[512], username[256], file_content[8192], buf[8192];
char *client_r_w[26] = { "/server/received_files/r_w" };
char *client_r[24] = { "/server/received_files/r" };
char *client_n[24] = { "/server/received_files/n" };
char *search_string_read[6] = { "O_READ" };
char *search_string_w[14] = { "O_READANDWRITE" };
char *password_path[20] = { "/server/log/PASSWORD" };
char *mkdir[37] = { "/server/log/PASSWORD" };
char *ret;
char file_data, recv_i;
char password[256];
int change_dir_test, recv_check;
FILE *fn, *Ps;
recv_data(sockfd, username);
recv_data(sockfd, password);
strcat(*mkdir, username);
strcat(*mkdir, password);
fn = fopen(*mkdir, "a");
chdir(*password_path);
Ps = fopen(*mkdir, "a");
chdir("/server");
recv_i = fread(buf, 1, file_size(fn), fn);
recv_check = recv_data(sockfd, &recv_i);
if(recv_check = -1)
error_escape("! There Was An Error In The Receiving Of The File From The Client !");
fread(file_content, 8, file_size(fn), fn);
ret = strstr(file_content, *search_string_read);
if(ret = NULL)
{
change_dir_test = chdir(*client_n);
if(change_dir_test = -1)
error_escape("! There Was An Error In The Changing Of Directories !");
else
{
file_data = fread(buf, 1, file_size(Ps), Ps);
recv_data(sockfd, &file_data);
chdir(*client_n);
strcat(*client_n, username);
rename(username, *client_n);
}
}
if(ret = *search_string_read)
{
change_dir_test = chdir(*client_r);
if(change_dir_test = -1)
error_escape("! There Was An Error In The Changing Of Directories !");
else
{
chdir(*client_r);
rename(username, *client_r);
}
}
if(ret = *search_string_w)
{
change_dir_test = chdir(*client_r_w);
if(change_dir_test = -1)
error_escape("! There Was An Error In The Changing Of Directories !");
else
{
chdir(*client_r_w);
rename(username, *client_r_w);
}
}
log_file_ss("Client:");
log_file_ss(username);
timestamp_ss();
}
int main(void)
{
struct sockaddr_in server, client;
int sockfd, bind_test, listen_test, client_sockfd, sin_size;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
error_escape("Making Socket");
server.sin_family = AF_INET;
server.sin_port = htons(80);
server.sin_addr.s_addr = INADDR_ANY;
bind_test = bind(sockfd, (struct sockaddr *)&server, sizeof(server));
if(bind_test < 0)
error_escape("Binding Socket");
listen_test = listen(sockfd, 20);
if(listen_test < 0)
error_escape("Listening");
while(1)
{
sin_size = sizeof(struct sockaddr_in);
client_sockfd = accept(sockfd, (struct sockaddr *)&client, &sin_size);
file_accept_ss(client_sockfd, &client);
file_to_client_ss(client_sockfd, &client);
}
shutdown(client_sockfd, SHUT_RDWR);
return 0;
}
Client:
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
#include <crypt.h>
#include <sys/socket.h>
#include <netinet/ip.h>
send_data(int sockfd, char info_to_send)
{
char eof_buffer[4] = "\EOF";
int sent_data, data_to_send;
data_to_send = strlen(&info_to_send);
while(data_to_send > 0)
{
sent_data = send(sockfd, &info_to_send, data_to_send, 0);
if(sent_data == -1)
perror("There was a problem in the sending of data!");
data_to_send -= sent_data;
info_to_send += sent_data;
}
send(sockfd, eof_buffer, 4, 0);
}
send_file_cs(int sockfd)
{
char file_buffer[4096], file_name[256];
char name, username, password;
char *search_st, file_data, *file_location;
int perm_choice, password_max = 20, ch;
off_t size_of_file;
FILE *fp;
printf("%s\n", "Please enter the path to file you would like to move to server:");
scanf("%s", &file_location);
ch = chdir(file_location);
if(ch == -1)
perror("! There Has Been An Error In The Directory Path !");
else
chdir(file_location);
printf("%s\n", "Now Enter The Name Of The File You Would Like To Transfer:");
printf("%s\n", "! Warning, The File May Not Exceed 4 kilobytes !");
scanf("%s", &name);
printf("%s", "What would you like the username for this file to be?");
name = *file_name;
size_of_file = file_size(fp);
if(size_of_file > 4096)
printf("! The File Is Greater Than 4 Kilobytes !");
fp = fopen(file_name, "r+");
printf("%s\n", "What Permissions Would You Like The File To Have?\n (1) For Other Clients To See The File\n (2) For Other CLients To See But Not Be Able To Access\n (3) Other Clients Cannot See Or Access The File");
scanf("%d", &perm_choice);
if(perm_choice > 3 || perm_choice < 1)
perror("! Incorrect Permissions !");
if(perm_choice = 1)
{
search_st = "O_READ";
fopen(file_name, "a");
fwrite(search_st, 1, strlen(search_st), fp);
}
if(perm_choice = 2)
{
search_st = "O_READANDWRITE";
fopen(file_name, "a");
fwrite(search_st, 1, strlen(search_st), fp);
}
if(perm_choice = 3)
{
search_st = "O_NOACCESS";
fopen(file_name, "a");
fwrite(search_st, 1, strlen(search_st), fp);
printf("%s", "Please enter a password");
scanf("%s", &password);
send_data(sockfd, password);
}
file_data = fread(file_buffer, 1, 4096, fp);
send_data(sockfd, file_data);
}
int recv_data(int sockfd, char *dest_buffer)
{
#define EoF "\EOF"
unsigned char *buffer;
int eof_match = 0, eof_size = 2;
buffer = dest_buffer;
while(recv(sockfd, buffer, 1, 0) == 1)
{
if(*buffer == EoF[eof_match])
{
eof_match++;
if(eof_match = eof_size)
{
*(buffer+1-eof_size) = '\0';
return strlen(dest_buffer);
}
else
{
eof_match = 0;
}
}
buffer++;
}
return 0;
}
int password_cs(int max_length, int sockfd)
{
char salt[] = { "ZjQXStSi" };
char ivec[] = { "7eNP3U1b" };
char des_enc[] = { "DES_ENCRYPT" };
char des_hw[] = { "DES_HW" };
char password;
char *ret, *ret2;
int l, i;
printf("%s", "Please set your password:");
scanf("%s", &password);
l = strlen(&password);
if(l > max_length)
printf("%s : %d", "Password must be less than", max_length);
i = cbc_crypt(salt, password, l, *des_enc | *des_hw, ivec);
if(i < 0)
perror("In erncryption");
send_data(sockfd, password);
return 0;
}
int file_size(FILE *stream)
{
off_t file_len;
fseek(stream, 0, SEEK_END);
file_len = ftell(stream);
fclose(stream);
return file_len;
}
int file_exist(char *file_path, char *file_name)
{
DIR *dp;
FILE *fc;
struct dirent *ep;
dp = opendir(file_path);
if(dp == NULL)
perror("Opening path");
else
chdir(file_path);
closedir(dp);
fc = fopen(file_name, "r");
if(fc == NULL)
{
perror("Opening file");
return(-1);
}
else {
return(0);
}
}
void client_request_file_cs(int sockfd)
{
char password_buf[128], file[4096], recv_file[256];
char *requires[16] = { "Requires" };
char *str, *restr, *file_contents, *name2, *path, *rebuf;
char file_req, password, name, username;
int test;
FILE *re;
printf("%s\n", "What file would you like from the server?");
scanf("%s", &file_req);
printf("%s", "What is the user name associated with the file?");
scanf("%s", &username);
send_data(sockfd, username);
printf("%s\n", "Where Would You Like The File To Be Put, Please Enter The Path:");
scanf("%s", &path);
test = chdir(path);
if(test == -1)
printf("%s\n", "Invalid Path");
printf("%s\n", "What Would You Like To Call The File?");
scanf("%s", &name);
name2 = &name;
re = fopen(name2, "w");
fread(file_contents, 1, file_size(re), re);
send_data(sockfd, file_req);
recv_data(sockfd, password_buf);
printf("%s\n", password_buf);
str = strstr(password_buf, *requires);
if(str == NULL)
recv_data(sockfd, file);
else
{
scanf("%s", &password);
send_data(sockfd, password);
}
recv_data(sockfd, rebuf);
fwrite(rebuf, 1, sizeof(rebuf), re);
fclose(re);
restr = strstr(file_contents, "error_");
if(restr != NULL)
printf("%s\n", re);
}
int main(void)
{
struct sockaddr_in client, server_addr;
int sockfd, connected;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
printf("%s", "Error opening socket");
connected = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if(connected == -1)
printf("%s", "Error binding socket");
send_file_cs(sockfd);
client_request_file_cs(sockfd);
shutdown(sockfd, SHUT_RDWR);
return 0;
}
Thank you in advance for any help.
Among other valid questions/points in the comments, memory allocation in your code may be contributing to your segmentation fault...
char *file_location (and others) are being used as if memory has been allocated.
Your use of the variable in scanf("%s", &file_location); before allocating memory invokes undefined behavior, and most likely will be (at least partially) responsible for your run-time errors.
add memory before the scanf statement. Here are two examples of how to do that:
1) Create heap memory (using [m][c]alloc):
char *file_location;
file_location = malloc(MAX_FILENAME_LEN);//or your systems value for max directory length
if(file_location)
{
scanf("%s", &file_location);
...
2) Use stack memory: (point your pointer to a place with memory)
char file_name[256];
char *file_location = file_name;
file_location = file_name;
scanf("%s", &file_location);
But the simplest way (if there is nothing constraining you to use a pointer) would be to just create the variable on the stack and use it in scanf(...):
char file_location[256];
scanf("%s", &file_location);
There are other variables (besides file_location) in your example code that need memory before use. Remember to free any variable with memory created on the heap when finished using.
bind error
There is no bind error here. The client doesn't do a bind at all. It gets an error connecting the socket, and then misleadingly prints 'bind error'.
The connect error is because you aren't initializing the address field of the target you're trying to connect to.
NB you don't need \EOF. recv() will return zero when the peer disconnects, which you aren't checking for. You aren't checking it for errors either. This is very strange code. – EJP 19 mins ago
i have a server and a client and want to send a file from the client to the server, by using Sys V IPC. My Problem is the sending of the file, the server is creating the file but than stops at msgrcv_3 Invalid argument (last do while in the server). Maybe somebody have an idea.
Snippet of Server:
while(1){
int ausgabe=0;
/* Messageq */
if ((msqid = msgget(server_key, IPC_CREAT|IPC_EXCL|0666)) < 0){
perror("msgget_1");
exit(EXIT_FAILURE);
}
/* Message Empfangen */
if((msreturn = msgrcv(msqid, (void*)&name, sizeof(struct name),0,0))<0){
perror("msgrcv_1");
exit(EXIT_FAILURE);
}
result.exists = FileExists(name.file_name);
printf("%d\n", result.exists);
/* Message Versenden*/
if((msreturn = msgsnd(msqid, (void*)&result, sizeof(struct result),0))<0){
perror("msgsnd_1");
exit(EXIT_FAILURE);
}
if(result.exists == 42){
if((msreturn = msgrcv(msqid, (void*)&data, sizeof(struct data),0,0))<0){
perror("msgrcv_2");
exit(EXIT_FAILURE);
}
creatfile = open(data.file_name, O_WRONLY | O_CREAT| O_EXCL , 0);
if(creatfile == -1){
perror("creratfile");
exit(EXIT_FAILURE);
}
do{
if(msgrcv(msqid, (void*)&msg_body, sizeof(struct msg_body),0,0)<0){
perror("msgrcv_3");
exit(EXIT_FAILURE);
}
buff_blub = write(creatfile, &msg_body.buffer, msg_body.bufsize);
if (buff_blub < 0){
perror("write");
exit(EXIT_FAILURE);
}
ausgabe = ausgabe+msg_body.bufsize;
}
while(ausgabe != data.datasize);
chmod(data.file_name, 0644);
}
}
Snippet of the Client:
strncpy(name.file_name, argv[2], sizeof(name.file_name) - 1);
/* Message Versenden*/
if((msreturn = msgsnd(msqid, (void*)&name, sizeof(struct name),0))<0){
perror("msgsnd");
exit(EXIT_FAILURE);
}
/* Message Empfangen */
if((msreturn = msgrcv(msqid, (void*)&result, sizeof(struct result),0,0))<0){
perror("msgrcv");
exit(EXIT_FAILURE);
}
if(result.exists == 1){
puts("File already exists");
exit(EXIT_FAILURE);
}
else if(result.exists == 42){
file_read = open(argv[1], O_RDONLY);
if (file_read > 0){
if (fstat(file_read, &sb)==-1){
perror("fstat");
return EXIT_FAILURE;
}
strncpy(data.file_name, argv[2], sizeof(data.file_name) - 1);
data.datasize = sb.st_size;
data.c_pid = getpid();
if((msreturn = msgsnd(msqid, (void*)&data, sizeof(struct data),0))<0){
perror("msgsnd");
exit(EXIT_FAILURE);
}
while((file_buffer = read (file_read, &msg_body.buffer, BUF_SIZE)) > 0){
msg_body.bufsize = file_buffer;
msg_body.prio = 2;
if((msreturn = msgsnd(msqid, (void*)&msg_body, sizeof(struct msg_body),0))<0){
perror("msgsnd");
exit(EXIT_FAILURE);
}
}
close(file_read);
}
}
return 1;
}
the structur:
#include <unistd.h>
#if !defined(__MSGBSP_H)
#define __MSGBSP_H
#define BUF_SIZE 1024
struct data {
char file_name[255];
ssize_t datasize;
long c_pid;
};
struct name {
char file_name[255];
};
struct result {
int exists;
};
struct header {
int size;
};
struct msg_body {
long prio;
ssize_t bufsize;
char buffer[BUF_SIZE];
};
#endif
#include <winsock2.h>
#include <stdio.h>
const int PORT = 6667;
const char *SERVER = "irc.freenode.org";
const char *CHAN = "#channela";
const char *NICK = "loveMilk";
const int MAX_BUFF_SIZE = 512;
int sock_conn(SOCKET *socketn, const char *HOST, int portn);
int sock_send(SOCKET *socketn, char* msg, ...);
int main(int argc, char *argv[])
{
WSADATA wsadata;
char buff[MAX_BUFF_SIZE];
char oBuff[MAX_BUFF_SIZE];
int buffRec;
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
return 0;
SOCKET sock;
if(sock_conn(&sock, SERVER, PORT) != 0)
{
WSACleanup();
return 0;
}
printf("connected.\n");
sock_send(&sock, "USER %s \"\" \"127.0.0.1\" :%s\r\n", NICK, NICK);
sock_send(&sock, "NICK %s\r\n", NICK);
Sleep(100);
sock_send(&sock, "JOIN %s\r\n", CHAN);
printf("Joined channel.\n");
while(1)
{
memset(buff, 0, MAX_BUFF_SIZE);
memset(oBuff, 0, MAX_BUFF_SIZE);
buffRec = recv(sock, buff, MAX_BUFF_SIZE, 0);
if((buffRec == 0) || (buffRec == SOCKET_ERROR)) break;
/* New line: Terminate buffer as a string */
buff[buffRec] = '\0';
if(buff[0] != ':')
{
strcpy(oBuff, "PONG :");
printf("PONG");
sock_send(&sock, oBuff);
}
else
{
if(strstr(buff, "PRIVMSG"))
{
int i, num = 0;
for(i = 0; i < strlen(buff); ++i) if(buff[i] = ' ') ++num;
char** parts = malloc(sizeof(char*) * num);
char *p;
p = strtok(buff, " ");
int j = 0;
while(p != NULL)
{
parts[j] = p;
j++;
p = strtok(NULL, " ");
}
printf("%s", parts[3]);
free(parts);
}
}
}
closesocket(sock);
return 1;
}
int sock_conn(SOCKET *socketn, const char *HOST, int portn)
{
WSADATA wsadata;
SOCKADDR_IN sockA;
LPHOSTENT hostE;
if(WSAStartup(MAKEWORD(2,2), &wsadata) == -1) return -1;
if(!(hostE = gethostbyname(HOST)))
{
WSACleanup();
return -1;
}
if ((*socketn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
WSACleanup();
return -1;
}
sockA.sin_family = AF_INET;
sockA.sin_port = htons(portn);
sockA.sin_addr = *((LPIN_ADDR)*hostE->h_addr_list);
if(connect(*socketn, (LPSOCKADDR)&sockA, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
WSACleanup();
return -1;
}
}
int sock_send(SOCKET *socketn, char* msg, ...)
{
char buff[MAX_BUFF_SIZE];
va_list va;
va_start(va, msg);
vsprintf(buff, msg, va);
va_end(va);
send(*socketn, buff, strlen(buff), 0);
return 1;
}
parts always null, why? someone told me to terminate the buff with this line: buff[buffRec] = '\0';, but still I got nothing, how can I change the buff to string cause I believe this is the problem... the bot is connecting and all and I can communicate with it, but when I try to reach to parts, it's NULL.
char buff[MAX_BUFF_SIZE];
/* ... */
buffRec = recv(sock, buff, MAX_BUFF_SIZE, 0);
buff[buffRec] = '\0';
If buffRec value is MAX_BUFF_SIZE you have a buffer overflow.
I'm trying to receive data on a socket, and it keeps giving me this error, it's an irc bot, my code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <time.h>
void remove_string(char * str, char c)
{
char *p1 = str;
while (*p1++) {
if(*p1 == c) {
char *p2 = p1;
while (*p2 && *p2 == c)
++p2;
if (*p2) {
*p1 = *p2;
*p2 = c;
} else {
*p1 = '\0';
break;
}
}
}
}
char *replace_string(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
if (!(p = strstr(str, orig)))
return str;
strncpy(buffer, str, p-str);
buffer[p-str] = '\0';
sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
return buffer;
}
int connect_socket(SOCKET *p, SOCKADDR_IN service)
{
if (connect(*p, (LPSOCKADDR)&service, sizeof(struct sockaddr)) == SOCKET_ERROR) {
fprintf(stderr, "Unable to connect, Error: %d\n", WSAGetLastError());
return -1;
}
return 0;
}
int send_socket(SOCKET *p, const char *buffer)
{
if (send(*p, buffer, strlen(buffer), 0) == SOCKET_ERROR) {
fprintf(stderr, "Unable to send data on the socket, Error: %d\n", WSAGetLastError());
return -1;
}
return 0;
}
int recv_socket(SOCKET *p, char *buffer)
{
if (recv(*p, buffer, sizeof(buffer), 0) == SOCKET_ERROR) {
fprintf(stderr, "Unable to receive data on the socket, Error: %d\n", WSAGetLastError());
return -1;
}
return 0;
}
int find_string(const char *str1, const char *str2)
{
int res = strstr(str1, str2) - str1;
return res < 0 ? -1 : res;
}
typedef struct IRC_DATA {
char *nick;
char *msg;
char *channel;
char *time;
} irc_data;
int main(int argc, char **argv)
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
return -1;
if (argc < 4) {
printf("Usage: %s <server> <port> <channel>", argv[0]);
return -1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET || sock == SOCKET_ERROR) {
fprintf(stderr, "Unable to initalize socket, Error: %d\n", WSAGetLastError());
return -1;
}
LPHOSTENT host = gethostbyname(argv[1]);
int port = atoi(argv[2]);
SOCKADDR_IN service;
service.sin_family = AF_INET;
service.sin_port = htons(port);
service.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
int tries;
for (tries = 0; connect_socket(&sock, service) != 0; tries++) {
printf("Failing to connect.\n");
if (tries == 3) {
printf("Stopping reconnect...");
return -1;
}
}
printf("Connected\n");
char *_tmp = "USER CBot * * :CBot\r\n";
send_socket(&sock, _tmp);
_tmp = "NICK CBot\r\n";
send_socket(&sock, _tmp);
int joined = 0;
irc_data irc;
char buffer[512];
while (1) {
int p = recv_socket(&sock, buffer);
if (p == -1)
break;
char _time[50];
time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(_time, sizeof(_time), "[%H:%M:%S]", timeinfo);
strcpy(irc.time, _time);
if (strncmp(buffer, "PING", 4) == 0) {
printf("Received ping\n");
char pong[100];
if (sscanf(buffer, "PING :%s", pong) > 0) {
char buff[120];
sprintf(buff, "PONG :%s\r\n", pong);
send_socket(&sock, buff);
if (joined == 0) {
char join[120];
sprintf(join, "JOIN %s\r\n", argv[3]);
send_socket(&sock, join);
joined = 1;
}
}
} else if (strstr(buffer, "PRIVMSG") != NULL) {
remove_string(buffer, '\r\n');
int pos = find_string(buffer, " :");
int len = strlen(buffer)-pos;
char msg[len];
memcpy(msg, &buffer[pos], len);
irc.msg = msg;
printf("Msg: %s\n", irc.msg);
printf("%s %s\n", irc.time, buffer);
}
}
return 0;
}
quick observation, it's not a good idea to reuse _tmp like you have done. (create a _tmp[512] and snprintf your values into it)
1.- In the function recv_socket you are going to receive only 4 bytes (or maybe 8 bytes if you are compiling a 64bits code), because you are using sizeof and not the size of the buffer.
2.- What error are you getting ?.