{"action":"created","comment":{"url":"https://api.github.com/repos/nibanks/openthread/pulls/comments/79408020","id":79408020,"diff_hunk":"@@ -0,0 +1,379 @@\n+// border-router.cpp : Defines the entry point for the console application.\n+//\n+\n+#include \"stdafx.h\"\n+#include <mbedtls/memory_buffer_alloc.h>\n+#include <thread/thread_uris.hpp>\n+#include <crypto/mbedtls.hpp>\n+#include <memory>\n+#include \"border-router.hpp\"\n+#include \"client.hpp\"\n+#include \"fake-leader.hpp\"\n+\n+#define MBED_MEMORY_BUF_SIZE  (2048 * sizeof(void*))\n+\n+extern \"C\" void otSignalTaskletPending(otInstance *)\n+{\n+}\n+\n+inline uint8_t _str1ToHex(const char charTuple) {\n+    if ('0' <= charTuple && charTuple <= '9') {\n+        return (uint8_t)(charTuple - '0');\n+    }\n+    else if ('A' <= charTuple && charTuple <= 'F') {\n+        return (uint8_t)(10 + (charTuple - 'A'));\n+    }\n+    else if ('a' <= charTuple && charTuple <= 'f') {\n+        return (uint8_t)(10 + (charTuple - 'a'));\n+    }\n+    return 0;\n+}\n+\n+inline uint8_t _str2ToHex(const char hexByte[2]) {\n+    const char hi = hexByte[0];\n+    const char lo = hexByte[1];\n+    return (_str1ToHex(hi) * 16) + _str1ToHex(lo);\n+}\n+\n+void printBuffer(char* buffer, int len)\n+{\n+    for (int i = 0; i < len; i++)\n+    {\n+        printf(\"%02x\", (unsigned char)*buffer++);\n+        if (i % 4 == 3)\n+        {\n+            printf(\" \");\n+        }\n+    }\n+    printf(\"\\n\");\n+}\n+\n+void getPSKc(const char* passPhrase, const char* networkName, const char* const xPanId, uint8_t* derivedKeyOut) {\n+    const char* saltPrefix = \"Thread\";\n+    const size_t preLen = strlen(saltPrefix);\n+    const size_t xpiLen = xPanId ? strlen(xPanId) / 2 : 0;\n+    const size_t nwLen = strlen(networkName);\n+    size_t saltLen = preLen + xpiLen + nwLen;\n+\n+    uint8_t* salt = new uint8_t[saltLen];\n+    memset(salt, 0, saltLen);\n+\n+    memcpy_s((char*)salt, saltLen, saltPrefix, preLen);\n+\n+    size_t  i;\n+    for (i = 0; i < xpiLen; i++) {\n+        uint8_t byteVal = _str2ToHex(xPanId + (2 * i));\n+        salt[preLen + i] = byteVal;\n+    }\n+\n+    memcpy_s((char*)(salt + preLen + xpiLen), nwLen, networkName, nwLen);\n+\n+    // Get a handle to the algorithm provider\n+    BCRYPT_ALG_HANDLE hKeyPbkdf2AlgoProv = nullptr;\n+    NTSTATUS ntStatus = BCryptOpenAlgorithmProvider(\n+        &hKeyPbkdf2AlgoProv,\n+        BCRYPT_PBKDF2_ALGORITHM,\n+        nullptr,\n+        0);\n+\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"open algorithm provider failed, 0x%x!\\n\", ntStatus);\n+        return;\n+    }\n+\n+    BCRYPT_ALG_HANDLE hKeyAesCmacAlgoProv = nullptr;\n+    ntStatus = BCryptOpenAlgorithmProvider(\n+        &hKeyAesCmacAlgoProv,\n+        BCRYPT_AES_CMAC_ALGORITHM,\n+        nullptr,\n+        0);\n+\n+\n+    BCRYPT_HASH_HANDLE  hHash = nullptr;\n+    uint8_t zeroKey[16] = {};\n+    ntStatus = BCryptCreateHash(hKeyAesCmacAlgoProv, &hHash, nullptr, 0, zeroKey, sizeof(zeroKey), 0);\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"BCryptCreateHash failed, 0x%x!\\n\", ntStatus);\n+        return;\n+    }\n+\n+    ntStatus = BCryptHashData(hHash, (PUCHAR)passPhrase, (ULONG)strlen(passPhrase), 0);\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"BCryptHashData failed, 0x%x!\\n\", ntStatus);\n+        return;\n+    }\n+\n+    BYTE    res1[128];\n+    ULONG   rlen = 16;\n+    ntStatus = BCryptFinishHash(hHash, res1, rlen, 0);\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"BCryptFinishHash failed, 0x%x!\\n\", ntStatus);\n+        return;\n+    }\n+\n+    ntStatus = BCryptDestroyHash(hHash);\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"BCryptFinishHash failed, 0x%x!\\n\", ntStatus);\n+        return;\n+    }\n+\n+    BCryptBufferDesc    ParamList;\n+    BCryptBuffer        pParamBuffer[3] = {};\n+\n+    pParamBuffer[0].BufferType = KDF_HASH_ALGORITHM;\n+    pParamBuffer[0].cbBuffer = (ULONG)wcslen(BCRYPT_AES_CMAC_ALGORITHM) * sizeof(WCHAR);\n+    pParamBuffer[0].pvBuffer = (void*)BCRYPT_AES_CMAC_ALGORITHM;\n+\n+    ULONGLONG ulIteration = 16384;\n+    pParamBuffer[1].BufferType = KDF_ITERATION_COUNT;\n+    pParamBuffer[1].cbBuffer = sizeof(ulIteration);\n+    pParamBuffer[1].pvBuffer = &ulIteration;\n+\n+    pParamBuffer[2].BufferType = KDF_SALT;\n+    pParamBuffer[2].cbBuffer = (ULONG)saltLen;\n+    pParamBuffer[2].pvBuffer = salt;\n+\n+    ParamList.cBuffers = 3;\n+    ParamList.pBuffers = pParamBuffer;\n+    ParamList.ulVersion = BCRYPTBUFFER_VERSION;\n+\n+    BCRYPT_KEY_HANDLE hKeySymmetricKey;\n+    ntStatus = BCryptGenerateSymmetricKey(\n+        hKeyPbkdf2AlgoProv,\n+        &hKeySymmetricKey,\n+        nullptr,\n+        0,\n+        res1,\n+        16,\n+        0);\n+\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"gen symmetrickey failed, 0x%x\\n\", ntStatus);\n+        return;\n+    }\n+\n+    DWORD cbResult = 0;\n+    ntStatus = BCryptKeyDerivation(hKeySymmetricKey,\n+        &ParamList,\n+        derivedKeyOut,\n+        16,\n+        &cbResult,\n+        0\n+    );\n+\n+\n+    if (!BCRYPT_SUCCESS(ntStatus))\n+    {\n+        printf(\"Derivekey failed, 0x%x\\n\", ntStatus);\n+        return;\n+    }\n+\n+    BCryptCloseAlgorithmProvider(hKeyPbkdf2AlgoProv, 0);\n+    BCryptCloseAlgorithmProvider(hKeyAesCmacAlgoProv, 0);\n+\n+    delete[] salt;\n+\n+    printf(\"PSKc Stretched Key:\\n\");\n+    printBuffer((char*)derivedKeyOut, 16);\n+}\n+\n+static unsigned char sMemoryBuf[Thread::Crypto::MbedTls::kMemorySize];\n+\n+int main()\n+{\n+    mbedtls_memory_buffer_alloc_init(sMemoryBuf, sizeof(sMemoryBuf));\n+    BorderRouter router;\n+    router.Start();\n+    //FakeLeader leader;\n+    //leader.Start();\n+    //Client client;\n+    //client.Start();\n+}\n+\n+BorderRouter::BorderRouter() :\n+    mCoapHandler(HandleCoapMessage, this)\n+{\n+    mCoap.AddResource(mCoapHandler);\n+}\n+\n+HRESULT BorderRouter::Start()\n+{\n+    WSADATA wsa;\n+    HRESULT hr = HRESULT_FROM_WIN32(WSAStartup(MAKEWORD(2, 2), &wsa));\n+    if (FAILED(hr))\n+    {\n+        return hr;\n+    }\n+\n+    hr = mCommissionerSocket.Initialize(HandleCommissionerSocketReceive, this);\n+    if (FAILED(hr))\n+    {\n+        return hr;\n+    }\n+\n+    hr = mThreadLeaderSocket.Initialize(HandleThreadSocketReceive, this);\n+    if (FAILED(hr))\n+    {\n+        return hr;\n+    }\n+\n+    hr = mCommissionerSocket.Bind(19779);\n+    if (FAILED(hr))\n+    {\n+        return hr;\n+    }\n+\n+    uint8_t derivedKey[16];\n+    getPSKc(\"12SECRETPASSWORD34\", \"TestNetwork1\", \"0001020304050607\", derivedKey);\n+    mDtls.SetPsk(derivedKey, sizeof(derivedKey));\n+    mDtls.Start(false, HandleDtlsReceive, HandleDtlsSend, this);\n+\n+    while (1)\n+    {\n+        printf(\"entering the read loop!\\n\");\n+        mCommissionerSocket.Read();\n+    }\n+\n+    return S_OK;\n+}\n+\n+void BorderRouter::Stop()\n+{\n+    WSACleanup();\n+}\n+\n+// static\n+void BorderRouter::HandleCommissionerSocketReceive(void *aContext, uint8_t *aBuf, DWORD aLength)\n+{\n+    static_cast<BorderRouter *>(aContext)->HandleCommissionerSocketReceive(aBuf, aLength);\n+}\n+\n+void BorderRouter::HandleCommissionerSocketReceive(uint8_t *aBuf, DWORD aLength)\n+{\n+    // just got something from the commissioner socket, need to decrypt it (or continue the DTLS handshake)\n+    if (!mDtls.IsConnected())\n+    {\n+        // The DTLS server requires that we set some client ID, or the handshake will fail. The documentation\n+        // states that it is usually an ip/port pair (something that identifies the peer on the transport).\n+        // Set it here.\n+        SOCKADDR currentPeer;\n+        mCommissionerSocket.GetLastPeer(&currentPeer);\n+        mDtls.SetClientId(reinterpret_cast<uint8_t*>(&currentPeer), sizeof(currentPeer));\n+    }\n+    mDtls.Receive(aBuf, static_cast<uint16_t>(aLength));\n+}\n+\n+// static\n+void BorderRouter::HandleThreadSocketReceive(void *aContext, uint8_t *aBuf, DWORD aLength)\n+{\n+    static_cast<BorderRouter *>(aContext)->HandleThreadSocketReceive(aBuf, aLength);\n+}\n+\n+void BorderRouter::HandleThreadSocketReceive(uint8_t* aBuf, DWORD aLength)\n+{\n+    // just got something from the thread socket. it will be a reply to something\n+    // we sent to the leader. replys don't have coap URIs so if the message format\n+    // is the same, we can just forward it directly as is","path":"examples/borderrouter/windows/border-router.cpp","position":282,"original_position":282,"commit_id":"e2d7edb743d46c1ab9feebcb9c227e90ddff12fe","original_commit_id":"e2d7edb743d46c1ab9feebcb9c227e90ddff12fe","user":{"login":"nibanks","id":20663557,"avatar_url":"https://avatars.githubusercontent.com/u/20663557?v=3","gravatar_id":"","url":"https://api.github.com/users/nibanks","html_url":"https://github.com/nibanks","followers_url":"https://api.github.com/users/nibanks/followers","following_url":"https://api.github.com/users/nibanks/following{/other_user}","gists_url":"https://api.github.com/users/nibanks/gists{/gist_id}","starred_url":"https://api.github.com/users/nibanks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nibanks/subscriptions","organizations_url":"https://api.github.com/users/nibanks/orgs","repos_url":"https://api.github.com/users/nibanks/repos","events_url":"https://api.github.com/users/nibanks/events{/privacy}","received_events_url":"https://api.github.com/users/nibanks/received_events","type":"User","site_admin":false},"body":"`replys` should be `replies`","created_at":"2016-09-19T14:47:38Z","updated_at":"2016-09-19T14:47:38Z","html_url":"https://github.com/nibanks/openthread/pull/3#discussion_r79408020","pull_request_url":"https://api.github.com/repos/nibanks/openthread/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/nibanks/openthread/pulls/comments/79408020"},"html":{"href":"https://github.com/nibanks/openthread/pull/3#discussion_r79408020"},"pull_request":{"href":"https://api.github.com/repos/nibanks/openthread/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/nibanks/openthread/pulls/3","id":85509776,"html_url":"https://github.com/nibanks/openthread/pull/3","diff_url":"https://github.com/nibanks/openthread/pull/3.diff","patch_url":"https://github.com/nibanks/openthread/pull/3.patch","issue_url":"https://api.github.com/repos/nibanks/openthread/issues/3","number":3,"state":"open","locked":false,"title":"initial commit of work-in-progress prototype off mesh border router","user":{"login":"jovergar","id":12835862,"avatar_url":"https://avatars.githubusercontent.com/u/12835862?v=3","gravatar_id":"","url":"https://api.github.com/users/jovergar","html_url":"https://github.com/jovergar","followers_url":"https://api.github.com/users/jovergar/followers","following_url":"https://api.github.com/users/jovergar/following{/other_user}","gists_url":"https://api.github.com/users/jovergar/gists{/gist_id}","starred_url":"https://api.github.com/users/jovergar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jovergar/subscriptions","organizations_url":"https://api.github.com/users/jovergar/orgs","repos_url":"https://api.github.com/users/jovergar/repos","events_url":"https://api.github.com/users/jovergar/events{/privacy}","received_events_url":"https://api.github.com/users/jovergar/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-09-16T02:08:37Z","updated_at":"2016-09-19T14:47:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"411749ff8135bf8e7283cc7dbd79ecf712116871","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/nibanks/openthread/pulls/3/commits","review_comments_url":"https://api.github.com/repos/nibanks/openthread/pulls/3/comments","review_comment_url":"https://api.github.com/repos/nibanks/openthread/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nibanks/openthread/issues/3/comments","statuses_url":"https://api.github.com/repos/nibanks/openthread/statuses/e2d7edb743d46c1ab9feebcb9c227e90ddff12fe","head":{"label":"jovergar:windows","ref":"windows","sha":"e2d7edb743d46c1ab9feebcb9c227e90ddff12fe","user":{"login":"jovergar","id":12835862,"avatar_url":"https://avatars.githubusercontent.com/u/12835862?v=3","gravatar_id":"","url":"https://api.github.com/users/jovergar","html_url":"https://github.com/jovergar","followers_url":"https://api.github.com/users/jovergar/followers","following_url":"https://api.github.com/users/jovergar/following{/other_user}","gists_url":"https://api.github.com/users/jovergar/gists{/gist_id}","starred_url":"https://api.github.com/users/jovergar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jovergar/subscriptions","organizations_url":"https://api.github.com/users/jovergar/orgs","repos_url":"https://api.github.com/users/jovergar/repos","events_url":"https://api.github.com/users/jovergar/events{/privacy}","received_events_url":"https://api.github.com/users/jovergar/received_events","type":"User","site_admin":false},"repo":{"id":68341887,"name":"openthread","full_name":"jovergar/openthread","owner":{"login":"jovergar","id":12835862,"avatar_url":"https://avatars.githubusercontent.com/u/12835862?v=3","gravatar_id":"","url":"https://api.github.com/users/jovergar","html_url":"https://github.com/jovergar","followers_url":"https://api.github.com/users/jovergar/followers","following_url":"https://api.github.com/users/jovergar/following{/other_user}","gists_url":"https://api.github.com/users/jovergar/gists{/gist_id}","starred_url":"https://api.github.com/users/jovergar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jovergar/subscriptions","organizations_url":"https://api.github.com/users/jovergar/orgs","repos_url":"https://api.github.com/users/jovergar/repos","events_url":"https://api.github.com/users/jovergar/events{/privacy}","received_events_url":"https://api.github.com/users/jovergar/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jovergar/openthread","description":"OpenThread released by Nest is an open-source implementation of the Thread networking protocol","fork":true,"url":"https://api.github.com/repos/jovergar/openthread","forks_url":"https://api.github.com/repos/jovergar/openthread/forks","keys_url":"https://api.github.com/repos/jovergar/openthread/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jovergar/openthread/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jovergar/openthread/teams","hooks_url":"https://api.github.com/repos/jovergar/openthread/hooks","issue_events_url":"https://api.github.com/repos/jovergar/openthread/issues/events{/number}","events_url":"https://api.github.com/repos/jovergar/openthread/events","assignees_url":"https://api.github.com/repos/jovergar/openthread/assignees{/user}","branches_url":"https://api.github.com/repos/jovergar/openthread/branches{/branch}","tags_url":"https://api.github.com/repos/jovergar/openthread/tags","blobs_url":"https://api.github.com/repos/jovergar/openthread/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jovergar/openthread/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jovergar/openthread/git/refs{/sha}","trees_url":"https://api.github.com/repos/jovergar/openthread/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jovergar/openthread/statuses/{sha}","languages_url":"https://api.github.com/repos/jovergar/openthread/languages","stargazers_url":"https://api.github.com/repos/jovergar/openthread/stargazers","contributors_url":"https://api.github.com/repos/jovergar/openthread/contributors","subscribers_url":"https://api.github.com/repos/jovergar/openthread/subscribers","subscription_url":"https://api.github.com/repos/jovergar/openthread/subscription","commits_url":"https://api.github.com/repos/jovergar/openthread/commits{/sha}","git_commits_url":"https://api.github.com/repos/jovergar/openthread/git/commits{/sha}","comments_url":"https://api.github.com/repos/jovergar/openthread/comments{/number}","issue_comment_url":"https://api.github.com/repos/jovergar/openthread/issues/comments{/number}","contents_url":"https://api.github.com/repos/jovergar/openthread/contents/{+path}","compare_url":"https://api.github.com/repos/jovergar/openthread/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jovergar/openthread/merges","archive_url":"https://api.github.com/repos/jovergar/openthread/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jovergar/openthread/downloads","issues_url":"https://api.github.com/repos/jovergar/openthread/issues{/number}","pulls_url":"https://api.github.com/repos/jovergar/openthread/pulls{/number}","milestones_url":"https://api.github.com/repos/jovergar/openthread/milestones{/number}","notifications_url":"https://api.github.com/repos/jovergar/openthread/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jovergar/openthread/labels{/name}","releases_url":"https://api.github.com/repos/jovergar/openthread/releases{/id}","deployments_url":"https://api.github.com/repos/jovergar/openthread/deployments","created_at":"2016-09-16T00:26:53Z","updated_at":"2016-09-16T00:26:55Z","pushed_at":"2016-09-17T01:09:44Z","git_url":"git://github.com/jovergar/openthread.git","ssh_url":"git@github.com:jovergar/openthread.git","clone_url":"https://github.com/jovergar/openthread.git","svn_url":"https://github.com/jovergar/openthread","homepage":"","size":273066,"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":"nibanks:windows","ref":"windows","sha":"0afb2ff3f656f5fe17b56c2b92c8630513fb7388","user":{"login":"nibanks","id":20663557,"avatar_url":"https://avatars.githubusercontent.com/u/20663557?v=3","gravatar_id":"","url":"https://api.github.com/users/nibanks","html_url":"https://github.com/nibanks","followers_url":"https://api.github.com/users/nibanks/followers","following_url":"https://api.github.com/users/nibanks/following{/other_user}","gists_url":"https://api.github.com/users/nibanks/gists{/gist_id}","starred_url":"https://api.github.com/users/nibanks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nibanks/subscriptions","organizations_url":"https://api.github.com/users/nibanks/orgs","repos_url":"https://api.github.com/users/nibanks/repos","events_url":"https://api.github.com/users/nibanks/events{/privacy}","received_events_url":"https://api.github.com/users/nibanks/received_events","type":"User","site_admin":false},"repo":{"id":65052520,"name":"openthread","full_name":"nibanks/openthread","owner":{"login":"nibanks","id":20663557,"avatar_url":"https://avatars.githubusercontent.com/u/20663557?v=3","gravatar_id":"","url":"https://api.github.com/users/nibanks","html_url":"https://github.com/nibanks","followers_url":"https://api.github.com/users/nibanks/followers","following_url":"https://api.github.com/users/nibanks/following{/other_user}","gists_url":"https://api.github.com/users/nibanks/gists{/gist_id}","starred_url":"https://api.github.com/users/nibanks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nibanks/subscriptions","organizations_url":"https://api.github.com/users/nibanks/orgs","repos_url":"https://api.github.com/users/nibanks/repos","events_url":"https://api.github.com/users/nibanks/events{/privacy}","received_events_url":"https://api.github.com/users/nibanks/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nibanks/openthread","description":"OpenThread released by Nest is an open-source implementation of the Thread networking protocol","fork":true,"url":"https://api.github.com/repos/nibanks/openthread","forks_url":"https://api.github.com/repos/nibanks/openthread/forks","keys_url":"https://api.github.com/repos/nibanks/openthread/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nibanks/openthread/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nibanks/openthread/teams","hooks_url":"https://api.github.com/repos/nibanks/openthread/hooks","issue_events_url":"https://api.github.com/repos/nibanks/openthread/issues/events{/number}","events_url":"https://api.github.com/repos/nibanks/openthread/events","assignees_url":"https://api.github.com/repos/nibanks/openthread/assignees{/user}","branches_url":"https://api.github.com/repos/nibanks/openthread/branches{/branch}","tags_url":"https://api.github.com/repos/nibanks/openthread/tags","blobs_url":"https://api.github.com/repos/nibanks/openthread/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nibanks/openthread/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nibanks/openthread/git/refs{/sha}","trees_url":"https://api.github.com/repos/nibanks/openthread/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nibanks/openthread/statuses/{sha}","languages_url":"https://api.github.com/repos/nibanks/openthread/languages","stargazers_url":"https://api.github.com/repos/nibanks/openthread/stargazers","contributors_url":"https://api.github.com/repos/nibanks/openthread/contributors","subscribers_url":"https://api.github.com/repos/nibanks/openthread/subscribers","subscription_url":"https://api.github.com/repos/nibanks/openthread/subscription","commits_url":"https://api.github.com/repos/nibanks/openthread/commits{/sha}","git_commits_url":"https://api.github.com/repos/nibanks/openthread/git/commits{/sha}","comments_url":"https://api.github.com/repos/nibanks/openthread/comments{/number}","issue_comment_url":"https://api.github.com/repos/nibanks/openthread/issues/comments{/number}","contents_url":"https://api.github.com/repos/nibanks/openthread/contents/{+path}","compare_url":"https://api.github.com/repos/nibanks/openthread/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nibanks/openthread/merges","archive_url":"https://api.github.com/repos/nibanks/openthread/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nibanks/openthread/downloads","issues_url":"https://api.github.com/repos/nibanks/openthread/issues{/number}","pulls_url":"https://api.github.com/repos/nibanks/openthread/pulls{/number}","milestones_url":"https://api.github.com/repos/nibanks/openthread/milestones{/number}","notifications_url":"https://api.github.com/repos/nibanks/openthread/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nibanks/openthread/labels{/name}","releases_url":"https://api.github.com/repos/nibanks/openthread/releases{/id}","deployments_url":"https://api.github.com/repos/nibanks/openthread/deployments","created_at":"2016-08-05T22:20:17Z","updated_at":"2016-08-05T22:20:19Z","pushed_at":"2016-09-17T14:27:46Z","git_url":"git://github.com/nibanks/openthread.git","ssh_url":"git@github.com:nibanks/openthread.git","clone_url":"https://github.com/nibanks/openthread.git","svn_url":"https://github.com/nibanks/openthread","homepage":"","size":273152,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nibanks/openthread/pulls/3"},"html":{"href":"https://github.com/nibanks/openthread/pull/3"},"issue":{"href":"https://api.github.com/repos/nibanks/openthread/issues/3"},"comments":{"href":"https://api.github.com/repos/nibanks/openthread/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/nibanks/openthread/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/nibanks/openthread/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nibanks/openthread/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/nibanks/openthread/statuses/e2d7edb743d46c1ab9feebcb9c227e90ddff12fe"}}}}
{"actor":{"display_login":"nibanks"}}