{"action":"created","comment":{"url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/comments/25128975","id":25128975,"diff_hunk":"@@ -0,0 +1,360 @@\n+// This file is public domain, in case it's useful to anyone. -comex\n+\n+#include \"Timer.h\"\n+#include \"Common/TraversalClient.h\"\n+\n+static void GetRandomishBytes(u8* buf, size_t size)\n+{\n+\t// We don't need high quality random numbers (which might not be available),\n+\t// just non-repeating numbers!\n+\tsrand(enet_time_get());\n+\tfor (size_t i = 0; i < size; i++)\n+\t\tbuf[i] = rand() & 0xff;\n+}\n+\n+TraversalClient::TraversalClient(ENetHost* netHost, const std::string& server, const u16 port)\n+\t: m_NetHost(netHost)\n+\t, m_Client(nullptr)\n+\t, m_FailureReason(0)\n+\t, m_ConnectRequestId(0)\n+\t, m_PendingConnect(false)\n+\t, m_Server(server)\n+\t, m_port(port)\n+\t, m_PingTime(0)\n+{\n+\tnetHost->intercept = TraversalClient::InterceptCallback;\n+\n+\tReset();\n+\n+\tReconnectToServer();\n+}\n+\n+TraversalClient::~TraversalClient()\n+{\n+}\n+\n+void TraversalClient::ReconnectToServer()\n+{\n+\tif (enet_address_set_host(&m_ServerAddress, m_Server.c_str()))\n+\t{\n+\t\tOnFailure(BadHost);\n+\t\treturn;\n+\t}\n+\tm_ServerAddress.port = m_port;\n+\n+\tm_State = Connecting;\n+\n+\tTraversalPacket hello = {};\n+\thello.type = TraversalPacketHelloFromClient;\n+\thello.helloFromClient.protoVersion = TraversalProtoVersion;\n+\tSendTraversalPacket(hello);\n+\tif (m_Client)\n+\t\tm_Client->OnTraversalStateChanged();\n+}\n+\n+static ENetAddress MakeENetAddress(TraversalInetAddress* address)\n+{\n+\tENetAddress eaddr;\n+\tif (address->isIPV6)\n+\t{\n+\t\teaddr.port = 0; // no support yet :(\n+\t}\n+\telse\n+\t{\n+\t\teaddr.host = address->address[0];\n+\t\teaddr.port = ntohs(address->port);\n+\t}\n+\treturn eaddr;\n+}\n+\n+void TraversalClient::ConnectToClient(const std::string& host)\n+{\n+\tif (host.size() > sizeof(TraversalHostId))\n+\t{\n+\t\tPanicAlert(\"host too long\");\n+\t\treturn;\n+\t}\n+\tTraversalPacket packet = {};\n+\tpacket.type = TraversalPacketConnectPlease;\n+\tmemcpy(packet.connectPlease.hostId.data(), host.c_str(), host.size());\n+\tm_ConnectRequestId = SendTraversalPacket(packet);\n+\tm_PendingConnect = true;\n+}\n+\n+bool TraversalClient::TestPacket(u8* data, size_t size, ENetAddress* from)\n+{\n+\tif (from->host == m_ServerAddress.host &&\n+\t    from->port == m_ServerAddress.port)\n+\t{\n+\t\tif (size < sizeof(TraversalPacket))\n+\t\t{\n+\t\t\tERROR_LOG(NETPLAY, \"Received too-short traversal packet.\");\n+\t\t}\n+\t\telse\n+\t\t{\n+\t\t\tHandleServerPacket((TraversalPacket*) data);\n+\t\t\treturn true;\n+\t\t}\n+\t}\n+\treturn false;\n+}\n+\n+//--Temporary until more of the old netplay branch is moved over\n+void TraversalClient::Update()\n+{\n+\tENetEvent netEvent;\n+\tif (enet_host_service(m_NetHost, &netEvent, 4) > 0)\n+\t{\n+\t\tswitch (netEvent.type)\n+\t\t{\n+\t\tcase ENET_EVENT_TYPE_RECEIVE:\n+\t\t\tTestPacket(netEvent.packet->data, netEvent.packet->dataLength, &netEvent.peer->address);\n+\n+\t\t\tenet_packet_destroy(netEvent.packet);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tHandleResends();\n+}\n+\n+void TraversalClient::HandleServerPacket(TraversalPacket* packet)\n+{\n+\tu8 ok = 1;\n+\tswitch (packet->type)\n+\t{\n+\tcase TraversalPacketAck:\n+\t\tif (!packet->ack.ok)\n+\t\t{\n+\t\t\tOnFailure(ServerForgotAboutUs);\n+\t\t\tbreak;\n+\t\t}\n+\t\tfor (auto it = m_OutgoingTraversalPackets.begin(); it != m_OutgoingTraversalPackets.end(); ++it)\n+\t\t{\n+\t\t\tif (it->packet.requestId == packet->requestId)\n+\t\t\t{\n+\t\t\t\tm_OutgoingTraversalPackets.erase(it);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tcase TraversalPacketHelloFromServer:\n+\t\tif (m_State != Connecting)\n+\t\t\tbreak;\n+\t\tif (!packet->helloFromServer.ok)\n+\t\t{\n+\t\t\tOnFailure(VersionTooOld);\n+\t\t\tbreak;\n+\t\t}\n+\t\tm_HostId = packet->helloFromServer.yourHostId;\n+\t\tm_State = Connected;\n+\t\tif (m_Client)\n+\t\t\tm_Client->OnTraversalStateChanged();\n+\t\tbreak;\n+\tcase TraversalPacketPleaseSendPacket:\n+\t\t{\n+\t\t// security is overrated.\n+\t\tENetAddress addr = MakeENetAddress(&packet->pleaseSendPacket.address);\n+\t\tif (addr.port != 0)\n+\t\t{\n+\t\t\tchar message[] = \"Hello from Dolphin Netplay...\";\n+\t\t\tENetBuffer buf;\n+\t\t\tbuf.data = message;\n+\t\t\tbuf.dataLength = sizeof(message) - 1;\n+\t\t\tenet_socket_send(m_NetHost->socket, &addr, &buf, 1);\n+\t\t}\n+\t\telse\n+\t\t{\n+\t\t\t// invalid IPV6\n+\t\t\tok = 0;\n+\t\t}\n+\t\tbreak;\n+\t\t}\n+\tcase TraversalPacketConnectReady:\n+\tcase TraversalPacketConnectFailed:\n+\t\t{\n+\t\tif (!m_PendingConnect || packet->connectReady.requestId != m_ConnectRequestId)\n+\t\t\tbreak;\n+\n+\t\tm_PendingConnect = false;\n+\n+\t\tif (!m_Client)\n+\t\t\tbreak;\n+\n+\t\tif (packet->type == TraversalPacketConnectReady)\n+\t\t\tm_Client->OnConnectReady(MakeENetAddress(&packet->connectReady.address));\n+\t\telse\n+\t\t\tm_Client->OnConnectFailed(packet->connectFailed.reason);\n+\t\tbreak;\n+\t\t}\n+\tdefault:\n+\t\tWARN_LOG(NETPLAY, \"Received unknown packet with type %d\", packet->type);\n+\t\tbreak;\n+\t}\n+\tif (packet->type != TraversalPacketAck)\n+\t{\n+\t\tTraversalPacket ack = {};\n+\t\tack.type = TraversalPacketAck;\n+\t\tack.requestId = packet->requestId;\n+\t\tack.ack.ok = ok;\n+\n+\t\tENetBuffer buf;\n+\t\tbuf.data = &ack;\n+\t\tbuf.dataLength = sizeof(ack);\n+\t\tif (enet_socket_send(m_NetHost->socket, &m_ServerAddress, &buf, 1) == -1)\n+\t\t\tOnFailure(SocketSendError);\n+\t}\n+}\n+\n+void TraversalClient::OnFailure(int reason)","path":"Source/Core/Common/TraversalClient.cpp","position":210,"original_position":210,"commit_id":"4cd8a9453242a0d48fd2953f23046890b204d314","original_commit_id":"4cd8a9453242a0d48fd2953f23046890b204d314","user":{"login":"lioncash","id":712067,"avatar_url":"https://avatars.githubusercontent.com/u/712067?v=3","gravatar_id":"","url":"https://api.github.com/users/lioncash","html_url":"https://github.com/lioncash","followers_url":"https://api.github.com/users/lioncash/followers","following_url":"https://api.github.com/users/lioncash/following{/other_user}","gists_url":"https://api.github.com/users/lioncash/gists{/gist_id}","starred_url":"https://api.github.com/users/lioncash/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lioncash/subscriptions","organizations_url":"https://api.github.com/users/lioncash/orgs","repos_url":"https://api.github.com/users/lioncash/repos","events_url":"https://api.github.com/users/lioncash/events{/privacy}","received_events_url":"https://api.github.com/users/lioncash/received_events","type":"User","site_admin":false},"body":"`int reason` might want to be changed to `FailureReason reason`. This way you can also eliminate the default case in the switch as well.","created_at":"2015-02-22T04:16:28Z","updated_at":"2015-02-22T04:16:28Z","html_url":"https://github.com/dolphin-emu/dolphin/pull/1995#discussion_r25128975","pull_request_url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995","_links":{"self":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/comments/25128975"},"html":{"href":"https://github.com/dolphin-emu/dolphin/pull/1995#discussion_r25128975"},"pull_request":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995"}}},"pull_request":{"url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995","id":28425804,"html_url":"https://github.com/dolphin-emu/dolphin/pull/1995","diff_url":"https://github.com/dolphin-emu/dolphin/pull/1995.diff","patch_url":"https://github.com/dolphin-emu/dolphin/pull/1995.patch","issue_url":"https://api.github.com/repos/dolphin-emu/dolphin/issues/1995","number":1995,"state":"open","locked":false,"title":"Added Enet and move traversal code from old netplay branch","user":{"login":"Ziek","id":8287045,"avatar_url":"https://avatars.githubusercontent.com/u/8287045?v=3","gravatar_id":"","url":"https://api.github.com/users/Ziek","html_url":"https://github.com/Ziek","followers_url":"https://api.github.com/users/Ziek/followers","following_url":"https://api.github.com/users/Ziek/following{/other_user}","gists_url":"https://api.github.com/users/Ziek/gists{/gist_id}","starred_url":"https://api.github.com/users/Ziek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ziek/subscriptions","organizations_url":"https://api.github.com/users/Ziek/orgs","repos_url":"https://api.github.com/users/Ziek/repos","events_url":"https://api.github.com/users/Ziek/events{/privacy}","received_events_url":"https://api.github.com/users/Ziek/received_events","type":"User","site_admin":false},"body":"Added Enet library, and replaced tcp calls in netplayserver and netplayclient over to enet\r\n\r\nGrabbed traversalproto.h and traversalclient.cpp/.h and moved it over with some change to fit current netplay.  Though I would like to start moving more over soon, so some of those changes may change back.\r\n\r\nMade some changes to NetPlay GUI so a person can switch between direct and traversal .\r\n\r\nmoved over the netplay copy code to be able to copy host code\r\n\r\nHost now sets everyone's g_netplay_gctime","created_at":"2015-02-01T03:45:51Z","updated_at":"2015-02-22T04:16:28Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dd3bc145793260ac402c70dc0dad19f263745c39","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995/commits","review_comments_url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995/comments","review_comment_url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/comments/{number}","comments_url":"https://api.github.com/repos/dolphin-emu/dolphin/issues/1995/comments","statuses_url":"https://api.github.com/repos/dolphin-emu/dolphin/statuses/4cd8a9453242a0d48fd2953f23046890b204d314","head":{"label":"Ziek:master","ref":"master","sha":"4cd8a9453242a0d48fd2953f23046890b204d314","user":{"login":"Ziek","id":8287045,"avatar_url":"https://avatars.githubusercontent.com/u/8287045?v=3","gravatar_id":"","url":"https://api.github.com/users/Ziek","html_url":"https://github.com/Ziek","followers_url":"https://api.github.com/users/Ziek/followers","following_url":"https://api.github.com/users/Ziek/following{/other_user}","gists_url":"https://api.github.com/users/Ziek/gists{/gist_id}","starred_url":"https://api.github.com/users/Ziek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ziek/subscriptions","organizations_url":"https://api.github.com/users/Ziek/orgs","repos_url":"https://api.github.com/users/Ziek/repos","events_url":"https://api.github.com/users/Ziek/events{/privacy}","received_events_url":"https://api.github.com/users/Ziek/received_events","type":"User","site_admin":false},"repo":{"id":29409477,"name":"dolphin","full_name":"Ziek/dolphin","owner":{"login":"Ziek","id":8287045,"avatar_url":"https://avatars.githubusercontent.com/u/8287045?v=3","gravatar_id":"","url":"https://api.github.com/users/Ziek","html_url":"https://github.com/Ziek","followers_url":"https://api.github.com/users/Ziek/followers","following_url":"https://api.github.com/users/Ziek/following{/other_user}","gists_url":"https://api.github.com/users/Ziek/gists{/gist_id}","starred_url":"https://api.github.com/users/Ziek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ziek/subscriptions","organizations_url":"https://api.github.com/users/Ziek/orgs","repos_url":"https://api.github.com/users/Ziek/repos","events_url":"https://api.github.com/users/Ziek/events{/privacy}","received_events_url":"https://api.github.com/users/Ziek/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Ziek/dolphin","description":"Dolphin is a GameCube/Wii emulator, allowing you to play games for these two platforms on PC, with improvements.","fork":true,"url":"https://api.github.com/repos/Ziek/dolphin","forks_url":"https://api.github.com/repos/Ziek/dolphin/forks","keys_url":"https://api.github.com/repos/Ziek/dolphin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Ziek/dolphin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Ziek/dolphin/teams","hooks_url":"https://api.github.com/repos/Ziek/dolphin/hooks","issue_events_url":"https://api.github.com/repos/Ziek/dolphin/issues/events{/number}","events_url":"https://api.github.com/repos/Ziek/dolphin/events","assignees_url":"https://api.github.com/repos/Ziek/dolphin/assignees{/user}","branches_url":"https://api.github.com/repos/Ziek/dolphin/branches{/branch}","tags_url":"https://api.github.com/repos/Ziek/dolphin/tags","blobs_url":"https://api.github.com/repos/Ziek/dolphin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Ziek/dolphin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Ziek/dolphin/git/refs{/sha}","trees_url":"https://api.github.com/repos/Ziek/dolphin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Ziek/dolphin/statuses/{sha}","languages_url":"https://api.github.com/repos/Ziek/dolphin/languages","stargazers_url":"https://api.github.com/repos/Ziek/dolphin/stargazers","contributors_url":"https://api.github.com/repos/Ziek/dolphin/contributors","subscribers_url":"https://api.github.com/repos/Ziek/dolphin/subscribers","subscription_url":"https://api.github.com/repos/Ziek/dolphin/subscription","commits_url":"https://api.github.com/repos/Ziek/dolphin/commits{/sha}","git_commits_url":"https://api.github.com/repos/Ziek/dolphin/git/commits{/sha}","comments_url":"https://api.github.com/repos/Ziek/dolphin/comments{/number}","issue_comment_url":"https://api.github.com/repos/Ziek/dolphin/issues/comments{/number}","contents_url":"https://api.github.com/repos/Ziek/dolphin/contents/{+path}","compare_url":"https://api.github.com/repos/Ziek/dolphin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Ziek/dolphin/merges","archive_url":"https://api.github.com/repos/Ziek/dolphin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Ziek/dolphin/downloads","issues_url":"https://api.github.com/repos/Ziek/dolphin/issues{/number}","pulls_url":"https://api.github.com/repos/Ziek/dolphin/pulls{/number}","milestones_url":"https://api.github.com/repos/Ziek/dolphin/milestones{/number}","notifications_url":"https://api.github.com/repos/Ziek/dolphin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Ziek/dolphin/labels{/name}","releases_url":"https://api.github.com/repos/Ziek/dolphin/releases{/id}","created_at":"2015-01-17T23:32:59Z","updated_at":"2015-02-19T07:34:25Z","pushed_at":"2015-02-19T07:34:03Z","git_url":"git://github.com/Ziek/dolphin.git","ssh_url":"git@github.com:Ziek/dolphin.git","clone_url":"https://github.com/Ziek/dolphin.git","svn_url":"https://github.com/Ziek/dolphin","homepage":null,"size":214140,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dolphin-emu:master","ref":"master","sha":"c8c61041ba6a3a9e8787d754c2aa672c76f65178","user":{"login":"dolphin-emu","id":5050316,"avatar_url":"https://avatars.githubusercontent.com/u/5050316?v=3","gravatar_id":"","url":"https://api.github.com/users/dolphin-emu","html_url":"https://github.com/dolphin-emu","followers_url":"https://api.github.com/users/dolphin-emu/followers","following_url":"https://api.github.com/users/dolphin-emu/following{/other_user}","gists_url":"https://api.github.com/users/dolphin-emu/gists{/gist_id}","starred_url":"https://api.github.com/users/dolphin-emu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dolphin-emu/subscriptions","organizations_url":"https://api.github.com/users/dolphin-emu/orgs","repos_url":"https://api.github.com/users/dolphin-emu/repos","events_url":"https://api.github.com/users/dolphin-emu/events{/privacy}","received_events_url":"https://api.github.com/users/dolphin-emu/received_events","type":"Organization","site_admin":false},"repo":{"id":11577304,"name":"dolphin","full_name":"dolphin-emu/dolphin","owner":{"login":"dolphin-emu","id":5050316,"avatar_url":"https://avatars.githubusercontent.com/u/5050316?v=3","gravatar_id":"","url":"https://api.github.com/users/dolphin-emu","html_url":"https://github.com/dolphin-emu","followers_url":"https://api.github.com/users/dolphin-emu/followers","following_url":"https://api.github.com/users/dolphin-emu/following{/other_user}","gists_url":"https://api.github.com/users/dolphin-emu/gists{/gist_id}","starred_url":"https://api.github.com/users/dolphin-emu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dolphin-emu/subscriptions","organizations_url":"https://api.github.com/users/dolphin-emu/orgs","repos_url":"https://api.github.com/users/dolphin-emu/repos","events_url":"https://api.github.com/users/dolphin-emu/events{/privacy}","received_events_url":"https://api.github.com/users/dolphin-emu/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dolphin-emu/dolphin","description":"Dolphin is a GameCube / Wii emulator, allowing you to play games for these two platforms on PC with improvements.","fork":false,"url":"https://api.github.com/repos/dolphin-emu/dolphin","forks_url":"https://api.github.com/repos/dolphin-emu/dolphin/forks","keys_url":"https://api.github.com/repos/dolphin-emu/dolphin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dolphin-emu/dolphin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dolphin-emu/dolphin/teams","hooks_url":"https://api.github.com/repos/dolphin-emu/dolphin/hooks","issue_events_url":"https://api.github.com/repos/dolphin-emu/dolphin/issues/events{/number}","events_url":"https://api.github.com/repos/dolphin-emu/dolphin/events","assignees_url":"https://api.github.com/repos/dolphin-emu/dolphin/assignees{/user}","branches_url":"https://api.github.com/repos/dolphin-emu/dolphin/branches{/branch}","tags_url":"https://api.github.com/repos/dolphin-emu/dolphin/tags","blobs_url":"https://api.github.com/repos/dolphin-emu/dolphin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dolphin-emu/dolphin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dolphin-emu/dolphin/git/refs{/sha}","trees_url":"https://api.github.com/repos/dolphin-emu/dolphin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dolphin-emu/dolphin/statuses/{sha}","languages_url":"https://api.github.com/repos/dolphin-emu/dolphin/languages","stargazers_url":"https://api.github.com/repos/dolphin-emu/dolphin/stargazers","contributors_url":"https://api.github.com/repos/dolphin-emu/dolphin/contributors","subscribers_url":"https://api.github.com/repos/dolphin-emu/dolphin/subscribers","subscription_url":"https://api.github.com/repos/dolphin-emu/dolphin/subscription","commits_url":"https://api.github.com/repos/dolphin-emu/dolphin/commits{/sha}","git_commits_url":"https://api.github.com/repos/dolphin-emu/dolphin/git/commits{/sha}","comments_url":"https://api.github.com/repos/dolphin-emu/dolphin/comments{/number}","issue_comment_url":"https://api.github.com/repos/dolphin-emu/dolphin/issues/comments{/number}","contents_url":"https://api.github.com/repos/dolphin-emu/dolphin/contents/{+path}","compare_url":"https://api.github.com/repos/dolphin-emu/dolphin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dolphin-emu/dolphin/merges","archive_url":"https://api.github.com/repos/dolphin-emu/dolphin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dolphin-emu/dolphin/downloads","issues_url":"https://api.github.com/repos/dolphin-emu/dolphin/issues{/number}","pulls_url":"https://api.github.com/repos/dolphin-emu/dolphin/pulls{/number}","milestones_url":"https://api.github.com/repos/dolphin-emu/dolphin/milestones{/number}","notifications_url":"https://api.github.com/repos/dolphin-emu/dolphin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dolphin-emu/dolphin/labels{/name}","releases_url":"https://api.github.com/repos/dolphin-emu/dolphin/releases{/id}","created_at":"2013-07-22T09:07:57Z","updated_at":"2015-02-21T23:54:56Z","pushed_at":"2015-02-21T23:54:55Z","git_url":"git://github.com/dolphin-emu/dolphin.git","ssh_url":"git@github.com:dolphin-emu/dolphin.git","clone_url":"https://github.com/dolphin-emu/dolphin.git","svn_url":"https://github.com/dolphin-emu/dolphin","homepage":"https://dolphin-emu.org/","size":279866,"stargazers_count":1096,"watchers_count":1096,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":338,"mirror_url":null,"open_issues_count":63,"forks":338,"open_issues":63,"watchers":1096,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995"},"html":{"href":"https://github.com/dolphin-emu/dolphin/pull/1995"},"issue":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/issues/1995"},"comments":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/issues/1995/comments"},"review_comments":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995/comments"},"review_comment":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/pulls/1995/commits"},"statuses":{"href":"https://api.github.com/repos/dolphin-emu/dolphin/statuses/4cd8a9453242a0d48fd2953f23046890b204d314"}}}}