diff --exclude CVS -r -u libwww-current/Library/src/HTFTP.c libwww-5.3.1/Library/src/HTFTP.c --- libwww-current/Library/src/HTFTP.c Wed Aug 9 12:43:08 2000 +++ libwww-5.3.1/Library/src/HTFTP.c Thu Aug 24 22:42:51 2000 @@ -126,6 +126,13 @@ BOOL stream_error; } ftp_data; +/* UGLY: Hardcoded max.lengths, but then... we can let the HTHost object + delete the protocolContext member */ +typedef struct _ftp_protocol_context { + char uid[80]; + char passwd[80]; +} ftp_protocol_context; + struct _HTStream { const HTStreamClass * isa; HTStream * target; @@ -1379,6 +1386,28 @@ return FTPEvent(soc, ctrl, HTEvent_BEGIN); } +PRIVATE int FTPControlCheck(HTHost *host, void *data) +{ + ftp_ctrl *ctrl = (ftp_ctrl *) data; + ftp_protocol_context *ctx = 0; + HTTRACE(PROT_TRACE, "FTP Check... %s\n" _ ctrl->uid); + + if (!host || !data) return 1; + + ctx = HTHost_protocolContext(host); + if (ctx == NULL) return 1; + + if ((strcmp(ctx->uid, ctrl->uid) == 0) && + (strcmp(ctx->passwd, ctrl->passwd) == 0)) { + HTTRACE(PROT_TRACE, "FTP Check... compatible channel!\n"); + return 1; + } + + HTTRACE(PROT_TRACE, "FTP Check... incompatible channel!\n"); + + return 0; +} + PRIVATE int FTPEvent (SOCKET soc, void * pVoid, HTEventType type) { ftp_ctrl * ctrl = (ftp_ctrl *) pVoid; @@ -1471,13 +1500,14 @@ case FTP_NEED_CCON: HTTRACE(PROT_TRACE, "FTP Event... now in state FTP_NEED_CONN\n"); - status = HTHost_connect(host, cnet, url); + status = HTHost_connect_with_check(host, cnet, url, + FTPControlCheck, ctrl); host = HTNet_host(cnet); if (status == HT_OK) { /* ** Check the protocol class to see if we have connected to a - ** the right class of server, in this case HTTP. + ** the right class of server, in this case FTP. */ { char * s_class = HTHost_class(host); @@ -1490,6 +1520,22 @@ HTHost_setClass(host, "ftp"); } + /* Record protocol context with the host */ + if (HTHost_protocolContext(host) == NULL) { + ftp_protocol_context *ctx = + (ftp_protocol_context *) HT_MALLOC(sizeof(ftp_protocol_context)); + if (ctx == NULL) { + HT_OUTOFMEM("ftp_protocol_context "); + } + ctx->uid[sizeof(ctx->uid)-1] = 0; + ctx->passwd[sizeof(ctx->passwd)-1] = 0; + + strncpy(ctx->uid, ctrl->uid, sizeof(ctx->uid)-1); + strncpy(ctx->passwd, ctrl->passwd, sizeof(ctx->passwd)-1); + + HTHost_setProtocolContext(host, ctx); + } + /* Check persistent connection */ if (HTNet_persistent(cnet)) { ctrl->server = HTHost_version(host); diff --exclude CVS -r -u libwww-current/Library/src/HTHost.c libwww-5.3.1/Library/src/HTHost.c --- libwww-current/Library/src/HTHost.c Fri Jul 28 15:56:08 2000 +++ libwww-5.3.1/Library/src/HTHost.c Thu Aug 24 20:08:07 2000 @@ -79,6 +79,12 @@ me->channel = NULL; } + /* Delete the protocol context (if any) */ + if (me->protocolContext) { + HT_FREE(me->protocolContext); + me->protocolContext = 0; + } + /* Unregister the events */ for (i = 0; i < HTEvent_TYPES; i++) HTEvent_delete(me->events[i]); @@ -262,18 +268,16 @@ return HT_OK; } -/* -** Search the host info cache for a host object or create a new one -** and add it. Examples of host names are -** -** www.w3.org -** www.foo.com:8000 -** 18.52.0.18 -** -** Returns Host object or NULL if error. You may get back an already -** existing host object - you're not guaranteed a new one each time. -*/ -PUBLIC HTHost * HTHost_new (char * host, u_short u_port) + +/* +** Extended version of HTHost_new. This version provides for a +** "channel compatibility check" and is intended to be used for +** Non-stateless connections. A protocol handler can use this +** function to test +*/ +PUBLIC HTHost * HTHost_new_with_check (char * host, u_short u_port, + HTHost_new_with_check_callback *ccbf, + void * cbdata) { HTList * list = NULL; /* Current list in cache */ HTHost * pres = NULL; @@ -306,35 +310,58 @@ HTTRACE(CORE_TRACE, "Host info... Collecting host info %p\n" _ pres); delete_object(list, pres); pres = NULL; + } else { + if (pres->channel) { + time_t t = time(NULL); + /* + ** If we have a TTL for this TCP connection then + ** check that we haven't passed it. + */ + if (pres->expires > 0) { + if (HTHost_isIdle(pres) && pres->expires < t) { + HTTRACE(CORE_TRACE, "Host info... Persistent channel %p gotten cold\n" _ + pres->channel); + HTHost_clearChannel(pres, HT_OK); + } + } + if (pres && pres->channel) { + /* We might move this check to embrace + this if ... */ + + /* Check if the channel is compatible + with what the caller wants ... */ + int candidate_ok = 1; + + if (ccbf) { + candidate_ok = ccbf(pres, cbdata); + } + + if (candidate_ok) { + pres->expires = t + HTPassiveTimeout; + HTTRACE(CORE_TRACE, + "Host info... REUSING CHANNEL %p\n" + _ pres->channel); + } else { + /* pres is not wanted by the caller ... */ + HTTRACE(CORE_TRACE, "Host info... Candidate channel refused by checking callback %p\n" _ pres->channel); + pres = 0; + } + } + } else { + HTTRACE(CORE_TRACE, "Host info... Found Host %p with no active channel\n" _ pres); + } + } + if (pres) { + break; } - break; } } } - - /* If not found then create new Host object, else use existing one */ - if (pres) { - if (pres->channel) { - - /* - ** If we have a TTL for this TCP connection then - ** check that we haven't passed it. - */ - if (pres->expires > 0) { - time_t t = time(NULL); - if (HTHost_isIdle(pres) && pres->expires < t) { - HTTRACE(CORE_TRACE, "Host info... Persistent channel %p gotten cold\n" _ - pres->channel); - HTHost_clearChannel(pres, HT_OK); - } else { - pres->expires = t + HTPassiveTimeout; - HTTRACE(CORE_TRACE, "Host info... REUSING CHANNEL %p\n" _ pres->channel); - } - } - } else { - HTTRACE(CORE_TRACE, "Host info... Found Host %p with no active channel\n" _ pres); - } - } else { + + /* If not found then create new Host object, else + use existing one */ + + if (!pres) { if ((pres = (HTHost *) HT_CALLOC(1, sizeof(HTHost))) == NULL) HT_OUTOFMEM("HTHost_add"); pres->hash = hash; @@ -356,7 +383,31 @@ return pres; } -PUBLIC HTHost * HTHost_newWParse (HTRequest * request, char * url, u_short u_port) +/* +** Search the host info cache for a host object or create a new one +** and add it. Examples of host names are +** +** www.w3.org +** www.foo.com:8000 +** 18.52.0.18 +** +** Returns Host object or NULL if error. You may get back an already +** existing host object - you're not guaranteed a new one each time. +*/ +PUBLIC HTHost * HTHost_new (char * host, u_short u_port) +{ + return HTHost_new_with_check(host, u_port, NULL, NULL); +} + + + + + +PUBLIC HTHost *HTHost_newWParse_with_check(HTRequest * request, + char * url, + u_short u_port, + HTHost_new_with_check_callback *ccbf, + void * cbdata) { char * port; char * fullhost = NULL; @@ -390,9 +441,10 @@ HTTRACE(PROT_TRACE, "HTHost parse Looking up `%s\' on port %u\n" _ parsedHost _ u_port); /* Find information about this host */ - if ((me = HTHost_new(parsedHost, u_port)) == NULL) { + if ((me = HTHost_new_with_check(parsedHost, u_port, ccbf, cbdata)) == NULL) { HTTRACE(PROT_TRACE, "HTHost parse Can't get host info\n"); - me->tcpstate = TCP_ERROR; + /* Removed, because it would cause a SIGSEGV !!! */ + /* me->tcpstate = TCP_ERROR; */ return NULL; } sin = &me->sock_addr; @@ -408,6 +460,11 @@ return me; } +PUBLIC HTHost * HTHost_newWParse (HTRequest * request, char * url, u_short u_port) +{ + return HTHost_newWParse_with_check(request, url, u_port, NULL, NULL); +} + /* ** Search the host info cache for a host object. Examples of host names: ** @@ -1288,13 +1345,17 @@ ** multiple pipelined engines. It then registers its own engine ** (HostEvent) with the event manager. */ -PUBLIC int HTHost_connect (HTHost * host, HTNet * net, char * url) +PUBLIC int HTHost_connect_with_check (HTHost * host, HTNet * net, char * url, + HTHost_new_with_check_callback *ccbf, + void *cbdata) { HTRequest * request = HTNet_request(net); int status = HT_OK; if (!host) { HTProtocol * protocol = HTNet_protocol(net); - if ((host = HTHost_newWParse(request, url, HTProtocol_id(protocol))) == NULL) + if ((host = HTHost_newWParse_with_check(request, url, + HTProtocol_id(protocol), + ccbf, cbdata)) == NULL) return HT_ERROR; /* @@ -1344,6 +1405,10 @@ } return HT_ERROR; /* @@@ - some more deletion and stuff here? */ } +PUBLIC int HTHost_connect (HTHost * host, HTNet * net, char * url) +{ + return HTHost_connect_with_check(host, net, url, NULL, NULL); +} PUBLIC int HTHost_listen (HTHost * host, HTNet * net, char * url) { @@ -1739,6 +1804,19 @@ PUBLIC void * HTHost_context (HTHost * me) { return me ? me->context : NULL; +} + +/* +** Protocol Context pointer to be used as a user defined context +*/ +PUBLIC void HTHost_setProtocolContext (HTHost * me, void * protocolContext) +{ + if (me) me->protocolContext = protocolContext; +} + +PUBLIC void * HTHost_protocolContext (HTHost * me) +{ + return me ? me->protocolContext : NULL; } PUBLIC int HTHost_eventTimeout (void) diff --exclude CVS -r -u libwww-current/Library/src/HTHost.html libwww-5.3.1/Library/src/HTHost.html --- libwww-current/Library/src/HTHost.html Wed Jul 7 17:43:28 1999 +++ libwww-5.3.1/Library/src/HTHost.html Thu Aug 24 17:43:01 2000 @@ -53,12 +53,27 @@
  • www.foo.com:8000 +

    + Check callback for HTHost_new_with_check_callback +

    +

    +Callback function type to be used with HTHost_new_with_check +

    +typedef int HTHost_new_with_check_callback(HTHost *, void *data);
    +

    Add a Host Object

     extern HTHost * HTHost_new (char * host, u_short u_port);
    +extern HTHost * HTHost_new_with_check (char * host, u_short u_port,
    +				       HTHost_new_with_check_callback *ccbf,
    +				       void *cbdata);
     extern HTHost * HTHost_newWParse(HTRequest * request, char * url, u_short u_port);
    +extern HTHost * HTHost_newWParse_with_check(HTRequest * request, 
    +					    char * url, u_short u_port,
    +					    HTHost_new_with_check_callback *ccbf,
    +					    void *cbdata);
     extern int HTHost_hash (HTHost * host);
     

    @@ -187,6 +202,16 @@ extern void HTHost_setContext (HTHost * me, void * context); extern void * HTHost_context (HTHost * me); +

    + Protocol Defined Contexts +

    +

    +This can be used for anything that the application would like to keep tabs +on. +

    +extern void HTHost_setProtocolContext (HTHost * me, void * protocolContext);
    +extern void * HTHost_protocolContext  (HTHost * me);
    +

    Register a Request on a Host Object

    @@ -215,9 +240,12 @@

    As a Net Object doesn't necessarily know whether there is a channel up and running and whether that channel can be reused, -it must do an explicit connect the the host. +it must do an explicit connect to the host.

     extern int HTHost_connect (HTHost * host, HTNet * net, char * url);
    +extern int HTHost_connect_with_check (HTHost * host, HTNet * net, char * url,
    +				      HTHost_new_with_check_callback *ccbf,
    +				      void *cbdata);
     
     extern int HTHost_accept  (HTHost * host, HTNet * net, char * url);
     
    diff --exclude CVS -r -u libwww-current/Library/src/HTHstMan.html libwww-5.3.1/Library/src/HTHstMan.html
    --- libwww-current/Library/src/HTHstMan.html	Fri Jul 28 15:52:23 2000
    +++ libwww-5.3.1/Library/src/HTHstMan.html	Thu Aug 24 17:00:59 2000
    @@ -102,6 +102,12 @@
         int			forceWriteFlush;
         int                 inFlush;         /* Tells if we're currently processing
                                                 a file flush */
    +    /* support for HTHost_new_with_check_callback functions */
    +    /* SHOULD WE USE *context instead of this one??? */ 
    +    /* NOTE: protocolContext is HT_FREE'd automatically when the HTHost
    +       object gets deleted - this is crude! Maybe we should change it...
    +       somehow?  */
    +    void *		protocolContext;	/* Protocol Specific context */
     };
     
     #define HTHost_bytesRead(me)		((me) ? (me)->bytes_read : -1)