📄 cdnsclient.c
字号:
/*************************************************************************** CDnsClient.c Network component (c) 2003-2004 Daniel Campos Fernández <danielcampos@netcourrier.com> 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __CDNSCLIENT_C#include <stdio.h>#include <stdlib.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/poll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <semaphore.h>#include <pthread.h>#include <errno.h>#include "main.h"#include "CDnsClient.h"#ifndef _REENTRANT#define _REENTRANT#endifvoid **dns_object=NULL;int dns_count=0;sem_t dns_th_pipe;int dns_r_pipe=-1;int dns_w_pipe=-1;DECLARE_EVENT (Finished);/********************************************************** DnsClient pipe message protocol: 1) (void*)DNSCLIENT* 2) Action : '0' --> dns_get_name, '1' --> dns_get_ip 3) Result : string finished with '\x10' *********************************************************/void dns_callback(long lParam){ /*********************************************************** This function reads a message sent by a thread, and then raises "Finished" event if necessary, and fills HostName and HostIP properties. This function will run on the main thread. ************************************************************/ CDNSCLIENT *mythis; void *v_obj; char Action[1]; char BufRead[1]; char *Buf=NULL; int Position; int myloop; int test_id; struct pollfd mypoll; int idata=1; if (dns_r_pipe==-1) return; sem_wait(&dns_th_pipe); while (1) { Position=0; BufRead[0]='\0'; mypoll.fd=dns_r_pipe; mypoll.events=POLLIN; mypoll.revents=0; idata=poll(&mypoll,1,0); if (!idata) break; read (dns_r_pipe,&v_obj,sizeof(void*)); read (dns_r_pipe,&test_id,sizeof(int)); read (dns_r_pipe,Action,sizeof(char)); GB.Alloc((void**)&Buf,sizeof(char)); while (BufRead[0] != '\x10') { read(dns_r_pipe,BufRead,sizeof(char)); if (BufRead[0]!='\x10') { Buf[Position]=BufRead[0]; Position++; GB.Realloc((void**)&Buf,(Position+1)*sizeof(char)); } else Buf[Position]='\0'; } Position=-1; for (myloop=0;myloop<dns_count;myloop++) { if ( dns_object[myloop]==v_obj) { Position=myloop; break; } } if ( Position>=0) { mythis=(CDNSCLIENT*)v_obj; if (mythis->iStatus && (mythis->i_id==test_id)) { if (Action[0]=='1') { GB.FreeString(&mythis->sHostIP); GB.NewString(&mythis->sHostIP, Buf ,0); } else { GB.FreeString(&mythis->sHostName); GB.NewString(&mythis->sHostName,Buf,0); } mythis->iStatus=0; if (mythis->finished_callback) { GB.Ref(mythis); GB.Post(mythis->finished_callback, (long)mythis->CliParent); } else { GB.Ref(mythis); GB.Post((void (*)())dns_event, (long)mythis); } } } GB.Free((void**)&Buf); } sem_post(&dns_th_pipe);}/************************************************** To raise an event **************************************************/void dns_event(CDNSCLIENT *mythis){ GB.Raise(mythis,Finished,0); GB.Unref((void**)&mythis);}void* dns_get_name(void* v_obj){ /**************************************************************** This function will run in a thread different from main thread, and when it finish its proccess, it sends a message to the main thread using a pipe *****************************************************************/ char Buf[1]; int myid; int res; CDNSCLIENT *mythis; char host[1024]; struct sockaddr_in sa; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); Buf[0]='0'; mythis=(CDNSCLIENT*)v_obj; sem_wait(&mythis->sem_id); myid=mythis->i_id; sem_post(&mythis->sem_id); ((struct sockaddr*)&sa)->sa_family=AF_INET; bzero(host,1024); sa.sin_port=0; inet_aton(mythis->sHostIP, &sa.sin_addr); res=getnameinfo((struct sockaddr*)&sa,sizeof(struct sockaddr_in),host,1024*sizeof(char),NULL,0,NI_NAMEREQD); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); sem_wait(&dns_th_pipe); write (dns_w_pipe,&v_obj,sizeof(void*)); /* object */ write (dns_w_pipe,&myid,sizeof(int)); /* id */ write (dns_w_pipe,Buf,sizeof(char)); /* Action */ if (!res) write (dns_w_pipe,host,strlen(host)*sizeof(char)); write (dns_w_pipe,"\x10",sizeof(char)); sem_post(&dns_th_pipe); return NULL;}/****************************************************************This function will run in a thread different from main thread,and when it finish its proccess, it sends a message to themain thread using a pipe*****************************************************************/void* dns_get_ip(void* v_obj){ char Buf[1]; char *BufData; int myid; struct addrinfo *stHost; struct sockaddr_in *addr; CDNSCLIENT *mythis; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); Buf[0]='1'; mythis=(CDNSCLIENT*)v_obj; sem_wait(&mythis->sem_id); myid=mythis->i_id; sem_post(&mythis->sem_id); if (getaddrinfo(mythis->sHostName,NULL,NULL,&stHost)) stHost=NULL; if (stHost) if ( stHost[0].ai_family!=PF_INET ) stHost=NULL; sem_wait(&dns_th_pipe); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); write (dns_w_pipe,&v_obj,sizeof(void*)); /* object */ write (dns_w_pipe,&myid,sizeof(int)); /* id */ write (dns_w_pipe,Buf,sizeof(char)); /* action */ if (stHost!=NULL) { addr=(struct sockaddr_in*)stHost[0].ai_addr; BufData=inet_ntoa(addr->sin_addr); if (BufData) write (dns_w_pipe,BufData,strlen(BufData)*sizeof(char)); } write (dns_w_pipe,"\x10",sizeof(char)); sem_post(&dns_th_pipe); return NULL;}void dns_close_all(CDNSCLIENT *mythis){ if (mythis->iStatus) { pthread_cancel(mythis->th_id); /* cancel thread */ pthread_join(mythis->th_id,NULL); sem_destroy(&mythis->sem_id); mythis->iStatus=0; /* inactive */ dns_callback(dns_r_pipe); /* freeing pipe data */ }}int dns_thread_getname(CDNSCLIENT *mythis){ sem_wait(&mythis->sem_id); mythis->i_id++; sem_post(&mythis->sem_id); mythis->iStatus=1; if (pthread_create(&mythis->th_id,NULL,dns_get_name,(void*)mythis) ) { mythis->iStatus=0; return 1; } pthread_detach(mythis->th_id); return 0;}int dns_thread_getip(CDNSCLIENT *mythis){ sem_wait(&mythis->sem_id); mythis->i_id++; sem_post(&mythis->sem_id); mythis->iStatus=1; if (pthread_create(&mythis->th_id,NULL,dns_get_ip,(void*)mythis) ) { mythis->iStatus=0; return 1; } pthread_detach(mythis->th_id); return 0;}int dns_set_async_mode(int myval,CDNSCLIENT *mythis){ int dpipe[2]; if (myval && (dns_r_pipe==-1)) { if (pipe(dpipe)) return 1; dns_r_pipe=dpipe[0]; dns_w_pipe=dpipe[1]; sem_init(&dns_th_pipe,0,1); GB.Watch(dns_r_pipe , GB_WATCH_READ , (void *)dns_callback,0); } mythis->iAsync=myval; return 0;}/*************************************************************************************###################################################################################### --------------------- DNSCLIENT GAMBAS INTERFACE IMPLEMENTATION -----------------######################################################################################**************************************************************************************//********************************************* This property gets/sets the name of a Host *********************************************/BEGIN_PROPERTY ( HostName ) if (READ_PROPERTY) { if (THIS->iStatus){ GB.ReturnString(NULL); return; } GB.ReturnString(THIS->sHostName); return; } if (THIS->iStatus) { GB.Error("HostIP can not be changed while working"); return;} GB.FreeString(&THIS->sHostName); GB.StoreString(PROP(GB_STRING), &THIS->sHostName);END_PROPERTY/************************************************* This property gets/sets the IP address of a Host *************************************************/BEGIN_PROPERTY ( HostIP ) if (READ_PROPERTY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -