一个简易的proxy程序的开发过程(2)

简易Proxy程序(源代码)

上次贴出了一篇<<一个简易的proxy程序的开发过程(1)>>和<<一个简易的UDP Proxy程序>>之后,有不少网友来信询问下文何时出现。我却一直忙于工作,忘记了将下文贴上来,非常抱歉。现在在这里把源代码贴出来。我 申明这个源代码基于GNU GPL,目的在于希望大家能够有时间去更加完善它。你也可以按照你自己的希望去改变它。不过,如果你做了任何大的改动,请通知我< ariesram@may10.ca>.

TODO:

1、使程序能够监听多个端口,并且连接多个远程服务。

2、使程序能够从配置文件中读取设定监听端口和所要连接的远程服务地址以及端口以满足多种服务并存

的需要。

sp.c

/*******************************************************************************

This program is free software; you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation; either version 2 of the License, or

(at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

*******************************************************************************/

/*******************************************************************************

Program: sp.c

Description: a smart proxy

Author: Alan Chen (ariesram@may10.ca)

Date: July 18, 2001

*******************************************************************************/

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/time.h>

#include <sys/wait.h>

#include <unistd.h>

#include <netinet/in.h>

#define ERRLOG "./sp.log"

int do_proxy(int infd, char* addr, int port);

int max(int i, int j);

void waitchild(int);

void version();

void usage();

void daemonize();

void p_error(const char * err_msg);

int main(int argc, char** argv) {

struct sockaddr_in servaddr, clientaddr;

int listenfd, connfd;

int clientlen;

pid_t chpid;

int service_port = 0, remote_port = 0;

char remote_addr[17];

const char optstring[] = "s:r:p:vh";

int opt;

extern char *optarg;

extern int optind, opterr, optopt;

extern FILE *stderr;

memset(remote_addr, 0, 17);

if( argc == 2 ) {

while( (opt = getopt(argc, argv, optstring)) != -1 ) {

if( opt == 'v' ) {

version();

exit(0);

}

else if ( opt == 'h' ) {

usage();

exit(0);

}

else {

printf("type sp -h for help message

");

usage();

exit(0);

}

}

}

else {

while( (opt = getopt(argc, argv, optstring)) != -1 ) {

switch(opt) {

case 's':

service_port = atoi(optarg);

break;

case 'r':

memcpy(remote_addr, optarg, strlen(optarg));

remote_addr[strlen(remote_addr)] = '';

break;

case 'p':

remote_port = atoi(optarg);

break;

default:

usage();

exit(0);

}

}

}

if( service_port == 0' 'remote_port == 0' 'remote_addr[0] == '') {

usage();

exit(0);

}

daemonize();

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(service_port);

servaddr.sin_addr.s_addr = INADDR_ANY;

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if(listenfd < 0) {

p_error("socket error");

exit(-1);

}

if( bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {

p_error("bind error");

exit(-1);

}

if( listen(listenfd, 5) < 0 ) {

p_error("listen error");

exit(-1);

}

signal(SIGCHLD, waitchild);

for(;;) {

connfd = accept( listenfd, (struct sockaddr *)&clientaddr,

&clientlen );

if( connfd < 0 ) {

p_error("accept error");

exit(-1);

}

if( (chpid = fork()) == -1 ) {

p_error("fork error");

exit(-1);

}

if( chpid == 0 ) {

close(listenfd);

do_proxy(connfd, remote_addr, remote_port);

exit(0);

}

if( chpid > 0 ) {

close(connfd);

}

}

exit(0);

}

int do_proxy(int infd, char *addr, int port) {

struct sockaddr_in rout;

int outfd;

int maxfd;

int count = 65535;

int n;

fd_set set;

char buf[count];

bzero(&rout, sizeof(rout));

rout.sin_family = AF_INET;

rout.sin_port = htons(port);

rout.sin_addr.s_addr = inet_addr(addr);

if( (outfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

p_error("socket error");

exit(-1);

}

if( connect(outfd, (struct sockaddr *)&rout, sizeof(rout)) < 0 ) {

p_error("connect error");

exit(-1);

}

while(1) {

FD_ZERO(&set);

FD_SET(infd, &set);

FD_SET(outfd, &set);

maxfd = max(outfd, infd);

if( select(maxfd + 1, &set, NULL, NULL, NULL) < 0 ) {

perror("select error:");

exit(-1);

}

if( FD_ISSET(infd, &set) ) {

n = read(infd, (void *)buf, count);

if( n <= 0)

break;

if( write(outfd, (const void *)buf, n) != n ) {

p_error("write error");

continue;

}

}

if( FD_ISSET(outfd, &set) ) {

n = read(outfd, (void *)buf, count);

if( n <= 0)

break;

if( write(infd, (const void *)buf, n) != n ) {

p_error("write error");

continue;

}

}

}

close(infd);

close(outfd);

}

int max(int i, int j) {

return i>j?i:j;

}

void waitchild(int signo) {

int status;

pid_t childpid;

if( (childpid = waitpid(-1, &status, WNOHANG)) < 0 ) {

p_error("wait error");

exit(1);

}

return;

}

void version() {

printf("GNU SP 1.0

Copyright 2001 Aryes Software Studio, Inc.

SP is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

");

}

void usage() {

printf("This is the GNU smart proxy daemon. Usage:

sp -s service_port -r remote_address -p remote_port

sp -v

sp -h

option:

-s specify service port of sp

-r specify remote address which sp will connect

-p specify remote port while sp will connect to

-v display version message

-h display this help message

Report bugs to <ariesram@may10.ca>.

");

}

void daemonize() {

int i;

#ifndef _DEBUG

signal(SIGINT, SIG_IGN);

#endif

signal(SIGHUP, SIG_IGN);

signal(SIGABRT, SIG_IGN);

signal(SIGSTOP, SIG_IGN);

signal(SIGCHLD, SIG_IGN);

#ifndef _DEBUG

if (fork() != 0)

exit(0);

setsid();

for (i = 256; i >= 0; i --)

#endif

#ifdef _DEBUG

for (i = 256; i >= 3; i --)

#endif

close(i);

}

void p_error(const char * err_msg)

{

FILE * fp;

#ifdef _DEBUG

printf("%s

", err_msg);

#endif

fp = fopen(ERRLOG, "a");

if (fp == NULL)

return;

fprintf(fp, "%s

", err_msg);

fclose(fp);

}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值