Initial Commit
[Projects.git] / pkgbuilds / wiifuse / src / wiifuse-0.2.0 / client.c
bloba7bf92c4d43315db649d40a0727bd816a9991f52
1 /*
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>
23 #include <sys/stat.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
28 #include <pthread.h>
30 #include "global.h"
31 #include "gecko.h"
32 #include "client.h"
34 static pthread_mutex_t gecko_mutex;
36 int get_id_file_size (const char *fn, u16 *size) {
37 struct stat st;
39 if (stat (fn, &st)) {
40 perror (fn);
41 return 1;
44 if (st.st_size > 0xffff)
45 return 1;
47 *size = st.st_size & 0xffff;
49 return 0;
52 int load_id_file (const char *fn, void *data, const u16 size) {
53 FILE *f;
55 f = fopen (fn, "rb");
56 if (f == NULL) {
57 perror (fn);
58 return 1;
61 if (size != fread (data, 1, size, f)) {
62 perror (fn);
63 fclose (f);
64 return 1;
67 fclose (f);
68 return 0;
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;
76 u16 total_size;
77 u8 *p;
78 int res;
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))
85 return 1;
87 if (get_id_file_size (fn_tmd, &tmd_size))
88 return 1;
90 if (get_id_file_size (fn_tik, &tik_size))
91 return 1;
93 total_size = certs_size + tmd_size + tik_size + 6;
95 *data = malloc (total_size);
96 if (*data == NULL)
97 return 1;
99 p = *data;
100 put_be16 (p, certs_size);
101 p += 2;
103 put_be16 (p, tmd_size);
104 p += 2;
106 put_be16 (p, tik_size);
107 p += 2;
109 res = 0;
110 res |= load_id_file (fn_certs, p, certs_size);
111 p += certs_size;
113 res |= load_id_file (fn_tmd, p, tmd_size);
114 p += tmd_size;
116 res |= load_id_file (fn_tik, p, tik_size);
118 if (res) {
119 free (*data);
120 return 1;
123 *data_size = total_size;
125 return 0;
128 int client_init (const char *dev, const char *id) {
129 struct server_response * r;
130 char *auth = WIIFUSE_AUTH_DATA;
131 u8 *identity;
132 u16 identity_size;
133 char *path;
135 if (get_identity (id, &identity, &identity_size)) {
136 LOG_ERR ("identity data \"%s\" not available!", id);
137 return 1;
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);
146 return 1;
149 LOG (1, "authenticating against server");
150 r = client_request (CMD_AUTH, NULL, auth, strlen (auth));
151 if (!r) {
152 LOG_ERR ("error while communicating with the server");
153 return 1;
156 if (r->result != RES_OK) {
157 LOG_ERR ("server won't let you in :p");
158 client_free_response (r);
159 return 1;
161 client_free_response (r);
163 LOG (1, "authenticated");
165 r = client_request (CMD_LOGLEVEL, NULL, &verbose_level, 1);
166 if (!r) {
167 LOG_ERR ("error while setting the server verbose level");
168 return 1;
171 if (r->result != RES_OK) {
172 LOG_ERR ("server didn't accept the verbose level (%d)",
173 r->result);
174 client_free_response (r);
175 return 1;
177 client_free_response (r);
179 LOG (1, "sending identity data");
180 r = client_request (CMD_ES_IDENTIFY, NULL, identity, identity_size);
181 if (!r) {
182 LOG_ERR ("error while communicating with the server");
183 return 1;
186 if (r->result != RES_OK || !r->data_size) {
187 LOG_ERR ("server failed to set the identity");
188 client_free_response (r);
189 return 1;
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);
200 return 0;
203 void client_deinit () {
204 gecko_close ();
205 pthread_mutex_destroy (&gecko_mutex);
208 void client_free_response (struct server_response *response) {
209 if (!response)
210 return;
212 if (response->data)
213 free (response->data);
215 free (response);
218 struct server_response *client_request (const enum remote_command command,
219 const char *filename,
220 const void *data, const u16 data_size) {
221 u8 *buf;
222 u8 fn_len = 0;
223 struct server_response *response;
225 buf = malloc (PACKET_REQUEST_PAYLOAD);
226 memset (buf, 0, PACKET_REQUEST_PAYLOAD);
228 buf[0] = 'W';
229 buf[1] = 'F';
230 buf[2] = 'R';
231 buf[3] = command;
233 if (filename) {
234 fn_len = strlen (filename);
235 buf[4] = fn_len;
238 if (data)
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");
246 free (buf);
247 return NULL;
249 free (buf);
251 if (filename) {
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");
256 return NULL;
260 if (data) {
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");
265 return NULL;
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");
276 free (buf);
277 return NULL;
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");
284 free (buf);
285 return NULL;
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]);
295 free (buf);
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");
303 free (response);
304 return NULL;
307 LOG (3, "received the response data");
309 pthread_mutex_unlock (&gecko_mutex);
311 return response;