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

#include<sys/stat.h>
#include<errno.h>

#include"sitar.h"
#include"sitar_scan.h"
#include"sitar_com.h"
#include<almemsys/almemsys.h>
#include"jpreturn.h"

extern global_data_t gd;

/* 1-> port No' 2-> Ipsddr 3-> return data,, return status code 0=open or=close
int scan_tcp_connect(int, char *, char *, int);
*/


/*----------------- SCAN TCP CONNECT --------------------*/
char * scan_tcp_connect(int port, char * url_data, char * backdata, int timeout, int * stat)
{
char ipa2[IP_LEN];
char * ip_addr2 = ipa2;
char ip[BUF_URL];
char * ip_addr = ip;
char pas[BUF_URL];
char * url_pass = pas;
char bu[IP_LEN];
char * buff = bu;

int sk, re, retval, arglen, port2, resolv_ret;
unsigned long resoip;
struct sockaddr_in my_addr;
fd_set rfds;
struct timeval tv;

arglen = sizeof(int);

errno = 0;
resolv_ret = 0;

memset(ip_addr, 0x00, BUF_URL);
memset(url_pass, 0x00, BUF_URL);
memset(buff, 0x00, IP_LEN);

// portの設定よりもURLに含まれるポートを優先する
port2 = urldompass_port(url_data, ip_addr, url_pass, strlen(url_data));
if(port2 > 0){
   port = port2;
   }


if((sk = socket(AF_INET, SOCK_STREAM, 0))==-1){
   backdata=safe_sprintf(backdata,BUF_MAX,
    "IP=%s Port=%d TCP %s", ip_addr, port, SOCK_1);
   * stat = -1;
   #ifdef TCP_BUG
   printf("TCP: scan_tcp_connect(1): NOT CLEATE SOCKET %s\n", backdata);
   #endif
   return backdata;
   }

my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);

resoip = 0;
// backdata = resolvename_th(backdata, ip_addr, timeout, &resoip);
// backdata = resolvename_sk(backdata, ip_addr, timeout, &resoip, &resolv_ret);

if(0 == self_memcmp(gd.di.dns_name, "RESOLV")){
   backdata = resolvename_th(backdata, ip_addr, timeout, &resoip);
   }
else{
   backdata = resolvename_sk(backdata, ip_addr, timeout, &resoip, gd.di.dns_name, &resolv_ret, '4');
   if(resolv_ret < 0){
      backdata = resolvename_sk(backdata, ip_addr, DEFAULT_TIMEOUT, &resoip, gd.di.dns_name2, &resolv_ret, '4');
      fprintf(stderr,"RESOLV ERR: DNS name resolution failure <%s> %s\n", ip_addr, backdata);
      }
   }


my_addr.sin_addr.s_addr = resoip;

if(0 == (int)my_addr.sin_addr.s_addr || resoip == (int)NULL){
// backdata=safe_sprintf(backdata,BUF_MAX,"%s%s %d\n", SOCK_2, ip_addr, (int)my_addr.sin_addr.s_addr);
   backdata=safe_sprintf(backdata,BUF_MAX,"%s%s\n", SOCK_2, ip_addr);
   #ifdef TCP_BUG
   printf("TCP: scan_tcp_connect(2): NOT RESOLV NAME %s\n", backdata);
   #endif
   close(sk);
   * stat = -1;
   return backdata;
   }

// ip_addr2 = inet_ntoa(my_addr.sin_addr);
ip_addr2 = (char *)inet_ntop(AF_INET, &my_addr.sin_addr, buff, IP_LEN);

#ifdef TCP_BUG
printf("TCP: scan_tcp_connetc(3): start TCPCHECK host<%s> ip<%s>\n", ip_addr2, ip_addr);
#endif

fcntl(sk, F_SETFL, O_NONBLOCK);
re = connect(sk, (struct sockaddr *)(long)&my_addr, sizeof(my_addr));

if(re >= 0){
   backdata=safe_sprintf(backdata,BUF_MAX,
    "HOST=%s IP=%s Port=%d TCP %s", ip_addr, ip_addr2, port, SOCK_3);
   #ifdef TCP_BUG
   printf("TCP: scan_tcp_connect(4): CONNECT SUCCESS %s\n", backdata);
   #endif
   fcntl(sk, F_SETFL, 0);
   close(sk);
   * stat = 0;
   return backdata;
   }

if(errno == EINPROGRESS){
   tv.tv_sec = timeout;
   tv.tv_usec = 0;

   while(1){
      FD_ZERO(&rfds);
      FD_SET(sk, &rfds);
      retval = select(sk + 1, NULL, &rfds, NULL, &tv);
      if(retval < 0){
         backdata=safe_sprintf(backdata,BUF_MAX,
          "HOST=%s IP=%s Port=%d %s %s", ip_addr, ip_addr2, port, SOCK_15, SOCK_5);
         #ifdef TCP_BUG
         printf("TCP: scan_tcp_connetc(5): select err BREAK-%d- %s\n", retval, backdata);
         #endif
         fcntl(sk, F_SETFL, 0);
         close(sk);
         * stat = -1;
         return backdata;
         }
      else if(retval == 0){
         backdata=safe_sprintf(backdata,BUF_MAX,
          "HOST=%s IP=%s Port=%d %s %s", ip_addr, ip_addr2, port, SOCK_16, SOCK_5);
         #ifdef TCP_BUG
         printf("TCP: scan_tcp_connetc(6): select time out BREAK-%d- %s\n", retval, backdata);
         #endif
         fcntl(sk, F_SETFL, 0);
         close(sk);
         * stat = -1;
         return backdata;
         }
      else{
         backdata=safe_sprintf(backdata,BUF_MAX,
          "HOST=%s IP=%s Port=%d TCP %s", ip_addr, ip_addr2, port, SOCK_3);
         #ifdef TCP_BUG
         printf("TCP: scan_tcp_connect(7): select time succes BREAK-%d- %s\n", retval, backdata);
         #endif
         break;
         }
      }

   fcntl(sk, F_SETFL, 0);

   if(getsockopt(sk, SOL_SOCKET, SO_ERROR, (void *)&retval, (void *)&arglen) < 0){
      backdata=safe_sprintf(backdata,BUF_MAX,
       "HOST=%s IP=%s Port=%d TCP %s", ip_addr, ip_addr2, port, SOCK_13);
      #ifdef TCP_BUG
      printf("TCP: scan_tcp_connect(8): getsockopt() Errors!\n");
      #endif
      close(sk);
      * stat = -1;
      return backdata;
      }
   else{
      if(retval){
         backdata=safe_sprintf(backdata,BUF_MAX,
          "HOST=%s IP=%s Port=%d %s: TCP %s", ip_addr, ip_addr2, port, (retval != 0) ? strerror(retval): "0", SOCK_5);
         #ifdef TCP_BUG
         printf("TCP: scan_tcp_connect(9): 1 SO_ERROR %d -\n", retval);
         printf("%s\n", backdata);
         #endif
         close(sk);
         * stat = -1;
         return backdata;
         }
      else{
         backdata=safe_sprintf(backdata,BUF_MAX,
          "HOST=%s IP=%s Port=%d TCP %s", ip_addr, ip_addr2, port, SOCK_3);
         #ifdef TCP_BUG
         printf("TCP: scan_tcp_connect(10): -1 SO_ERROR %d -\n", retval);
         printf("%s\n", backdata);
         #endif
         close(sk);
         * stat = 0;
         return backdata;
         }
      }
   }

fcntl(sk, F_SETFL, 0);

backdata=safe_sprintf(backdata,BUF_MAX,
 "HOST=%s IP=%s Port=%d TCP %s", ip_addr, ip_addr2, port, SOCK_14); 
#ifdef TCP_BUG
printf("TCP: scan_tcp_connect(11): --- LAST END ---\n");
printf("%s\n", backdata);
#endif

close(sk);
* stat = -1;
return backdata;

}


