1 /* NB: the transfer isn't *really* done until you're finishing uploading and/or downloading, 2 but we actually ignore that; not ignoring makes a slightly irritating circular reference danger. 3 */ 4 #ifndef __GSK_URL_TRANSFER_H_ 5 #define __GSK_URL_TRANSFER_H_ 6 7 #include "gskurl.h" 8 #include "../gsksocketaddress.h" 9 #include "../gskmainloop.h" 10 #include "../gskpacket.h" 11 12 G_BEGIN_DECLS 13 14 typedef struct _GskUrlTransferClass GskUrlTransferClass; 15 typedef struct _GskUrlTransferRedirect GskUrlTransferRedirect; 16 typedef struct _GskUrlTransfer GskUrlTransfer; 17 18 GType gsk_url_transfer_get_type(void) G_GNUC_CONST; 19 #define GSK_TYPE_URL_TRANSFER (gsk_url_transfer_get_type ()) 20 #define GSK_URL_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_URL_TRANSFER, GskUrlTransfer)) 21 #define GSK_URL_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_URL_TRANSFER, GskUrlTransferClass)) 22 #define GSK_URL_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_URL_TRANSFER, GskUrlTransferClass)) 23 #define GSK_IS_URL_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_URL_TRANSFER)) 24 #define GSK_IS_URL_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_URL_TRANSFER)) 25 26 typedef enum 27 { 28 GSK_URL_TRANSFER_ERROR_BAD_REQUEST, 29 GSK_URL_TRANSFER_ERROR_BAD_NAME, 30 GSK_URL_TRANSFER_ERROR_NO_SERVER, 31 GSK_URL_TRANSFER_ERROR_NOT_FOUND, 32 GSK_URL_TRANSFER_ERROR_SERVER_ERROR, 33 GSK_URL_TRANSFER_ERROR_UNSUPPORTED, 34 GSK_URL_TRANSFER_ERROR_TIMED_OUT, 35 GSK_URL_TRANSFER_ERROR_REDIRECT_LOOP, 36 GSK_URL_TRANSFER_REDIRECT, 37 GSK_URL_TRANSFER_CANCELLED, 38 GSK_URL_TRANSFER_SUCCESS 39 } GskUrlTransferResult; 40 41 #define GSK_URL_TRANSFER_N_RESULTS (GSK_URL_TRANSFER_SUCCESS+1) 42 43 const char *gsk_url_transfer_result_name (GskUrlTransferResult result); 44 45 typedef void (*GskUrlTransferFunc) (GskUrlTransfer *info, 46 gpointer user_data); 47 typedef GskStream *(*GskUrlUploadFunc)(gpointer upload_data, 48 gssize *size_out, 49 GError **error); 50 51 struct _GskUrlTransferClass 52 { 53 GObjectClass base_class; 54 55 /* The test() method is called before the instance 56 is constructed, to give the class an opportunity to 57 see if it can handle the url. */ 58 gboolean (*test) (GskUrlTransferClass *transfer_class, 59 const GskUrl *url); 60 61 /* The start() method is called on an instance which 62 has been configured. It returns TRUE if the transfer is started. 63 If it returns FALSE, an error has occurred. */ 64 gboolean (*start) (GskUrlTransfer *transfer, 65 GError **error); 66 67 void (*cancel)(GskUrlTransfer *transfer); 68 69 char *(*get_constructing_state) (GskUrlTransfer *transfer); 70 char *(*get_running_state) (GskUrlTransfer *transfer); 71 char *(*get_done_state) (GskUrlTransfer *transfer); 72 73 /* default impl calls gsk_url_transfer_task_notify_done(ERROR_TIMEOUT) */ 74 void (*timed_out)(GskUrlTransfer *transfer); 75 }; 76 77 struct _GskUrlTransferRedirect 78 { 79 gboolean is_permanent; 80 GskUrl *url; 81 GObject *request; 82 GObject *response; 83 GskUrlTransferRedirect *next; 84 }; 85 86 87 88 struct _GskUrlTransfer 89 { 90 GObject base_instance; 91 92 /*< public >*/ 93 /* --- information prepared for the handler --- */ 94 GskUrlTransferResult result; 95 GskUrl *url; 96 GSList *redirect_urls; // XXX: unused 97 GskUrlTransferRedirect *first_redirect, *last_redirect; 98 GskSocketAddress *address; 99 100 /* may be available: protocol-specific headers */ 101 GObject *request; /* a GskHttpRequest probably */ 102 GObject *response; /* a GskHttpResponse probably */ 103 104 GskStream *content; /* the downloading content */ 105 106 /* the last redirect (if any) */ 107 GskUrl *redirect_url; /* [just a peeked version of last_redirect->url, not a ref] */ 108 gboolean redirect_is_permanent; 109 110 /* ERROR status codes */ 111 GError *error; 112 113 /*< protected >*/ 114 GskSocketAddress *address_hint; 115 guint follow_redirects : 1; 116 guint has_timeout : 1; 117 guint timed_out : 1; 118 119 /*< private >*/ 120 GskSource *timeout_source; 121 guint timeout_ms; 122 123 GskUrlTransferFunc handler; 124 gpointer handler_data; 125 GDestroyNotify handler_data_destroy; 126 127 GskUrlUploadFunc upload_func; 128 gpointer upload_data; 129 GDestroyNotify upload_destroy; 130 131 guint transfer_state; 132 }; 133 134 gboolean gsk_url_transfer (GskUrl *url, 135 GskUrlUploadFunc upload_func, 136 gpointer upload_data, 137 GDestroyNotify upload_destroy, 138 GskUrlTransferFunc handler, 139 gpointer data, 140 GDestroyNotify destroy, 141 GError **error); 142 143 GskUrlTransfer *gsk_url_transfer_new (GskUrl *url); 144 145 void gsk_url_transfer_set_handler(GskUrlTransfer *transfer, 146 GskUrlTransferFunc handler, 147 gpointer data, 148 GDestroyNotify destroy); 149 void gsk_url_transfer_set_url (GskUrlTransfer *transfer, 150 GskUrl *url); 151 void gsk_url_transfer_set_upload (GskUrlTransfer *transfer, 152 GskUrlUploadFunc func, 153 gpointer data, 154 GDestroyNotify destroy); 155 void gsk_url_transfer_set_upload_packet(GskUrlTransfer *transfer, 156 GskPacket *packet); 157 void gsk_url_transfer_set_oneshot_upload(GskUrlTransfer *transfer, 158 GskStream *stream, 159 gssize size); 160 161 void gsk_url_transfer_set_timeout(GskUrlTransfer *transfer, 162 guint millis); 163 void gsk_url_transfer_clear_timeout(GskUrlTransfer *transfer); 164 165 void gsk_url_transfer_set_follow_redirects(GskUrlTransfer *transfer, 166 gboolean follow_redirs); 167 void gsk_url_transfer_set_address_hint(GskUrlTransfer *transfer, 168 GskSocketAddress *address); 169 170 /* Starting a transfer */ 171 gboolean gsk_url_transfer_start (GskUrlTransfer *transfer, 172 GError **error); 173 174 /* Cancelling a started transfer */ 175 void gsk_url_transfer_cancel (GskUrlTransfer *transfer); 176 177 178 char * gsk_url_transfer_get_state_string (GskUrlTransfer *transfer); 179 180 181 /* --- Treating a Transfer as a Stream --- */ 182 GskStream * gsk_url_transfer_stream_new (GskUrlTransfer *transfer, 183 GError **error); 184 185 /* --- Protected API --- */ 186 gboolean gsk_url_transfer_has_upload (GskUrlTransfer *transfer); 187 GskStream *gsk_url_transfer_create_upload (GskUrlTransfer *transfer, 188 gssize *size_out, 189 GError **error); 190 gboolean gsk_url_transfer_peek_expects_download_stream (GskUrlTransfer *transfer); 191 192 /* whether gsk_url_transfer_notify_done() has been called */ 193 gboolean gsk_url_transfer_is_done (GskUrlTransfer *transfer); 194 195 /* invoke the notification callbacks as needed */ 196 void gsk_url_transfer_set_address (GskUrlTransfer *transfer, 197 GskSocketAddress *addr); 198 gboolean gsk_url_transfer_add_redirect (GskUrlTransfer *transfer, 199 GObject *request, 200 GObject *response, 201 gboolean is_permanent, 202 GskUrl *dest_url); 203 void gsk_url_transfer_set_download (GskUrlTransfer *transfer, 204 GskStream *content); 205 void gsk_url_transfer_set_request (GskUrlTransfer *transfer, 206 GObject *request); 207 void gsk_url_transfer_set_response (GskUrlTransfer *transfer, 208 GObject *response); 209 210 void gsk_url_transfer_set_error (GskUrlTransfer *transfer, 211 const GError *error); 212 void gsk_url_transfer_take_error (GskUrlTransfer *transfer, 213 GError *error); 214 215 /* NOTE: does a g_object_unref() (undoing the one in gsk_url_transfer_start), 216 so the transfer may be destroyed by this function. */ 217 void gsk_url_transfer_notify_done (GskUrlTransfer *transfer, 218 GskUrlTransferResult result); 219 220 /* Registering a transfer type */ 221 void gsk_url_transfer_class_register (GskUrlScheme scheme, 222 GskUrlTransferClass *transfer_class); 223 224 G_END_DECLS 225 226 #endif 227