📄 client.c
字号:
/* * Copyright (C) 2008 dhewg, #wiidev efnet * * this file is part of wiifuse * http://wiibrew.org/index.php?title=Wiifuse * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <sys/types.h>#include <sys/stat.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pthread.h>#include "global.h"#include "gecko.h"#include "client.h"static pthread_mutex_t gecko_mutex;int get_id_file_size (const char *fn, u16 *size) { struct stat st; if (stat (fn, &st)) { perror (fn); return 1; } if (st.st_size > 0xffff) return 1; *size = st.st_size & 0xffff; return 0;}int load_id_file (const char *fn, void *data, const u16 size) { FILE *f; f = fopen (fn, "rb"); if (f == NULL) { perror (fn); return 1; } if (size != fread (data, 1, size, f)) { perror (fn); fclose (f); return 1; } fclose (f); return 0;}int get_identity (const char *id, u8 **data, u16 *data_size) { char fn_certs[MAX_FILENAME_SIZE]; char fn_tmd[MAX_FILENAME_SIZE]; char fn_tik[MAX_FILENAME_SIZE]; u16 certs_size, tmd_size, tik_size; u16 total_size; u8 *p; int res; snprintf (fn_certs, MAX_FILENAME_SIZE, "%s/%s.certs", DATA_PREFIX, id); snprintf (fn_tmd, MAX_FILENAME_SIZE, "%s/%s.tmd", DATA_PREFIX, id); snprintf (fn_tik, MAX_FILENAME_SIZE, "%s/%s.tik", DATA_PREFIX, id); if (get_id_file_size (fn_certs, &certs_size)) return 1; if (get_id_file_size (fn_tmd, &tmd_size)) return 1; if (get_id_file_size (fn_tik, &tik_size)) return 1; total_size = certs_size + tmd_size + tik_size + 6; *data = malloc (total_size); if (*data == NULL) return 1; p = *data; put_be16 (p, certs_size); p += 2; put_be16 (p, tmd_size); p += 2; put_be16 (p, tik_size); p += 2; res = 0; res |= load_id_file (fn_certs, p, certs_size); p += certs_size; res |= load_id_file (fn_tmd, p, tmd_size); p += tmd_size; res |= load_id_file (fn_tik, p, tik_size); if (res) { free (*data); return 1; } *data_size = total_size; return 0;}int client_init (const char *dev, const char *id) { struct server_response * r; char *auth = WIIFUSE_AUTH_DATA; u8 *identity; u16 identity_size; char *path; if (get_identity (id, &identity, &identity_size)) { LOG_ERR ("identity data \"%s\" not available!", id); return 1; } LOG (1, "initializing gecko interface"); pthread_mutex_init (&gecko_mutex, NULL); if (gecko_open (dev)) { LOG_ERR ("error using device %s", dev); return 1; } LOG (1, "authenticating against server"); r = client_request (CMD_AUTH, NULL, auth, strlen (auth)); if (!r) { LOG_ERR ("error while communicating with the server"); return 1; } if (r->result != RES_OK) { LOG_ERR ("server won't let you in :p"); client_free_response (r); return 1; } client_free_response (r); LOG (1, "authenticated"); r = client_request (CMD_LOGLEVEL, NULL, &verbose_level, 1); if (!r) { LOG_ERR ("error while setting the server verbose level"); return 1; } if (r->result != RES_OK) { LOG_ERR ("server didn't accept the verbose level (%d)", r->result); client_free_response (r); return 1; } client_free_response (r); LOG (1, "sending identity data"); r = client_request (CMD_ES_IDENTIFY, NULL, identity, identity_size); if (!r) { LOG_ERR ("error while communicating with the server"); return 1; } if (r->result != RES_OK || !r->data_size) { LOG_ERR ("server failed to set the identity"); client_free_response (r); return 1; } path = malloc (r->data_size + 1); memcpy (path, r->data, r->data_size); path[r->data_size] = 0; printf ("title's data path is \"%s\"\n", path); client_free_response (r); return 0;}void client_deinit () { gecko_close (); pthread_mutex_destroy (&gecko_mutex);}void client_free_response (struct server_response *response) { if (!response) return; if (response->data) free (response->data); free (response);}struct server_response *client_request (const enum remote_command command, const char *filename, const void *data, const u16 data_size) { u8 *buf; u8 fn_len = 0; struct server_response *response; buf = malloc (PACKET_REQUEST_PAYLOAD); memset (buf, 0, PACKET_REQUEST_PAYLOAD); buf[0] = 'W'; buf[1] = 'F'; buf[2] = 'R'; buf[3] = command; if (filename) { fn_len = strlen (filename); buf[4] = fn_len; } if (data) put_be16 (&buf[5], data_size); pthread_mutex_lock (&gecko_mutex); if (gecko_write (buf, PACKET_REQUEST_PAYLOAD)) { pthread_mutex_unlock (&gecko_mutex); LOG_ERR ("error sending request"); free (buf); return NULL; } free (buf); if (filename) { LOG (3, "sending filename (%d)", fn_len); if (gecko_write (filename, fn_len)) { pthread_mutex_unlock (&gecko_mutex); LOG_ERR ("error sending filename"); return NULL; } } if (data) { LOG (3, "sending data (%d)", data_size); if (gecko_write (data, data_size)) { pthread_mutex_unlock (&gecko_mutex); LOG_ERR ("error sending data"); return NULL; } } buf = malloc (PACKET_RESPONSE_PAYLOAD); memset (buf, 0, PACKET_RESPONSE_PAYLOAD); LOG (3, "reading response"); if (gecko_read (buf, PACKET_RESPONSE_PAYLOAD)) { pthread_mutex_unlock (&gecko_mutex); LOG_ERR ("error reading response"); free (buf); return NULL; } LOG (3, "received a response"); if (buf[0] != 'W' || buf[1] != 'F' || buf[2] != 'A') { pthread_mutex_unlock (&gecko_mutex); LOG_ERR ("received an invalid response"); free (buf); return NULL; } response = (struct server_response *) malloc (sizeof (struct server_response)); memset (response, 0, sizeof (struct server_response)); response->result = buf[3]; response->data_size = get_be16 (&buf[4]); free (buf); if (response->data_size) { LOG (3, "waiting for response data (%u)", response->data_size); response->data = malloc (response->data_size); if (gecko_read (response->data, response->data_size)) { pthread_mutex_unlock (&gecko_mutex); LOG_ERR ("error reading response data"); free (response); return NULL; } } LOG (3, "received the response data"); pthread_mutex_unlock (&gecko_mutex); return response;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -