
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.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<fcntl.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"

// #define DHW_BUG

extern global_data_t gd;


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


/*----------------- SCAN DHW CONNECT --------------------*/
char * scan_dhw_connect(char * comand, int port, char * url_dom, char * backdata, int timeout, int * pst)
{
int sk, re, ret, retval, arglen, dcount, resolv_ret;
char ipa[IP_LEN];
char * ip_addr = ipa;
unsigned long resoip;
struct sockaddr_in my_addr;
fd_set rfds;
struct timeval tv;
char recvd[BUF_LEN];
char sendd[BUF_LEN];
char * recvdata = recvd;
char * senddata = sendd;
char bu[IP_LEN];
char * buff = bu;

memset(recvdata, 0x00, BUF_LEN);
memset(senddata, 0x00, BUF_LEN);

ret = -1;
errno = 0;
arglen = sizeof(int);
dcount = 0;

#ifdef DHW_BUG
printf("DHW: scan_dhw_connect(1): DHW COMMAND %s\n", comand);
#endif


if((sk = socket(AF_INET, SOCK_STREAM, 0))==-1){
   fprintf(stderr,"scan_dhw URL=%s Port=%d tcp %s", url_dom, port, SOCK_1);
   backdata=safe_sprintf(backdata, BUF_MAX, "DHW=%s Port=%d: %s", url_dom, port, SOCK_1);
   * pst = -1;
   return backdata;
   }

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

resoip = 0;
resolv_ret = 0;

if(0 == self_memcmp(gd.di.dns_name, "RESOLV")){
   backdata = resolvename_th(backdata, url_dom, timeout, &resoip);
   }
else{
   backdata = resolvename_sk(backdata, url_dom, timeout, &resoip, gd.di.dns_name, &resolv_ret, '4');
   if(resolv_ret < 0){
      backdata = resolvename_sk(backdata, url_dom, DEFAULT_TIMEOUT, &resoip, gd.di.dns_name2, &resolv_ret, '4');
      fprintf(stderr,"RESOLV ERR: DNS name resolution failure <%s> %s\n", url_dom, 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 %d: %s\n", SOCK_2, url_dom, (int)my_addr.sin_addr.s_addr, SOCK_2);
   close(sk);
   * pst = -1;
   return backdata;
   }

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

#ifdef DHW_BUG
printf("DHW: scan_dhw_connect(2): connect start %s %s %d\n", url_dom, ip_addr, port);
#endif

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

if(re >= 0){
   fcntl(sk, F_SETFL, 0);
   backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_5);
   #ifdef URL_BUG
   printf("URL: scan_dhw_connect(3): CONNECT SUCCESS %s\n", backdata);
   #endif
   goto notselect;
   }

// error がEINPROGRESSな場合
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);
      // select異常終了
      if(retval < 0){
         backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_15);
         #ifdef DHW_BUG
         printf("DHW: scan_dhw_connect(4): select err BREAK- %d - %s\n", retval, backdata);
         #endif
         // 非同期から同期通信へ
         fcntl(sk, F_SETFL, 0);
         close(sk);
         * pst = -1;
         return backdata;
         }
      // selectのタイムアウト
      else if(retval == 0){
         backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_16);
         #ifdef DHW_BUG
         printf("DHW: scan_dhw_connect(5): select time out BREAK- %d - %s\n",
           retval, backdata);
         #endif
         // 非同期通信から同期通信へ
         fcntl(sk, F_SETFL, 0);
         close(sk);
         * pst = -1;
         return backdata;
         }
      // 時間内に接続出来たのでLoopOUTします。
      else{
         // 非同期通信から同期通信に
         fcntl(sk, F_SETFL, 0);
         backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_3);
         #ifdef DHW_BUG
         printf("DHW: scan_dhw_connect(6): select time succes BREAK- %d - %s\n", retval, backdata);
         #endif
         break;
         }
      }



   // select を省いたGOTO
   notselect :;

   // socketに関するペンディングエラーを返す
   if(getsockopt(sk, SOL_SOCKET, SO_ERROR, (void *)&retval, (void *)&arglen) < 0){
      backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_13);
      #ifdef DHW_BUG
      fprintf(stderr,"getsockopt(7) Errors!\n");
      #endif
      close(sk);
      * pst = -1;
      return backdata;
      }

   else{
      // エラーがある
      if(retval){
         backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s: %s", url_dom, ip_addr, port, (retval != 0) ? strerror(retval): "0", SOCK_5);
         #ifdef DHW_BUG
         printf("DHW: scan_dhw_connect(8): 1 SO_ERROR %d -%s\n", retval, backdata);
         #endif
         close(sk);
         * pst = -1;
         return backdata;
         }

      // エラーがない
      else{
         backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_3);
         #ifdef DHW_BUG
         printf("DHW: scan_dhw_connect(9): 1 SO_ERROR else %d -%s\n", retval, backdata);
         #endif

         if((strlen(comand) + 5) < BUF_LEN){
            sprintf(senddata, "%s\n\n", comand);
            }
         else{
            sprintf(senddata, "%s\n\n", "/bin/long_long_command! ");
            }

         #ifdef DHW_BUG
         printf("DHW: scan_dhw_connect(10): set_request*send-- %s --\n", senddata);
         #endif 

         // 非同期通信の開始
         fcntl(sk, F_SETFL, O_NONBLOCK);

         // DHWコマンドの送信
         send(sk, senddata, strlen(senddata), 0);

         tv.tv_sec = timeout;
         tv.tv_usec = 0;
         while(1){
            FD_ZERO(&rfds);
            FD_SET(sk, &rfds);
            retval = select(sk + 1, &rfds, NULL, NULL, &tv);

            // select の異常終了
            if(retval < 0){
               #ifdef DHW_BUG
               printf("DHW: scan_dhw_connect(11): retval 0 ERR\n");
               #endif 
               backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_15);
               // 非同期通信から同期通信に
               fcntl(sk, F_SETFL, 0);
               close(sk);
               * pst = -1;
               return backdata;
               }
            // selectのタイムアウト
            else if(retval == 0){
               #ifdef DHW_BUG
               printf("DHW: scan_dhw_connect(12): retval 1 ERR\n"); 
               #endif 
               backdata=safe_sprintf(backdata,BUF_MAX,
                "DHW=%s IP=%s Port=%d: %s" , url_dom, ip_addr, port, SOCK_16);
               // 非同期通信から同期通信に
               fcntl(sk, F_SETFL, 0);
               close(sk);
               * pst = -1;
               return backdata;
               }

            // select 正常
            else{
               // 非同期通信から同期通信に戻す
               fcntl(sk, F_SETFL, 0);
//             dcount = recv(sk, recvdata, BUF_LEN, 0);
               dcount = socket_readas(sk, recvdata, BUF_LEN, timeout, 0);

               swap_mem(recvdata, '\t', ' ');
               swap_mem(recvdata, ',', ' ');
               swap_mem(recvdata, '"', ' ');

               #ifdef DHW_BUG
               printf("DHW: scan_dhw_connect(13): recv-- %s --\n", recvdata);
               #endif

               // 受信量がゼロ
               if(dcount < 1){
                  ret = -1;
                  backdata = safe_sprintf(backdata,BUF_MAX, "%s", DHW_ERR4);
                  #ifdef DHW_BUG
                  printf("DHW: scan_dhw_connect(14): <%s> %d\n", backdata, ret);
                  #endif
                  }

               // 何らかのエラーを取得した場合
               else{
                  // 先頭が###DHWINFOな場合
                  if(0 == memcmp(recvdata, "###DHWINFO ", 11)){ 
                     int an;
                     an = 1 + (mem_tcount(recvdata, '\n'));
                     // 改行までのサイズと受信サイズが等しいので正常終了
                     if(dcount == an){
                        backdata = safe_sprintf(backdata, BUF_MAX,"%s", DHW_ERR3);
                        rm_char(backdata, '\n');
                        ret = 0;
                        #ifdef DHW_BUG
                        printf("DHW: scan_dhw_connect(test): <%s> dcount=%d tcount=%d\n",
                          recvdata, dcount, an);
                        #endif
                        }
                     // 改行のあとにまだある場合
                     else{
                        if(0 == memcmp(recvdata + an, "###DHWINFO ", 11)){ 
                           int in;
                           in = 1 + (char_point(recvdata, '\n', 2));
                           // 改行までのサイズと受信サイズが等しいので正常終了
                           if(dcount == in){
                              backdata = safe_sprintf(backdata, BUF_MAX,"%s", DHW_ERR3);
                              rm_char(backdata, '\n');
                              ret = 0;
                              #ifdef DHW_BUG
                              printf("DHW: scan_dhw_connect(test): <%s> dcount=%d tcount=%d\n",
                                recvdata, dcount, in);
                              #endif
                              }
                           else{
                              backdata = safe_sprintf(backdata, BUF_MAX,"RETURN=%s : %s", recvdata + in, DHW_ERR1);
                              rm_char(backdata, '\n');
                              ret = -1;
                              #ifdef DHW_BUG
                              printf("DHW: scan_dhw_connect(15): <%d> %s\n", ret, backdata);
                              #endif
                              }
                           }
                        else{
                           backdata = safe_sprintf(backdata, BUF_MAX,"RETURN=%s : %s", recvdata + an, DHW_ERR1);
                           rm_char(backdata, '\n');
                           ret = -1;
                           #ifdef DHW_BUG
                           printf("DHW: scan_dhw_connect(16): <%d> %s\n", ret, backdata);
                           #endif
                           }
                        }
                     }

                  // 先頭が###DHWINFOでないのでダメ
                  else{
                     int an;
                     an = 1 + (mem_tcount(recvdata, '\n'));

                     if(dcount == an){
                        backdata = safe_sprintf(backdata, BUF_MAX,"%s", DHW_ERR2);
                        rm_char(backdata, '\n');
                        ret = -1;
                        printf("DHW: scan_dhw_connect(test): <%s> dcount=%d tcount=%d\n",
                          recvdata, dcount, 1 + (mem_tcount(recvdata, '\n')));
                        }
                     else{
                        backdata = safe_sprintf(backdata, BUF_MAX,"RETURN=%s : %s", recvdata + an, DHW_ERR2);
                        rm_char(backdata, '\n');
                        ret = -1;
                        #ifdef DHW_BUG
                        printf("DHW: scan_dhw_connect(17): <%d> %s\n", ret, backdata);
                        #endif
                        }

                     }

                  }

               #ifdef DHW_BUG
               printf("DHW: scan_dhw_connect(18): %d <2> %s\n", ret, backdata);
               #endif

               // 非同期通信から同期通信に戻す
           //  fcntl(sk, F_SETFL, 0);
               close(sk);
               * pst = ret;
               return backdata;
               }
            }

         // 非同期通信から同期通信に戻す
         fcntl(sk, F_SETFL, 0);
         close(sk);
         * pst = ret;
         return backdata;
         }
      }
   }


// HOST IP 等が存在すらしない場合の処理

// 非同期通信から同期通信
fcntl(sk, F_SETFL, 0);
backdata=safe_sprintf(backdata,BUF_MAX, "DHW=%s IP=%s Port=%d: %s", url_dom, ip_addr, port, SOCK_14);
#ifdef DHW_BUG
printf("DHW: scan_dhw_connect(19): not connection last out\n");
#endif

close(sk);
* pst = -1;

return backdata;

}







