2 * Copyright (C) 2008 dhewg, #wiidev efnet
4 * this file is part of wiifuse
5 * http://wiibrew.org/index.php?title=Wiifuse
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <sys/types.h>
34 static pthread_mutex_t gecko_mutex
;
36 int get_id_file_size (const char *fn
, u16
*size
) {
44 if (st
.st_size
> 0xffff)
47 *size
= st
.st_size
& 0xffff;
52 int load_id_file (const char *fn
, void *data
, const u16 size
) {
61 if (size
!= fread (data
, 1, size
, f
)) {
71 int get_identity (const char *id
, u8
**data
, u16
*data_size
) {
72 char fn_certs
[MAX_FILENAME_SIZE
];
73 char fn_tmd
[MAX_FILENAME_SIZE
];
74 char fn_tik
[MAX_FILENAME_SIZE
];
75 u16 certs_size
, tmd_size
, tik_size
;
80 snprintf (fn_certs
, MAX_FILENAME_SIZE
, "%s/%s.certs", DATA_PREFIX
, id
);
81 snprintf (fn_tmd
, MAX_FILENAME_SIZE
, "%s/%s.tmd", DATA_PREFIX
, id
);
82 snprintf (fn_tik
, MAX_FILENAME_SIZE
, "%s/%s.tik", DATA_PREFIX
, id
);
84 if (get_id_file_size (fn_certs
, &certs_size
))
87 if (get_id_file_size (fn_tmd
, &tmd_size
))
90 if (get_id_file_size (fn_tik
, &tik_size
))
93 total_size
= certs_size
+ tmd_size
+ tik_size
+ 6;
95 *data
= malloc (total_size
);
100 put_be16 (p
, certs_size
);
103 put_be16 (p
, tmd_size
);
106 put_be16 (p
, tik_size
);
110 res
|= load_id_file (fn_certs
, p
, certs_size
);
113 res
|= load_id_file (fn_tmd
, p
, tmd_size
);
116 res
|= load_id_file (fn_tik
, p
, tik_size
);
123 *data_size
= total_size
;
128 int client_init (const char *dev
, const char *id
) {
129 struct server_response
* r
;
130 char *auth
= WIIFUSE_AUTH_DATA
;
135 if (get_identity (id
, &identity
, &identity_size
)) {
136 LOG_ERR ("identity data \"%s\" not available!", id
);
140 LOG (1, "initializing gecko interface");
142 pthread_mutex_init (&gecko_mutex
, NULL
);
144 if (gecko_open (dev
)) {
145 LOG_ERR ("error using device %s", dev
);
149 LOG (1, "authenticating against server");
150 r
= client_request (CMD_AUTH
, NULL
, auth
, strlen (auth
));
152 LOG_ERR ("error while communicating with the server");
156 if (r
->result
!= RES_OK
) {
157 LOG_ERR ("server won't let you in :p");
158 client_free_response (r
);
161 client_free_response (r
);
163 LOG (1, "authenticated");
165 r
= client_request (CMD_LOGLEVEL
, NULL
, &verbose_level
, 1);
167 LOG_ERR ("error while setting the server verbose level");
171 if (r
->result
!= RES_OK
) {
172 LOG_ERR ("server didn't accept the verbose level (%d)",
174 client_free_response (r
);
177 client_free_response (r
);
179 LOG (1, "sending identity data");
180 r
= client_request (CMD_ES_IDENTIFY
, NULL
, identity
, identity_size
);
182 LOG_ERR ("error while communicating with the server");
186 if (r
->result
!= RES_OK
|| !r
->data_size
) {
187 LOG_ERR ("server failed to set the identity");
188 client_free_response (r
);
192 path
= malloc (r
->data_size
+ 1);
193 memcpy (path
, r
->data
, r
->data_size
);
194 path
[r
->data_size
] = 0;
196 printf ("title's data path is \"%s\"\n", path
);
198 client_free_response (r
);
203 void client_deinit () {
205 pthread_mutex_destroy (&gecko_mutex
);
208 void client_free_response (struct server_response
*response
) {
213 free (response
->data
);
218 struct server_response
*client_request (const enum remote_command command
,
219 const char *filename
,
220 const void *data
, const u16 data_size
) {
223 struct server_response
*response
;
225 buf
= malloc (PACKET_REQUEST_PAYLOAD
);
226 memset (buf
, 0, PACKET_REQUEST_PAYLOAD
);
234 fn_len
= strlen (filename
);
239 put_be16 (&buf
[5], data_size
);
241 pthread_mutex_lock (&gecko_mutex
);
243 if (gecko_write (buf
, PACKET_REQUEST_PAYLOAD
)) {
244 pthread_mutex_unlock (&gecko_mutex
);
245 LOG_ERR ("error sending request");
252 LOG (3, "sending filename (%d)", fn_len
);
253 if (gecko_write (filename
, fn_len
)) {
254 pthread_mutex_unlock (&gecko_mutex
);
255 LOG_ERR ("error sending filename");
261 LOG (3, "sending data (%d)", data_size
);
262 if (gecko_write (data
, data_size
)) {
263 pthread_mutex_unlock (&gecko_mutex
);
264 LOG_ERR ("error sending data");
269 buf
= malloc (PACKET_RESPONSE_PAYLOAD
);
270 memset (buf
, 0, PACKET_RESPONSE_PAYLOAD
);
272 LOG (3, "reading response");
273 if (gecko_read (buf
, PACKET_RESPONSE_PAYLOAD
)) {
274 pthread_mutex_unlock (&gecko_mutex
);
275 LOG_ERR ("error reading response");
279 LOG (3, "received a response");
281 if (buf
[0] != 'W' || buf
[1] != 'F' || buf
[2] != 'A') {
282 pthread_mutex_unlock (&gecko_mutex
);
283 LOG_ERR ("received an invalid response");
288 response
= (struct server_response
*)
289 malloc (sizeof (struct server_response
));
290 memset (response
, 0, sizeof (struct server_response
));
292 response
->result
= buf
[3];
293 response
->data_size
= get_be16 (&buf
[4]);
297 if (response
->data_size
) {
298 LOG (3, "waiting for response data (%u)", response
->data_size
);
299 response
->data
= malloc (response
->data_size
);
300 if (gecko_read (response
->data
, response
->data_size
)) {
301 pthread_mutex_unlock (&gecko_mutex
);
302 LOG_ERR ("error reading response data");
307 LOG (3, "received the response data");
309 pthread_mutex_unlock (&gecko_mutex
);