SPEC
OS: Linux
COMPILER: GCC
(잡았음) 처음 접속은 성공적이나 두번째 접속부터 target_sock의 할당이 제대로 이루어지지 않고 있음. 이 버그를 잡아야함.
(Not Yet) target() 함수가 종료되지 않음. recv()를 Non-Blocking으로 할당하고 Message가 오지 않으면 target() 함수를 종료시키는 방법을 써야겠음.
fork()로 child process 생성 후, parent process를 제거.
child process에서 setsid()로 session leader권한 부여.
child process는 thread를 사용하여 동기화함.
child process는 daemon process로 background에서 실행됨.
www protocol도 사용 가능하지만 www protocol로 제작된 것이 아니여서 하나의 사이트만 접속 가능.
irc proxy 제작을 목표로 완성 되었음.
// www protocol을 구현하려면 thread 시작 부분에서 connect 부분을 고쳐야함.
// 물론 www protocol의 RFC 문서를 참고하여 패킷 교환 방식을 제작해야함.
~cpp
// pthread 라이브러리를 링크시 첨가해야함.
// gcc source.c -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>
#if !defined(TRUE)
#define TRUE 1
#endif
#define MSG_MAX 1024
#if !defined(_REENTRANT)
#define _REENTRANT
#endif
void *target(void *arg);
void *client(void *arg);
pthread_mutex_t mutex;
int main(int argc, char *argv[])
{
int server_sock;
int client_sock;
int target_sock;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
struct sockaddr_in target_addr;
struct hostent *h = NULL;
int client_addr_size;
int option = TRUE;
pid_t pid;
pthread_t tid;
int sock[2];
if(argc != 4)
fprintf(stderr, "Usage: %s <Target-Host> <Target-Port> <Port>\n", argv[0]), exit(-1);
h = gethostbyname(argv[1]);
if(h == NULL)
fprintf(stderr, "gethostbyname() error: %s\n", argv[1]), exit(-1);
server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_sock == -1)
fprintf(stderr, "socket() error: server_sock(%d)\n", server_sock), exit(-1);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(atoi(argv[3]));
memset(&target_addr, 0, sizeof(target_addr));
target_addr.sin_family = AF_INET;
target_addr.sin_addr = *(struct in_addr *)h->h_addr_list[0];
target_addr.sin_port = htons(atoi(argv[2]));
if(setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) == -1)
fprintf(stderr, "setsockopt() error: server_sock(%d)\n", server_sock), exit(-1);
if(bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
fprintf(stderr, "bind() error: server_sock(%d)\n", server_sock), exit(-1);
if(listen(server_sock, 1) == -1)
fprintf(stderr, "listen() error: server_sock(%d)\n", server_sock), exit(-1);
pthread_mutex_init(&mutex, NULL);
pid = fork();
switch(pid)
{
case -1:
fprintf(stderr, "fork() error: pid(%d)\n", pid), exit(-1);
case 0:
while(1){
client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_size);
if(client_sock == -1)
fprintf(stderr, "accept() error: client_sock(%d)\n", client_sock), exit(-1);
target_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(target_sock == -1)
fprintf(stderr, socket() error: target_sock(%d)\n", target_sock), exit(-1);
if(connect(target_sock, (struct sockaddr *)&target_addr, sizeof(target_addr)) == -1)
fprintf(stderr, "connect() error: target_sock(%d)\n", target_sock), exit(-1);
sock[0] = client_sock;
sock[1] = target_sock;
pthread_create(&tid, NULL, target, (void *)sock);
pthread_create(&tid, NULL, client, (void *)sock);
}
return 0;
default:
close(server_sock);
return 0;
}
}
void *target(void *arg)
{
int msg_len;
char msg[MSG_MAX];
int client_sock = ((int *)arg)[0];
int target_sock = ((int *)arg)[1];
while((msg_len = recv(client_sock, msg, MSG_MAX, 0)) != 0){
msg[msg_len] = '\0';
if(send(target_sock, msg, strlen(msg), 0) == -1)
break;
}
pthread_mutex_lock(&mutex);
if(target_sock)
close(target_sock);
if(client_sock)
close(client_sock);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void *client(void *arg)
{
int msg_len;
char msg[MSG_MAX];
int client_sock = ((int *)arg)[0];
int target_sock = ((int *)arg)[1];
while((msg_len = recv(target_sock, msg, MSG_MAX, 0)) != 0){
msg[msg_len] = '\0';
if(send(client_sock, msg, strlen(msg), 0) == -1)
break;
}
pthread_mutex_lock(&mutex);
if(target_sock)
close(target_sock);
if(client_sock)
close(client_sock);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}