+/* pay attention to levels of indirection */
+typedef struct socket_function_table **Socket;
+typedef struct plug_function_table **Plug;
+
+#ifndef OSSOCKET_DEFINED
+typedef void *OSSocket;
+#endif
+
+struct socket_function_table {
+ Plug(*plug) (Socket s, Plug p);
+ /* use a different plug (return the old one) */
+ /* if p is NULL, it doesn't change the plug */
+ /* but it does return the one it's using */
+ void (*close) (Socket s);
+ int (*write) (Socket s, const char *data, int len);
+ int (*write_oob) (Socket s, const char *data, int len);
+ void (*flush) (Socket s);
+ void (*set_private_ptr) (Socket s, void *ptr);
+ void *(*get_private_ptr) (Socket s);
+ void (*set_frozen) (Socket s, int is_frozen);
+ /* ignored by tcp, but vital for ssl */
+ const char *(*socket_error) (Socket s);
+};
+
+struct plug_function_table {
+ int (*closing)
+ (Plug p, const char *error_msg, int error_code, int calling_back);
+ /* error_msg is NULL iff it is not an error (ie it closed normally) */
+ /* calling_back != 0 iff there is a Plug function */
+ /* currently running (would cure the fixme in try_send()) */
+ int (*receive) (Plug p, int urgent, char *data, int len);
+ /*
+ * - urgent==0. `data' points to `len' bytes of perfectly
+ * ordinary data.
+ *
+ * - urgent==1. `data' points to `len' bytes of data,
+ * which were read from before an Urgent pointer.
+ *
+ * - urgent==2. `data' points to `len' bytes of data,
+ * the first of which was the one at the Urgent mark.
+ */
+ void (*sent) (Plug p, int bufsize);
+ /*
+ * The `sent' function is called when the pending send backlog
+ * on a socket is cleared or partially cleared. The new backlog
+ * size is passed in the `bufsize' parameter.
+ */
+ int (*accepting)(Plug p, OSSocket sock);
+ /*
+ * returns 0 if the host at address addr is a valid host for connecting or error
+ */
+};
+
+/* proxy indirection layer */
+/* NB, control of 'addr' is passed via new_connection, which takes
+ * responsibility for freeing it */
+Socket new_connection(SockAddr addr, char *hostname,
+ int port, int privport,
+ int oobinline, int nodelay, int keepalive,
+ Plug plug, const Config *cfg);
+Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
+ const Config *cfg, int addressfamily);
+SockAddr name_lookup(char *host, int port, char **canonicalname,
+ const Config *cfg, int addressfamily);
+
+/* platform-dependent callback from new_connection() */
+/* (same caveat about addr as new_connection()) */
+Socket platform_new_connection(SockAddr addr, char *hostname,
+ int port, int privport,
+ int oobinline, int nodelay, int keepalive,
+ Plug plug, const Config *cfg);
+
+/* socket functions */