]> granicus.if.org Git - curl/commitdiff
Added per-protocol callback static tables, replacing callback ptr storage
authorPatrick Monnerat <Patrick.Monnerat@datasphere.ch>
Fri, 12 Oct 2007 13:36:37 +0000 (13:36 +0000)
committerPatrick Monnerat <Patrick.Monnerat@datasphere.ch>
Fri, 12 Oct 2007 13:36:37 +0000 (13:36 +0000)
in the connectdata structure by a single handler table ptr.

19 files changed:
CHANGES
lib/curl_ldap.h
lib/dict.c
lib/dict.h
lib/file.c
lib/file.h
lib/ftp.c
lib/ftp.h
lib/http.c
lib/http.h
lib/ldap.c
lib/ssh.c
lib/ssh.h
lib/telnet.c
lib/telnet.h
lib/tftp.c
lib/tftp.h
lib/url.c
lib/urldata.h

diff --git a/CHANGES b/CHANGES
index 1fe68b576ca02d4eb8386f71a8e420eeac6114e9..56f7c79f9dd73f2c5650acc2383a8b6147cc751f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,10 @@
 
                                   Changelog
 
+Patrick M (12 October 2007)
+- Added per-protocol callback static tables, replacing callback ptr storage
+  in the connectdata structure by a single handler table ptr.
+
 Dan F (11 October 2007)
 - Fixed the -l option of runtests.pl
 
index 071cbcb43d200e72edcb79347fbad01d639bdce7..7813ae70b33f1a9a8e6d68892ef6a5725f677b1a 100644 (file)
  * $Id$
  ***************************************************************************/
 #ifndef CURL_DISABLE_LDAP
-CURLcode Curl_ldap(struct connectdata *conn, bool *done);
+extern const struct Curl_handler Curl_handler_ldap;
+
+#ifdef HAVE_LDAP_SSL
+extern const struct Curl_handler Curl_handler_ldaps;
+#endif
+
 #endif
 #endif /* __CURL_LDAP_H */
index 43bc72ebf8ec915513c84318a89c55d95770877d..8266e2bb6c29a892e74db641a048a6105ba5b5bc 100644 (file)
 /* The last #include file should be: */
 #include "memdebug.h"
 
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode Curl_dict(struct connectdata *conn, bool *done);
+
+/*
+ * DICT protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_dict = {
+  "DICT",                               /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_dict,                            /* do_it */
+  NULL,                                 /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_DICT,                            /* defport */
+  PROT_DICT                             /* protocol */
+};
+
 static char *unescape_word(struct SessionHandle *data, const char *inp)
 {
   char *newp;
@@ -115,7 +142,7 @@ static char *unescape_word(struct SessionHandle *data, const char *inp)
   return dictp;
 }
 
-CURLcode Curl_dict(struct connectdata *conn, bool *done)
+static CURLcode Curl_dict(struct connectdata *conn, bool *done)
 {
   char *word;
   char *eword;
index d3da1936f60f89004a07fc405fdc7fbf463580f9..eb4fb9d3b99857847c78b0f4d654cf45587f2353 100644 (file)
@@ -24,7 +24,6 @@
  * $Id$
  ***************************************************************************/
 #ifndef CURL_DISABLE_DICT
-CURLcode Curl_dict(struct connectdata *conn, bool *done);
-CURLcode Curl_dict_done(struct connectdata *conn);
+extern const struct Curl_handler Curl_handler_dict;
 #endif
 #endif
index 88d6bf26afce9d6327b75c941774030876b1c40e..dcee427ee4ad834c1eba27182ce581e5bbc1b71b 100644 (file)
 /* The last #include file should be: */
 #include "memdebug.h"
 
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode Curl_file(struct connectdata *, bool *done);
+
+/*
+ * FILE scheme handler.
+ */
+
+const struct Curl_handler Curl_handler_file = {
+  "FILE",                               /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_file,                            /* do_it */
+  Curl_file_done,                       /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  0,                                    /* defport */
+  PROT_FILE                             /* protocol */
+};
+
 /*
  * Curl_file_connect() gets called from Curl_protocol_connect() to allow us to
  * do protocol-specific actions at connect-time.  We emulate a
@@ -316,7 +343,7 @@ static CURLcode file_upload(struct connectdata *conn)
  * opposed to sockets) we instead perform the whole do-operation in this
  * function.
  */
-CURLcode Curl_file(struct connectdata *conn, bool *done)
+static CURLcode Curl_file(struct connectdata *conn, bool *done)
 {
   /* This implementation ignores the host name in conformance with
      RFC 1738. Only local files (reachable via the standard file system)
index 20a1c4c063e7498b6db654117cdcc8a1be461dd1..227c0d18115fb5fcff88b3d4581b3bdd2a11390b 100644 (file)
@@ -24,7 +24,8 @@
  * $Id$
  ***************************************************************************/
 #ifndef CURL_DISABLE_FILE
-CURLcode Curl_file(struct connectdata *, bool *done);
+extern const struct Curl_handler Curl_handler_file;
+
 CURLcode Curl_file_done(struct connectdata *, CURLcode, bool premature);
 CURLcode Curl_file_connect(struct connectdata *);
 #endif
index 1cb5d14dad64465e8a7cf14b495bdcaa7ab38371..19b1f4efcea0d6933536a51c03597ea4c943b537 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -133,6 +133,20 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
                             bool ascii, ftpstate newstate);
 static int ftp_need_type(struct connectdata *conn,
                          bool ascii);
+static CURLcode Curl_ftp(struct connectdata *conn, bool *done);
+static CURLcode Curl_ftp_done(struct connectdata *conn,
+                              CURLcode, bool premature);
+static CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
+static CURLcode Curl_ftp_disconnect(struct connectdata *conn);
+static CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
+static CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
+static int Curl_ftp_getsock(struct connectdata *conn,
+                            curl_socket_t *socks,
+                            int numsocks);
+static CURLcode Curl_ftp_doing(struct connectdata *conn,
+                               bool *dophase_done);
+static CURLcode Curl_ftp_setup_connection(struct connectdata * conn);
+static CURLcode Curl_ftps_setup_connection(struct connectdata * conn);
 
 /* easy-to-use macro: */
 #define FTPSENDF(x,y,z)    if ((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \
@@ -141,6 +155,95 @@ static int ftp_need_type(struct connectdata *conn,
                               return result
 
 
+/*
+ * FTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftp = {
+  "FTP",                                /* scheme */
+  Curl_ftp_setup_connection,            /* setup_connection */
+  Curl_ftp,                             /* do_it */
+  Curl_ftp_done,                        /* done */
+  Curl_ftp_nextconnect,                 /* do_more */
+  Curl_ftp_connect,                     /* connect_it */
+  Curl_ftp_multi_statemach,             /* connecting */
+  Curl_ftp_doing,                       /* doing */
+  Curl_ftp_getsock,                     /* proto_getsock */
+  Curl_ftp_getsock,                     /* doing_getsock */
+  Curl_ftp_disconnect,                  /* disconnect */
+  PORT_FTP,                             /* defport */
+  PROT_FTP                              /* protocol */
+};
+
+
+#ifdef USE_SSL
+/*
+ * FTPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftps = {
+  "FTPS",                               /* scheme */
+  Curl_ftps_setup_connection,           /* setup_connection */
+  Curl_ftp,                             /* do_it */
+  Curl_ftp_done,                        /* done */
+  Curl_ftp_nextconnect,                 /* do_more */
+  Curl_ftp_connect,                     /* connect_it */
+  Curl_ftp_multi_statemach,             /* connecting */
+  Curl_ftp_doing,                       /* doing */
+  Curl_ftp_getsock,                     /* proto_getsock */
+  Curl_ftp_getsock,                     /* doing_getsock */
+  Curl_ftp_disconnect,                  /* disconnect */
+  PORT_FTPS,                            /* defport */
+  PROT_FTP | PROT_FTPS | PROT_SSL       /* protocol */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed FTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftp_proxy = {
+  "FTP",                                /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_http,                            /* do_it */
+  Curl_http_done,                       /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_FTP,                             /* defport */
+  PROT_HTTP                             /* protocol */
+};
+
+
+# ifdef USE_SSL
+/*
+ * HTTP-proxyed FTPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftps_proxy = {
+  "FTPS",                               /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_http,                            /* do_it */
+  Curl_http_done,                       /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_FTPS,                            /* defport */
+  PROT_HTTP                             /* protocol */
+};
+# endif
+#endif
+
+
 /*
  * NOTE: back in the old days, we added code in the FTP code that made NOBODY
  * requests on files respond with headers passed to the client/stdout that
@@ -706,9 +809,9 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
 }
 
 /* For the FTP "protocol connect" and "doing" phases only */
-int Curl_ftp_getsock(struct connectdata *conn,
-                     curl_socket_t *socks,
-                     int numsocks)
+static int Curl_ftp_getsock(struct connectdata *conn,
+                            curl_socket_t *socks,
+                            int numsocks)
 {
   struct ftp_conn *ftpc = &conn->proto.ftpc;
 
@@ -2819,8 +2922,8 @@ static long ftp_state_timeout(struct connectdata *conn)
 
 
 /* called repeatedly until done from multi.c */
-CURLcode Curl_ftp_multi_statemach(struct connectdata *conn,
-                                  bool *done)
+static CURLcode Curl_ftp_multi_statemach(struct connectdata *conn,
+                                         bool *done)
 {
   curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int rc;
@@ -2928,8 +3031,8 @@ static CURLcode ftp_init(struct connectdata *conn)
  * phase is done when this function returns, or FALSE is not. When called as
  * a part of the easy interface, it will always be TRUE.
  */
-CURLcode Curl_ftp_connect(struct connectdata *conn,
-                          bool *done) /* see description above */
+static CURLcode Curl_ftp_connect(struct connectdata *conn,
+                                 bool *done) /* see description above */
 {
   CURLcode result;
 #ifndef CURL_DISABLE_HTTP
@@ -3017,8 +3120,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,
  *
  * Input argument is already checked for validity.
  */
-CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status,
-                       bool premature)
+static CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status,
+                              bool premature)
 {
   struct SessionHandle *data = conn->data;
   struct FTP *ftp = data->reqdata.proto.ftp;
@@ -3368,7 +3471,7 @@ static CURLcode ftp_range(struct connectdata *conn)
  * connected.
  */
 
-CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
+static CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
 {
   struct SessionHandle *data=conn->data;
   CURLcode result = CURLE_OK;
@@ -3485,7 +3588,7 @@ CURLcode ftp_perform(struct connectdata *conn,
  *
  * The input argument is already checked for validity.
  */
-CURLcode Curl_ftp(struct connectdata *conn, bool *done)
+static CURLcode Curl_ftp(struct connectdata *conn, bool *done)
 {
   CURLcode retcode = CURLE_OK;
 
@@ -3682,7 +3785,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
  * Disconnect from an FTP server. Cleanup protocol-specific per-connection
  * resources. BLOCKING.
  */
-CURLcode Curl_ftp_disconnect(struct connectdata *conn)
+static CURLcode Curl_ftp_disconnect(struct connectdata *conn)
 {
   struct ftp_conn *ftpc= &conn->proto.ftpc;
 
@@ -3933,8 +4036,8 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
 }
 
 /* called from multi.c while DOing */
-CURLcode Curl_ftp_doing(struct connectdata *conn,
-                        bool *dophase_done)
+static CURLcode Curl_ftp_doing(struct connectdata *conn,
+                               bool *dophase_done)
 {
   CURLcode result;
   result = Curl_ftp_multi_statemach(conn, dophase_done);
@@ -3996,4 +4099,64 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
   return result;
 }
 
+static CURLcode Curl_ftp_setup_connection(struct connectdata * conn)
+{
+  struct SessionHandle *data = conn->data;
+  char * type;
+  char command;
+
+  if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+    /* Unless we have asked to tunnel ftp operations through the proxy, we
+       switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+  if (conn->handler == &Curl_handler_ftp)
+    conn->handler = &Curl_handler_ftp_proxy;
+  else
+    conn->handler = &Curl_handler_ftps_proxy;
+#else
+    failf(data, "FTP over http proxy requires HTTP support built-in!");
+    return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+  }
+
+  data->reqdata.path++;   /* don't include the initial slash */
+
+  /* FTP URLs support an extension like ";type=<typecode>" that
+   * we'll try to get now! */
+  type = strstr(data->reqdata.path, ";type=");
+
+  if (!type)
+    type = strstr(conn->host.rawalloc, ";type=");
+
+  if (type) {
+    *type = 0;                     /* it was in the middle of the hostname */
+    command = (char) toupper((int) type[6]);
+
+    switch (command) {
+    case 'A': /* ASCII mode */
+      data->set.prefer_ascii = TRUE;
+      break;
+
+    case 'D': /* directory mode */
+      data->set.ftp_list_only = TRUE;
+      break;
+
+    case 'I': /* binary mode */
+    default:
+      /* switch off ASCII */
+      data->set.prefer_ascii = FALSE;
+      break;
+    }
+  }
+
+  return CURLE_OK;
+}
+
+static CURLcode Curl_ftps_setup_connection(struct connectdata * conn)
+{
+  struct SessionHandle *data = conn->data;
+
+  conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLUSESSL_CONTROL;
+  return Curl_ftp_setup_connection(conn);
+}
 #endif /* CURL_DISABLE_FTP */
index b64e705061d2a5d90065e9fe492ba0bcb902ab6c..13652acda4a6445cc3953509fbd81bceb56811af 100644 (file)
--- a/lib/ftp.h
+++ b/lib/ftp.h
  ***************************************************************************/
 
 #ifndef CURL_DISABLE_FTP
-CURLcode Curl_ftp(struct connectdata *conn, bool *done);
-CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode, bool premature);
-CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
-CURLcode Curl_ftp_disconnect(struct connectdata *conn);
+extern const struct Curl_handler Curl_handler_ftp;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_ftps;
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+extern const struct Curl_handler Curl_handler_ftp_proxy;
+
+# ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_ftps_proxy;
+# endif
+#endif
+
 CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
 CURLcode Curl_nbftpsendf(struct connectdata *, const char *fmt, ...);
 CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
                              int *ftpcode);
-CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
-CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
-int Curl_ftp_getsock(struct connectdata *conn,
-                     curl_socket_t *socks,
-                     int numsocks);
-CURLcode Curl_ftp_doing(struct connectdata *conn,
-                        bool *dophase_done);
 #endif /* CURL_DISABLE_FTP */
 #endif /* __FTP_H */
index babd406d8d052a0ba1b1bc73bdaf8d38b3f80506..173106c6e30654c8e02084ecd14cb01017bf2cc9 100644 (file)
 /* The last #include file should be: */
 #include "memdebug.h"
 
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
+static int Curl_https_getsock(struct connectdata *conn,
+                              curl_socket_t *socks,
+                              int numsocks);
+
+/*
+ * HTTP handler interface.
+ */
+const struct Curl_handler Curl_handler_http = {
+  "HTTP",                               /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_http,                            /* do_it */
+  Curl_http_done,                       /* done */
+  NULL,                                 /* do_more */
+  Curl_http_connect,                    /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_HTTP,                            /* defport */
+  PROT_HTTP,                            /* protocol */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTPS handler interface.
+ */
+const struct Curl_handler Curl_handler_https = {
+  "HTTPS",                              /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_http,                            /* do_it */
+  Curl_http_done,                       /* done */
+  NULL,                                 /* do_more */
+  Curl_http_connect,                    /* connect_it */
+  Curl_https_connecting,                /* connecting */
+  NULL,                                 /* doing */
+  Curl_https_getsock,                   /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_HTTPS,                           /* defport */
+  PROT_HTTP | PROT_HTTPS | PROT_SSL     /* protocol */
+};
+#endif
+
+
 /*
  * checkheaders() checks the linked list of custom HTTP headers for a
  * particular header (prefix).
@@ -1619,7 +1670,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
   return CURLE_OK;
 }
 
-CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
+static CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
 {
   CURLcode result;
   DEBUGASSERT((conn) && (conn->protocol & PROT_HTTPS));
@@ -1635,9 +1686,9 @@ CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
 #ifdef USE_SSLEAY
 /* This function is OpenSSL-specific. It should be made to query the generic
    SSL layer instead. */
-int Curl_https_getsock(struct connectdata *conn,
-                       curl_socket_t *socks,
-                       int numsocks)
+static int Curl_https_getsock(struct connectdata *conn,
+                              curl_socket_t *socks,
+                              int numsocks)
 {
   if (conn->protocol & PROT_HTTPS) {
     struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
index 0b8f8b63efa643b64ae8ab04da1c6636f0951fbb..f41ebb6e8df273c3ab51bb4c0b0029e206d5cc3f 100644 (file)
  * $Id$
  ***************************************************************************/
 #ifndef CURL_DISABLE_HTTP
+
+extern const struct Curl_handler Curl_handler_http;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_https;
+#endif
+
 bool Curl_compareheader(const char *headerline,  /* line to check */
                         const char *header,   /* header keyword _with_ colon */
                         const char *content); /* content string to find */
@@ -37,10 +44,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
 CURLcode Curl_http(struct connectdata *conn, bool *done);
 CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
 CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
-CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
-int Curl_https_getsock(struct connectdata *conn,
-                       curl_socket_t *socks,
-                       int numsocks);
 
 /* The following functions are defined in http_chunks.c */
 void Curl_httpchunk_init(struct connectdata *conn);
index 365c112fee984f908187968737f8bfd1ac02f98d..e9467e0097be5de2e005a564e10413ee7890c586 100644 (file)
@@ -118,7 +118,52 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp);
 #endif
 
 
-CURLcode Curl_ldap(struct connectdata *conn, bool *done)
+static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
+
+/*
+ * LDAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldap = {
+  "LDAP",                               /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_ldap,                            /* do_it */
+  NULL,                                 /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_LDAP,                            /* defport */
+  PROT_LDAP                             /* protocol */
+};
+
+#ifdef HAVE_LDAP_SSL
+/*
+ * LDAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldaps = {
+  "LDAPS",                              /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_ldap,                            /* do_it */
+  NULL,                                 /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_LDAPS,                           /* defport */
+  PROT_LDAP | PROT_SSL                  /* protocol */
+};
+#endif
+
+
+static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 {
   CURLcode status = CURLE_OK;
   int rc = 0;
index 9dce096305e35dfa9703e3f7ccf55dc8db537fbf..9d5e71e1ce125c823494d245e92921d90d30731c 100644 (file)
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -134,6 +134,63 @@ static LIBSSH2_FREE_FUNC(libssh2_free);
 
 static int get_pathname(const char **cpp, char **path);
 
+static CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done);
+static CURLcode Curl_ssh_multi_statemach(struct connectdata *conn, bool *done);
+
+static CURLcode Curl_scp_do(struct connectdata *conn, bool *done);
+static CURLcode Curl_scp_done(struct connectdata *conn,
+                              CURLcode, bool premature);
+static CURLcode Curl_scp_doing(struct connectdata *conn,
+                               bool *dophase_done);
+
+static CURLcode Curl_sftp_do(struct connectdata *conn, bool *done);
+static CURLcode Curl_sftp_done(struct connectdata *conn,
+                               CURLcode, bool premature);
+static CURLcode Curl_sftp_doing(struct connectdata *conn,
+                                bool *dophase_done);
+
+/*
+ * SCP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_scp = {
+  "SCP",                                /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_scp_do,                          /* do_it */
+  Curl_scp_done,                        /* done */
+  NULL,                                 /* do_more */
+  Curl_ssh_connect,                     /* connect_it */
+  Curl_ssh_multi_statemach,             /* connecting */
+  Curl_scp_doing,                       /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_SSH,                             /* defport */
+  PROT_SCP                              /* protocol */
+};
+
+
+/*
+ * SFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_sftp = {
+  "SFTP",                               /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_sftp_do,                         /* do_it */
+  Curl_sftp_done,                       /* done */
+  NULL,                                 /* do_more */
+  Curl_ssh_connect,                     /* connect_it */
+  Curl_ssh_multi_statemach,             /* connecting */
+  Curl_sftp_doing,                      /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_SSH,                             /* defport */
+  PROT_SFTP                             /* protocol */
+};
+
+
 static void
 kbd_callback(const char *name, int name_len, const char *instruction,
              int instruction_len, int num_prompts,
@@ -1719,8 +1776,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
 }
 
 /* called repeatedly until done from multi.c */
-CURLcode Curl_ssh_multi_statemach(struct connectdata *conn,
-                                  bool *done)
+static CURLcode Curl_ssh_multi_statemach(struct connectdata *conn, bool *done)
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
   CURLcode result = CURLE_OK;
@@ -1783,7 +1839,7 @@ static CURLcode ssh_init(struct connectdata *conn)
  * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
  * do protocol-specific actions at connect-time.
  */
-CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
+static CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
 {
   struct SSHPROTO *ssh;
   curl_socket_t sock;
@@ -1878,8 +1934,8 @@ CURLcode scp_perform(struct connectdata *conn,
 }
 
 /* called from multi.c while DOing */
-CURLcode Curl_scp_doing(struct connectdata *conn,
-                         bool *dophase_done)
+static CURLcode Curl_scp_doing(struct connectdata *conn,
+                               bool *dophase_done)
 {
   CURLcode result;
   result = Curl_ssh_multi_statemach(conn, dophase_done);
@@ -1891,7 +1947,7 @@ CURLcode Curl_scp_doing(struct connectdata *conn,
 }
 
 
-CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
+static CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
 {
   CURLcode res;
   bool connected = 0;
@@ -1931,8 +1987,8 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
   return res;
 }
 
-CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
-                       bool premature)
+static CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
+                              bool premature)
 {
   CURLcode result = CURLE_OK;
   bool done = FALSE;
@@ -2048,8 +2104,8 @@ CURLcode sftp_perform(struct connectdata *conn,
 }
 
 /* called from multi.c while DOing */
-CURLcode Curl_sftp_doing(struct connectdata *conn,
-                         bool *dophase_done)
+static CURLcode Curl_sftp_doing(struct connectdata *conn,
+                                bool *dophase_done)
 {
   CURLcode result;
   result = Curl_ssh_multi_statemach(conn, dophase_done);
@@ -2060,7 +2116,7 @@ CURLcode Curl_sftp_doing(struct connectdata *conn,
   return result;
 }
 
-CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
+static CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
 {
   CURLcode res;
   bool connected = 0;
@@ -2100,8 +2156,8 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
   return res;
 }
 
-CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
-                        bool premature)
+static CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
+                               bool premature)
 {
   CURLcode result = CURLE_OK;
   bool done = FALSE;
index 71b48db04927d24df8c66c27298ab9ebffcb01ea..8ac2a41eef5b7099ca43568dac2839c71e970016 100644 (file)
--- a/lib/ssh.h
+++ b/lib/ssh.h
  ***************************************************************************/
 
 #ifdef USE_LIBSSH2
-
-CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done);
-CURLcode Curl_ssh_multi_statemach(struct connectdata *conn, bool *done);
-
-CURLcode Curl_scp_do(struct connectdata *conn, bool *done);
-CURLcode Curl_scp_done(struct connectdata *conn, CURLcode, bool premature);
+extern const struct Curl_handler Curl_handler_scp;
+extern const struct Curl_handler Curl_handler_sftp;
 
 ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
                       void *mem, size_t len);
 ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
                       char *mem, size_t len);
-CURLcode Curl_sftp_do(struct connectdata *conn, bool *done);
-CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode, bool premature);
 
 ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
                        void *mem, size_t len);
 ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
                        char *mem, size_t len);
-CURLcode Curl_sftp_doing(struct connectdata *conn,
-                         bool *dophase_done);
-CURLcode Curl_scp_doing(struct connectdata *conn,
-                        bool *dophase_done);
 
 #endif /* USE_LIBSSH2 */
 
index 93a598252343fa45c31bf7da18bba64c61eb2678..b7c4701258b5be3d7773b5c09e251f2378008036 100644 (file)
@@ -125,6 +125,10 @@ static void printsub(struct SessionHandle *data,
                      size_t length);
 static void suboption(struct connectdata *);
 
+static CURLcode Curl_telnet(struct connectdata *conn, bool *done);
+static CURLcode Curl_telnet_done(struct connectdata *conn,
+                                 CURLcode, bool premature);
+
 /* For negotiation compliant to RFC 1143 */
 #define CURL_NO          0
 #define CURL_YES         1
@@ -170,6 +174,28 @@ struct TELNET {
   TelnetReceive telrcv_state;
 };
 
+
+/*
+ * TELNET protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_telnet = {
+  "TELNET",                             /* scheme */
+  NULL,                                 /* setup_connection */
+  Curl_telnet,                          /* do_it */
+  Curl_telnet_done,                     /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_TELNET,                          /* defport */
+  PROT_TELNET                           /* protocol */
+};
+
+
 #ifdef USE_WINSOCK
 static CURLcode
 check_wsock2 ( struct SessionHandle *data )
@@ -1074,7 +1100,8 @@ void telrcv(struct connectdata *conn,
   }
 }
 
-CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status, bool premature)
+static CURLcode Curl_telnet_done(struct connectdata *conn,
+                                 CURLcode status, bool premature)
 {
   struct TELNET *tn = (struct TELNET *)conn->data->reqdata.proto.telnet;
   (void)status; /* unused */
@@ -1088,7 +1115,7 @@ CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status, bool premat
   return CURLE_OK;
 }
 
-CURLcode Curl_telnet(struct connectdata *conn, bool *done)
+static CURLcode Curl_telnet(struct connectdata *conn, bool *done)
 {
   CURLcode code;
   struct SessionHandle *data = conn->data;
index 693abf3f86d8ac659e7522d703a4a34cab010437..44ec49bc0b9590b2a3648a1c3022a6c595d67377 100644 (file)
@@ -24,7 +24,6 @@
  * $Id$
  ***************************************************************************/
 #ifndef CURL_DISABLE_TELNET
-CURLcode Curl_telnet(struct connectdata *conn, bool *done);
-CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode, bool premature);
+extern const struct Curl_handler Curl_handler_telnet;
 #endif
 #endif
index 938c2e2398542f487b577265d04678155073bafd..81cd938c53f3df2858a2b94747f8b3b9d3724ad6 100644 (file)
@@ -151,6 +151,33 @@ typedef struct tftp_state_data {
 /* Forward declarations */
 static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
 static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
+static CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done);
+static CURLcode Curl_tftp(struct connectdata *conn, bool *done);
+static CURLcode Curl_tftp_done(struct connectdata *conn,
+                               CURLcode, bool premature);
+static CURLcode Curl_tftp_setup_connection(struct connectdata * conn);
+
+
+/*
+ * TFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_tftp = {
+  "TFTP",                               /* scheme */
+  Curl_tftp_setup_connection,           /* setup_connection */
+  Curl_tftp,                            /* do_it */
+  Curl_tftp_done,                       /* done */
+  NULL,                                 /* do_more */
+  Curl_tftp_connect,                    /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  PORT_TFTP,                            /* defport */
+  PROT_TFTP                             /* protocol */
+};
+
 
 /**********************************************************
  *
@@ -575,7 +602,7 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
  * The connect callback
  *
  **********************************************************/
-CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
+static CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
 {
   CURLcode code;
   tftp_state_data_t     *state;
@@ -636,8 +663,8 @@ CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
  * The done callback
  *
  **********************************************************/
-CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status,
-                        bool premature)
+static CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status,
+                               bool premature)
 {
   (void)status; /* unused */
   (void)premature; /* not used */
@@ -662,7 +689,7 @@ CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status,
  *
  **********************************************************/
 
-CURLcode Curl_tftp(struct connectdata *conn, bool *done)
+static CURLcode Curl_tftp(struct connectdata *conn, bool *done)
 {
   struct SessionHandle  *data = conn->data;
   tftp_state_data_t     *state =
@@ -836,4 +863,41 @@ CURLcode Curl_tftp(struct connectdata *conn, bool *done)
     code = CURLE_OK;
   return code;
 }
+
+static CURLcode Curl_tftp_setup_connection(struct connectdata * conn)
+{
+  struct SessionHandle *data = conn->data;
+  char * type;
+  char command;
+
+  conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
+
+  /* TFTP URLs support an extension like ";mode=<typecode>" that
+   * we'll try to get now! */
+  type = strstr(data->reqdata.path, ";mode=");
+
+  if (!type)
+    type = strstr(conn->host.rawalloc, ";mode=");
+
+  if (type) {
+    *type = 0;                   /* it was in the middle of the hostname */
+    command = (char) toupper((int) type[6]);
+
+    switch (command) {
+    case 'A': /* ASCII mode */
+    case 'N': /* NETASCII mode */
+      data->set.prefer_ascii = TRUE;
+      break;
+
+    case 'O': /* octet mode */
+    case 'I': /* binary mode */
+    default:
+      /* switch off ASCII */
+      data->set.prefer_ascii = FALSE;
+      break;
+    }
+  }
+
+  return CURLE_OK;
+}
 #endif
index c7125417b9938e663c3f38c96d95cb6a1f420152..c9d2ef3c94a3436c8f5bcf64228f27649b27c365 100644 (file)
@@ -24,8 +24,6 @@
  * $Id$
  ***************************************************************************/
 #ifndef CURL_DISABLE_TFTP
-CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done);
-CURLcode Curl_tftp(struct connectdata *conn, bool *done);
-CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode, bool premature);
+extern const struct Curl_handler Curl_handler_tftp;
 #endif
 #endif
index c74a1d858dafa88c05931a7e4eafbea152a231ba..bc3d235a82e06cad6c90c973897ffcd1402d06c9 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -178,6 +178,7 @@ static void flush_cookies(struct SessionHandle *data, int cleanup);
 
 #define ZERO_NULL 0
 
+
 #ifndef USE_ARES
 /* not for ares builds */
 
@@ -188,6 +189,82 @@ static void flush_cookies(struct SessionHandle *data, int cleanup);
 extern sigjmp_buf curl_jmpenv;
 #endif
 
+
+/*
+ * Protocol table.
+ */
+
+static const struct Curl_handler * protocols[] = {
+
+#ifndef CURL_DISABLE_HTTP
+  &Curl_handler_http,
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+  &Curl_handler_https,
+#endif
+
+#ifndef CURL_DISABLE_FTP
+  &Curl_handler_ftp,
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+  &Curl_handler_ftps,
+#endif
+
+#ifndef CURL_DISABLE_TELNET
+  &Curl_handler_telnet,
+#endif
+
+#ifndef CURL_DISABLE_DICT
+  &Curl_handler_dict,
+#endif
+
+#ifndef CURL_DISABLE_LDAP
+  &Curl_handler_ldap,
+#endif
+
+#if defined(HAVE_LDAP_SSL) && !defined(CURL_DISABLE_SSL)
+  &Curl_handler_ldaps,
+#endif
+
+#ifndef CURL_DISABLE_FILE
+  &Curl_handler_file,
+#endif
+
+#ifndef CURL_DISABLE_TFTP
+  &Curl_handler_tftp,
+#endif
+
+#ifdef USE_LIBSSH2
+  &Curl_handler_scp,
+  &Curl_handler_sftp,
+#endif
+
+  (struct Curl_handler *) NULL
+};
+
+/*
+ * Dummy handler for undefined protocol schemes.
+ */
+
+const struct Curl_handler Curl_handler_dummy = {
+  "<no protocol>",                      /* scheme */
+  NULL,                                 /* setup_connection */
+  NULL,                                 /* do_it */
+  NULL,                                 /* done */
+  NULL,                                 /* do_more */
+  NULL,                                 /* connect_it */
+  NULL,                                 /* connecting */
+  NULL,                                 /* doing */
+  NULL,                                 /* proto_getsock */
+  NULL,                                 /* doing_getsock */
+  NULL,                                 /* disconnect */
+  0,                                    /* defport */
+  0                                     /* protocol */
+};
+
+
 #ifdef SIGALRM
 static
 RETSIGTYPE alarmfunc(int sig)
@@ -1999,9 +2076,9 @@ CURLcode Curl_disconnect(struct connectdata *conn)
     Curl_ntlm_cleanup(conn);
   }
 
-  if(conn->curl_disconnect)
+  if(conn->handler->disconnect)
     /* This is set if protocol-specific cleanups should be made */
-    conn->curl_disconnect(conn);
+    conn->handler->disconnect(conn);
 
   if(-1 != conn->connectindex) {
     /* unlink ourselves! */
@@ -2519,8 +2596,8 @@ int Curl_protocol_getsock(struct connectdata *conn,
                           curl_socket_t *socks,
                           int numsocks)
 {
-  if(conn->curl_proto_getsock)
-    return conn->curl_proto_getsock(conn, socks, numsocks);
+  if(conn->handler->proto_getsock)
+    return conn->handler->proto_getsock(conn, socks, numsocks);
   return GETSOCK_BLANK;
 }
 
@@ -2528,8 +2605,8 @@ int Curl_doing_getsock(struct connectdata *conn,
                        curl_socket_t *socks,
                        int numsocks)
 {
-  if(conn && conn->curl_doing_getsock)
-    return conn->curl_doing_getsock(conn, socks, numsocks);
+  if(conn && conn->handler && conn->handler->doing_getsock)
+    return conn->handler->doing_getsock(conn, socks, numsocks);
   return GETSOCK_BLANK;
 }
 
@@ -2544,9 +2621,9 @@ CURLcode Curl_protocol_connecting(struct connectdata *conn,
 {
   CURLcode result=CURLE_OK;
 
-  if(conn && conn->curl_connecting) {
+  if(conn && conn->handler && conn->handler->connecting) {
     *done = FALSE;
-    result = conn->curl_connecting(conn, done);
+    result = conn->handler->connecting(conn, done);
   }
   else
     *done = TRUE;
@@ -2563,9 +2640,9 @@ CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
 {
   CURLcode result=CURLE_OK;
 
-  if(conn && conn->curl_doing) {
+  if(conn && conn->handler && conn->handler->doing) {
     *done = FALSE;
-    result = conn->curl_doing(conn, done);
+    result = conn->handler->doing(conn, done);
   }
   else
     *done = TRUE;
@@ -2593,7 +2670,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
 
        Unless this protocol doesn't have any protocol-connect callback, as
        then we know we're done. */
-    if(!conn->curl_connecting)
+    if(!conn->handler->connecting)
       *protocol_done = TRUE;
 
     return CURLE_OK;
@@ -2608,7 +2685,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
   }
 
   if(!conn->bits.protoconnstart) {
-    if(conn->curl_connect) {
+    if(conn->handler->connect_it) {
       /* is there a protocol-specific connect() procedure? */
 
       /* Set start time here for timeout purposes in the connect procedure, it
@@ -2616,7 +2693,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
       conn->now = Curl_tvnow();
 
       /* Call the protocol-specific connect function */
-      result = conn->curl_connect(conn, protocol_done);
+      result = conn->handler->connect_it(conn, protocol_done);
     }
     else
       *protocol_done = TRUE;
@@ -2943,285 +3020,39 @@ static CURLcode setup_range(struct SessionHandle *data)
 static CURLcode setup_connection_internals(struct SessionHandle *data,
                                            struct connectdata *conn)
 {
-  conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
-
-  if (strequal(conn->protostr, "HTTP")) {
-#ifndef CURL_DISABLE_HTTP
-    conn->port = PORT_HTTP;
-    conn->remote_port = PORT_HTTP;
-    conn->protocol |= PROT_HTTP;
-    conn->curl_do = Curl_http;
-    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
-    conn->curl_done = Curl_http_done;
-    conn->curl_connect = Curl_http_connect;
-#else
-    failf(data, LIBCURL_NAME
-          " was built with HTTP disabled, http: not supported!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
+  const struct Curl_handler * * pp;
+  const struct Curl_handler * p;
+  CURLcode result;
 
-  else if (strequal(conn->protostr, "HTTPS")) {
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+  conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
 
-    conn->port = PORT_HTTPS;
-    conn->remote_port = PORT_HTTPS;
-    conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
-
-    conn->curl_do = Curl_http;
-    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
-    conn->curl_done = Curl_http_done;
-    conn->curl_connect = Curl_http_connect;
-    conn->curl_connecting = Curl_https_connecting;
-    conn->curl_proto_getsock = Curl_https_getsock;
-
-#else /* USE_SSL */
-    failf(data, LIBCURL_NAME
-          " was built with SSL disabled, https: not supported!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif /* !USE_SSL */
-  }
+  /* Scan protocol handler table. */
 
-  else if(strequal(conn->protostr, "FTP") ||
-          strequal(conn->protostr, "FTPS")) {
+  for (pp = protocols; p = *pp; pp++)
+    if (strequal(p->scheme, conn->protostr)) {
+      /* Protocol found in table. Perform setup complement if some. */
+      conn->handler = p;
 
-#ifndef CURL_DISABLE_FTP
-    char *type;
-    int port = PORT_FTP;
-
-    if(strequal(conn->protostr, "FTPS")) {
-#ifdef USE_SSL
-      conn->protocol |= PROT_FTPS|PROT_SSL;
-      /* send data securely unless specifically requested otherwise */
-      conn->ssl[SECONDARYSOCKET].use = data->set.ftp_ssl != CURLUSESSL_CONTROL;
-      port = PORT_FTPS;
-#else
-      failf(data, LIBCURL_NAME
-            " was built with SSL disabled, ftps: not supported!");
-      return CURLE_UNSUPPORTED_PROTOCOL;
-#endif /* !USE_SSL */
-    }
+      if (p->setup_connection) {
+        result = (*p->setup_connection)(conn);
 
-    conn->port = port;
-    conn->remote_port = (unsigned short)port;
-    conn->protocol |= PROT_FTP;
+        if (result != CURLE_OK)
+          return result;
 
-    if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
-      /* Unless we have asked to tunnel ftp operations through the proxy, we
-         switch and use HTTP operations only */
-#ifndef CURL_DISABLE_HTTP
-      conn->curl_do = Curl_http;
-      conn->curl_done = Curl_http_done;
-      conn->protocol = PROT_HTTP; /* switch to HTTP */
-#else
-      failf(data, "FTP over http proxy requires HTTP support built-in!");
-      return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-    }
-    else {
-      conn->curl_do = Curl_ftp;
-      conn->curl_do_more = Curl_ftp_nextconnect;
-      conn->curl_done = Curl_ftp_done;
-      conn->curl_connect = Curl_ftp_connect;
-      conn->curl_connecting = Curl_ftp_multi_statemach;
-      conn->curl_doing = Curl_ftp_doing;
-      conn->curl_proto_getsock = Curl_ftp_getsock;
-      conn->curl_doing_getsock = Curl_ftp_getsock;
-      conn->curl_disconnect = Curl_ftp_disconnect;
-    }
-
-    data->reqdata.path++; /* don't include the initial slash */
-
-    /* FTP URLs support an extension like ";type=<typecode>" that
-     * we'll try to get now! */
-    type=strstr(data->reqdata.path, ";type=");
-    if(!type) {
-      type=strstr(conn->host.rawalloc, ";type=");
-    }
-    if(type) {
-      char command;
-      *type=0;                     /* it was in the middle of the hostname */
-      command = (char)toupper((int)type[6]);
-      switch(command) {
-      case 'A': /* ASCII mode */
-        data->set.prefer_ascii = TRUE;
-        break;
-      case 'D': /* directory mode */
-        data->set.ftp_list_only = TRUE;
-        break;
-      case 'I': /* binary mode */
-      default:
-        /* switch off ASCII */
-        data->set.prefer_ascii = FALSE;
-        break;
+        p = conn->handler;              /* May have changed. */
       }
-    }
-#else /* CURL_DISABLE_FTP */
-    failf(data, LIBCURL_NAME
-          " was built with FTP disabled, ftp/ftps: not supported!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-
-  else if(strequal(conn->protostr, "TELNET")) {
-#ifndef CURL_DISABLE_TELNET
-    /* telnet testing factory */
-    conn->protocol |= PROT_TELNET;
-
-    conn->port = PORT_TELNET;
-    conn->remote_port = PORT_TELNET;
-    conn->curl_do = Curl_telnet;
-    conn->curl_done = Curl_telnet_done;
-#else
-    failf(data, LIBCURL_NAME
-          " was built with TELNET disabled!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-
-  else if (strequal(conn->protostr, "DICT")) {
-#ifndef CURL_DISABLE_DICT
-    conn->protocol |= PROT_DICT;
-    conn->port = PORT_DICT;
-    conn->remote_port = PORT_DICT;
-    conn->curl_do = Curl_dict;
-    /* no DICT-specific done */
-    conn->curl_done = (Curl_done_func)ZERO_NULL;
-#else
-    failf(data, LIBCURL_NAME
-          " was built with DICT disabled!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-
-  else if (strequal(conn->protostr, "LDAP")) {
-#ifndef CURL_DISABLE_LDAP
-    conn->protocol |= PROT_LDAP;
-    conn->port = PORT_LDAP;
-    conn->remote_port = PORT_LDAP;
-    conn->curl_do = Curl_ldap;
-    /* no LDAP-specific done */
-    conn->curl_done = (Curl_done_func)ZERO_NULL;
-#else
-    failf(data, LIBCURL_NAME
-          " was built with LDAP disabled!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-
-#ifdef HAVE_LDAP_SSL
-  else if (strequal(conn->protostr, "LDAPS")) {
-#ifndef CURL_DISABLE_LDAP
-    conn->protocol |= PROT_LDAP|PROT_SSL;
-    conn->port = PORT_LDAPS;
-    conn->remote_port = PORT_LDAPS;
-    conn->curl_do = Curl_ldap;
-    /* no LDAP-specific done */
-    conn->curl_done = (Curl_done_func)ZERO_NULL;
-#else
-    failf(data, LIBCURL_NAME
-          " was built with LDAP disabled!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-#endif /* CURL_LDAP_USE_SSL */
-
-  else if (strequal(conn->protostr, "FILE")) {
-#ifndef CURL_DISABLE_FILE
-    conn->protocol |= PROT_FILE;
-
-    conn->curl_do = Curl_file;
-    conn->curl_done = Curl_file_done;
-#else
-    failf(data, LIBCURL_NAME
-          " was built with FILE disabled!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
 
-  else if (strequal(conn->protostr, "TFTP")) {
-#ifndef CURL_DISABLE_TFTP
-    char *type;
-    conn->socktype = SOCK_DGRAM; /* UDP datagram based */
-    conn->protocol |= PROT_TFTP;
-    conn->port = PORT_TFTP;
-    conn->remote_port = PORT_TFTP;
-    conn->curl_connect = Curl_tftp_connect;
-    conn->curl_do = Curl_tftp;
-    conn->curl_done = Curl_tftp_done;
-    /* TFTP URLs support an extension like ";mode=<typecode>" that
-     * we'll try to get now! */
-    type=strstr(data->reqdata.path, ";mode=");
-    if(!type) {
-      type=strstr(conn->host.rawalloc, ";mode=");
+      conn->port = p->defport;
+      conn->remote_port = p->defport;
+      conn->protocol |= p->protocol;
+      return CURLE_OK;
     }
-    if(type) {
-      char command;
-      *type=0;                     /* it was in the middle of the hostname */
-      command = (char)toupper((int)type[6]);
-      switch(command) {
-      case 'A': /* ASCII mode */
-      case 'N': /* NETASCII mode */
-        data->set.prefer_ascii = TRUE;
-        break;
-      case 'O': /* octet mode */
-      case 'I': /* binary mode */
-      default:
-        /* switch off ASCII */
-        data->set.prefer_ascii = FALSE;
-        break;
-      }
-    }
-#else
-    failf(data, LIBCURL_NAME
-          " was built with TFTP disabled!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-
-  else if (strequal(conn->protostr, "SCP")) {
-#ifdef USE_LIBSSH2
-    conn->port = PORT_SSH;
-    conn->remote_port = PORT_SSH;
-    conn->protocol = PROT_SCP;
-    conn->curl_connect = Curl_ssh_connect; /* ssh_connect? */
-    conn->curl_do = Curl_scp_do;
-    conn->curl_done = Curl_scp_done;
-    conn->curl_connecting = Curl_ssh_multi_statemach;
-    conn->curl_doing = Curl_scp_doing;
-    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
-#else
-    failf(data, LIBCURL_NAME
-          " was built without LIBSSH2, scp: not supported!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
 
-  else if (strequal(conn->protostr, "SFTP")) {
-#ifdef USE_LIBSSH2
-    conn->port = PORT_SSH;
-    conn->remote_port = PORT_SSH;
-    conn->protocol = PROT_SFTP;
-    conn->curl_connect = Curl_ssh_connect; /* ssh_connect? */
-    conn->curl_do = Curl_sftp_do;
-    conn->curl_done = Curl_sftp_done;
-    conn->curl_connecting = Curl_ssh_multi_statemach;
-    conn->curl_doing = Curl_sftp_doing;
-    conn->curl_do_more = (Curl_do_more_func)ZERO_NULL;
-#else
-    failf(data, LIBCURL_NAME
-          " was built without LIBSSH2, scp: not supported!");
-    return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-  }
-
-  else {
-    /* We fell through all checks and thus we don't support the specified
-       protocol */
-    failf(data, "Unsupported protocol: %s", conn->protostr);
-    return CURLE_UNSUPPORTED_PROTOCOL;
-  }
-  return CURLE_OK;
+  /* Protocol not found in table. */
+  conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined. */
+  failf(data, "Protocol %s not supported or disabled in " LIBCURL_NAME,
+        conn->protostr);
+  return CURLE_UNSUPPORTED_PROTOCOL;
 }
 
 /****************************************************************
@@ -4495,8 +4326,8 @@ CURLcode Curl_done(struct connectdata **connp,
   }
 
   /* this calls the protocol-specific function pointer previously set */
-  if(conn->curl_done)
-    result = conn->curl_done(conn, status, premature);
+  if(conn->handler->done)
+    result = conn->handler->done(conn, status, premature);
   else
     result = CURLE_OK;
 
@@ -4548,9 +4379,9 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
   conn->bits.done = FALSE; /* Curl_done() is not called yet */
   conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
 
-  if(conn->curl_do) {
+  if(conn->handler->do_it) {
     /* generic protocol-specific function pointer set in curl_connect() */
-    result = conn->curl_do(conn, done);
+    result = conn->handler->do_it(conn, done);
 
     /* This was formerly done in transfer.c, but we better do it here */
 
@@ -4599,7 +4430,7 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
           }
 
           /* ... finally back to actually retry the DO phase */
-          result = conn->curl_do(conn, done);
+          result = conn->handler->do_it(conn, done);
         }
       }
     }
@@ -4611,8 +4442,8 @@ CURLcode Curl_do_more(struct connectdata *conn)
 {
   CURLcode result=CURLE_OK;
 
-  if(conn->curl_do_more)
-    result = conn->curl_do_more(conn);
+  if(conn->handler->do_more)
+    result = conn->handler->do_more(conn);
 
   return result;
 }
index 52647a1cbef895384fc0a2daaa71ae8fb49101ef..ef685e183acc62e2b80f59a209c5101303957dc1 100644 (file)
@@ -809,6 +809,59 @@ struct HandleData {
   } proto;
 };
 
+/*
+ * Specific protocol handler.
+ */
+
+struct Curl_handler {
+  const char * scheme;        /* URL scheme name. */
+
+  /* Complement to setup_connection_internals(). */
+  CURLcode (*setup_connection)(struct connectdata *);
+
+  /* These two functions MUST be set to be protocol dependent */
+  CURLcode (*do_it)(struct connectdata *, bool *done);
+  Curl_done_func done;
+
+  /* If the curl_do() function is better made in two halves, this
+   * curl_do_more() function will be called afterwards, if set. For example
+   * for doing the FTP stuff after the PASV/PORT command.
+   */
+  Curl_do_more_func do_more;
+
+  /* This function *MAY* be set to a protocol-dependent function that is run
+   * after the connect() and everything is done, as a step in the connection.
+   * The 'done' pointer points to a bool that should be set to TRUE if the
+   * function completes before return. If it doesn't complete, the caller
+   * should call the curl_connecting() function until it is.
+   */
+  CURLcode (*connect_it)(struct connectdata *, bool *done);
+
+  /* See above. Currently only used for FTP. */
+  CURLcode (*connecting)(struct connectdata *, bool *done);
+  CURLcode (*doing)(struct connectdata *, bool *done);
+
+  /* Called from the multi interface during the PROTOCONNECT phase, and it
+     should then return a proper fd set */
+  int (*proto_getsock)(struct connectdata *conn,
+                       curl_socket_t *socks,
+                       int numsocks);
+
+  /* Called from the multi interface during the DOING phase, and it should
+     then return a proper fd set */
+  int (*doing_getsock)(struct connectdata *conn,
+                       curl_socket_t *socks,
+                       int numsocks);
+
+  /* This function *MAY* be set to a protocol-dependent function that is run
+   * by the curl_disconnect(), as a step in the disconnection.
+   */
+  CURLcode (*disconnect)(struct connectdata *);
+
+  long defport;       /* Default port. */
+  long protocol;      /* PROT_* flags concerning the protocol set */
+};
+
 /*
  * The connectdata struct contains all fields and variables that should be
  * unique for an entire connection.
@@ -894,50 +947,7 @@ struct connectdata {
 
   struct ConnectBits bits;    /* various state-flags for this connection */
 
-  /* These two functions MUST be set by the curl_connect() function to be
-     be protocol dependent */
-  CURLcode (*curl_do)(struct connectdata *, bool *done);
-  Curl_done_func curl_done;
-
-  /* If the curl_do() function is better made in two halves, this
-   * curl_do_more() function will be called afterwards, if set. For example
-   * for doing the FTP stuff after the PASV/PORT command.
-   */
-  Curl_do_more_func curl_do_more;
-
-  /* This function *MAY* be set to a protocol-dependent function that is run
-   * after the connect() and everything is done, as a step in the connection.
-   * The 'done' pointer points to a bool that should be set to TRUE if the
-   * function completes before return. If it doesn't complete, the caller
-   * should call the curl_connecting() function until it is.
-   */
-  CURLcode (*curl_connect)(struct connectdata *, bool *done);
-
-  /* See above. Currently only used for FTP. */
-  CURLcode (*curl_connecting)(struct connectdata *, bool *done);
-  CURLcode (*curl_doing)(struct connectdata *, bool *done);
-
-  /* Called from the multi interface during the PROTOCONNECT phase, and it
-     should then return a proper fd set */
-  int (*curl_proto_getsock)(struct connectdata *conn,
-                            curl_socket_t *socks,
-                            int numsocks);
-
-  /* Called from the multi interface during the DOING phase, and it should
-     then return a proper fd set */
-  int (*curl_doing_getsock)(struct connectdata *conn,
-                            curl_socket_t *socks,
-                            int numsocks);
-
-  /* This function *MAY* be set to a protocol-dependent function that is run
-   * by the curl_disconnect(), as a step in the disconnection.
-   */
-  CURLcode (*curl_disconnect)(struct connectdata *);
-
-  /* This function *MAY* be set to a protocol-dependent function that is run
-   * in the curl_close() function if protocol-specific cleanups are required.
-   */
-  CURLcode (*curl_close)(struct connectdata *);
+  const struct Curl_handler * handler;  /* Connection's protocol handler. */
 
   /**** curl_get() phase fields */