📄 csocket.c
字号:
{ mythis->iStatus=-2; GB.Ref (mythis); CSocket_post_error(mythis); return 2; } mythis->iPort=myport; mythis->conn_type=0; /****************************************** Let's turn hostname into host IP *******************************************/ if (!mythis->DnsTool) { GB.New((void**)&mythis->DnsTool,GB.FindClass("DnsClient"),NULL,NULL); mythis->DnsTool->CliParent=(void*)mythis; } if (mythis->DnsTool->iStatus > 0 ) dns_close_all(mythis->DnsTool); dns_set_async_mode(1,mythis->DnsTool); GB.FreeString (&(mythis->DnsTool->sHostName)); GB.NewString(&mythis->DnsTool->sHostName,sHost,lenhost); mythis->DnsTool->finished_callback=CSocket_CallBackFromDns; /******************************************** We start DNS lookup, when it is finished it will call to CSocket_CallBack_fromDns, and we'll continue there connection proccess ********************************************/ mythis->iStatus=5; /* looking for IP */ dns_thread_getip(mythis->DnsTool); mythis->stream.desc=&SocketStream; mythis->stream._free[0]=(long)mythis; mythis->iUsePort=mythis->iPort; // $BM if (mythis->Host) GB.FreeString(&mythis->Host); if (mythis->Path) GB.FreeString(&mythis->Path); GB.NewString(&mythis->Host,sHost,0); return 0;}/**********************************************This function is used to peek data from socket,you have to pass 3 parameters:mythis -> CSocket objectbuf -> Data Buffer (you have to free it after using it!)MaxLen -> 0 no limit, >0 max. data t read***********************************************/int CSocket_peek_data(CSOCKET *mythis,char **buf,int MaxLen){ int retval=0; int NoBlock=0; int nread=0; int bytes=0; (*buf)=NULL; nread=ioctl(mythis->Socket,FIONREAD,&bytes); /* Is there anythig to read? */ if (nread) retval=-1; else retval=0; if ( (!retval) && (bytes) ) /* if there's anything to receive */ { if (bytes > MAX_CLIENT_BUFFER_SIZE) bytes=MAX_CLIENT_BUFFER_SIZE; if (MaxLen >0 ) bytes=MaxLen; GB.Alloc((void**)buf,bytes); (*buf)[0]='\0'; ioctl(mythis->Socket,FIONBIO,&NoBlock); USE_MSG_NOSIGNAL(retval=recv(mythis->Socket,(void*)(*buf),bytes*sizeof(char),MSG_PEEK|MSG_NOSIGNAL)); NoBlock++; ioctl(mythis->Socket,FIONBIO,&NoBlock); } if (retval==-1) { /* An error happened while trying to receive data : SOCKET ERROR */ if (*buf) { GB.Free((void**)buf); buf=NULL; } GB.Watch (mythis->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0); mythis->stream.desc=NULL; close(mythis->Socket); mythis->iStatus=-4; GB.Ref (mythis); CSocket_post_error(mythis); return -1; } return retval;}/*****************************************************************************************##########################################################################################-------------------------SOCKET GAMBAS INTERFACE IMPLEMENTATION---------------------##########################################################################################******************************************************************************************//********************************************************************Returns current Status of the socket (connected,connecting,closed)*********************************************************************/BEGIN_PROPERTY ( CSOCKET_Status ) GB.ReturnInteger(THIS->iStatus);END_PROPERTY/******************************************************************** Port to connect to. Can be 'Net.Local' for Unix sockets, or 1-65535 for TCP sockets ********************************************************************/BEGIN_PROPERTY(CSOCKET_Port) if (READ_PROPERTY) { GB.ReturnInteger(THIS->iUsePort); return; } if (THIS->iStatus>0) { GB.Error("Port property can not be changed while working"); return; } if (VPROP(GB_INTEGER)<0) { THIS->iUsePort=0; return; } if (VPROP(GB_INTEGER)>65535) { THIS->iUsePort=65535; return; } THIS->iUsePort=VPROP(GB_INTEGER);END_PROPERTY/********************************************************************* Host or Path to connect to. If 'Port' value is zero, this will be a local path, else, a remote host name**********************************************************************/// $BMBEGIN_PROPERTY (CSOCKET_Host) if (READ_PROPERTY) { GB.ReturnNewString(THIS->Host,0); return; } GB.StoreString(PROP(GB_STRING), &THIS->Host);END_PROPERTYBEGIN_PROPERTY (CSOCKET_Path) if (READ_PROPERTY) { GB.ReturnNewString(THIS->Path,0); return; } GB.StoreString(PROP(GB_STRING), &THIS->Path);END_PROPERTY/******************************************************************** Returns current TCP remote port (only when connected via TCP) *********************************************************************/BEGIN_PROPERTY ( CSOCKET_RemotePort ) if ( THIS->iStatus != 7 ) { GB.ReturnInteger(0); return; } if ( THIS->conn_type != 0 ) { GB.ReturnInteger(0); return; } GB.ReturnInteger(THIS->iPort);END_PROPERTY/******************************************************************** Returns current TCP local port (only when connected via TCP) *********************************************************************/BEGIN_PROPERTY ( CSOCKET_LocalPort ) if ( THIS->iStatus != 7 ) { GB.ReturnInteger(0); return; } if ( THIS->conn_type != 0 ) { GB.ReturnInteger(0); return; } GB.ReturnInteger(THIS->iLocalPort);END_PROPERTY/*********************************************************************** Returns current foreing host IP (only when connected via TCP) ***********************************************************************/BEGIN_PROPERTY ( CSOCKET_RemoteHost ) if ( THIS->iStatus==7 && (THIS->conn_type==0) ) { GB.ReturnString(THIS->sRemoteHostIP); return; } GB.ReturnString(NULL);END_PROPERTY/*********************************************************************** Returns current local host IP (only when connected via TCP) ***********************************************************************/BEGIN_PROPERTY ( CSOCKET_LocalHost ) if ( THIS->iStatus==7 && (THIS->conn_type==0) ) { GB.ReturnString(THIS->sLocalHostIP); return; } GB.ReturnString(NULL);END_PROPERTY// $BM#if 0/*********************************************************************** Returns current Path (only when connected via UNIX socket) ***********************************************************************/BEGIN_PROPERTY ( CSOCKET_Path ) int mylen; char numtmp[6]; char *strtmp; if ( (THIS->iStatus==7) && (THIS->conn_type==1) ) { GB.ReturnString(THIS->sPath); return; } if ( (THIS->iStatus==7) && (THIS->conn_type==0) ) { snprintf(numtmp,6,"%d",THIS->iPort); mylen=strlen(THIS->sRemoteHostIP); mylen++; mylen+=strlen(numtmp); mylen++; GB.Alloc((void**)&strtmp,sizeof(char)*mylen); strcpy(strtmp,THIS->sRemoteHostIP); strcat(strtmp,":"); strcat(strtmp,numtmp); GB.ReturnNewString(strtmp,0); GB.Free((void**)&strtmp); return; } GB.ReturnString(NULL);END_PROPERTY#endif/**************************************************** Gambas object "Constructor" ****************************************************///BEGIN_METHOD(CSOCKET_new,GB_STRING sPath;)BEGIN_METHOD_VOID(CSOCKET_new) //char *buf=NULL; //int retval; //int nport=0; // $BM - The object is filled with zero at creation //THIS->stream.desc=NULL; //THIS->c_parent=NULL; //THIS->DnsTool=NULL; //THIS->conn_type=0; //THIS->iStatus=0; THIS->iUsePort=80; //THIS->sLocalHostIP=NULL; //THIS->sRemoteHostIP=NULL; //THIS->HostOrPath=NULL; //THIS->OnClose=NULL; /* if (MISSING (sPath) ) return; if (!STRING (sPath) ) return; retval=IsHostPath(STRING(sPath),&buf,&nport); if (!retval) { GB.Error("Invalid Host / Path string"); return; } if (retval==2) { switch(CSocket_connect_unix(THIS,STRING(sPath),LENGTH(sPath))) { case 1: GB.Error("Socket is already connected. Close it first."); return; case 2: GB.Error("Invalid Path length"); return; } return; } if (retval==1) { if (!buf) { GB.Error("Invalid host name"); return; } if (nport < 1) { GB.Error("Invalid Port"); return; } retval=CSocket_connect_socket(THIS,buf,strlen(buf),nport ); GB.Free((void**)&buf); switch(retval) { case 1: GB.Error("Socket is already connected. Close it first."); return; case 8: GB.Error("Port value out of range."); return; case 9: GB.Error("Invalid Host Name."); return; } return; } */END_METHOD/************************************************** Gambas object "Destructor" **************************************************/BEGIN_METHOD_VOID(CSOCKET_free) if (THIS->DnsTool) { dns_close_all(THIS->DnsTool); GB.Unref((void**)&THIS->DnsTool); THIS->DnsTool=NULL; } if (THIS->iStatus>0) { GB.Watch (THIS->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0); THIS->stream.desc=NULL; close(THIS->Socket); if (THIS->OnClose) THIS->OnClose((void*)THIS); THIS->iStatus=0; } GB.FreeString(&THIS->sPath); GB.FreeString(&THIS->sLocalHostIP); GB.FreeString(&THIS->sRemoteHostIP); // $BM GB.FreeString(&THIS->Host); GB.FreeString(&THIS->Path);END_METHODBEGIN_METHOD_VOID(CSOCKET_exit) END_METHOD/************************************************************* To Peek data arrived from the other side of the socket **************************************************************/BEGIN_METHOD_VOID(CSOCKET_Peek) char *buf=NULL; int retval=0; if (THIS->iStatus != 7) /* if socket is not connected we can't receive anything */ { GB.Error("Socket is not active. Connect it first."); return; } retval=CSocket_peek_data(THIS,&buf,0); if (retval==-1) { /* An error happened while trying to receive data : SOCKET ERROR */ if (buf) GB.Free((void**)&buf); GB.ReturnNewString(NULL,0); return; } if ( retval>0) GB.ReturnNewString (buf,retval); else GB.ReturnNewString (NULL,0); if (buf) GB.Free((void**)&buf);END_METHOD/************************************************************************** To start a TCP or UNIX connection **************************************************************************/ // $BM BEGIN_METHOD(CSOCKET_Connect,GB_STRING HostOrPath;GB_INTEGER Port;) int port; int err; port = VARGOPT(Port, THIS->iUsePort); if (!port) { if (MISSING(HostOrPath)) err = CSocket_connect_unix(THIS,THIS->Path,GB.StringLength(THIS->Path)); else err = CSocket_connect_unix(THIS,STRING(HostOrPath),LENGTH(HostOrPath)); } else { if (MISSING(HostOrPath)) err = CSocket_connect_socket(THIS,THIS->Host,GB.StringLength(THIS->Host),port); else err = CSocket_connect_socket(THIS,STRING(HostOrPath),LENGTH(HostOrPath),port); } switch (err) { case 1: GB.Error("Socket is already connected. Close it first."); return; case 2: GB.Error("Invalid Path length"); return; case 8: GB.Error("Port value out of range."); return; case 9: GB.Error("Invalid Host Name."); return; }END_METHOD/********************************************************** Here we declare public structure of Socket Class ***********************************************************/GB_DESC CSocketDesc[] ={ GB_DECLARE("Socket", sizeof(CSOCKET)), GB_INHERITS(".Stream"), GB_EVENT("Error", NULL, NULL, &SocketError), GB_EVENT("Read", NULL, NULL, &Socket_Read), GB_EVENT("Ready", NULL, NULL, &Connected), GB_EVENT("Closed", NULL, NULL, &Closed), GB_EVENT("Found", NULL, NULL, &HostFound), GB_STATIC_METHOD ( "_exit" , NULL , CSOCKET_exit , NULL ), //GB_METHOD("_new", NULL, CSOCKET_new, "[(Path)s]"), GB_METHOD("_new", NULL, CSOCKET_new, NULL), GB_METHOD("_free", NULL, CSOCKET_free, NULL), GB_METHOD("Peek", "s", CSOCKET_Peek, NULL), GB_METHOD("Connect",NULL, CSOCKET_Connect,"[(HostOrPath)s(Port)i]"), GB_PROPERTY_READ("Status", "i", CSOCKET_Status), GB_PROPERTY_READ("RemotePort", "i", CSOCKET_RemotePort), GB_PROPERTY_READ("LocalPort", "i", CSOCKET_LocalPort), GB_PROPERTY_READ("RemoteHost", "s", CSOCKET_RemoteHost), GB_PROPERTY_READ("LocalHost","s",CSOCKET_LocalHost), GB_PROPERTY("Host","s",CSOCKET_Host), GB_PROPERTY("Path","s",CSOCKET_Path), GB_PROPERTY("Port","i",CSOCKET_Port), GB_CONSTANT("_Properties", "s", "Host,Path,Port=80"), GB_CONSTANT("_DefaultEvent", "s", "Read"), GB_END_DECLARE};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -