📄 ccurl.c
字号:
/*************************************************************************** CCurl.c Advanced 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 __CCURL_C#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <curl/curl.h>#include <curl/easy.h>#include <curl/multi.h>#include "main.h"#include "gambas.h"#include "CCurl.h"#include "CProxy.h"DECLARE_EVENT (CURL_FINISHED);DECLARE_EVENT (CURL_ERROR);DECLARE_EVENT (CURL_CONNECT);DECLARE_EVENT (CURL_READ);/***************************************************** CURLM : a pointer to use curl_multi interface, allowing asynchrnous work without using threads in this class. ******************************************************/CURLM *CCURL_multicurl;int CCURL_pipe[]={-1,-1};/****************************************************** Events from this class ******************************************************/GB_STREAM_DESC CurlStream = { CCURL_stream_open, CCURL_stream_close, CCURL_stream_read, CCURL_stream_write, CCURL_stream_seek, CCURL_stream_tell, CCURL_stream_flush, CCURL_stream_eof, CCURL_stream_lof};////////////////////////////////////////////////////////////////////// STREAM ///////////////////////////////////////////////////////////////////////* not allowed stream methods */int CCURL_stream_open(GB_STREAM *stream, const char *path, int mode, void *data){return -1;}int CCURL_stream_seek(GB_STREAM *stream, long pos, int whence){ return -1;}int CCURL_stream_tell(GB_STREAM *stream, long *pos){return -1; }int CCURL_stream_flush(GB_STREAM *stream) { return 0;}int CCURL_stream_close(GB_STREAM *stream) { return -1;}int CCURL_stream_write(GB_STREAM *stream, char *buffer, long len){return -1;}int CCURL_stream_lof(GB_STREAM *stream, long *len){ void *_object; curl_easy_getinfo(stream->_free[1],CURLINFO_PRIVATE,(char**)&_object); *len=0; if ((THIS_STATUS !=4 ) && (THIS_STATUS != 0)) return -1; *len=THIS->len_data; return 0;}int CCURL_stream_eof(GB_STREAM *stream){ void *_object; curl_easy_getinfo(stream->_free[1],CURLINFO_PRIVATE,(char**)&_object); if ((THIS_STATUS !=4 ) && (THIS_STATUS != 0)) return -1; if (!THIS->len_data) return -1; return 0;}int CCURL_stream_read(GB_STREAM *stream, char *buffer, long len){ void *_object; curl_easy_getinfo(stream->_free[1],CURLINFO_PRIVATE,(char**)&_object); if ((THIS_STATUS !=4 ) && (THIS_STATUS != 0)) return -1; if (THIS->len_data < len) return -1; memcpy(buffer,THIS->buf_data,len); if (THIS->len_data == len) { THIS->len_data=0; GB.Free((void**)&THIS->buf_data); return 0; } THIS->len_data-=len; memmove(THIS->buf_data,len+THIS->buf_data,THIS->len_data); GB.Realloc((void**)&THIS->buf_data,THIS->len_data); return 0;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*******************************************************************#################################################################### POSTED FUNCTIONS TO RAISE EVENTS####################################################################********************************************************************/void CCURL_raise_finished(long lParam){ void *mythis; mythis=(void*)lParam; GB.Raise(mythis,CURL_FINISHED,0); GB.Unref(&mythis);}void CCURL_raise_error(long lParam){ void *mythis; mythis=(void*)lParam; GB.Raise(mythis,CURL_ERROR,0); GB.Unref(&mythis);}void CCURL_raise_connect(long lParam){ void *mythis; mythis=(void*)lParam; GB.Raise(mythis,CURL_CONNECT,0); GB.Unref(&mythis);}void CCURL_raise_read(long lParam){ void *mythis; mythis=(void*)lParam; GB.Raise(mythis,CURL_READ,0); GB.Unref(&mythis);}void CCURL_Manage_ErrCode(void *_object,long ErrCode){ if (THIS_FILE) { fclose(THIS_FILE); THIS_FILE=NULL; } switch ( ErrCode ) { case CURLE_OK: curl_multi_remove_handle(CCURL_multicurl,THIS_CURL); THIS_STATUS=0; GB.Ref(THIS); GB.Post(CCURL_raise_finished,(long)THIS); break; default: curl_multi_remove_handle(CCURL_multicurl,THIS_CURL); THIS_STATUS=-1*(1000+ErrCode); GB.Ref(THIS); GB.Post(CCURL_raise_error,(long)THIS); break; }}/*************************************************************** This CallBack is called each event loop by Gambas to test the status of curl descriptors ***************************************************************/void CCURL_stop(void *_object){ if (THIS_FILE) { fclose(THIS_FILE); THIS_FILE=NULL; } if (THIS_CURL) { curl_multi_remove_handle(CCURL_multicurl,THIS_CURL); curl_easy_cleanup(THIS_CURL); THIS_CURL=NULL; } THIS_STATUS=0;}void CCURL_init_post(void){ if (CCURL_pipe[0]!=-1) return; pipe(CCURL_pipe); GB.Watch (CCURL_pipe[0] ,GB_WATCH_READ,CCURL_post_curl,0); write(CCURL_pipe[1],"1",sizeof(char));}void CCURL_post_curl(long data){ CURLMsg *Msg; int nread; int post=1; void *_object; struct timespec mywait; do { mywait.tv_sec=0; mywait.tv_nsec=1000000; nanosleep(&mywait,NULL); } while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(CCURL_multicurl,&nread)); if (!nread) post=0; do { Msg=curl_multi_info_read(CCURL_multicurl,&nread); if (!Msg) nread=0; if (Msg) { curl_easy_getinfo(Msg->easy_handle,CURLINFO_PRIVATE,(char**)&_object); CCURL_Manage_ErrCode(THIS,Msg->data.result); } } while (nread); if (!post) { GB.Watch (CCURL_pipe[0] ,GB_WATCH_NONE,CCURL_post_curl,0); close(CCURL_pipe[0]); close(CCURL_pipe[1]); CCURL_pipe[0]=-1; } }//////////////////////////////////////////////////////////////////////////###################### PROXY related properties ######################/////////////////////////////////////////////////////////////////////////********************************************* Proxy name and port ( Host:Port format) *********************************************/BEGIN_PROPERTY (CCURL_Proxy) GB.ReturnObject(THIS->proxy);END_PROPERTY//////////////////////////////////////////////////////////////////////////########################## Other properties ##########################/////////////////////////////////////////////////////////////////////////********************************************* FTP User ( User:Password format ) *********************************************/BEGIN_PROPERTY ( CCURL_sUser ) if (READ_PROPERTY) { GB.ReturnString(THIS->user.user); return; } if (THIS_STATUS > 0) { GB.Error ("User property can not be changed while working"); return; } if ( THIS->user.user ) GB.FreeString ( &(THIS->user.user) ); GB.StoreString(PROP(GB_STRING), &(THIS->user.user) ); END_PROPERTYBEGIN_PROPERTY ( CCURL_Password ) if (READ_PROPERTY) { GB.ReturnString(THIS->user.pwd); return; } if (THIS_STATUS > 0) { GB.Error ("User property can not be changed while working"); return; } if ( THIS->user.pwd ) GB.FreeString ( &(THIS->user.pwd) ); GB.StoreString(PROP(GB_STRING), &(THIS->user.pwd) ); END_PROPERTY/********************************************* Status : inactive, working or Error code *********************************************/BEGIN_PROPERTY ( CCURL_Status ) GB.ReturnInteger(THIS_STATUS);END_PROPERTY/***************************************************************** URL to work with *****************************************************************/BEGIN_PROPERTY ( CCURL_URL ) char *tmp=NULL; if (READ_PROPERTY) { GB.ReturnNewString(THIS_URL,0); return; } if (THIS_STATUS > 0) { GB.Error ("URL property can not be changed while working"); return; } if (THIS_URL) { tmp=THIS_URL; GB.Free((void**)&tmp); } GB.Alloc((void**)&tmp,(strlen(GB.ToZeroString(PROP(GB_STRING)))+1)*sizeof(char)); strcpy(tmp,GB.ToZeroString(PROP(GB_STRING))); Adv_correct_url(&tmp,THIS_PROTOCOL); THIS_URL=tmp;END_PROPERTYBEGIN_PROPERTY(CCURL_tag) if (READ_PROPERTY) { GB.ReturnPtr(GB_T_VARIANT, &THIS->tag); return; } GB.StoreVariant(PROP(GB_VARIANT), (void *)&THIS->tag);END_METHODBEGIN_METHOD_VOID(CCURL_new) THIS->stream.desc=NULL; THIS_CURL=NULL; THIS_URL=NULL; THIS_FILE=NULL; GB.StoreVariant(NULL, (void *)&THIS->tag); Adv_user_NEW (&THIS->user); GB.New ((void**)&THIS->proxy,GB.FindClass(".Proxy"),NULL,NULL); GB.Ref((void*)THIS->proxy); Adv_proxy_NEW(&THIS->proxy->proxy); THIS->proxy->parent_status=&THIS->stream._free[0];END_METHODBEGIN_METHOD_VOID(CCURL_free) char *tmp=THIS_URL; if (tmp) GB.Free((void**)&tmp); if (THIS_FILE) fclose(THIS_FILE); if (THIS_CURL) curl_easy_cleanup(THIS_CURL); Adv_user_CLEAR (&THIS->user); Adv_proxy_CLEAR(&THIS->proxy->proxy); GB.Unref((void**)&THIS->proxy); tmp=THIS_PROTOCOL; GB.Free((void**)&tmp); END_METHODBEGIN_METHOD_VOID(CCURL_init) CCURL_multicurl=curl_multi_init();END_METHODBEGIN_METHOD_VOID(CCURL_exit) curl_multi_cleanup(CCURL_multicurl);END_METHODBEGIN_METHOD_VOID(CCURL_Peek) if ( (THIS->len_data) && (THIS->buf_data) ) { GB.ReturnNewString(THIS->buf_data,THIS->len_data); return; } GB.ReturnNewString(NULL,0);END_METHOD//*************************************************************************//#################### GAMBAS INTERFACE ###################################//*************************************************************************GB_DESC CCurlDesc[] ={ GB_DECLARE("Curl", sizeof(CCURL)), GB_NOT_CREATABLE(), GB_INHERITS(".Stream"), GB_METHOD("_new", NULL, CCURL_new, NULL), GB_METHOD("_free", NULL, CCURL_free, NULL), GB_METHOD("Peek","s", CCURL_Peek, NULL), GB_STATIC_METHOD("_init",NULL,CCURL_init, NULL), GB_STATIC_METHOD("_exit",NULL,CCURL_exit, NULL), GB_EVENT("Finished", NULL, NULL, &CURL_FINISHED), GB_EVENT("Connect", NULL, NULL, &CURL_CONNECT), GB_EVENT("Read", NULL, NULL, &CURL_READ), GB_EVENT("Error", NULL,NULL, &CURL_ERROR), GB_PROPERTY("URL", "s",CCURL_URL), GB_PROPERTY("User","s",CCURL_sUser), GB_PROPERTY("Password","s",CCURL_Password), GB_PROPERTY("Tag", "v", CCURL_tag), GB_PROPERTY_READ("Proxy",".Proxy",CCURL_Proxy), GB_PROPERTY_READ("Status","i",CCURL_Status), GB_END_DECLARE};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -