From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/include/m_netlib.h | 748 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 748 insertions(+) create mode 100644 miranda-wine/include/m_netlib.h (limited to 'miranda-wine/include/m_netlib.h') diff --git a/miranda-wine/include/m_netlib.h b/miranda-wine/include/m_netlib.h new file mode 100644 index 0000000..8ee4c92 --- /dev/null +++ b/miranda-wine/include/m_netlib.h @@ -0,0 +1,748 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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 2 +of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_NETLIB_H__ +#define M_NETLIB_H__ 1 + +#include "m_utils.h" + +//this module was created in 0.1.2.2 +//All error codes are returned via GetLastError() (or WSAGetLastError(): +//they're the same). +//This module is thread-safe where it is sensible for it to be so. This +//basically means that you can call anything from any thread, but don't try +//to predict what will happen if you try to recv() on the same connection from +//two different threads at the same time. +//Note that because the vast majority of the routines in this module return +//a pointer, I have decided to diverge from the rest of Miranda and go with +//the convention that functions return false on failure and nonzero on success. + +struct NETLIBHTTPREQUEST_tag; +typedef struct NETLIBHTTPREQUEST_tag NETLIBHTTPREQUEST; +struct NETLIBOPENCONNECTION_tag; +typedef struct NETLIBOPENCONNECTION_tag NETLIBOPENCONNECTION; + +//Initialises the netlib for a set of connections +//wParam=0 +//lParam=(LPARAM)(NETLIBUSER*)&nu +//Returns a HANDLE to be used for future netlib calls, NULL on failure +//NOTE: Netlib is loaded after any plugins, so you need to wait until +// ME_SYSTEM_MODULESLOADED before calling this function +//Netlib settings are stored under the module szSettingsModule +//All netlib settings being with "NL". +//The default settings for registered users that don't have any settings stored +//in the database are the same as those displayed by the page +//of the netlib options page. +//See notes below this function for the behaviour of HTTP gateways +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME +typedef int (*NETLIBHTTPGATEWAYINITPROC)(HANDLE hConn,NETLIBOPENCONNECTION *nloc,NETLIBHTTPREQUEST *nlhr); +typedef int (*NETLIBHTTPGATEWAYBEGINPROC)(HANDLE hConn,NETLIBOPENCONNECTION *nloc); +typedef int (*NETLIBHTTPGATEWAYWRAPSENDPROC)(HANDLE hConn,PBYTE buf,int len,int flags,MIRANDASERVICE pfnNetlibSend); +typedef PBYTE (*NETLIBHTTPGATEWAYUNWRAPRECVPROC)(NETLIBHTTPREQUEST *nlhr,PBYTE buf,int len,int *outBufLen,void *(*NetlibRealloc)(void*,size_t)); +typedef struct { + int cbSize; + char *szSettingsModule; //used for db settings and log + char *szDescriptiveName; //used in options dialog, already translated + DWORD flags; + char *szHttpGatewayHello; + char *szHttpGatewayUserAgent; //can be NULL to send no user-agent, also used by HTTPS proxies + NETLIBHTTPGATEWAYINITPROC pfnHttpGatewayInit; + NETLIBHTTPGATEWAYBEGINPROC pfnHttpGatewayBegin; //can be NULL if no beginning required + NETLIBHTTPGATEWAYWRAPSENDPROC pfnHttpGatewayWrapSend; //can be NULL if no wrapping required + NETLIBHTTPGATEWAYUNWRAPRECVPROC pfnHttpGatewayUnwrapRecv; //can be NULL if no wrapping required + int minIncomingPorts; //only if NUF_INCOMING. Will be used for validation of user input. +} NETLIBUSER; +#define NUF_INCOMING 0x01 //binds incoming ports +#define NUF_OUTGOING 0x02 //makes outgoing plain connections +#define NUF_HTTPGATEWAY 0x04 //can use HTTP gateway for plain sockets. ???HttpGateway* are valid. Enables the HTTP proxy option in options. +#define NUF_NOOPTIONS 0x08 //don't create an options page for this. szDescriptiveName is never used. +#define NUF_HTTPCONNS 0x10 //at least some connections are made for HTTP communication. Enables the HTTP proxy option in options. +#define NUF_NOHTTPSOPTION 0x20 //disable the HTTPS proxy option in options. Use this if all communication is HTTP. +#define MS_NETLIB_REGISTERUSER "Netlib/RegisterUser" + +//Assign a Netlib user handle a set of dynamic HTTP headers to be used with all +// +//HTTP connections that enable the HTTP-use-sticky headers flag. +//The headers persist until cleared with lParam=NULL. +// +//All memory should be allocated by the caller using malloc() from MS_SYSTEM_GET_MMI +//Once it has passed to Netlib, Netlib is the owner of it, the caller should not refer to the memory +//In any way after this point. +// +//wParam=(WPARAM)hNetLibUser +//lParam=(LPARAM)(char*)szHeaders +// +//NOTE: The szHeaders parameter should be a NULL terminated string following the HTTP header syntax. +//This string will be injected verbatim, thus the user should be aware of setting strings that are not +//headers. This service is NOT THREAD SAFE, only a single thread is expected to set the headers and a single +//thread reading the pointer internally, stopping race conditions and mutual exclusion don't happen. +// +//Version 0.3.2a+ (2003/10/27) +// +#define MS_NETLIB_SETSTICKYHEADERS "Netlib/SetStickyHeaders" + +/* Notes on HTTP gateway usage +When a connection is initiated through an HTTP proxy using +MS_NETLIB_OPENCONNECTION, netlib will GET nlu.szHttpGatewayHello and read +the replied headers. Once this succeeds nlu.pfnHttpGatewayInit will be called +with a valid handle to the connection, the NETLIBOPENCONNECTION structure that +MS_NETLIB_OPENCONNECTION was called with, and the replied HTTP headers as its +parameters. This function is responsible for recving and parsing the data then +calling MS_NETLIB_SETHTTPPROXYINFO with the appropriate information. +nlu.pfnHttpGatewayInit should return nonzero on success. If it returns zero +then the entire connection attempt will return signalling failure. If your +function needs to return an error code it can do so via SetLastError(). +If nlu.pfnHttpGatewayInit returns success without having called +MS_NETLIB_SETHTTPPROXYINFO then the connection attempt will fail anyway. +If you need more fine-tuned control over the GET/POST URLs than just appending +sequence numbers you can call MS_NETLIB_SETHTTPPROXYINFO from within your +wrap/unwrap functions (see below). + +Just prior to MS_NETLIB_OPENCONNECTION returning nlu.pfnHttpGatewayBegin is +called with the handle to the connection and the NETLIBOPENCONNECTION structure +as its parameters. This is for gateways that need special non-protocol +initialisation. If you do send any packets in this function, you probably want +to remember to use the MSG_NOHTTPGATEWAYWRAP flag. This function pointer can be +NULL if this functionality isn't needed. This function must return nonzero on +success. If it fails the connect attempt will return failure without changing +LastError. + +Whenever MS_NETLIB_SEND is called on a connection through an HTTP proxy and +the MSG_NOHTTPGATEWAYWRAP flags is not set and nlu.pfnHttpGatewayWrapSend is +not NULL, nlu.pfnHttpGatewayWrapSend will be called *instead* of sending the +data. It is this function's responsibility to wrap the sending data +appropriately for transmission and call pfnNetlibSend to send it again. +The flags parameter to nlu.pfnHttpGatewayWrapSend should be passed straight +through to the pfnNetlibSend call. It has already been ORed with +MSG_NOHTTPGATEWAYWRAP. nlu.pfnHttpGatewayWrapSend should return the a +number of the same type as MS_NETLIB_SEND, ie the number of bytes sent or +SOCKET_ERROR. The number of wrapping bytes should be subtracted so that the +return value appears as if the proxy wasn't there. +pfnNetlibSend() is identical to CallService(MS_NETLIB_SEND,...) but it's +quicker to call using this pointer than to do the CallService() lookup again. + +Whenever an HTTP reply is received inside MS_NETLIB_RECV the headers and data +are read into memory. If the headers indicate success then the data is passed +to nlu.pfnHttpGatewayUnwrapRecv (if it's non-NULL) for processing. This +function should remove (and do other processing if necessary) all HTTP proxy +specific headers and return a pointer to the buffer whose size is returned in +*outBufLen. If the buffer needs to be resized then NetlibRealloc() should be +used for that purpose, *not* your own CRT's realloc(). NetlibRealloc() behaves +identically to realloc() so it's possible to free the original buffer and +create a new one if that's the most sensible way to write your parser. +If errors are encountered you should SetLastError() and return NULL; +MS_NETLIB_RECV will return SOCKET_ERROR. If the passed buffer unwraps to +contain no actual data you should set *outBufLen to 0 but make sure you return +some non-NULL buffer that can be freed. + +When you call MS_NETLIB_SEND or MS_NETLIB_RECV from any of these functions, you +should use the MSG_DUMPPROXY flag so that the logging is neat. +*/ + +//Gets the user-configured settings for a netlib user +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBUSERSETTINGS*)&nlus +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//The pointers referred to in the returned struct will remain valid until +//the hUser handle is closed, or until the user changes the settings in the +//options page, so it's best not to rely on them for too long. +//Errors: ERROR_INVALID_PARAMETER +#define PROXYTYPE_SOCKS4 1 +#define PROXYTYPE_SOCKS5 2 +#define PROXYTYPE_HTTP 3 +#define PROXYTYPE_HTTPS 4 +typedef struct { + int cbSize; //to be filled in before calling + int useProxy; //1 or 0 + int proxyType; //a PROXYTYPE_ + char *szProxyServer; //can be NULL + int wProxyPort; //host byte order + int useProxyAuth; //1 or 0. Always 0 for SOCKS4 + char *szProxyAuthUser; //can be NULL, always used by SOCKS4 + char *szProxyAuthPassword; //can be NULL + int useProxyAuthNtlm; //1 or 0, only used by HTTP, HTTPS + int dnsThroughProxy; //1 or 0 + int specifyIncomingPorts; //1 or 0 + char *szIncomingPorts; //can be NULL. Of form "1024-1050,1060-1070,2000" + int specifyOutgoingPorts; // 0.3.3a+ + char *szOutgoingPorts; // 0.3.3a+ +} NETLIBUSERSETTINGS; +#define MS_NETLIB_GETUSERSETTINGS "Netlib/GetUserSettings" + +//Changes the user-configurable settings for a netlib user +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBUSERSETTINGS*)&nlus +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function is only really useful for people that specify NUF_NOOPTIONS +//and want to create their own options. +//Even if a setting is not active (eg szProxyAuthPassword when useProxyAuth is +//zero) that settings is still set for use in the options dialog. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_SETUSERSETTINGS "Netlib/SetUserSettings" + +//Closes a netlib handle +//wParam=(WPARAM)(HANDLE)hNetlibHandle +//lParam=0 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function should be called on all handles returned by netlib functions +//once you are done with them. If it's called on a socket-type handle, the +//socket will be closed. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_CLOSEHANDLE "Netlib/CloseHandle" +__inline static int Netlib_CloseHandle(HANDLE h) {return CallService(MS_NETLIB_CLOSEHANDLE,(WPARAM)h,0);} + +//Open a port and wait for connections on it +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBBIND*)&nlb +//Returns a HANDLE on success, NULL on failure +//hUser should have been returned by MS_NETLIB_REGISTERUSER +//This function does the equivalent of socket(), bind(), getsockname(), +//listen(), accept() +//Internally this function creates a new thread which waits around in accept() +//for new connections. When one is received it calls nlb.pfnNewConnection *from +//this new thread* and then loops back to wait again. +//Close the returned handle to end the thread and close the open port. +//Errors: ERROR_INVALID_PARAMETER, any returned by socket() or bind() or +// listen() or getsockname() +// +// Notes: +// +// During development of 0.3.1a+ (2003/07/04) passing wPort != 0 +// will result in an attempt to bind on the port given in wPort +// if this port is taken then you will get an error, so be sure to check +// for such conditions. +// +// passing wPort != 0 is for people who need to open a set port for +// daemon activities, usually passing wPort==0 is what you want and +// will result in a free port given by the TCP/IP socket layer and/or +// seeded from the user selected port ranges. +// +// also note that wPort if != 0, will have be converted to network byte order +// +/* pExtra was added during 0.3.4+, prior its just two args, since we use the cdecl convention +it shouldnt matter */ + +#define NETLIBBIND_SIZEOF_V1 16 // sizeof(NETLIBBIND) prior to 0.3.4+ (2004/08/05) +#define NETLIBBIND_SIZEOF_V2 20 // sizeof(NETLIBBIND) prior to 0.6+ (2006/07/03) + +typedef void (*NETLIBNEWCONNECTIONPROC_V2)(HANDLE hNewConnection,DWORD dwRemoteIP, void * pExtra); +typedef void (*NETLIBNEWCONNECTIONPROC)(HANDLE hNewConnection,DWORD dwRemoteIP); +/* This is NETLIBBIND prior to 2004/08/05+, DONT use this anymore unless you want to work +with older cores, pExtra isnt available on older cores and never will be - for a period of time, the ABI +for this service was broken and older NETLIBBINDs were not supported, if NULL is returned and the +argument is good, then tell the user to upgrade to the latest CVS. + +The older structure was used til around 2004/08/05 */ +typedef struct { + int cbSize; + NETLIBNEWCONNECTIONPROC pfnNewConnection; + //function to call when there's a new connection. Params are: the + //new connection, IP of remote machine (host byte order) + DWORD dwInternalIP; //set on return, host byte order + WORD wPort; //set on return, host byte order +} NETLIBBINDOLD; + +typedef struct { + int cbSize; + union { // new code should use V2 + NETLIBNEWCONNECTIONPROC pfnNewConnection; + NETLIBNEWCONNECTIONPROC_V2 pfnNewConnectionV2; + }; + //function to call when there's a new connection. Params are: the + //new connection, IP of remote machine (host byte order) + DWORD dwInternalIP; //set on return, host byte order + WORD wPort; //set on return, host byte order + void * pExtra; //argument is sent to callback, added during 0.3.4+ + DWORD dwExternalIP; //set on return, host byte order + WORD wExPort; //set on return, host byte order +} NETLIBBIND; +#define MS_NETLIB_BINDPORT "Netlib/BindPort" + +//Open a connection +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBOPENCONNECTION*)&nloc +//Returns a HANDLE to the new connection on success, NULL on failure +//hUser must have been returned by MS_NETLIB_REGISTERUSER +//Internally this function is the equivalent of socket(), gethostbyname(), +//connect() +//If NLOCF_HTTP is set and hUser is configured for an HTTP or HTTPS proxy then +//this function will connect() to the proxy server only, without performing any +//initialisation conversation. +//If hUser is configured for an HTTP proxy and does not support HTTP gateways +//and you try to open a connection without specifying NLOCF_HTTP then this +//function will first attempt to open an HTTPS connection, if that fails it +//will try a direct connection, if that fails it will return failure with the +//error from the connect() during the direct connection attempt. +//Errors: ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(), +// connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select() +// ERROR_TIMEOUT (during proxy communication) +// ERROR_BAD_FORMAT (very invalid proxy reply) +// ERROR_ACCESS_DENIED (by proxy) +// ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd) +// ERROR_INVALID_ACCESS (proxy refused identd auth) +// ERROR_INVALID_DATA (proxy returned invalid code) +// ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported) +// ERROR_GEN_FAILURE (socks5/https general failure) +// ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported) +// ERROR_INVALID_ADDRESS (socks5 address type not supported) +// HTTP: anything from nlu.pfnHttpGatewayInit, nlu.pfnHttpGatewayBegin, +// MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS +#define NLOCF_HTTP 0x0001 //this connection will be used for HTTP communications. If configured for an HTTP/HTTPS proxy the connection is opened as if there was no proxy. +#define NLOCF_STICKYHEADERS 0x0002 //this connection should send the sticky headers associated with NetLib user apart of any HTTP request +#define NLOCF_V2 0x0004 //this connection understands the newer structure, newer cbSize isnt enough + +/* Added during 0.4.0+ development!! (2004/11/29) prior to this, connect() blocks til a connection is made or +a hard timeout is reached, this can be anywhere between 30-60 seconds, and it stops Miranda from unloading whilst +this is attempted, clearing sucking - so now you can set a timeout of any value, there is still a hard limit which is +always reached by Windows, If a timeout occurs, or Miranda is exiting then you will get ERROR_TIMEOUT as soon as possible. +*/ +#define NETLIBOPENCONNECTION_V1_SIZE 16 /* old sizeof() is 14 bytes, but there is padding of 2 bytes */ +struct NETLIBOPENCONNECTION_tag { + int cbSize; + const char *szHost; //can contain the string representation of an IP + WORD wPort; //host byte order + DWORD flags; + unsigned int timeout; + /* optional, called in the context of the thread that issued the attempt, if it returns 0 the connection attempt is + stopped, the remaining timeout value can also be adjusted */ + int (*waitcallback) (unsigned int * timeout); +}; +//typedef struct NETLIBOPENCONNECTION_tag NETLIBOPENCONNECTION; //(above for reasons of forward referencing) +#define MS_NETLIB_OPENCONNECTION "Netlib/OpenConnection" + +//Sets the required information for an HTTP proxy connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBHTTPPROXYINFO*)&nlhpi +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function is designed to be called from within pfnHttpGatewayInit +//See notes below MS_NETLIB_REGISTERUSER. +//Errors: ERROR_INVALID_PARAMETER +#define NLHPIF_USEGETSEQUENCE 0x0001 //append sequence numbers to GET requests +#define NLHPIF_USEPOSTSEQUENCE 0x0002 //append sequence numbers to POST requests +#define NLHPIF_GETPOSTSAMESEQUENCE 0x0004 //GET and POST use the same sequence +#define NLHPIF_HTTP11 0x0008 //HTTP 1.1 proxy +typedef struct { + int cbSize; + DWORD flags; + char *szHttpPostUrl; + char *szHttpGetUrl; + int firstGetSequence,firstPostSequence; +} NETLIBHTTPPROXYINFO; +#define MS_NETLIB_SETHTTPPROXYINFO "Netlib/SetHttpProxyInfo" + +//Gets the SOCKET associated with a netlib handle +//wParam=(WPARAM)(HANDLE)hNetlibHandle +//lParam=0 +//Returns the SOCKET on success, INVALID_SOCKET on failure +//hNetlibHandle should have been returned by MS_NETLIB_BINDPORT or +//MS_NETLIB_OPENCONNECTION only. +//Be careful how you use this socket because you might be connected via an +//HTTP proxy in which case calling send() or recv() will totally break things. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_GETSOCKET "Netlib/GetSocket" + +//URL-encode a string for x-www-form-urlencoded (and other) transmission +//wParam=0 +//lParam=(LPARAM)(const char *)pszString +//Returns a char* containing the new string. This must be freed with +//HeapFree(GetProcessHeap(),0,pszReturnString) when you're done with it. +//Returns NULL on error. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY +#define MS_NETLIB_URLENCODE "Netlib/UrlEncode" + +//Base64 decode a string. See rfc1421. +//wParam=0 +//lParam=(LPARAM)(NETLIBBASE64*)&nlb64 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//nlb64.pszEncoded and nlb64.cchEncoded contain the input string and its length +//(excluding terminating zero). +//nlb64.pbDecoded and nlb64.cbDecoded contain the buffer in which to put the +//output and the length of this buffer. The maximum output size for a given +//input is available from the macro Netlib_GetBase64DecodedBufferSize() below. +//On return nlb64.cbDecoded is set to the actual length of the decoded data. +//Errors: ERROR_INVALID_PARAMETER, ERROR_INVALID_DATA, ERROR_BUFFER_OVERFLOW +typedef struct { + char *pszEncoded; + int cchEncoded; + PBYTE pbDecoded; + int cbDecoded; +} NETLIBBASE64; +#define Netlib_GetBase64DecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3) +#define MS_NETLIB_BASE64DECODE "Netlib/Base64Decode" + +//Base64 encode a string. See rfc1421. +//wParam=0 +//lParam=(LPARAM)(NETLIBBASE64*)&nlb64 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//nlb64.pbDecoded and nlb64.cbDecoded contain the input buffer and its length +//nlb64.pszEncoded and nlb64.cchEncoded contain the buffer in which to put the +//output and the length of this buffer. The maximum output size for a given +//input is available from the macro Netlib_GetBase64EncodedBufferSize() below. +//nlb64.pszEncoded is terminated with a 0. +//On return nlb64.cchEncoded is set to the actual length of the decoded data, +//excluding the terminating 0. +//Errors: ERROR_INVALID_PARAMETER, ERROR_BUFFER_OVERFLOW +#define Netlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1) +#define MS_NETLIB_BASE64ENCODE "Netlib/Base64Encode" + +//Send an HTTP request over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr +//Returns number of bytes sent on success, SOCKET_ERROR on failure +//hConnection must have been returned by MS_NETLIB_OPENCONNECTION +//Note that if you use NLHRF_SMARTAUTHHEADER and NTLM authentication is in use +//then the full NTLM authentication transaction occurs, comprising sending the +//domain, receiving the challenge, then sending the response. +//nlhr.resultCode and nlhr.szResultDescr are ignored by this function. +//Errors: ERROR_INVALID_PARAMETER, anything returned by MS_NETLIB_SEND +typedef struct { + char *szName; + char *szValue; +} NETLIBHTTPHEADER; + +#define REQUEST_RESPONSE 0 //used by structure returned by MS_NETLIB_RECVHTTPHEADERS +#define REQUEST_GET 1 +#define REQUEST_POST 2 +#define REQUEST_CONNECT 3 +#define REQUEST_HEAD 4 // new in 0.5.1 +#define NLHRF_GENERATEHOST 0x00000001 //auto-generate a "Host" header from szUrl +#define NLHRF_REMOVEHOST 0x00000002 //remove any host and/or protocol portion of szUrl before sending it +#define NLHRF_SMARTREMOVEHOST 0x00000004 //removes host and/or protocol from szUrl unless the connection was opened through an HTTP or HTTPS proxy. +#define NLHRF_SMARTAUTHHEADER 0x00000008 //if the connection was opened through an HTTP or HTTPS proxy then send a Proxy-Authorization header if required. +#define NLHRF_HTTP11 0x00000010 //use HTTP 1.1 +#define NLHRF_NODUMP 0x00010000 //never dump this to the log +#define NLHRF_NODUMPHEADERS 0x00020000 //don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION) +#define NLHRF_DUMPPROXY 0x00040000 //this transaction is a proxy communication. For dump filtering only. +#define NLHRF_DUMPASTEXT 0x00080000 //dump posted and reply data as text. Headers are always dumped as text. +struct NETLIBHTTPREQUEST_tag { + int cbSize; + int requestType; //a REQUEST_ + DWORD flags; + char *szUrl; + NETLIBHTTPHEADER *headers; //If this is a POST request and headers + //doesn't contain a Content-Length it'll be added automatically + int headersCount; + char *pData; //data to be sent in POST request. + int dataLength; //must be 0 for REQUEST_GET/REQUEST_CONNECT + int resultCode; + char *szResultDescr; + HANDLE nlc; +}; +//typedef struct NETLIBHTTPREQUEST_tag NETLIBHTTPREQUEST; //(above for reasons of forward referencing) +#define MS_NETLIB_SENDHTTPREQUEST "Netlib/SendHttpRequest" + +//Receive HTTP headers +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=0 +//Returns a pointer to a NETLIBHTTPREQUEST structure on success, NULL on +//failure. +//Call MS_NETLIB_FREEHTTPREQUESTSTRUCT to free this. +//hConnection must have been returned by MS_NETLIB_OPENCONNECTION +//nlhr->pData=NULL and nlhr->dataLength=0 always. The requested data should +//be retrieved using MS_NETLIB_RECV once the header has been parsed. +//If the headers haven't finished within 60 seconds the function returns NULL +//and ERROR_TIMEOUT. +//Errors: ERROR_INVALID_PARAMETER, any from MS_NETLIB_RECV or select() +// ERROR_HANDLE_EOF (connection closed before headers complete) +// ERROR_TIMEOUT (headers still not complete after 60 seconds) +// ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank) +// ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long) +// ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line) +#define MS_NETLIB_RECVHTTPHEADERS "Netlib/RecvHttpHeaders" + +//Free the memory used by a NETLIBHTTPREQUEST structure +//wParam=0 +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)pnlhr +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This should only be called on structures returned by +//MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an +//arbitrary structure will have disastrous results. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_FREEHTTPREQUESTSTRUCT "Netlib/FreeHttpRequestStruct" + +//Do an entire HTTP transaction +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr +//Returns a pointer to another NETLIBHTTPREQUEST structure on success, NULL on +//failure. +//Call MS_NETLIB_FREEHTTPREQUESTSTRUCT to free this. +//hUser must have been returned by MS_NETLIB_REGISTERUSER +//nlhr.szUrl should be a full HTTP URL. If it does not start with http://, that +//will be assumed (but it's best not to use this fact, for reasons of +//extensibility). +//This function is the equivalent of MS_NETLIB_OPENCONNECTION, +//MS_NETLIB_SENDHTTPREQ, MS_NETLIB_RECVHTTPHEADERS, MS_NETLIB_RECV, +//MS_NETLIB_CLOSEHANDLE +//nlhr.headers will be augmented with the following headers unless they have +//already been set by the caller: +// "Host" (regardless of whether it is requested in nlhr.flags) +// "User-Agent" (of the form "Miranda/0.1.2.2 (alpha)" or "Miranda/0.1.2.2") +// "Content-Length" (for POSTs only. Set to nlhr.dataLength) +//If you do not want to send one of these headers, create a nlhr.headers with +//szValue=NULL. +//In the return value headers, headerCount, pData, dataLength, resultCode and +//szResultDescr are all valid. +//In the return value pData[dataLength]==0 always, as an extra safeguard +//against programming slips. +//Note that the function can succeed (ie not return NULL) yet result in an HTTP +//error code. You should check that resultCode==2xx before proceeding. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, anything from the above +// list of functions +#define MS_NETLIB_HTTPTRANSACTION "Netlib/HttpTransaction" + +//Send data over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBBUFFER*)&nlb +//Returns the number of bytes sent on success, SOCKET_ERROR on failure +//Errors: ERROR_INVALID_PARAMETER +// anything from send(), nlu.pfnHttpGatewayWrapSend() +// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx) +// anything from socket(), connect(), +// MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS +//flags: +#define MSG_NOHTTPGATEWAYWRAP 0x010000 //don't wrap the outgoing packet using nlu.pfnHttpGatewayWrapSend +#define MSG_NODUMP 0x020000 //don't dump this packet to the log +#define MSG_DUMPPROXY 0x040000 //this is proxy communiciation. For dump filtering only. +#define MSG_DUMPASTEXT 0x080000 //this is textual data, don't dump as hex +#define MSG_RAW 0x100000 //send as raw data, bypass any HTTP proxy stuff +typedef struct { + char *buf; + int len; + int flags; +} NETLIBBUFFER; +#define MS_NETLIB_SEND "Netlib/Send" +static __inline int Netlib_Send(HANDLE hConn,const char *buf,int len,int flags) { + NETLIBBUFFER nlb={(char*)buf,len,flags}; + return CallService(MS_NETLIB_SEND,(WPARAM)hConn,(LPARAM)&nlb); +} + +//Receive data over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBBUFFER*)&nlb +//Returns the number of bytes read on success, SOCKET_ERROR on failure, +//0 if the connection has been closed +//Flags supported: MSG_PEEK, MSG_NODUMP, MSG_DUMPPROXY, MSG_NOHTTPGATEWAYWRAP, +// MSG_DUMPASTEXT, MSG_RAW +//On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are +// batched and cached and stuff, using this flag is not a guarantee that it +// will be obeyed, and if it is it may even be propogated to future calls +// even if you don't specify it then. Because of this, the flag should be +// considered an all-or-nothing thing: either use it for the entire duration +// of a connection, or not at all. +//Errors: ERROR_INVALID_PARAMETER, anything from recv() +// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx) +// ERROR_INVALID_DATA (no Content-Length header in reply) +// ERROR_NOT_ENOUGH_MEMORY (Content-Length very large) +// ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved) +// anything from select(), MS_NETLIB_RECVHTTPHEADERS, +// nlu.pfnHttpGatewayUnwrapRecv, socket(), connect(), +// MS_NETLIB_SENDHTTPREQUEST +#define MS_NETLIB_RECV "Netlib/Recv" +static __inline int Netlib_Recv(HANDLE hConn,char *buf,int len,int flags) { + NETLIBBUFFER nlb={buf,len,flags}; + return CallService(MS_NETLIB_RECV,(WPARAM)hConn,(LPARAM)&nlb); +} + +//Determine the status of one or more connections +//wParam=0 +//lParam=(LPARAM)(NETLIBSELECT*)&nls +//Returns the number of ready connections, SOCKET_ERROR on failure, +//0 if the timeout expired. +//All handles passed to this function must have been returned by either +//MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT. +//The last handle in each list must be followed by either NULL or +//INVALID_HANDLE_VALUE. +//Errors: ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select() +typedef struct { + int cbSize; + DWORD dwTimeout; //in milliseconds, INFINITE is acceptable + HANDLE hReadConns[FD_SETSIZE+1]; + HANDLE hWriteConns[FD_SETSIZE+1]; + HANDLE hExceptConns[FD_SETSIZE+1]; +} NETLIBSELECT; + +typedef struct { + int cbSize; + DWORD dwTimeout; //in milliseconds, INFINITE is acceptable + HANDLE hReadConns[FD_SETSIZE+1]; + HANDLE hWriteConns[FD_SETSIZE+1]; + HANDLE hExceptConns[FD_SETSIZE+1]; + /* Added in v0.3.3+ */ + BOOL hReadStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ + BOOL hWriteStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ + BOOL hExceptStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ +} NETLIBSELECTEX; + +#define MS_NETLIB_SELECT "Netlib/Select" +// added in v0.3.3 +#define MS_NETLIB_SELECTEX "Netlib/SelectEx" + +//Create a packet receiver +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(int)maxPacketSize +//Returns a HANDLE on success, NULL on failure +//The packet receiver implements the common situation where you have variable +//length packets coming in over a connection and you want to split them up +//in order to handle them. +//The major limitation is that the buffer is created in memory, so you can't +//have arbitrarily large packets. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY +#define MS_NETLIB_CREATEPACKETRECVER "Netlib/CreatePacketRecver" + +//Get the next set of packets from a packet receiver +//wParam=(WPARAM)(HANDLE)hPacketRecver +//lParam=(LPARAM)(NETLIBPACKETRECVER*)&nlpr +//Returns the total number of bytes available in the buffer, 0 if the +//connection was closed, SOCKET_ERROR on error. +//hPacketRecver must have been returned by MS_NETLIB_CREATEPACKETRECVER +//If nlpr.bytesUsed is set to zero and the buffer is already full up to +//maxPacketSize, it is assumed that too large a packet has been received. All +//data in the buffer is discarded and receiving is begun anew. This will +//probably cause alignment problems so if you think this is likely to happen +//then you should deal with it yourself. +//Closing the packet receiver will not close the associated connection, but +//will discard any bytes still in the buffer, so if you intend to carry on +//reading from that connection, make sure you have processed the buffer first. +//This function is the equivalent of a memmove() to remove the first bytesUsed +//from the buffer, select() if dwTimeout is not INFINITE, then MS_NETLIB_RECV. +//Errors: ERROR_INVALID_PARAMETER, ERROR_TIMEOUT, +// anything from select(), MS_NETLIB_RECV +typedef struct { + int cbSize; + DWORD dwTimeout; //fill before calling. In milliseconds. INFINITE is valid + int bytesUsed; //fill before calling. This many bytes are removed from the start of the buffer. Set to 0 on return + int bytesAvailable; //equal to the return value, unless the return value is 0 + int bufferSize; //same as parameter to MS_NETLIB_CREATEPACKETRECVER + BYTE *buffer; //contains the recved data +} NETLIBPACKETRECVER; +#define MS_NETLIB_GETMOREPACKETS "Netlib/GetMorePackets" + +//Add a message to the log (if it's running) +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(const char *)szMessage +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//Do not include a final line ending in szMessage. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_LOG "Netlib/Log" + +//Sets a gateway polling timeout interval +//wParam=(WPARAM)(HANDLE)hConn +//lParam=(LPARAM)timeout +//Returns previous timeout value +//Errors: -1 +#define MS_NETLIB_SETPOLLINGTIMEOUT "Netlib/SetPollingTimeout" + +//here's a handy piece of code to let you log using printf-style specifiers: +//#include and before including this header in order to +//use it. +#if defined va_start && (defined _STDIO_DEFINED || defined _STDIO_H_) && (!defined NETLIB_NOLOGGING) +static __inline int Netlib_Logf(HANDLE hUser,const char *fmt,...) +{ + va_list va; + char szText[1024]; + + va_start(va,fmt); + mir_vsnprintf(szText,sizeof(szText),fmt,va); + va_end(va); + return CallService(MS_NETLIB_LOG,(WPARAM)hUser,(LPARAM)szText); +} +#endif //defined va_start + +/* Notes on being backwards compatible with 0.1.2.1 +One way to do back compatibility is to create your own mini netlib that only +supports a minimal set of features. Here's some sample code: + +//This function is called during the ME_SYSTEM_MODULESLOADED hook +int MyPluginModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + //if this is executed on a version of Miranda with netlib then all + //these calls will fail and the proper netlib will be used. + CreateServiceFunction(MS_NETLIB_CLOSEHANDLE,MiniNetlibCloseHandle); + CreateServiceFunction(MS_NETLIB_OPENCONNECTION,MiniNetlibOpenConnection); + CreateServiceFunction(MS_NETLIB_SEND,MiniNetlibSend); + CreateServiceFunction(MS_NETLIB_RECV,MiniNetlibRecv); + CreateServiceFunction(MS_NETLIB_SELECT,MiniNetlibSelect); + return 0; +} + +int MiniNetlibCloseHandle(WPARAM wParam,LPARAM lParam) +{ + closesocket((SOCKET)wParam); + return 1; +} + +int MiniNetlibOpenConnection(WPARAM wParam,LPARAM lParam) +{ + NETLIBOPENCONNECTION *nloc=(NETLIBOPENCONNECTION*)lParam; + SOCKADDR_IN sin; + SOCKET s; + + sin.s_addr=inet_addr(szHost); + if(sin.sin_addr.S_un.S_addr==INADDR_NONE) { + HOSTENT *host=gethostbyname(szHost); + if(host) sin.sin_addr.S_un.S_addr=*(u_long *)host->h_addr_list[0]; + else return (int)INVALID_SOCKET; + } + s=socket(AF_INET,SOCK_STREAM,0); + sin.sin_family=AF_INET; + sin.sin_port=(short)htons(nloc->wPort); + if(connect(s,(SOCKADDR*)sin,sizeof(sin))==SOCKET_ERROR) { + closesocket(s); + return (int)INVALID_SOCKET; + } + return (int)s; +} + +int MiniNetlibSend(WPARAM wParam,LPARAM lParam) +{ + NETLIBBUFFER *nlb=(NETLIBBUFFER*)lParam; + return send((SOCKET)wParam,nlb->buf,nlb->len,nlb->flags); +} + +int MiniNetlibRecv(WPARAM wParam,LPARAM lParam) +{ + NETLIBBUFFER *nlb=(NETLIBBUFFER*)lParam; + return recv((SOCKET)wParam,nlb->buf,nlb->len,nlb->flags); +} + +int MiniNetlibSelect(WPARAM wParam,LPARAM lParam) +{ + NETLIBSELECT *nls=(NETLIBSELECT*)lParam; + fd_set readfd,writefd,exceptfd; + TIMEVAL tv; + int i; + + tv.tv_sec=nls->dwTimeout/1000; + tv.tv_usec=(nls->dwTimeout%1000)*1000; + FD_ZERO(&readfd); for(i=0;nls->hReadConns[i];i++) FD_SET((SOCKET)nls->hReadConns[i],&readfd); + FD_ZERO(&writefd); for(i=0;nls->hWriteConns[i];i++) FD_SET((SOCKET)nls->hWriteConns[i],&writefd); + FD_ZERO(&exceptfd); for(i=0;nls->hExceptConns[i];i++) FD_SET((SOCKET)nls->hExceptConns[i],&exceptfd); + return select(0,&readfd,&writefd,&exceptfd,nls->dwTimeout==INFINITE?NULL:&tv); +} + +/// +NB: I haven't actually tested that this even compiles. +*/ + +#endif // M_NETLIB_H__ + -- cgit v1.2.3