// sitar_proxy.c
// $Id: sitar_proxy.c,v 1.2 2007/10/17 11:24:23 sendan Exp $
// masashi shimakura

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in_systm.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>

#include"proxy.h"
#include<almemsys/almemsys.h>

struct my_sock ip;
struct buf_data bf;
struct exec_id exid;

/* argv[1] = my ip
   argv[2] = my port
   argv[3] = connect ip
   argv[4] = connect port
   argv[5] = max connection
   argv[6] = UID  */


int main(int argc, char * argv[])
{
/* pthread_t t1; */
int fdcount;

if(argc != 7){
   fprintf(stdout,"%s\n", CL_VAR);
   fprintf(stdout,"The number of arguments is different. %d\n", argc);
   fprintf(stdout,"Please execute it referring to the following. \n");
   fprintf(stdout,"sitar_proxy <open ip> <open port> <connect ip> <connect port> <max connection> <exec UID>\n");
   exit(1);
   } 

malloc_set(argc, argv);

if(exid.uid <= 0){
   fprintf(stderr,"Not exec user id. %d\n", exid.uid);
   exit(-1);
   }
if(setuid(exid.uid)){
   fprintf(stderr,"Not setuid err %d\n", exid.uid);
   exit(-1);
   } 

// socket_bind2(ip.in.port, ip.in.ip_addr);
socket_bind(&ip.in.my_addr, ip.in.port, ip.in.ip_addr, &ip.in.ls);

for(;;){
   for(fdcount = 0; fdcount < ip.max_count; fdcount++){
      if(ip.fdstat[fdcount] != 1){
         ip.fdstat[fdcount] = 1;
         break;
         }
      } 
   #ifdef PROXY_BUG
   printf("PROXY_BUG: main(): in fdno = %d\n",fdcount); 
   #endif
   if(fdcount < ip.max_count){
//    socket_accept2(fdcount);
      socket_accept(&ip.in.my_addr, &ip.in.ls, &ip.in.sk[fdcount]);
      pthread_create( &ip.pt[fdcount], NULL, (void *)connect_open, NULL);
      }
   else {
      fprintf(stderr,"It waits for 10 seconds that exceeded connected number threshold.%d\n",fdcount);
      sleep(10); 
      }
   }

/* --- It doesn't reach. ---*/
close(ip.in.ls);
return 0;
}




int connect_open(void)
{
int fdno = ip.fdno;
int stat;

#ifdef PROXY_BUG
printf("PROXY_BUG: connect_open(0): out fdno & bufno = %d\n", fdno);
#endif

pthread_detach(pthread_self());

// if(socket_connect2(ip.out.port, ip.out.ip_addr, fdno) != -1){
if(socket_connect(&ip.out.my_addr, ip.out.port, ip.out.ip_addr, &ip.out.sk[fdno]) !=-1){
   while(1){

      bf.getdata[fdno] = select_fdcat(ip.in.sk[fdno], bf.getdata[fdno], &stat, BUF_MAX, INT_VAL);

      if(stat < 0){ break;}
      #ifdef PROXY_BUG
      printf("PROXY_BUG: connect_open(1): OUT.sk=%d bf.getdata[%d]=<%s>\n",
         ip.out.sk[fdno], fdno, bf.getdata[fdno]);
      #endif
      stat = socket_send(ip.out.sk[fdno], bf.getdata[fdno], INT_VAL);

      if(stat < 0){ break;}
      bf.getdata[fdno] = select_fdcat(ip.out.sk[fdno], bf.getdata[fdno], &stat, BUF_MAX, INT_VAL);

      if(stat < 0){ break;}
      #ifdef PROXY_BUG
      printf("PROXY_BUG: connect_open(2): IN.sk=%d bf.getdata[%d]=<%s>\n",
         ip.in.sk[fdno], fdno, bf.getdata[fdno]);
      #endif
      stat = socket_send(ip.in.sk[fdno], bf.getdata[fdno], INT_VAL);

      if(stat < 0){ break;}
      } 
   }

#ifdef PROXY_BUG
printf("PROXY_BUG: connect_open(3): break loop or not connection\n");
#endif
ip.fdstat[fdno] = 0;

close(ip.out.sk[fdno]);
close(ip.in.sk[fdno]);

return 0;
}



