2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
|
|
|
CSocket.c
|
|
|
|
|
|
|
|
Network component
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
(c) 2003-2004 Daniel Campos Fernández <dcamposf@gmail.com>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
This is the implementation of Socket Gambas Class
|
|
|
|
|
|
|
|
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 __CSOCKET_C
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "tools.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "CSocket.h"
|
|
|
|
#include "CServerSocket.h"
|
|
|
|
#include "CDnsClient.h"
|
|
|
|
#define MAX_CLIENT_BUFFER_SIZE 65536
|
|
|
|
#define UNIXPATHMAX 108
|
|
|
|
|
|
|
|
DECLARE_EVENT (SocketError);
|
|
|
|
DECLARE_EVENT (Closed);
|
|
|
|
DECLARE_EVENT (HostFound);
|
|
|
|
DECLARE_EVENT (Socket_Read);
|
|
|
|
DECLARE_EVENT (Connected);
|
|
|
|
|
|
|
|
|
|
|
|
GB_STREAM_DESC SocketStream = {
|
|
|
|
open: CSocket_stream_open,
|
|
|
|
close: CSocket_stream_close,
|
|
|
|
read: CSocket_stream_read,
|
|
|
|
write: CSocket_stream_write,
|
|
|
|
seek: CSocket_stream_seek,
|
|
|
|
tell: CSocket_stream_tell,
|
|
|
|
flush: CSocket_stream_flush,
|
|
|
|
eof: CSocket_stream_eof,
|
|
|
|
lof: CSocket_stream_lof,
|
|
|
|
handle: CSocket_stream_handle
|
|
|
|
};
|
2008-01-17 22:39:26 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
/**********************************
|
|
|
|
Routines to call events
|
|
|
|
**********************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_post_error(void *_object)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Raise(THIS,SocketError,0);
|
|
|
|
GB.Unref(POINTER(&_object));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_post_closed(void *_object)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Raise(THIS,Closed,0);
|
|
|
|
GB.Unref(POINTER(&_object));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_post_hostfound(void *_object)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Raise(THIS,HostFound,0);
|
|
|
|
GB.Unref(POINTER(&_object));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_post_connected(void *_object)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Raise(THIS,Connected,0);
|
|
|
|
GB.Unref(POINTER(&_object));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_post_data_available(void *_object)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->iStatus==7) GB.Raise(THIS,Socket_Read,0);
|
|
|
|
GB.Unref(POINTER(&_object));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************
|
|
|
|
This function is called by DnsClient to inform
|
|
|
|
that it has finished its work
|
|
|
|
*************************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_CallBackFromDns(void *_object)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
int NoBlock=1;
|
|
|
|
int myval=0;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if ( THIS->iStatus != 5) return;
|
|
|
|
if ( !THIS->DnsTool->sHostIP)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=-6; /* error host not found */
|
|
|
|
dns_close_all(THIS->DnsTool);
|
|
|
|
GB.Unref(POINTER(&THIS->DnsTool));
|
|
|
|
THIS->DnsTool=NULL;
|
|
|
|
GB.Ref (THIS);
|
|
|
|
GB.Post (CSocket_post_error,(intptr_t)THIS);
|
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.FreeString (&THIS->sRemoteHostIP);
|
|
|
|
GB.NewString ( &THIS->sRemoteHostIP ,THIS->DnsTool->sHostIP,0);
|
2007-12-30 17:41:49 +01:00
|
|
|
/* Let's turn socket to async mode */
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
2007-12-30 17:41:49 +01:00
|
|
|
/* Third, we connect the socket */
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->Server.sin_family=AF_INET;
|
|
|
|
THIS->Server.sin_port=htons(THIS->iPort);
|
|
|
|
THIS->Server.sin_addr.s_addr =inet_addr(THIS->DnsTool->sHostIP);
|
|
|
|
bzero(&(THIS->Server.sin_zero),8);
|
|
|
|
myval=connect(THIS->Socket,(struct sockaddr*)&(THIS->Server), sizeof(struct sockaddr));
|
2007-12-30 17:41:49 +01:00
|
|
|
if (errno==EINPROGRESS) /* this is the good answer : connect in progress */
|
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=6;
|
|
|
|
GB.Watch (THIS->Socket,GB_WATCH_WRITE,(void *)CSocket_CallBackConnecting,(long)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);
|
|
|
|
THIS->stream.desc=NULL;
|
|
|
|
close(THIS->Socket);
|
|
|
|
THIS->iStatus=0;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->DnsTool)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
dns_close_all(THIS->DnsTool);
|
|
|
|
GB.Unref(POINTER(&THIS->DnsTool));
|
|
|
|
THIS->DnsTool=NULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
if ( THIS->iStatus<=0 )
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=-3;
|
|
|
|
GB.Ref (THIS);
|
|
|
|
GB.Post (CSocket_post_error,(intptr_t)THIS);
|
|
|
|
if (THIS->OnClose) THIS->OnClose((void*)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Ref(THIS);
|
|
|
|
GB.Post(CSocket_post_hostfound,(intptr_t)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
This CallBack is used while waiting to finish a connection process
|
|
|
|
******************************************************************/
|
|
|
|
void CSocket_CallBackConnecting(int t_sock,int type,long lParam)
|
|
|
|
{
|
|
|
|
struct sockaddr_in myhost;
|
|
|
|
int mylen;
|
|
|
|
struct timespec mywait;
|
2008-02-15 12:12:55 +01:00
|
|
|
void *_object;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/* Just sleeping a little to reduce CPU waste */
|
|
|
|
mywait.tv_sec=0;
|
|
|
|
mywait.tv_nsec=1000000;
|
|
|
|
nanosleep(&mywait,NULL);
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
_object=(void*)lParam;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->iStatus!=6) return;
|
2007-12-30 17:41:49 +01:00
|
|
|
/****************************************************
|
|
|
|
Checks if Connection was Stablished or there was
|
|
|
|
an error trying to connect
|
|
|
|
****************************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=CheckConnection(THIS->Socket);
|
|
|
|
if (THIS->iStatus == 0)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);
|
|
|
|
THIS->stream.desc=NULL;
|
|
|
|
close(THIS->Socket);
|
|
|
|
THIS->iStatus=-3;
|
|
|
|
GB.Ref (THIS);
|
|
|
|
GB.Post (CSocket_post_error,(intptr_t)THIS);
|
|
|
|
if (THIS->OnClose) THIS->OnClose((void*)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->iStatus != 7) return;
|
2007-12-30 17:41:49 +01:00
|
|
|
// we obtain local IP and host
|
|
|
|
mylen=sizeof(struct sockaddr);
|
2008-02-15 12:12:55 +01:00
|
|
|
getsockname (THIS->Socket,(struct sockaddr*)&myhost,(socklen_t *)&mylen);
|
|
|
|
THIS->iLocalPort=ntohs(myhost.sin_port);
|
|
|
|
GB.FreeString( &THIS->sLocalHostIP);
|
|
|
|
GB.NewString ( &THIS->sLocalHostIP ,inet_ntoa(myhost.sin_addr),0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket,GB_WATCH_NONE,(void *)CSocket_CallBack,(long)THIS);
|
|
|
|
GB.Watch (THIS->Socket,GB_WATCH_WRITE,(void *)CSocket_CallBack,(long)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->stream.desc=&SocketStream;
|
|
|
|
GB.Ref(THIS);
|
|
|
|
GB.Post(CSocket_post_connected,(intptr_t)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
This CallBack is used while socket is connected to remote host
|
|
|
|
******************************************************************/
|
|
|
|
void CSocket_CallBack(int t_sock,int type,long lParam)
|
|
|
|
{
|
|
|
|
char buf[1];
|
|
|
|
struct pollfd mypoll;
|
|
|
|
int numpoll;
|
|
|
|
struct timespec mywait;
|
2008-02-15 12:12:55 +01:00
|
|
|
void *_object;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/* Just sleeping a little to reduce CPU waste */
|
|
|
|
mywait.tv_sec=0;
|
|
|
|
mywait.tv_nsec=100000;
|
|
|
|
nanosleep(&mywait,NULL);
|
|
|
|
/* is there data avilable or an error? */
|
2008-02-15 12:12:55 +01:00
|
|
|
_object=(void*)lParam;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->iStatus!=7) return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
mypoll.fd=t_sock;
|
|
|
|
mypoll.events=POLLIN | POLLNVAL;
|
|
|
|
mypoll.revents=0;
|
|
|
|
numpoll=poll(&mypoll,1,0);
|
|
|
|
if (numpoll<=0) return;
|
|
|
|
/* there's data available */
|
|
|
|
USE_MSG_NOSIGNAL(numpoll=recv(t_sock,(void*)buf,sizeof(char),MSG_PEEK | MSG_NOSIGNAL));
|
|
|
|
if (!numpoll)
|
|
|
|
{ /* socket error, no valid data received */
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);
|
|
|
|
THIS->stream.desc=NULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
close(t_sock);
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=0;
|
|
|
|
GB.Ref(THIS);
|
|
|
|
GB.Post(CSocket_post_closed,(intptr_t)THIS);
|
|
|
|
if (THIS->OnClose) THIS->OnClose((void*)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/******************************************************
|
|
|
|
There's data available to read, so we'll raise event
|
|
|
|
Socket_Read
|
|
|
|
*******************************************************/
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Ref(_object);
|
|
|
|
GB.Post(CSocket_post_data_available,(intptr_t)THIS);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
void CSocket_stream_internal_error(void *_object,int ncode)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
/* fatal socket error handling */
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket,GB_WATCH_NONE,(void *)CSocket_CallBack,0);
|
|
|
|
THIS->stream.desc=NULL;
|
|
|
|
close(THIS->Socket);
|
|
|
|
THIS->iStatus = ncode;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//################################################################################
|
|
|
|
/*********************************************************************************
|
|
|
|
"PUBLIC" C/C++ INTERFACE
|
|
|
|
**********************************************************************************/
|
|
|
|
//################################################################################
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/* not allowed methods */
|
|
|
|
int CSocket_stream_open(GB_STREAM *stream, const char *path, int mode, void *data){return -1;}
|
2008-01-17 22:39:26 +01:00
|
|
|
int CSocket_stream_seek(GB_STREAM *stream, int64_t pos, int whence){return -1;}
|
|
|
|
int CSocket_stream_tell(GB_STREAM *stream, int64_t *pos){return -1;}
|
2007-12-30 17:41:49 +01:00
|
|
|
int CSocket_stream_flush(GB_STREAM *stream)
|
|
|
|
{
|
|
|
|
return 0; /* OK */
|
|
|
|
}
|
|
|
|
int CSocket_stream_handle(GB_STREAM *stream)
|
|
|
|
{
|
|
|
|
return 0; /* OK */
|
|
|
|
}
|
|
|
|
int CSocket_stream_close(GB_STREAM *stream)
|
|
|
|
{
|
2008-10-04 14:31:49 +02:00
|
|
|
void *_object = stream->tag;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (!THIS ) return -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->DnsTool)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
dns_close_all(THIS->DnsTool);
|
|
|
|
GB.Unref(POINTER(&THIS->DnsTool));
|
|
|
|
THIS->DnsTool=NULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->iStatus > 0) /* if it's not connected, does nothing */
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);
|
2007-12-30 17:41:49 +01:00
|
|
|
stream->desc=NULL;
|
2008-02-15 12:12:55 +01:00
|
|
|
close(THIS->Socket);
|
|
|
|
THIS->iStatus=0;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2008-01-17 22:39:26 +01:00
|
|
|
int CSocket_stream_lof(GB_STREAM *stream, int64_t *len)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-04 14:31:49 +02:00
|
|
|
void *_object = stream->tag;
|
2007-12-30 17:41:49 +01:00
|
|
|
int bytes;
|
|
|
|
|
|
|
|
*len=0;
|
2008-02-15 12:12:55 +01:00
|
|
|
if (!THIS) return -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (ioctl(THIS->Socket,FIONREAD,&bytes))
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
CSocket_stream_internal_error(THIS,-4);
|
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*len=bytes;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int CSocket_stream_eof(GB_STREAM *stream)
|
|
|
|
{
|
2008-10-04 14:31:49 +02:00
|
|
|
void *_object = stream->tag;
|
2007-12-30 17:41:49 +01:00
|
|
|
int bytes;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (!THIS) return -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (ioctl(THIS->Socket,FIONREAD,&bytes))
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
CSocket_stream_internal_error(THIS,-4);
|
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!bytes) return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
int CSocket_stream_read(GB_STREAM *stream, char *buffer, int len)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-04 14:31:49 +02:00
|
|
|
void *_object = stream->tag;
|
|
|
|
int npos=-1;
|
|
|
|
int NoBlock=0;
|
2007-12-30 17:41:49 +01:00
|
|
|
int bytes;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (!THIS) return -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (ioctl(THIS->Socket,FIONREAD,&bytes))
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
CSocket_stream_internal_error(THIS,-4);
|
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (bytes < len) return -1;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
|
|
|
USE_MSG_NOSIGNAL(npos=recv(THIS->Socket,(void*)buffer,len*sizeof(char),MSG_NOSIGNAL));
|
2007-12-30 17:41:49 +01:00
|
|
|
NoBlock++;
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
2007-12-30 17:41:49 +01:00
|
|
|
if (npos==len) return 0;
|
|
|
|
if (npos<0)
|
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
CSocket_stream_internal_error(THIS,-4);
|
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
int CSocket_stream_write(GB_STREAM *stream, char *buffer, int len)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-04 14:31:49 +02:00
|
|
|
void *_object = stream->tag;
|
2007-12-30 17:41:49 +01:00
|
|
|
int npos=-1;
|
|
|
|
int NoBlock=0;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (!THIS) return -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
|
|
|
USE_MSG_NOSIGNAL(npos=send(THIS->Socket,(void*)buffer,len*sizeof(char),MSG_NOSIGNAL));
|
2007-12-30 17:41:49 +01:00
|
|
|
NoBlock++;
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
2007-12-30 17:41:49 +01:00
|
|
|
if (npos>=0) return 0;
|
2008-02-15 12:12:55 +01:00
|
|
|
CSocket_stream_internal_error(THIS,-5);
|
|
|
|
if (THIS->OnClose) THIS->OnClose(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
To start a UNIX connection
|
|
|
|
**************************************************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
int CSocket_connect_unix(void *_object,char *sPath,int lenpath)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
int NoBlock=1;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if ( THIS->iStatus > 0 ) return 1;
|
2007-12-30 17:41:49 +01:00
|
|
|
if (!sPath) return 7;
|
|
|
|
if ( (lenpath<1) || (lenpath>UNIXPATHMAX) ) return 7;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.FreeString(&THIS->sRemoteHostIP);
|
|
|
|
GB.FreeString(&THIS->sLocalHostIP);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->UServer.sun_family=AF_UNIX;
|
|
|
|
strcpy(THIS->UServer.sun_path,sPath);
|
|
|
|
if ( (THIS->Socket=socket(AF_UNIX,SOCK_STREAM,0))==-1 )
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=-2;
|
|
|
|
GB.Ref (THIS);
|
|
|
|
CSocket_post_error(_object); /* Unable to create socket */
|
2007-12-30 17:41:49 +01:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.FreeString(&THIS->sPath);
|
|
|
|
GB.NewString ( &THIS->sPath , THIS->UServer.sun_path ,0);
|
|
|
|
THIS->conn_type=1;
|
|
|
|
if (connect(THIS->Socket,(struct sockaddr*)&THIS->UServer,sizeof(struct sockaddr_un))==0)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=7;
|
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
|
|
|
GB.Watch (THIS->Socket,GB_WATCH_WRITE,(void *)CSocket_CallBack,(long)THIS);
|
|
|
|
THIS->stream.desc=&SocketStream;
|
2007-12-30 17:41:49 +01:00
|
|
|
// $BM
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->Host) GB.FreeString(&THIS->Host);
|
|
|
|
if (THIS->Path) GB.FreeString(&THIS->Path);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.NewString(&THIS->Path,sPath,0);
|
|
|
|
GB.Ref (THIS);
|
|
|
|
CSocket_post_connected(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* Error */
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->stream.desc=NULL;
|
|
|
|
close(THIS->Socket);
|
|
|
|
GB.FreeString(&THIS->sPath);
|
|
|
|
THIS->iStatus=-3;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Ref (THIS);
|
|
|
|
CSocket_post_error(_object); /* Unable to connect to remote host */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
To start a TCP connection
|
|
|
|
**************************************************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
int CSocket_connect_socket(void *_object,char *sHost,int lenhost,int myport)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
if ( THIS->iStatus > 0 ) return 1;
|
2007-12-30 17:41:49 +01:00
|
|
|
if (!lenhost) return 9;
|
|
|
|
if (!sHost) return 9;
|
|
|
|
if ( (myport<1) || (myport>65535) ) return 8;
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.FreeString(&THIS->sRemoteHostIP);
|
|
|
|
GB.FreeString(&THIS->sLocalHostIP);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if ( (THIS->Socket=socket(AF_INET,SOCK_STREAM,0))==-1 )
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=-2;
|
|
|
|
GB.Ref (THIS);
|
|
|
|
CSocket_post_error(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iPort=myport;
|
|
|
|
THIS->conn_type=0;
|
2007-12-30 17:41:49 +01:00
|
|
|
/******************************************
|
|
|
|
Let's turn hostname into host IP
|
|
|
|
*******************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
if (!THIS->DnsTool)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.New(POINTER(&THIS->DnsTool),GB.FindClass("DnsClient"),NULL,NULL);
|
|
|
|
THIS->DnsTool->CliParent=_object;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->DnsTool->iStatus > 0 ) dns_close_all(THIS->DnsTool);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
dns_set_async_mode(1,THIS->DnsTool);
|
|
|
|
GB.FreeString (&(THIS->DnsTool->sHostName));
|
|
|
|
GB.NewString(&THIS->DnsTool->sHostName,sHost,lenhost);
|
|
|
|
THIS->DnsTool->finished_callback=CSocket_CallBackFromDns;
|
2007-12-30 17:41:49 +01:00
|
|
|
/********************************************
|
|
|
|
We start DNS lookup, when it is finished
|
|
|
|
it will call to CSocket_CallBack_fromDns,
|
|
|
|
and we'll continue there connection proccess
|
|
|
|
********************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
THIS->iStatus=5; /* looking for IP */
|
|
|
|
dns_thread_getip(THIS->DnsTool);
|
|
|
|
THIS->stream.desc=&SocketStream;
|
|
|
|
THIS->iUsePort=THIS->iPort;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
// $BM
|
2008-02-15 12:12:55 +01:00
|
|
|
if (THIS->Host) GB.FreeString(&THIS->Host);
|
|
|
|
if (THIS->Path) GB.FreeString(&THIS->Path);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.NewString(&THIS->Host,sHost,0);
|
2007-12-30 17:41:49 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************
|
|
|
|
This function is used to peek data from socket,
|
|
|
|
you have to pass 3 parameters:
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
_object-> CSocket object
|
2007-12-30 17:41:49 +01:00
|
|
|
buf -> Data Buffer (you have to free it after using it!)
|
|
|
|
MaxLen -> 0 no limit, >0 max. data t read
|
|
|
|
***********************************************/
|
2008-02-15 12:12:55 +01:00
|
|
|
int CSocket_peek_data(void *_object,char **buf,int MaxLen)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
int retval=0;
|
|
|
|
int NoBlock=0;
|
|
|
|
int nread=0;
|
|
|
|
int bytes=0;
|
|
|
|
|
|
|
|
(*buf)=NULL;
|
2008-02-15 12:12:55 +01:00
|
|
|
nread=ioctl(THIS->Socket,FIONREAD,&bytes); /* Is there anythig to read? */
|
2007-12-30 17:41:49 +01:00
|
|
|
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';
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
|
|
|
USE_MSG_NOSIGNAL(retval=recv(THIS->Socket,(void*)(*buf),bytes*sizeof(char),MSG_PEEK|MSG_NOSIGNAL));
|
2007-12-30 17:41:49 +01:00
|
|
|
NoBlock++;
|
2008-02-15 12:12:55 +01:00
|
|
|
ioctl(THIS->Socket,FIONBIO,&NoBlock);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (retval==-1)
|
|
|
|
{
|
|
|
|
/* An error happened while trying to receive data : SOCKET ERROR */
|
|
|
|
if (*buf)
|
|
|
|
{
|
|
|
|
GB.Free(POINTER(buf));
|
|
|
|
buf=NULL;
|
|
|
|
}
|
2008-02-15 12:12:55 +01:00
|
|
|
GB.Watch (THIS->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);
|
|
|
|
THIS->stream.desc=NULL;
|
|
|
|
close(THIS->Socket);
|
|
|
|
THIS->iStatus=-4;
|
|
|
|
GB.Ref (THIS);
|
|
|
|
CSocket_post_error(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
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
|
|
|
|
**********************************************************************/
|
|
|
|
// $BM
|
|
|
|
|
|
|
|
BEGIN_PROPERTY (CSOCKET_Host)
|
|
|
|
|
|
|
|
if (READ_PROPERTY)
|
|
|
|
{
|
|
|
|
GB.ReturnNewString(THIS->Host,0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
GB.StoreString(PROP(GB_STRING), &THIS->Host);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
BEGIN_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_VOID(CSOCKET_new)
|
|
|
|
|
2008-10-04 14:31:49 +02:00
|
|
|
THIS->stream.tag = THIS;
|
|
|
|
THIS->iUsePort = 80;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
/**************************************************
|
|
|
|
Gambas object "Destructor"
|
|
|
|
**************************************************/
|
|
|
|
BEGIN_METHOD_VOID(CSOCKET_free)
|
|
|
|
|
|
|
|
if (THIS->DnsTool)
|
|
|
|
{
|
|
|
|
dns_close_all(THIS->DnsTool);
|
|
|
|
GB.Unref(POINTER(&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_METHOD
|
|
|
|
|
|
|
|
BEGIN_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 */
|
|
|
|
{
|
2008-10-04 14:31:49 +02:00
|
|
|
GB.Error("Socket is not active. Connect it first");
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-15 12:12:55 +01:00
|
|
|
retval=CSocket_peek_data(_object,&buf,0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (retval==-1)
|
|
|
|
{
|
|
|
|
/* An error happened while trying to receive data : SOCKET ERROR */
|
|
|
|
if (buf) GB.Free(POINTER(&buf));
|
|
|
|
GB.ReturnNewString(NULL,0);
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( retval>0)
|
|
|
|
GB.ReturnNewString (buf,retval);
|
|
|
|
else
|
|
|
|
GB.ReturnNewString (NULL,0);
|
|
|
|
|
|
|
|
if (buf) GB.Free(POINTER(&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))
|
2008-02-15 12:12:55 +01:00
|
|
|
err = CSocket_connect_unix(_object,THIS->Path,GB.StringLength(THIS->Path));
|
2007-12-30 17:41:49 +01:00
|
|
|
else
|
2008-02-15 12:12:55 +01:00
|
|
|
err = CSocket_connect_unix(_object,STRING(HostOrPath),LENGTH(HostOrPath));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (MISSING(HostOrPath))
|
2008-02-15 12:12:55 +01:00
|
|
|
err = CSocket_connect_socket(_object,THIS->Host,GB.StringLength(THIS->Host),port);
|
2007-12-30 17:41:49 +01:00
|
|
|
else
|
2008-02-15 12:12:55 +01:00
|
|
|
err = CSocket_connect_socket(_object,STRING(HostOrPath),LENGTH(HostOrPath),port);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (err)
|
|
|
|
{
|
|
|
|
case 1: GB.Error("Socket is already connected"); return;
|
|
|
|
case 2: GB.Error("Invalid path length"); return;
|
2008-10-04 14:31:49 +02:00
|
|
|
case 8: GB.Error("Port value out of range"); return;
|
|
|
|
case 9: GB.Error("Invalid host name"); return;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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, 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
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|