
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<unistd.h>
#include<netdb.h>
#include<errno.h>

#include<fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>

#include<pthread.h>

#include<arpa/inet.h>
#include<netinet/in.h>

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

// #define TH_RESOLV_BUG


void * thread_resolv(stred_t * redd)
{
struct sockaddr_in my_addr;
struct hostent ht;
struct hostent *hostelement;
char buffer[1024];
char ntp[IP_LEN];
char * ntopbuff = ntp;
int thd_errno;

// このスレッドはデタッチされます
pthread_detach(pthread_self());

#ifdef TH_RESOLV_BUG
printf("TH_RESOLV_BUG: thread_resolv(): 名前変換スレッド初め\n");
#endif

memset(buffer, 0x00, 1024);

if((gethostbyname_r(redd->name_data, &ht, buffer, 1024, &hostelement, &thd_errno)) != 0){
   #ifdef TH_RESOLV_BUG
   fprintf(stderr,"TH_RESOLV_BUG: thread_resolv(): gethostbyname()が失敗しました  %s\n", redd->name_data);
   #endif
   hostelement = NULL;
   }

// 引けない
if(hostelement == NULL){
   #ifdef TH_RESOLV_BUG
   fprintf(stderr,"TH_RESOLV_BUG: thread_resolv(): gethostbyname()にて対象のエントリが見つかりません  %s\n", redd->name_data);
   #endif
   my_addr.sin_addr.s_addr = 0;
// self_memcpy(redd->back_data, inet_ntoa(my_addr.sin_addr), BUF_LEN);
   self_memcpy(redd->back_data, (char *)inet_ntop(AF_INET, &my_addr.sin_addr, ntopbuff, IP_LEN), BUF_LEN);
   }
// 引けた
else{
   my_addr.sin_addr.s_addr = *((unsigned long *)ht.h_addr_list[0]);
// self_memcpy(redd->back_data, inet_ntoa(my_addr.sin_addr), BUF_LEN);
   self_memcpy(redd->back_data, (char *)inet_ntop(AF_INET, &my_addr.sin_addr, ntopbuff, IP_LEN), BUF_LEN);
   }


// チェックスレッド用のマーク
redd->check = 1;


#ifdef TH_RESOLV_BUG
printf("TH_RESOLV_BUG: thread_resolv(): 名前変換スレッド終わり base name = <%s>,  return name = <%s>\n", redd->name_data, redd->back_data);
#endif

return NULL;
}





void * thread_resolv_chk(stred_t * redd)
{
int co;
int stat;
#ifdef TH_RESOLV_BUG
printf("TH_RESOLV_BUG: thread_resolv_chk(): チェックスレッド開始\n");
#endif

for(co = 0; co < redd->time; co++){
   sleep(1);
   if(redd->check == 1){
      #ifdef TH_RESOLV_BUG
      printf("TH_RESOLV_BUG: thread_resolv_chk(): 名前変換スレッドが終わっているのでチェック終了 回数<%d>\n", co);
      #endif
      return NULL;
      }
   }

// 名前変換スレッドが時間内に戻らないので強制終了
stat = pthread_cancel(redd->t_ret);

if(stat == 0){
   #ifdef TH_RESOLV_BUG
   printf("TH_RESOLV_BUG: thread_resolv_chk(): 名前変換スレッドが時間内に終わらないので強制終了 回数<%d> STAT=<%d>\n", co, stat);
   #endif
   self_memcpy(redd->back_data, "0.0.0.0", BUF_LEN);
   }
else{
   #ifdef TH_RESOLV_BUG
   printf("TH_RESOLV_BUG: thread_resolv_chk(): 強制終了に失敗 回数<%d> STAT=<%d>\n", co, stat);
   #endif
   }

return NULL;
}




char * th_resolv(char * name, char * back, int interval, int out)
{
int ret;
ret = 0;

stred_t thd;

#ifdef TH_RESOLV_BUG
printf("TH_RESOLV_BUG: th_resolv(): in data name =%s, back =%s, interval =%d, out =%d\n", name, back, interval, out);
#endif

if(0 >= strlen(name)){
   back = safe_memcpy(back, "not name.\n", BUF_LEN);
   return back;
   }
else{
   // 構造体初期化
   memset(thd.name_data, (char)0x00, 1024);
   memset(thd.back_data, (char)0x00, 1024);
   thd.time = interval;
   thd.check = 0;
// pthread_mutex_init(&thd.back_data_mutex, NULL);

   self_memcpy(thd.name_data, name, 1024);

   if((ret = pthread_create(&thd.t_ret, NULL, (void *)thread_resolv, &thd)) == 0){
      if((ret = pthread_create(&thd.t_chk, NULL, (void *)thread_resolv_chk, &thd)) == 0){
         }
      else{
         pthread_cancel(thd.t_ret);
         fprintf(stderr,"sitar_scan.c: pthread_create(0): %d %d\n",ret, errno);
         back = safe_memcpy(back, "0.0.0.0", BUF_LEN);
         return back;
         }
      }
   else{
      fprintf(stderr,"sitar_scan.c: pthread_create(2): %d %d\n",ret, errno);
      back = safe_memcpy(back, "0.0.0.0", BUF_LEN);
      return back;
      }

// pthread_join(thd.t_ret, NULL);
   pthread_join(thd.t_chk, NULL);
   }

back = safe_memcpy(back, thd.back_data, BUF_LEN);

#ifdef TH_RESOLV_BUG
printf("TH_RESOLV_BUG: th_resolv(): out data BASE NAME = %s, RESOLV NAMES = %s\n", thd.name_data, back);
#endif

return back;
}




