📄 cudpsocket.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 + -