diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 805508a..09b5d50 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -3,12 +3,15 @@ set(HEADER_FILES
include/chiaki/session.h
include/chiaki/common.h
include/chiaki/thread.h
- include/chiaki/base64.h)
+ include/chiaki/base64.h
+ include/chiaki/http.h)
set(SOURCE_FILES
+ src/common.c
src/session.c
src/thread.c
- src/base64.c)
+ src/base64.c
+ src/http.c)
add_library(chiaki-lib ${HEADER_FILES} ${SOURCE_FILES})
set_target_properties(chiaki-lib PROPERTIES OUTPUT_NAME chiaki)
diff --git a/lib/include/chiaki/common.h b/lib/include/chiaki/common.h
index 78e9a0c..f725c69 100644
--- a/lib/include/chiaki/common.h
+++ b/lib/include/chiaki/common.h
@@ -24,6 +24,20 @@ extern "C" {
#define CHIAKI_EXPORT
+
+typedef enum
+{
+ CHIAKI_ERR_SUCCESS = 0,
+ CHIAKI_ERR_PARSE_ADDR = 1,
+ CHIAKI_ERR_THREAD = 2,
+ CHIAKI_ERR_MEMORY = 3,
+ CHIAKI_ERR_NETWORK = 4,
+ CHIAKI_ERR_INVALID_DATA = 5
+} ChiakiErrorCode;
+
+CHIAKI_EXPORT const char *chiaki_error_string(ChiakiErrorCode code);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/include/chiaki/http.h b/lib/include/chiaki/http.h
new file mode 100644
index 0000000..f694921
--- /dev/null
+++ b/lib/include/chiaki/http.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki 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 Chiaki. If not, see .
+ */
+
+#ifndef CHIAKI_HTTP_H
+#define CHIAKI_HTTP_H
+
+#include "common.h"
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct chiaki_http_header_t
+{
+ const char *key;
+ const char *value;
+ struct chiaki_http_header_t *next;
+} ChiakiHttpHeader;
+
+typedef struct chiaki_http_response_t
+{
+ int code;
+ ChiakiHttpHeader *headers;
+} ChiakiHttpResponse;
+
+CHIAKI_EXPORT void chiaki_http_header_free(ChiakiHttpHeader *header);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_http_header_parse(ChiakiHttpHeader **header, char *buf, size_t buf_size);
+
+CHIAKI_EXPORT void chiaki_http_response_fini(ChiakiHttpResponse *response);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_http_response_parse(ChiakiHttpResponse *response, char *buf, size_t buf_size);
+
+CHIAKI_EXPORT ChiakiErrorCode chiaki_recv_http_header(int sock, char *buf, size_t buf_size, size_t *header_size, size_t *received_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CHIAKI_HTTP_H
diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h
index f80edc3..1489053 100644
--- a/lib/include/chiaki/session.h
+++ b/lib/include/chiaki/session.h
@@ -22,6 +22,7 @@
#include "thread.h"
#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -40,7 +41,8 @@ typedef struct chiaki_session_t
{
struct
{
- char *host;
+ struct addrinfo *host_addrinfos;
+ struct addrinfo *host_addrinfo_selected;
char *regist_key;
char *ostype;
char auth[0x10];
@@ -50,10 +52,10 @@ typedef struct chiaki_session_t
ChiakiThread session_thread;
} ChiakiSession;
-CHIAKI_EXPORT void chiaki_session_init(ChiakiSession *session, ChiakiConnectInfo *connect_info);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, ChiakiConnectInfo *connect_info);
CHIAKI_EXPORT void chiaki_session_fini(ChiakiSession *session);
-CHIAKI_EXPORT bool chiaki_session_start(ChiakiSession *session);
-CHIAKI_EXPORT void chiaki_session_join(ChiakiSession *session);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_start(ChiakiSession *session);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_join(ChiakiSession *session);
#ifdef __cplusplus
}
diff --git a/lib/include/chiaki/thread.h b/lib/include/chiaki/thread.h
index 910973e..3ba8bb3 100644
--- a/lib/include/chiaki/thread.h
+++ b/lib/include/chiaki/thread.h
@@ -20,8 +20,6 @@
#include "common.h"
-#include
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -35,8 +33,8 @@ typedef struct chiaki_thread_t
typedef void *(*ChiakiThreadFunc)(void *);
-CHIAKI_EXPORT bool chiaki_thread_create(ChiakiThread *thread, ChiakiThreadFunc func, void *arg);
-CHIAKI_EXPORT bool chiaki_thread_join(ChiakiThread *thread, void **retval);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_create(ChiakiThread *thread, ChiakiThreadFunc func, void *arg);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_join(ChiakiThread *thread, void **retval);
#ifdef __cplusplus
}
diff --git a/lib/src/common.c b/lib/src/common.c
new file mode 100644
index 0000000..42b5a60
--- /dev/null
+++ b/lib/src/common.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki 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 Chiaki. If not, see .
+ */
+
+#include
+
+CHIAKI_EXPORT const char *chiaki_error_string(ChiakiErrorCode code)
+{
+ switch(code)
+ {
+ case CHIAKI_ERR_SUCCESS:
+ return "Success";
+ case CHIAKI_ERR_PARSE_ADDR:
+ return "Failed to parse host address";
+ case CHIAKI_ERR_THREAD:
+ return "Thread error";
+ case CHIAKI_ERR_MEMORY:
+ return "Memory error";
+ case CHIAKI_ERR_NETWORK:
+ return "Network error";
+ case CHIAKI_ERR_INVALID_DATA:
+ return "Invalid data";
+ default:
+ return "Unknown";
+ }
+}
\ No newline at end of file
diff --git a/lib/src/http.c b/lib/src/http.c
new file mode 100644
index 0000000..4788413
--- /dev/null
+++ b/lib/src/http.c
@@ -0,0 +1,126 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki 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 Chiaki. If not, see .
+ */
+
+#include
+
+#include
+#include
+#include
+
+
+CHIAKI_EXPORT void chiaki_http_header_free(ChiakiHttpHeader *header)
+{
+ while(header)
+ {
+ ChiakiHttpHeader *cur = header;
+ header = header->next;
+ free(cur);
+ }
+}
+
+CHIAKI_EXPORT ChiakiErrorCode chiaki_http_header_parse(ChiakiHttpHeader **header, char *buf, size_t buf_size)
+{
+ *header = NULL;
+ return CHIAKI_ERR_SUCCESS;
+}
+
+CHIAKI_EXPORT void chiaki_http_response_fini(ChiakiHttpResponse *response)
+{
+ if(!response)
+ return;
+ chiaki_http_header_free(response->headers);
+}
+
+CHIAKI_EXPORT ChiakiErrorCode chiaki_http_response_parse(ChiakiHttpResponse *response, char *buf, size_t buf_size)
+{
+ static const char *http_version = "HTTP/1.1 ";
+ static const size_t http_version_size = 9;
+
+ if(buf_size < http_version_size)
+ return CHIAKI_ERR_INVALID_DATA;
+
+ if(strncmp(buf, http_version, http_version_size) != 0)
+ return CHIAKI_ERR_INVALID_DATA;
+
+ buf += http_version_size;
+ buf_size -= http_version_size;
+
+ char *line_end = memchr(buf, '\r', buf_size);
+ if(!line_end)
+ return CHIAKI_ERR_INVALID_DATA;
+ size_t line_length = (line_end - buf) + 2;
+ if(buf_size <= line_length || line_end[1] != '\n')
+ return CHIAKI_ERR_INVALID_DATA;
+ *line_end = '\0';
+
+ char *endptr;
+ response->code = (int)strtol(buf, &endptr, 10);
+ if(response->code == 0)
+ return CHIAKI_ERR_INVALID_DATA;
+
+ buf += line_length;
+ buf_size -= line_length;
+
+ return chiaki_http_header_parse(&response->headers, buf, buf_size);
+}
+
+CHIAKI_EXPORT ChiakiErrorCode chiaki_recv_http_header(int sock, char *buf, size_t buf_size, size_t *header_size, size_t *received_size)
+{
+ // 0 = ""
+ // 1 = "\r"
+ // 2 = "\r\n"
+ // 3 = "\r\n\r"
+ // 4 = "\r\n\r\n" (final)
+ int nl_state = 0;
+ static const int transitions_r[] = { 1, 1, 3, 1 };
+ static const int transitions_n[] = { 0, 2, 0, 4 };
+
+ *received_size = 0;
+ while(true)
+ {
+ ssize_t received = recv(sock, buf, buf_size, 0);
+ if(received <= 0)
+ return CHIAKI_ERR_NETWORK;
+
+ *received_size += received;
+ for(; received > 0; buf++, received--)
+ {
+ switch(*buf)
+ {
+ case '\r':
+ nl_state = transitions_r[nl_state];
+ break;
+ case '\n':
+ nl_state = transitions_n[nl_state];
+ break;
+ default:
+ nl_state = 0;
+ break;
+ }
+ if(nl_state == 4)
+ break;
+ }
+
+ if(nl_state == 4)
+ {
+ *header_size = *received_size - received;
+ break;
+ }
+ }
+
+ return CHIAKI_ERR_SUCCESS;
+}
\ No newline at end of file
diff --git a/lib/src/session.c b/lib/src/session.c
index 57662e7..f6556ed 100644
--- a/lib/src/session.c
+++ b/lib/src/session.c
@@ -16,58 +16,198 @@
*/
#include
+#include
#include
#include
#include
+#include
+
+#include
+#include
-static const char session_request[] =
- "GET /sce/rp/session HTTP/1.1\r\n"
- "Host: 192.168. 1. 8:9295\r\n"
- "User-Agent: remoteplay Windows\r\n"
- "Connection: close\r\n"
- "Content-Length: 0\r\n"
- "RP-Registkey: 3131633065363864\r\n"
- "Rp-Version: 8.0\r\n"
- "\r\n";
+#define SESSION_PORT 9295
+
static void *session_thread_func(void *arg);
-CHIAKI_EXPORT void chiaki_session_init(ChiakiSession *session, ChiakiConnectInfo *connect_info)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, ChiakiConnectInfo *connect_info)
{
- session->connect_info.host = strdup(connect_info->host);
+ memset(session, 0, sizeof(ChiakiSession));
+
+ int r = getaddrinfo(connect_info->host, NULL, NULL, &session->connect_info.host_addrinfos);
+ if(r != 0)
+ {
+ chiaki_session_fini(session);
+ return CHIAKI_ERR_PARSE_ADDR;
+ }
+
session->connect_info.regist_key = strdup(connect_info->regist_key);
+ if(!session->connect_info.regist_key)
+ {
+ chiaki_session_fini(session);
+ return CHIAKI_ERR_MEMORY;
+ }
+
session->connect_info.ostype = strdup(connect_info->ostype);
+ if(!session->connect_info.regist_key)
+ {
+ chiaki_session_fini(session);
+ return CHIAKI_ERR_MEMORY;
+ }
+
memcpy(session->connect_info.auth, connect_info->auth, sizeof(session->connect_info.auth));
memcpy(session->connect_info.morning, connect_info->morning, sizeof(session->connect_info.morning));
+
+ return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT void chiaki_session_fini(ChiakiSession *session)
{
- free(session->connect_info.host);
+ if(!session)
+ return;
free(session->connect_info.regist_key);
free(session->connect_info.ostype);
+ freeaddrinfo(session->connect_info.host_addrinfos);
}
-CHIAKI_EXPORT bool chiaki_session_start(ChiakiSession *session)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_start(ChiakiSession *session)
{
- bool r = chiaki_thread_create(&session->session_thread, session_thread_func, session);
- if(!r)
- return false;
- return true;
+ return chiaki_thread_create(&session->session_thread, session_thread_func, session);
}
-CHIAKI_EXPORT void chiaki_session_join(ChiakiSession *session)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_join(ChiakiSession *session)
{
- chiaki_thread_join(&session->session_thread, NULL);
+ return chiaki_thread_join(&session->session_thread, NULL);
}
+
+
+static ChiakiErrorCode session_thread_request_session(ChiakiSession *session);
+
static void *session_thread_func(void *arg)
{
ChiakiSession *session = arg;
- printf("Sleepy...\n");
+ ChiakiErrorCode err;
+
+ err = session_thread_request_session(session);
+ if(err != CHIAKI_ERR_SUCCESS)
+ return NULL;
+
return NULL;
-}
\ No newline at end of file
+}
+
+
+static ChiakiErrorCode session_thread_request_session(ChiakiSession *session)
+{
+ int session_sock = -1;
+ char host_buf[128];
+ for(struct addrinfo *ai=session->connect_info.host_addrinfos; ai; ai=ai->ai_next)
+ {
+ struct sockaddr *sa = malloc(ai->ai_addrlen);
+ if(!sa)
+ continue;
+ memcpy(sa, ai->ai_addr, ai->ai_addrlen);
+
+ if(sa->sa_family == AF_INET)
+ ((struct sockaddr_in *)sa)->sin_port = htons(SESSION_PORT);
+ else if(sa->sa_family == AF_INET6)
+ ((struct sockaddr_in6 *)sa)->sin6_port = htons(SESSION_PORT);
+ else
+ {
+ free(sa);
+ continue;
+ }
+
+ int r = getnameinfo(sa, ai->ai_addrlen, host_buf, sizeof(host_buf), NULL, 0, 0);
+ if(r != 0)
+ {
+ free(sa);
+ continue;
+ }
+
+ session_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if(session_sock < 0)
+ continue;
+ r = connect(session_sock, sa, ai->ai_addrlen);
+ if(r < 0)
+ {
+ close(session_sock);
+ session_sock = -1;
+ free(sa);
+ continue;
+ }
+ free(sa);
+
+ session->connect_info.host_addrinfo_selected = ai;
+ break;
+ }
+
+
+ if(session_sock < 0)
+ {
+ printf("Session Connection Failed.\n");
+ return CHIAKI_ERR_NETWORK;
+ }
+
+ printf("Connected to %s:%u\n", host_buf, SESSION_PORT);
+
+
+ static const char session_request_fmt[] =
+ "GET /sce/rp/session HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "User-Agent: remoteplay Windows\r\n"
+ "Connection: close\r\n"
+ "Content-Length: 0\r\n"
+ "RP-Registkey: %s\r\n"
+ "Rp-Version: 8.0\r\n"
+ "\r\n";
+
+ char buf[512];
+ int request_len = snprintf(buf, sizeof(buf), session_request_fmt,
+ host_buf, SESSION_PORT, session->connect_info.regist_key);
+ if(request_len < 0 || request_len >= sizeof(buf))
+ {
+ printf("Session Request Building Failed.\n");
+ close(session_sock);
+ return CHIAKI_ERR_MEMORY;
+ }
+
+ printf("sending\n%s\n", buf);
+
+ ssize_t sent = send(session_sock, buf, (size_t)request_len, 0);
+ if(sent < 0)
+ {
+ printf("Session Request Send Failed.\n");
+ perror("send");
+ close(session_sock);
+ return CHIAKI_ERR_NETWORK;
+ }
+
+ size_t header_size;
+ size_t received_size;
+ ChiakiErrorCode err = chiaki_recv_http_header(session_sock, buf, sizeof(buf), &header_size, &received_size);
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ close(session_sock);
+ return err;
+ }
+
+ buf[received_size] = '\0';
+ printf("received\n%s\n", buf);
+
+ ChiakiHttpResponse response;
+ err = chiaki_http_response_parse(&response, buf, header_size);
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ close(session_sock);
+ return err;
+ }
+
+ close(session_sock);
+ return CHIAKI_ERR_SUCCESS;
+}
+
diff --git a/lib/src/thread.c b/lib/src/thread.c
index 256be43..a9f8873 100644
--- a/lib/src/thread.c
+++ b/lib/src/thread.c
@@ -20,24 +20,18 @@
#include
-CHIAKI_EXPORT bool chiaki_thread_create(ChiakiThread *thread, ChiakiThreadFunc func, void *arg)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_create(ChiakiThread *thread, ChiakiThreadFunc func, void *arg)
{
int r = pthread_create(&thread->thread, NULL, func, arg);
if(r != 0)
- {
- perror("pthread_create");
- return false;
- }
- return true;
+ return CHIAKI_ERR_THREAD;
+ return CHIAKI_ERR_SUCCESS;
}
-CHIAKI_EXPORT bool chiaki_thread_join(ChiakiThread *thread, void **retval)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_join(ChiakiThread *thread, void **retval)
{
int r = pthread_join(thread->thread, retval);
if(r != 0)
- {
- perror("pthread_join");
- return false;
- }
- return true;
+ return CHIAKI_ERR_THREAD;
+ return CHIAKI_ERR_SUCCESS;
}
\ No newline at end of file