⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cudpsocket.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  CUdpSocket.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 __CUDPSOCKET_C#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/poll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <time.h>#include "main.h"#include "tools.h"#include "CUdpSocket.h"GB_STREAM_DESC UdpSocketStream = {	CUdpSocket_stream_open,	CUdpSocket_stream_close,	CUdpSocket_stream_read,	CUdpSocket_stream_write,	CUdpSocket_stream_seek,	CUdpSocket_stream_tell,	CUdpSocket_stream_flush,	CUdpSocket_stream_eof,	CUdpSocket_stream_lof};DECLARE_EVENT (CUDPSOCKET_Read);DECLARE_EVENT (CUDPSOCKET_SocketError);void CUdpSocket_post_data(long Param){	CUDPSOCKET *t_obj;	t_obj=(CUDPSOCKET*)Param;	GB.Raise(t_obj,CUDPSOCKET_Read,0);	GB.Unref((void**)&t_obj);}void CUdpSocket_post_error(long Param){	CUDPSOCKET *t_obj;	t_obj=(CUDPSOCKET*)Param;	GB.Raise(t_obj,CUDPSOCKET_SocketError,0);	GB.Unref((void**)&t_obj);}void CUdpSocket_CallBack(int t_sock,int type,long param){	char buf[1];	int numpoll;	struct sockaddr_in t_test;	int t_test_len;	struct timespec mywait;	CUDPSOCKET *t_obj;	/*	Just sleeping a little to reduce CPU waste	*/	mywait.tv_sec=0;	mywait.tv_nsec=100000;	nanosleep(&mywait,NULL);		t_obj=(CUDPSOCKET*)param;	if (t_obj->iStatus<=0) return;		t_test.sin_port=0;	t_test_len=sizeof(struct sockaddr);			USE_MSG_NOSIGNAL(numpoll=recvfrom(t_sock,(void*)buf, sizeof(char), MSG_PEEK | MSG_NOSIGNAL \		              , (struct sockaddr*)&t_test, &t_test_len));	if (t_test.sin_port)	{		GB.Ref((void*)t_obj);		GB.Post(CUdpSocket_post_data,(long)t_obj);	}}/* not allowed methods */int CUdpSocket_stream_open(GB_STREAM *stream, const char *path, int mode, void *data){return -1;}int CUdpSocket_stream_seek(GB_STREAM *stream, long pos, int whence){return -1;}int CUdpSocket_stream_tell(GB_STREAM *stream, long *pos){ 	*pos=0;	return -1; /* not allowed */}int CUdpSocket_stream_flush(GB_STREAM *stream){	return 0; /* OK */}int CUdpSocket_stream_close(GB_STREAM *stream){	CUDPSOCKET *mythis;		if ( !(mythis=(CUDPSOCKET*)stream->_free[0]) ) return -1;	stream->desc=NULL;	if (mythis->iStatus > 0)	{		GB.Watch (mythis->Socket,GB_WATCH_NONE,(void *)CUdpSocket_CallBack,(long)mythis);		close(mythis->Socket);		mythis->iStatus=0;	}	if (mythis->shost) GB.FreeString(&mythis->shost);	if (mythis->thost) GB.FreeString(&mythis->thost);	mythis->shost=NULL;	mythis->thost=NULL;	mythis->sport=0;	mythis->tport=0;	mythis->iStatus=0;	return 0;}int CUdpSocket_stream_lof(GB_STREAM *stream, long *len){	CUDPSOCKET *mythis;	int bytes;	if ( !(mythis=(CUDPSOCKET*)stream->_free[0]) ) return -1;	if (ioctl(mythis->Socket,FIONREAD,&bytes))	{		CUdpSocket_stream_close(stream);		mythis->iStatus=-4;		return -1;	}	*len=bytes;	return 0;}int CUdpSocket_stream_eof(GB_STREAM *stream){	CUDPSOCKET *mythis;	int bytes;	if ( !(mythis=(CUDPSOCKET*)stream->_free[0]) ) return -1;	if (ioctl(mythis->Socket,FIONREAD,&bytes))	{		CUdpSocket_stream_close(stream);		mythis->iStatus=-4;		return -1;	}	if (!bytes) return -1;	return 0;}int CUdpSocket_stream_read(GB_STREAM *stream, char *buffer, long len){	CUDPSOCKET *mythis;    	int retval;	int bytes=0;	int NoBlock=0;	int rem_host_len;	struct sockaddr_in remhost;		if ( !(mythis=(CUDPSOCKET*)stream->_free[0]) ) return -1;	if (ioctl(mythis->Socket,FIONREAD,&bytes))	{		CUdpSocket_stream_close(stream);		mythis->iStatus=-4;		return -1;	}	if (bytes<len) return -1;	rem_host_len=sizeof(struct sockaddr);	ioctl(mythis->Socket,FIONBIO,&NoBlock);	USE_MSG_NOSIGNAL(retval=recvfrom(mythis->Socket,(void*)buffer,len*sizeof(char) \	       ,MSG_NOSIGNAL,(struct sockaddr*)&remhost,&rem_host_len));	NoBlock++;	ioctl(mythis->Socket,FIONBIO,&NoBlock);	if (retval<0)	{		CUdpSocket_stream_close(&mythis->stream);		mythis->iStatus=-4;		return -1;	}	mythis->sport=ntohs(remhost.sin_port);	GB.FreeString(&mythis->shost);	GB.NewString (&mythis->shost , inet_ntoa(remhost.sin_addr) ,0);	return 0;}int CUdpSocket_stream_write(GB_STREAM *stream, char *buffer, long len){	CUDPSOCKET *mythis;    	int retval;	int NoBlock=0;	struct sockaddr_in remhost;	struct in_addr rem_ip;	if ( !(mythis=(CUDPSOCKET*)stream->_free[0]) ) return -1;		if (!mythis->thost) return -1;	if ( (mythis->tport<1) || (mythis->tport>65535) ) return -1;	if (!inet_aton ( (const char*)mythis->thost,&rem_ip)) return -1;	remhost.sin_family=AF_INET;	remhost.sin_port=htons(mythis->tport);	remhost.sin_addr.s_addr=rem_ip.s_addr;	bzero(&(remhost.sin_zero),8);	ioctl(mythis->Socket,FIONBIO,&NoBlock);	USE_MSG_NOSIGNAL(retval=sendto(mythis->Socket,(void*)buffer,len*sizeof(char) \		              ,MSG_NOSIGNAL,(struct sockaddr*)&remhost,sizeof(struct sockaddr)));	NoBlock++;	ioctl(mythis->Socket,FIONBIO,&NoBlock);	if (retval>=0) return 0;	CUdpSocket_stream_close(stream);	mythis->iStatus= -5;	return -1;}/************************************************************************************************ ################################################################################################ --------------------UDPSOCKET CLASS GAMBAS INTERFACE IMPLEMENTATION------------------------------ ################################################################################################ ***********************************************************************************************//********************************************************** This property gets status : 0 --> Inactive, 1 --> Working **********************************************************/BEGIN_PROPERTY ( CUDPSOCKET_Status )  GB.ReturnInteger(THIS->iStatus);END_PROPERTYBEGIN_PROPERTY ( CUDPSOCKET_SourceHost )  GB.ReturnString(THIS->shost);END_PROPERTYBEGIN_PROPERTY ( CUDPSOCKET_SourcePort )  GB.ReturnInteger(THIS->sport);END_PROPERTYBEGIN_PROPERTY ( CUDPSOCKET_TargetHost )  	char *strtmp;  	struct in_addr rem_ip;  	if (READ_PROPERTY)  	{  		GB.ReturnString(THIS->thost);		return;  	}  	strtmp=GB.ToZeroString(PROP(GB_STRING));  	if ( !inet_aton(strtmp,&rem_ip) )	{		GB.Error ("Invalid IP address");		return;	}  	GB.StoreString(PROP(GB_STRING), &THIS->thost);END_PROPERTYBEGIN_PROPERTY ( CUDPSOCKET_TargetPort )  if (READ_PROPERTY)  {  	GB.ReturnInteger(THIS->sport);	return;  }  if ( (VPROP(GB_INTEGER)<1) || (VPROP(GB_INTEGER)>65535) )  {  	GB.Error("Invalid Port value");	return;  }  THIS->tport=VPROP(GB_INTEGER);END_PROPERTY/************************************************* Gambas object "Constructor" *************************************************/BEGIN_METHOD(CUDPSOCKET_new,GB_INTEGER Port;)  THIS->iStatus=0;  THIS->iPort=0;  THIS->shost=NULL;  THIS->thost=NULL;  THIS->sport=0;  THIS->tport=0;  if (MISSING (Port) ) return;  dgram_start(THIS,VARG(Port));END_METHOD/************************************************* Gambas object "Destructor" *************************************************/BEGIN_METHOD_VOID(CUDPSOCKET_free)	CUdpSocket_stream_close(&THIS->stream);END_METHODBEGIN_METHOD_VOID (CUDPSOCKET_Peek)	char *sData=NULL;	struct sockaddr_in remhost;	int rem_host_len;	int retval=0;	int NoBlock=0;	int peeking;	int bytes=0;	if (THIS->iStatus <= 0)	{		GB.Error ("Inactive");		return;	}		peeking=MSG_NOSIGNAL | MSG_PEEK;	ioctl(THIS->Socket,FIONREAD,&bytes);	if (bytes)	{		GB.Alloc( (void**)&sData,bytes*sizeof(char) );		rem_host_len=sizeof(struct sockaddr);		ioctl(THIS->Socket,FIONBIO,&NoBlock);		USE_MSG_NOSIGNAL(retval=recvfrom(THIS->Socket,(void*)sData,1024*sizeof(char) \		       ,peeking,(struct sockaddr*)&remhost,&rem_host_len));		if (retval<0)		{			GB.Free((void**)&sData);			CUdpSocket_stream_close(&THIS->stream);			THIS->iStatus=-4;			GB.Raise(THIS,CUDPSOCKET_SocketError,0);			GB.ReturnNewString(NULL,0);			return;		}		NoBlock++;		ioctl(THIS->Socket,FIONBIO,&NoBlock);		THIS->sport=ntohs(remhost.sin_port);		GB.FreeString(&THIS->shost);		GB.NewString ( &THIS->shost , inet_ntoa(remhost.sin_addr) ,0);		if (retval>0)			GB.ReturnNewString(sData,retval);		else			GB.ReturnNewString(NULL,0);		GB.Free((void**)&sData);	}	else	{		GB.FreeString(&THIS->shost);		THIS->shost=NULL;		THIS->sport=0;		GB.ReturnNewString(NULL,0);	}END_METHODint dgram_start(CUDPSOCKET *mythis,int myport){	int NoBlock=1;	struct sockaddr_in Srv;	if (mythis->iStatus > 0) return 1;	if ( (myport <0) || (myport>65535) ) return 8;	if ( (mythis->Socket = socket(AF_INET,SOCK_DGRAM,0))<1 )	{		mythis->iStatus=-2;		GB.Ref(mythis);		GB.Post(CUdpSocket_post_error,(long)mythis);		return 2;	}	Srv.sin_family=AF_INET;	Srv.sin_addr.s_addr=htonl(INADDR_ANY);	Srv.sin_port=htons(myport);	bzero(&(Srv.sin_zero),8);	if ( bind (mythis->Socket,(struct sockaddr*)&Srv,sizeof(struct sockaddr)) < 0)	{		close (mythis->Socket);		mythis->iStatus=-10;		GB.Ref(mythis);		GB.Post(CUdpSocket_post_error,(long)mythis);		return 10;	}	mythis->iStatus=1;	ioctl(mythis->Socket,FIONBIO,&NoBlock);	GB.Watch (mythis->Socket,GB_WATCH_WRITE,(void *)CUdpSocket_CallBack,(long)mythis);	mythis->stream.desc=&UdpSocketStream;	mythis->stream._free[0]=(long)mythis;	return 0;}BEGIN_METHOD (CUDPSOCKET_Bind,GB_INTEGER Port;)	switch( dgram_start(THIS,VARG(Port)) )	{		case 1:			GB.Error("Already working");			return;		case 8:			GB.Error("Port value is not valid.");			return;	}END_METHOD/*************************************************************** Here we declare the public interface of UdpSocket class ***************************************************************/GB_DESC CUdpSocketDesc[] ={  GB_DECLARE("UdpSocket", sizeof(CUDPSOCKET)),  GB_INHERITS(".Stream"),  GB_EVENT("Error", NULL, NULL, &CUDPSOCKET_SocketError),  GB_EVENT("Read", NULL, NULL, &CUDPSOCKET_Read),  GB_METHOD("_new", NULL, CUDPSOCKET_new, "[(Port)i]"),  GB_METHOD("_free", NULL, CUDPSOCKET_free, NULL),  GB_METHOD("Bind", NULL, CUDPSOCKET_Bind,"(Port)i"),  GB_METHOD("Peek","s",CUDPSOCKET_Peek,NULL),  GB_PROPERTY_READ("Status", "i", CUDPSOCKET_Status),  GB_PROPERTY_READ("SourceHost", "s", CUDPSOCKET_SourceHost),  GB_PROPERTY_READ("SourcePort", "i", CUDPSOCKET_SourcePort),  GB_PROPERTY("TargetHost", "s", CUDPSOCKET_TargetHost),  GB_PROPERTY("TargetPort", "i", CUDPSOCKET_TargetPort),    GB_CONSTANT("_Properties", "s", "TargetHost,TargetPort"),  GB_CONSTANT("_DefaultEvent", "s", "Read"),  GB_END_DECLARE};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -