diff --git a/src/core/download.c b/src/core/download.c index f748d023..bc890127 100644 --- a/src/core/download.c +++ b/src/core/download.c @@ -30,6 +30,8 @@ #include #include +static struct async_operations download_async_operations; + /** Registered download protocols */ static struct download_protocol download_protocols[0] __table_start ( struct download_protocol, download_protocols ); @@ -53,53 +55,6 @@ static struct download_protocol * find_protocol ( const char *name ) { return NULL; } -/** Free download resources */ -static void download_reap ( struct async *async ) { - struct download *download = - container_of ( async, struct download, async ); - - free ( download ); -} - -/** - * Handle download termination - * - * @v async Download asynchronous operation - * @v signal SIGCHLD - */ -static void download_sigchld ( struct async *async, - enum signal signal __unused ) { - struct download *download = - container_of ( async, struct download, async ); - int rc; - - /* Reap child */ - async_wait ( async, &rc, 1 ); - - /* Clean up */ - if ( rc == 0 ) { - /* Transfer ownership of buffer to parent */ - *(download->data) = download->buffer.addr; - *(download->len) = download->buffer.fill; - } else { - /* Discard the buffer */ - ufree ( download->buffer.addr ); - } - free_uri ( download->uri ); - download->uri = NULL; - - /* Terminate ourselves */ - async_done ( async, rc ); -} - -/** Download asynchronous operations */ -static struct async_operations download_async_operations = { - .reap = download_reap, - .signal = { - [SIGCHLD] = download_sigchld, - }, -}; - /** * Start download * @@ -170,3 +125,51 @@ int start_download ( const char *uri_string, struct async *parent, free ( download ); return rc; } + +/** + * Handle download termination + * + * @v async Download asynchronous operation + * @v signal SIGCHLD + */ +static void download_sigchld ( struct async *async, + enum signal signal __unused ) { + struct download *download = + container_of ( async, struct download, async ); + int rc; + + /* Reap child */ + async_wait ( async, &rc, 1 ); + + /* Clean up */ + if ( rc == 0 ) { + /* Transfer ownership of buffer to parent */ + *(download->data) = download->buffer.addr; + *(download->len) = download->buffer.fill; + } else { + /* Discard the buffer */ + ufree ( download->buffer.addr ); + } + free_uri ( download->uri ); + download->uri = NULL; + + /* Terminate ourselves */ + async_done ( async, rc ); +} + +/** + * Free download resources + * + * @v async Download asynchronous operation + */ +static void download_reap ( struct async *async ) { + free ( container_of ( async, struct download, async ) ); +} + +/** Download asynchronous operations */ +static struct async_operations download_async_operations = { + .reap = download_reap, + .signal = { + [SIGCHLD] = download_sigchld, + }, +}; diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c index 6ae664ad..84b8e166 100644 --- a/src/net/tcp/http.c +++ b/src/net/tcp/http.c @@ -37,6 +37,8 @@ #include #include +static struct async_operations http_async_operations; + static inline struct http_request * tcp_to_http ( struct tcp_application *app ) { return container_of ( app, struct http_request, tcp ); @@ -356,58 +358,6 @@ static struct tcp_operations http_tcp_operations = { .senddata = http_senddata, }; -/** - * Reap asynchronous operation - * - * @v async Asynchronous operation - */ -static void http_reap ( struct async *async ) { - struct http_request *http = - container_of ( async, struct http_request, async ); - - free ( http ); -} - -/** - * Handle name resolution completion - * - * @v async HTTP asynchronous operation - * @v signal SIGCHLD - */ -static void http_sigchld ( struct async *async, enum signal signal __unused ) { - struct http_request *http = - container_of ( async, struct http_request, async ); - struct sockaddr_tcpip *st = ( struct sockaddr_tcpip * ) &http->server; - int rc; - - /* Reap child */ - async_wait ( async, &rc, 1 ); - - /* If name resolution failed, abort now */ - if ( rc != 0 ) { - http_done ( http, rc ); - return; - } - - /* Otherwise, start the HTTP connection */ - http->tcp.tcp_op = &http_tcp_operations; - st->st_port = htons ( uri_port ( http->uri, HTTP_PORT ) ); - if ( ( rc = tcp_connect ( &http->tcp, st, 0 ) ) != 0 ) { - DBGC ( http, "HTTP %p could not open TCP connection: %s\n", - http, strerror ( rc ) ); - http_done ( http, rc ); - return; - } -} - -/** HTTP asynchronous operations */ -static struct async_operations http_async_operations = { - .reap = http_reap, - .signal = { - [SIGCHLD] = http_sigchld, - }, -}; - /** * Initiate a HTTP connection * @@ -420,12 +370,6 @@ int http_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) { struct http_request *http = NULL; int rc; - /* Sanity check */ - if ( ! uri->host ) { - rc = -EINVAL; - goto err; - } - /* Allocate and populate HTTP structure */ http = malloc ( sizeof ( *http ) ); if ( ! http ) @@ -456,6 +400,53 @@ int http_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) { return rc; } +/** + * Handle name resolution completion + * + * @v async HTTP asynchronous operation + * @v signal SIGCHLD + */ +static void http_sigchld ( struct async *async, enum signal signal __unused ) { + struct http_request *http = + container_of ( async, struct http_request, async ); + struct sockaddr_tcpip *st = ( struct sockaddr_tcpip * ) &http->server; + int rc; + + /* If name resolution failed, abort now */ + async_wait ( async, &rc, 1 ); + if ( rc != 0 ) { + http_done ( http, rc ); + return; + } + + /* Otherwise, start the HTTP connection */ + http->tcp.tcp_op = &http_tcp_operations; + st->st_port = htons ( uri_port ( http->uri, HTTP_PORT ) ); + if ( ( rc = tcp_connect ( &http->tcp, st, 0 ) ) != 0 ) { + DBGC ( http, "HTTP %p could not open TCP connection: %s\n", + http, strerror ( rc ) ); + http_done ( http, rc ); + return; + } +} + +/** + * Free HTTP connection + * + * @v async Asynchronous operation + */ +static void http_reap ( struct async *async ) { + free ( container_of ( async, struct http_request, async ) ); +} + +/** HTTP asynchronous operations */ +static struct async_operations http_async_operations = { + .reap = http_reap, + .signal = { + [SIGCHLD] = http_sigchld, + }, +}; + /** HTTP download protocol */ struct download_protocol http_download_protocol __download_protocol = { .name = "http",