{"action":"created","comment":{"url":"https://api.github.com/repos/UAVCAN/libcanard/pulls/comments/49933904","id":49933904,"diff_hunk":"@@ -1,6 +1,845 @@\n+/*\n+ * The MIT License (MIT)\n+ * \n+ * Copyright (c) 2016 UAVCAN Team\n+ * \n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ * \n+ * The above copyright notice and this permission notice shall be included in all\n+ * copies or substantial portions of the Software.\n+ * \n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+ * SOFTWARE. \n+ */\n+\n #include \"canard.h\"\n #include \"canard_internals.h\"\n \n+#define CANARD_MAKE_TRANSFER_DESCRIPTOR(data_type_id, transfer_type, \\\n+                                        src_node_id, dst_node_id) \\\n+    ((data_type_id) | ((transfer_type) << 16) | \\\n+     ((src_node_id) << 18) | ((dst_node_id) << 25))\n+\n+struct CanardTxQueueItem\n+{\n+  CanardTxQueueItem* next;\n+  CanardCANFrame frame;\n+};\n+\n+/**\n+ *  API functions\n+ */\n+\n+/**\n+ * Initializes the library state.\n+ * Local node ID will be set to zero, i.e. the node will be anonymous.\n+ */\n+void canardInit(CanardInstance* out_ins,  void* mem_arena, size_t mem_arena_size,\n+                  canardOnTransferReception on_reception, canardShouldAcceptTransferPtr should_accept)\n+{\n+  out_ins->node_id = CANARD_BROADCAST_NODE_ID;\n+  out_ins->on_reception = on_reception;\n+  out_ins->should_accept = should_accept;\n+  out_ins->rx_states = NULL;\n+  out_ins->tx_queue = NULL;\n+  canardInitPoolAllocator(&out_ins->allocator, mem_arena, mem_arena_size/CANARD_MEM_BLOCK_SIZE);\n+}\n+\n+/**\n+ * Assigns a new node ID value to the current node.\n+ */\n+void canardSetLocalNodeID(CanardInstance* ins, uint8_t self_node_id)\n+{\n+  ins->node_id = self_node_id;\n+}\n+\n+/**\n+ * Returns node ID of the local node.\n+ * Returns zero if the node ID has not been set.\n+ */\n+uint8_t canardGetLocalNodeID(const CanardInstance* ins)\n+{\n+  return ins->node_id;\n+}\n+\n+/**\n+ * Sends a broadcast transfer.\n+ * If the node is in passive mode, only single frame transfers will be allowed.\n+ */\n+ int canardBroadcast(CanardInstance* ins,\n+                      uint64_t data_type_signature,\n+                      uint16_t data_type_id,\n+                      uint8_t* inout_transfer_id,\n+                      uint8_t priority,\n+                      const void* payload,\n+                      uint16_t payload_len)\n+ {\n+  uint32_t can_id;\n+  uint16_t crc = 0xFFFFU;\n+\n+  if (payload == NULL)\n+  {\n+      return -1;\n+  }\n+  if (priority > 31)\n+  {\n+      return -1;\n+  }\n+  if (canardGetLocalNodeID(ins) == 0)\n+  { \n+    if (payload_len > 7)\n+    {\n+      return -1;\n+    } else \n+    {\n+      //anonymous transfer, random discriminator\n+      uint16_t discriminator = (crc_add(0xFFFFU, payload, payload_len)) & 0x7FFEU;\n+      can_id = ((uint32_t)priority << 24) | (uint32_t)(discriminator << 9) |\n+        ((uint32_t)(data_type_id & 0xFF) << 8) | (uint32_t)canardGetLocalNodeID(ins);\n+    }\n+  } else\n+  {\n+    can_id = ((uint32_t)priority << 24) | ((uint32_t)data_type_id << 8) | (uint32_t)canardGetLocalNodeID(ins);\n+    \n+    if (payload_len > 7)\n+    {\n+      crc = crc_add_signature(crc, data_type_signature);\n+      crc = crc_add(crc, payload, payload_len);\n+    }\n+  }\n+\n+  canardEnqueueData(ins, can_id, inout_transfer_id, crc, payload, payload_len);\n+\n+  tidIncrement(inout_transfer_id);\n+\n+  return 1;\n+}\n+\n+/**\n+ * Sends a request or a response transfer.\n+ * Fails if the node is in passive mode.\n+ */\n+int canardRequestOrRespond(CanardInstance* ins,\n+                            uint8_t destination_node_id,\n+                            uint64_t data_type_signature,\n+                            uint16_t data_type_id,\n+                            uint8_t* inout_transfer_id,\n+                            uint8_t priority,\n+                            CanardRequestResponse kind,\n+                            const void* payload,\n+                            uint16_t payload_len)\n+{\n+  if (payload == NULL)\n+  {\n+      return -1;\n+  }\n+  if (canardGetLocalNodeID(ins) == 0)\n+  {\n+    return -1;\n+  }\n+  if (priority > 31)\n+  {\n+      return -1;\n+  }\n+\n+  const uint32_t can_id = ((uint32_t)priority << 24) | ((uint32_t)data_type_id << 16) | \n+                            ((uint32_t)kind << 15) | ((uint32_t)destination_node_id << 8) | \n+                              (1 << 7) | (uint32_t)canardGetLocalNodeID(ins);\n+  uint16_t crc = 0xFFFFU;\n+\n+  if (payload_len > 7)\n+  {\n+    crc = crc_add_signature(crc, data_type_signature);\n+    crc = crc_add(crc, payload, payload_len);\n+  }\n+\n+  canardEnqueueData(ins, can_id, inout_transfer_id, crc, payload, payload_len);\n+\n+  tidIncrement(inout_transfer_id);\n+\n+  return 1;\n+}\n+\n+/**\n+ * Returns a pointer to the top priority frame in the TX queue.\n+ * Returns NULL if the TX queue is empty.\n+ */\n+const CanardCANFrame* canardPeekTxQueue(const CanardInstance* ins)\n+{\n+  if (ins->tx_queue == NULL)\n+  {\n+    return NULL;\n+  }\n+  return &ins->tx_queue->frame;\n+}\n+\n+/**\n+ * Removes the top priority frame from the TX queue.\n+ */\n+void canardPopTxQueue(CanardInstance* ins) \n+{\n+  CanardTxQueueItem* item = ins->tx_queue;\n+  ins->tx_queue = item->next;\n+  canardFreeBlock(&ins->allocator, item);\n+}\n+\n+/**\n+ * Processes a received CAN frame with a timestamp.\n+ */\n+void canardHandleRxFrame(CanardInstance* ins, const CanardCANFrame* frame, uint64_t timestamp_usec)\n+{\n+  \n+  uint8_t transfer_type = canardTransferType(frame->id);\n+  uint8_t priority = CANARD_PRIORITY_FROM_ID(frame->id);\n+  uint8_t source_node_id = CANARD_SOURCE_ID_FROM_ID(frame->id);\n+  uint8_t destination_node_id = (transfer_type == CanardTransferTypeBroadcast) ? 0 : CANARD_DEST_ID_FROM_ID(frame->id);\n+  uint16_t data_type_id = canardDataType(frame->id);\n+  uint32_t transfer_descriptor = CANARD_MAKE_TRANSFER_DESCRIPTOR(data_type_id, transfer_type, source_node_id, destination_node_id);\n+  \n+  CanardRxState* rxstate;\n+  unsigned char tail_byte = frame->data[frame->data_len-1];\n+\n+  if (IS_START_OF_TRANSFER(tail_byte))\n+  {\n+    uint64_t data_type_signature;\n+\n+    if(ins->should_accept(ins, &data_type_signature, data_type_id, transfer_type, source_node_id))\n+    {\n+      rxstate = canardRxStateTraversal(ins, transfer_descriptor);\n+      rxstate->calculated_crc = crc_add_signature(0xFFFFU, data_type_signature);\n+    }\n+  } else if (!IS_START_OF_TRANSFER(tail_byte))","path":"src/canard.c","position":221,"original_position":221,"commit_id":"7a4f3205b45e7856f674511e2d436554c76b6a8d","original_commit_id":"7a4f3205b45e7856f674511e2d436554c76b6a8d","user":{"login":"pavel-kirienko","id":3298404,"avatar_url":"https://avatars.githubusercontent.com/u/3298404?v=3","gravatar_id":"","url":"https://api.github.com/users/pavel-kirienko","html_url":"https://github.com/pavel-kirienko","followers_url":"https://api.github.com/users/pavel-kirienko/followers","following_url":"https://api.github.com/users/pavel-kirienko/following{/other_user}","gists_url":"https://api.github.com/users/pavel-kirienko/gists{/gist_id}","starred_url":"https://api.github.com/users/pavel-kirienko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pavel-kirienko/subscriptions","organizations_url":"https://api.github.com/users/pavel-kirienko/orgs","repos_url":"https://api.github.com/users/pavel-kirienko/repos","events_url":"https://api.github.com/users/pavel-kirienko/events{/privacy}","received_events_url":"https://api.github.com/users/pavel-kirienko/received_events","type":"User","site_admin":false},"body":"Redundant condition, static analysers will complain about that. By the way, we'll need to scan it with Coverity later.\r\n\r\nShould be plain `else`.","created_at":"2016-01-16T16:35:03Z","updated_at":"2016-01-16T16:35:03Z","html_url":"https://github.com/UAVCAN/libcanard/pull/3#discussion_r49933904","pull_request_url":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/UAVCAN/libcanard/pulls/comments/49933904"},"html":{"href":"https://github.com/UAVCAN/libcanard/pull/3#discussion_r49933904"},"pull_request":{"href":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3","id":54285567,"html_url":"https://github.com/UAVCAN/libcanard/pull/3","diff_url":"https://github.com/UAVCAN/libcanard/pull/3.diff","patch_url":"https://github.com/UAVCAN/libcanard/pull/3.patch","issue_url":"https://api.github.com/repos/UAVCAN/libcanard/issues/3","number":3,"state":"open","locked":false,"title":"Implement Libcanard Library","user":{"login":"masierra","id":10148293,"avatar_url":"https://avatars.githubusercontent.com/u/10148293?v=3","gravatar_id":"","url":"https://api.github.com/users/masierra","html_url":"https://github.com/masierra","followers_url":"https://api.github.com/users/masierra/followers","following_url":"https://api.github.com/users/masierra/following{/other_user}","gists_url":"https://api.github.com/users/masierra/gists{/gist_id}","starred_url":"https://api.github.com/users/masierra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/masierra/subscriptions","organizations_url":"https://api.github.com/users/masierra/orgs","repos_url":"https://api.github.com/users/masierra/repos","events_url":"https://api.github.com/users/masierra/events{/privacy}","received_events_url":"https://api.github.com/users/masierra/received_events","type":"User","site_admin":false},"body":"Included is my current working version of libcanard. canardReadRxTransferPayload is the only missing function right now. Recent updates to the design document have also not been implemented (ftp://pkir.net/libcanard.diff). canard_test.c, based on simple_sensor_node is what I've been using to test the library. It sends 3 data types on the can interface. There's also a function, random_drop(x), called on the bottom of the send thread that will randomly drop a frame. Set that to the probability you want frames dropped, 0 if you dont want anything dropped. Right now canard_test just prints out the data received from the library.\r\n\r\nTo do:\r\nimplement crc checking\r\nignore incomplete transfers (probably has to do with the above)\r\n\r\nask any questions!","created_at":"2015-12-21T18:08:15Z","updated_at":"2016-01-16T16:35:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dc698f8d1e639bf42b9c4c01b97513d6f13fef64","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3/commits","review_comments_url":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3/comments","review_comment_url":"https://api.github.com/repos/UAVCAN/libcanard/pulls/comments{/number}","comments_url":"https://api.github.com/repos/UAVCAN/libcanard/issues/3/comments","statuses_url":"https://api.github.com/repos/UAVCAN/libcanard/statuses/7a4f3205b45e7856f674511e2d436554c76b6a8d","head":{"label":"masierra:msprivate/master","ref":"msprivate/master","sha":"7a4f3205b45e7856f674511e2d436554c76b6a8d","user":{"login":"masierra","id":10148293,"avatar_url":"https://avatars.githubusercontent.com/u/10148293?v=3","gravatar_id":"","url":"https://api.github.com/users/masierra","html_url":"https://github.com/masierra","followers_url":"https://api.github.com/users/masierra/followers","following_url":"https://api.github.com/users/masierra/following{/other_user}","gists_url":"https://api.github.com/users/masierra/gists{/gist_id}","starred_url":"https://api.github.com/users/masierra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/masierra/subscriptions","organizations_url":"https://api.github.com/users/masierra/orgs","repos_url":"https://api.github.com/users/masierra/repos","events_url":"https://api.github.com/users/masierra/events{/privacy}","received_events_url":"https://api.github.com/users/masierra/received_events","type":"User","site_admin":false},"repo":{"id":48129756,"name":"libcanard","full_name":"masierra/libcanard","owner":{"login":"masierra","id":10148293,"avatar_url":"https://avatars.githubusercontent.com/u/10148293?v=3","gravatar_id":"","url":"https://api.github.com/users/masierra","html_url":"https://github.com/masierra","followers_url":"https://api.github.com/users/masierra/followers","following_url":"https://api.github.com/users/masierra/following{/other_user}","gists_url":"https://api.github.com/users/masierra/gists{/gist_id}","starred_url":"https://api.github.com/users/masierra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/masierra/subscriptions","organizations_url":"https://api.github.com/users/masierra/orgs","repos_url":"https://api.github.com/users/masierra/repos","events_url":"https://api.github.com/users/masierra/events{/privacy}","received_events_url":"https://api.github.com/users/masierra/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/masierra/libcanard","description":"Minimal implementation of the UAVCAN protocol stack in C for resource constrained applications","fork":true,"url":"https://api.github.com/repos/masierra/libcanard","forks_url":"https://api.github.com/repos/masierra/libcanard/forks","keys_url":"https://api.github.com/repos/masierra/libcanard/keys{/key_id}","collaborators_url":"https://api.github.com/repos/masierra/libcanard/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/masierra/libcanard/teams","hooks_url":"https://api.github.com/repos/masierra/libcanard/hooks","issue_events_url":"https://api.github.com/repos/masierra/libcanard/issues/events{/number}","events_url":"https://api.github.com/repos/masierra/libcanard/events","assignees_url":"https://api.github.com/repos/masierra/libcanard/assignees{/user}","branches_url":"https://api.github.com/repos/masierra/libcanard/branches{/branch}","tags_url":"https://api.github.com/repos/masierra/libcanard/tags","blobs_url":"https://api.github.com/repos/masierra/libcanard/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/masierra/libcanard/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/masierra/libcanard/git/refs{/sha}","trees_url":"https://api.github.com/repos/masierra/libcanard/git/trees{/sha}","statuses_url":"https://api.github.com/repos/masierra/libcanard/statuses/{sha}","languages_url":"https://api.github.com/repos/masierra/libcanard/languages","stargazers_url":"https://api.github.com/repos/masierra/libcanard/stargazers","contributors_url":"https://api.github.com/repos/masierra/libcanard/contributors","subscribers_url":"https://api.github.com/repos/masierra/libcanard/subscribers","subscription_url":"https://api.github.com/repos/masierra/libcanard/subscription","commits_url":"https://api.github.com/repos/masierra/libcanard/commits{/sha}","git_commits_url":"https://api.github.com/repos/masierra/libcanard/git/commits{/sha}","comments_url":"https://api.github.com/repos/masierra/libcanard/comments{/number}","issue_comment_url":"https://api.github.com/repos/masierra/libcanard/issues/comments{/number}","contents_url":"https://api.github.com/repos/masierra/libcanard/contents/{+path}","compare_url":"https://api.github.com/repos/masierra/libcanard/compare/{base}...{head}","merges_url":"https://api.github.com/repos/masierra/libcanard/merges","archive_url":"https://api.github.com/repos/masierra/libcanard/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/masierra/libcanard/downloads","issues_url":"https://api.github.com/repos/masierra/libcanard/issues{/number}","pulls_url":"https://api.github.com/repos/masierra/libcanard/pulls{/number}","milestones_url":"https://api.github.com/repos/masierra/libcanard/milestones{/number}","notifications_url":"https://api.github.com/repos/masierra/libcanard/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/masierra/libcanard/labels{/name}","releases_url":"https://api.github.com/repos/masierra/libcanard/releases{/id}","created_at":"2015-12-16T19:12:01Z","updated_at":"2015-12-16T19:12:02Z","pushed_at":"2016-01-15T23:14:33Z","git_url":"git://github.com/masierra/libcanard.git","ssh_url":"git@github.com:masierra/libcanard.git","clone_url":"https://github.com/masierra/libcanard.git","svn_url":"https://github.com/masierra/libcanard","homepage":null,"size":88,"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":"UAVCAN:master","ref":"master","sha":"d4e846c4a74333496e521238c3816fda5b2cb949","user":{"login":"UAVCAN","id":10167381,"avatar_url":"https://avatars.githubusercontent.com/u/10167381?v=3","gravatar_id":"","url":"https://api.github.com/users/UAVCAN","html_url":"https://github.com/UAVCAN","followers_url":"https://api.github.com/users/UAVCAN/followers","following_url":"https://api.github.com/users/UAVCAN/following{/other_user}","gists_url":"https://api.github.com/users/UAVCAN/gists{/gist_id}","starred_url":"https://api.github.com/users/UAVCAN/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/UAVCAN/subscriptions","organizations_url":"https://api.github.com/users/UAVCAN/orgs","repos_url":"https://api.github.com/users/UAVCAN/repos","events_url":"https://api.github.com/users/UAVCAN/events{/privacy}","received_events_url":"https://api.github.com/users/UAVCAN/received_events","type":"Organization","site_admin":false},"repo":{"id":40349382,"name":"libcanard","full_name":"UAVCAN/libcanard","owner":{"login":"UAVCAN","id":10167381,"avatar_url":"https://avatars.githubusercontent.com/u/10167381?v=3","gravatar_id":"","url":"https://api.github.com/users/UAVCAN","html_url":"https://github.com/UAVCAN","followers_url":"https://api.github.com/users/UAVCAN/followers","following_url":"https://api.github.com/users/UAVCAN/following{/other_user}","gists_url":"https://api.github.com/users/UAVCAN/gists{/gist_id}","starred_url":"https://api.github.com/users/UAVCAN/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/UAVCAN/subscriptions","organizations_url":"https://api.github.com/users/UAVCAN/orgs","repos_url":"https://api.github.com/users/UAVCAN/repos","events_url":"https://api.github.com/users/UAVCAN/events{/privacy}","received_events_url":"https://api.github.com/users/UAVCAN/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/UAVCAN/libcanard","description":"Minimal implementation of the UAVCAN protocol stack in C for resource constrained applications","fork":false,"url":"https://api.github.com/repos/UAVCAN/libcanard","forks_url":"https://api.github.com/repos/UAVCAN/libcanard/forks","keys_url":"https://api.github.com/repos/UAVCAN/libcanard/keys{/key_id}","collaborators_url":"https://api.github.com/repos/UAVCAN/libcanard/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/UAVCAN/libcanard/teams","hooks_url":"https://api.github.com/repos/UAVCAN/libcanard/hooks","issue_events_url":"https://api.github.com/repos/UAVCAN/libcanard/issues/events{/number}","events_url":"https://api.github.com/repos/UAVCAN/libcanard/events","assignees_url":"https://api.github.com/repos/UAVCAN/libcanard/assignees{/user}","branches_url":"https://api.github.com/repos/UAVCAN/libcanard/branches{/branch}","tags_url":"https://api.github.com/repos/UAVCAN/libcanard/tags","blobs_url":"https://api.github.com/repos/UAVCAN/libcanard/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/UAVCAN/libcanard/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/UAVCAN/libcanard/git/refs{/sha}","trees_url":"https://api.github.com/repos/UAVCAN/libcanard/git/trees{/sha}","statuses_url":"https://api.github.com/repos/UAVCAN/libcanard/statuses/{sha}","languages_url":"https://api.github.com/repos/UAVCAN/libcanard/languages","stargazers_url":"https://api.github.com/repos/UAVCAN/libcanard/stargazers","contributors_url":"https://api.github.com/repos/UAVCAN/libcanard/contributors","subscribers_url":"https://api.github.com/repos/UAVCAN/libcanard/subscribers","subscription_url":"https://api.github.com/repos/UAVCAN/libcanard/subscription","commits_url":"https://api.github.com/repos/UAVCAN/libcanard/commits{/sha}","git_commits_url":"https://api.github.com/repos/UAVCAN/libcanard/git/commits{/sha}","comments_url":"https://api.github.com/repos/UAVCAN/libcanard/comments{/number}","issue_comment_url":"https://api.github.com/repos/UAVCAN/libcanard/issues/comments{/number}","contents_url":"https://api.github.com/repos/UAVCAN/libcanard/contents/{+path}","compare_url":"https://api.github.com/repos/UAVCAN/libcanard/compare/{base}...{head}","merges_url":"https://api.github.com/repos/UAVCAN/libcanard/merges","archive_url":"https://api.github.com/repos/UAVCAN/libcanard/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/UAVCAN/libcanard/downloads","issues_url":"https://api.github.com/repos/UAVCAN/libcanard/issues{/number}","pulls_url":"https://api.github.com/repos/UAVCAN/libcanard/pulls{/number}","milestones_url":"https://api.github.com/repos/UAVCAN/libcanard/milestones{/number}","notifications_url":"https://api.github.com/repos/UAVCAN/libcanard/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/UAVCAN/libcanard/labels{/name}","releases_url":"https://api.github.com/repos/UAVCAN/libcanard/releases{/id}","created_at":"2015-08-07T08:16:09Z","updated_at":"2015-09-13T14:19:06Z","pushed_at":"2016-01-15T23:14:34Z","git_url":"git://github.com/UAVCAN/libcanard.git","ssh_url":"git@github.com:UAVCAN/libcanard.git","clone_url":"https://github.com/UAVCAN/libcanard.git","svn_url":"https://github.com/UAVCAN/libcanard","homepage":null,"size":45,"stargazers_count":5,"watchers_count":5,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":4,"forks":5,"open_issues":4,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3"},"html":{"href":"https://github.com/UAVCAN/libcanard/pull/3"},"issue":{"href":"https://api.github.com/repos/UAVCAN/libcanard/issues/3"},"comments":{"href":"https://api.github.com/repos/UAVCAN/libcanard/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/UAVCAN/libcanard/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/UAVCAN/libcanard/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/UAVCAN/libcanard/statuses/7a4f3205b45e7856f674511e2d436554c76b6a8d"}}}}