[process] Include process name in debug messages
[ipxe.git] / src / core / open.c
1 /*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdarg.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <ipxe/xfer.h>
30 #include <ipxe/uri.h>
31 #include <ipxe/socket.h>
32 #include <ipxe/open.h>
33
34 /** @file
35 *
36 * Data transfer interface opening
37 *
38 */
39
40 /**
41 * Find opener for URI scheme
42 *
43 * @v scheme URI scheme
44 * @ret opener Opener, or NULL
45 */
46 struct uri_opener * xfer_uri_opener ( const char *scheme ) {
47 struct uri_opener *opener;
48
49 for_each_table_entry ( opener, URI_OPENERS ) {
50 if ( strcmp ( scheme, opener->scheme ) == 0 )
51 return opener;
52 }
53 return NULL;
54 }
55
56 /**
57 * Open URI
58 *
59 * @v intf Data transfer interface
60 * @v uri URI
61 * @ret rc Return status code
62 *
63 * The URI will be regarded as being relative to the current working
64 * URI (see churi()).
65 */
66 int xfer_open_uri ( struct interface *intf, struct uri *uri ) {
67 struct uri_opener *opener;
68 struct uri *resolved_uri;
69 int rc;
70
71 /* Resolve URI */
72 resolved_uri = resolve_uri ( cwuri, uri );
73 if ( ! resolved_uri ) {
74 rc = -ENOMEM;
75 goto err_resolve_uri;
76 }
77
78 /* Find opener which supports this URI scheme */
79 opener = xfer_uri_opener ( resolved_uri->scheme );
80 if ( ! opener ) {
81 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
82 "unsupported URI scheme \"%s\"\n",
83 INTF_DBG ( intf ), resolved_uri->scheme );
84 rc = -ENOTSUP;
85 goto err_opener;
86 }
87
88 /* Call opener */
89 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening %s URI\n",
90 INTF_DBG ( intf ), resolved_uri->scheme );
91 if ( ( rc = opener->open ( intf, resolved_uri ) ) != 0 ) {
92 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " could not open: "
93 "%s\n", INTF_DBG ( intf ), strerror ( rc ) );
94 goto err_open;
95 }
96
97 err_open:
98 err_opener:
99 uri_put ( resolved_uri );
100 err_resolve_uri:
101 return rc;
102 }
103
104 /**
105 * Open URI string
106 *
107 * @v intf Data transfer interface
108 * @v uri_string URI string (e.g. "http://ipxe.org/kernel")
109 * @ret rc Return status code
110 *
111 * The URI will be regarded as being relative to the current working
112 * URI (see churi()).
113 */
114 int xfer_open_uri_string ( struct interface *intf,
115 const char *uri_string ) {
116 struct uri *uri;
117 int rc;
118
119 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening URI %s\n",
120 INTF_DBG ( intf ), uri_string );
121
122 uri = parse_uri ( uri_string );
123 if ( ! uri )
124 return -ENOMEM;
125
126 rc = xfer_open_uri ( intf, uri );
127
128 uri_put ( uri );
129 return rc;
130 }
131
132 /**
133 * Open socket
134 *
135 * @v intf Data transfer interface
136 * @v semantics Communication semantics (e.g. SOCK_STREAM)
137 * @v peer Peer socket address
138 * @v local Local socket address, or NULL
139 * @ret rc Return status code
140 */
141 int xfer_open_socket ( struct interface *intf, int semantics,
142 struct sockaddr *peer, struct sockaddr *local ) {
143 struct socket_opener *opener;
144
145 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening (%s,%s) socket\n",
146 INTF_DBG ( intf ), socket_semantics_name ( semantics ),
147 socket_family_name ( peer->sa_family ) );
148
149 for_each_table_entry ( opener, SOCKET_OPENERS ) {
150 if ( ( opener->semantics == semantics ) &&
151 ( opener->family == peer->sa_family ) ) {
152 return opener->open ( intf, peer, local );
153 }
154 }
155
156 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
157 "unsupported socket type (%s,%s)\n",
158 INTF_DBG ( intf ), socket_semantics_name ( semantics ),
159 socket_family_name ( peer->sa_family ) );
160 return -ENOTSUP;
161 }
162
163 /**
164 * Open location
165 *
166 * @v intf Data transfer interface
167 * @v type Location type
168 * @v args Remaining arguments depend upon location type
169 * @ret rc Return status code
170 */
171 int xfer_vopen ( struct interface *intf, int type, va_list args ) {
172 switch ( type ) {
173 case LOCATION_URI_STRING: {
174 const char *uri_string = va_arg ( args, const char * );
175
176 return xfer_open_uri_string ( intf, uri_string ); }
177 case LOCATION_URI: {
178 struct uri *uri = va_arg ( args, struct uri * );
179
180 return xfer_open_uri ( intf, uri ); }
181 case LOCATION_SOCKET: {
182 int semantics = va_arg ( args, int );
183 struct sockaddr *peer = va_arg ( args, struct sockaddr * );
184 struct sockaddr *local = va_arg ( args, struct sockaddr * );
185
186 return xfer_open_socket ( intf, semantics, peer, local ); }
187 default:
188 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to "
189 "open unsupported location type %d\n",
190 INTF_DBG ( intf ), type );
191 return -ENOTSUP;
192 }
193 }
194
195 /**
196 * Open location
197 *
198 * @v intf Data transfer interface
199 * @v type Location type
200 * @v ... Remaining arguments depend upon location type
201 * @ret rc Return status code
202 */
203 int xfer_open ( struct interface *intf, int type, ... ) {
204 va_list args;
205 int rc;
206
207 va_start ( args, type );
208 rc = xfer_vopen ( intf, type, args );
209 va_end ( args );
210 return rc;
211 }
212
213 /**
214 * Reopen location
215 *
216 * @v intf Data transfer interface
217 * @v type Location type
218 * @v args Remaining arguments depend upon location type
219 * @ret rc Return status code
220 *
221 * This will close the existing connection and open a new connection
222 * using xfer_vopen(). It is intended to be used as a .vredirect
223 * method handler.
224 */
225 int xfer_vreopen ( struct interface *intf, int type, va_list args ) {
226
227 /* Close existing connection */
228 intf_restart ( intf, 0 );
229
230 /* Open new location */
231 return xfer_vopen ( intf, type, args );
232 }