{"action":"created","comment":{"url":"https://api.github.com/repos/tock/tock/pulls/comments/207074400","pull_request_review_id":142613231,"id":207074400,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwNzA3NDQwMA==","diff_hunk":"@@ -0,0 +1,494 @@\n+//! UDP userspace interface for transmit and receive.\n+//!\n+//! Implements a userspace interface for sending and receiving UDP messages.\n+//! Also exposes a list of interface addresses to the application (currently\n+//! hard-coded.\n+\n+use core::cell::Cell;\n+use core::{cmp, mem};\n+use kernel::common::cells::TakeCell;\n+use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared};\n+use net::ipv6::ip_utils::IPAddr;\n+use net::udp::udp_recv::{UDPReceiver, UDPRecvClient};\n+use net::udp::udp_send::{UDPSendClient, UDPSender};\n+\n+/// Syscall number\n+pub const DRIVER_NUM: usize = 0x30002;\n+\n+const INTERFACES: [IPAddr; 2] = [\n+    IPAddr([\n+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,\n+        0x0f,\n+    ]),\n+    IPAddr([\n+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,\n+        0x1f,\n+    ]),\n+];\n+\n+#[derive(Debug)]\n+struct IPAddrPort {\n+    addr: IPAddr,\n+    port: u16,\n+}\n+\n+#[derive(Default)]\n+pub struct App {\n+    rx_callback: Option<Callback>,\n+    tx_callback: Option<Callback>,\n+    app_read: Option<AppSlice<Shared, u8>>,\n+    app_write: Option<AppSlice<Shared, u8>>,\n+    app_cfg: Option<AppSlice<Shared, u8>>,\n+    app_rx_cfg: Option<AppSlice<Shared, u8>>,\n+    pending_tx: Option<[IPAddrPort; 2]>,\n+}\n+\n+#[allow(dead_code)]\n+pub struct UDPDriver<'a> {\n+    /// UDP sender\n+    sender: &'a UDPSender<'a>,\n+\n+    /// UDP receiver\n+    receiver: &'a UDPReceiver<'a>,\n+\n+    /// Grant of apps that use this radio driver.\n+    apps: Grant<App>,\n+    /// ID of app whose transmission request is being processed.\n+    current_app: Cell<Option<AppId>>,\n+\n+    /// Buffer that stores the UDP frame to be transmitted.\n+    kernel_tx: TakeCell<'static, [u8]>,\n+}\n+\n+impl<'a> UDPDriver<'a> {\n+    pub fn new(\n+        sender: &'a UDPSender<'a>,\n+        receiver: &'a UDPReceiver<'a>,\n+        grant: Grant<App>,\n+        kernel_tx: &'static mut [u8],\n+    ) -> UDPDriver<'a> {\n+        UDPDriver {\n+            sender: sender,\n+            receiver: receiver,\n+            apps: grant,\n+            current_app: Cell::new(None),\n+            kernel_tx: TakeCell::new(kernel_tx),\n+        }\n+    }\n+\n+    /// Utility function to perform an action on an app in a system call.\n+    #[inline]\n+    fn do_with_app<F>(&self, appid: AppId, closure: F) -> ReturnCode\n+    where\n+        F: FnOnce(&mut App) -> ReturnCode,\n+    {\n+        self.apps\n+            .enter(appid, |app, _| closure(app))\n+            .unwrap_or_else(|err| err.into())\n+    }\n+\n+    /// Utility function to perform an action using an app's config buffer.\n+    #[inline]\n+    #[allow(dead_code)]\n+    fn do_with_cfg<F>(&self, appid: AppId, len: usize, closure: F) -> ReturnCode\n+    where\n+        F: FnOnce(&[u8]) -> ReturnCode,\n+    {\n+        self.apps\n+            .enter(appid, |app, _| {\n+                app.app_cfg\n+                    .take()\n+                    .as_ref()\n+                    .map_or(ReturnCode::EINVAL, |cfg| {\n+                        if cfg.len() != len {\n+                            return ReturnCode::EINVAL;\n+                        }\n+                        closure(cfg.as_ref())\n+                    })\n+            })\n+            .unwrap_or_else(|err| err.into())\n+    }\n+\n+    /// Utility function to perform a write to an app's config buffer.\n+    #[inline]\n+    fn do_with_cfg_mut<F>(&self, appid: AppId, len: usize, closure: F) -> ReturnCode\n+    where\n+        F: FnOnce(&mut [u8]) -> ReturnCode,\n+    {\n+        self.apps\n+            .enter(appid, |app, _| {\n+                app.app_cfg\n+                    .take()\n+                    .as_mut()\n+                    .map_or(ReturnCode::EINVAL, |cfg| {\n+                        if cfg.len() != len {\n+                            return ReturnCode::EINVAL;\n+                        }\n+                        closure(cfg.as_mut())\n+                    })\n+            })\n+            .unwrap_or_else(|err| err.into())\n+    }\n+\n+    /// Utility function to perform an action using an app's RX config buffer.\n+    /// (quick and dirty ctrl-c, ctrl-v from above)\n+    #[inline]\n+    #[allow(dead_code)]\n+    fn do_with_rx_cfg<F>(&self, appid: AppId, len: usize, closure: F) -> ReturnCode\n+    where\n+        F: FnOnce(&[u8]) -> ReturnCode,\n+    {\n+        self.apps\n+            .enter(appid, |app, _| {\n+                app.app_rx_cfg\n+                    .take()\n+                    .as_ref()\n+                    .map_or(ReturnCode::EINVAL, |cfg| {\n+                        if cfg.len() != len {\n+                            return ReturnCode::EINVAL;\n+                        }\n+                        closure(cfg.as_ref())\n+                    })\n+            })\n+            .unwrap_or_else(|err| err.into())\n+    }\n+\n+    /// Utility function to perform a write to an app's RX config buffer.\n+    /// (also a quick and dirty ctrl-c)\n+    #[inline]\n+    #[allow(dead_code)]\n+    fn do_with_rx_cfg_mut<F>(&self, appid: AppId, len: usize, closure: F) -> ReturnCode\n+    where\n+        F: FnOnce(&mut [u8]) -> ReturnCode,\n+    {\n+        self.apps\n+            .enter(appid, |app, _| {\n+                app.app_rx_cfg\n+                    .take()\n+                    .as_mut()\n+                    .map_or(ReturnCode::EINVAL, |cfg| {\n+                        if cfg.len() != len {\n+                            return ReturnCode::EINVAL;\n+                        }\n+                        closure(cfg.as_mut())\n+                    })\n+            })\n+            .unwrap_or_else(|err| err.into())\n+    }\n+\n+    /// If the driver is currently idle and there are pending transmissions,\n+    /// pick an app with a pending transmission and return its `AppId`.\n+    fn get_next_tx_if_idle(&self) -> Option<AppId> {\n+        if self.current_app.get().is_some() { // Tx already in progress\n+            return None;\n+        }\n+        let mut pending_app = None;\n+        for app in self.apps.iter() {","path":"capsules/src/net/udp/driver.rs","position":188,"original_position":186,"commit_id":"117261e5074f0623155efa90ae45328ef89b0f50","original_commit_id":"405fadcde79e5d44fde607f81e39cf248ece8c83","user":{"login":"hudson-ayers","id":32688905,"node_id":"MDQ6VXNlcjMyNjg4OTA1","avatar_url":"https://avatars0.githubusercontent.com/u/32688905?v=4","gravatar_id":"","url":"https://api.github.com/users/hudson-ayers","html_url":"https://github.com/hudson-ayers","followers_url":"https://api.github.com/users/hudson-ayers/followers","following_url":"https://api.github.com/users/hudson-ayers/following{/other_user}","gists_url":"https://api.github.com/users/hudson-ayers/gists{/gist_id}","starred_url":"https://api.github.com/users/hudson-ayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hudson-ayers/subscriptions","organizations_url":"https://api.github.com/users/hudson-ayers/orgs","repos_url":"https://api.github.com/users/hudson-ayers/repos","events_url":"https://api.github.com/users/hudson-ayers/events{/privacy}","received_events_url":"https://api.github.com/users/hudson-ayers/received_events","type":"User","site_admin":false},"body":"This is correct. I'll document it in the file and in the design doc.","created_at":"2018-08-02T00:53:32Z","updated_at":"2018-08-02T00:53:32Z","html_url":"https://github.com/tock/tock/pull/1134#discussion_r207074400","pull_request_url":"https://api.github.com/repos/tock/tock/pulls/1134","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/tock/tock/pulls/comments/207074400"},"html":{"href":"https://github.com/tock/tock/pull/1134#discussion_r207074400"},"pull_request":{"href":"https://api.github.com/repos/tock/tock/pulls/1134"}},"in_reply_to_id":207065715},"pull_request":{"url":"https://api.github.com/repos/tock/tock/pulls/1134","id":204005672,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA0MDA1Njcy","html_url":"https://github.com/tock/tock/pull/1134","diff_url":"https://github.com/tock/tock/pull/1134.diff","patch_url":"https://github.com/tock/tock/pull/1134.patch","issue_url":"https://api.github.com/repos/tock/tock/issues/1134","number":1134,"state":"open","locked":false,"title":"IP Userland","user":{"login":"hudson-ayers","id":32688905,"node_id":"MDQ6VXNlcjMyNjg4OTA1","avatar_url":"https://avatars0.githubusercontent.com/u/32688905?v=4","gravatar_id":"","url":"https://api.github.com/users/hudson-ayers","html_url":"https://github.com/hudson-ayers","followers_url":"https://api.github.com/users/hudson-ayers/followers","following_url":"https://api.github.com/users/hudson-ayers/following{/other_user}","gists_url":"https://api.github.com/users/hudson-ayers/gists{/gist_id}","starred_url":"https://api.github.com/users/hudson-ayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hudson-ayers/subscriptions","organizations_url":"https://api.github.com/users/hudson-ayers/orgs","repos_url":"https://api.github.com/users/hudson-ayers/repos","events_url":"https://api.github.com/users/hudson-ayers/events{/privacy}","received_events_url":"https://api.github.com/users/hudson-ayers/received_events","type":"User","site_admin":false},"body":"### Pull Request Overview\r\n\r\nThis pull request adds a userland interface to the IP stack. Specifically, it adds an interface via which\r\nuserspace applications can send and receive UDP packets. The heavy lifting of this PR is in the userspace driver that enables this, though it also inculdes changes throughout the networing stack that make it possible. This PR is paired with an example application -- IP_Sense -- for sending sensor data from userland using UDP. It is also paired with a udp_rx app that is intended to allow for receiving UDP packets (though this app is currently non-functional).  These two applications are included in a pull request to the tock/libtock-c repository.\r\n\r\n### Testing Strategy\r\n\r\nRunning the userland applications that utilize this interface and verifying that UDP packets are sent and between two boards as expectred. Because the udp_rx application is not yet functional, the ieee802154 radio_rx application was used to verify, as was a packet sniffer.\r\n\r\n### TODO or Help Wanted\r\n\r\n1. Updates to `imix/src/main.rs` so that the networking stack better utilizes the component interface\r\n\r\n2. Fix for the bug that prevents received UDP packets from reaching userspace\r\n\r\n3. Greatly improved management of the many addresses and settings that are required to allow for succesful use of the IP stack. A discussion of how this management currently occurs can be found in `doc/ip_config_notes.md` which is part of this PR, along with some of my personal thoughts on how this should change. However, I would greatly appreciate feedback on this topic in particular.\r\n\r\n4. Interface beyond just UDP - what about ICMP, or sending raw IP packets?\r\n\r\n5. More comprehensive tests that involve varied packet formats and simultaneous reception by multiple applications\r\n\r\n### Documentation Updated\r\n\r\n- [x] Adds Networking_Userland.md to docs, though this file will still need to be updated again once configuration aspects of the stack are finalized.\r\n\r\n- [x] Adds ip_config_notes.md to docs, which includes notes on configuration of the stack\r\n\r\n### Formatting\r\n\r\n- I am still having issues with my rustfmt version being too new, so I have not run formatall. I will do my best to fix issues if Travis identifies any.\r\n","created_at":"2018-07-26T01:33:22Z","updated_at":"2018-08-02T00:53:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8720bf5a78ce9f191c99f4d7abd41c3b16c314d6","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/tock/tock/pulls/1134/commits","review_comments_url":"https://api.github.com/repos/tock/tock/pulls/1134/comments","review_comment_url":"https://api.github.com/repos/tock/tock/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tock/tock/issues/1134/comments","statuses_url":"https://api.github.com/repos/tock/tock/statuses/117261e5074f0623155efa90ae45328ef89b0f50","head":{"label":"ptcrews:ip_userland","ref":"ip_userland","sha":"117261e5074f0623155efa90ae45328ef89b0f50","user":{"login":"ptcrews","id":19220100,"node_id":"MDQ6VXNlcjE5MjIwMTAw","avatar_url":"https://avatars1.githubusercontent.com/u/19220100?v=4","gravatar_id":"","url":"https://api.github.com/users/ptcrews","html_url":"https://github.com/ptcrews","followers_url":"https://api.github.com/users/ptcrews/followers","following_url":"https://api.github.com/users/ptcrews/following{/other_user}","gists_url":"https://api.github.com/users/ptcrews/gists{/gist_id}","starred_url":"https://api.github.com/users/ptcrews/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ptcrews/subscriptions","organizations_url":"https://api.github.com/users/ptcrews/orgs","repos_url":"https://api.github.com/users/ptcrews/repos","events_url":"https://api.github.com/users/ptcrews/events{/privacy}","received_events_url":"https://api.github.com/users/ptcrews/received_events","type":"User","site_admin":false},"repo":{"id":87756349,"node_id":"MDEwOlJlcG9zaXRvcnk4Nzc1NjM0OQ==","name":"tock","full_name":"ptcrews/tock","owner":{"login":"ptcrews","id":19220100,"node_id":"MDQ6VXNlcjE5MjIwMTAw","avatar_url":"https://avatars1.githubusercontent.com/u/19220100?v=4","gravatar_id":"","url":"https://api.github.com/users/ptcrews","html_url":"https://github.com/ptcrews","followers_url":"https://api.github.com/users/ptcrews/followers","following_url":"https://api.github.com/users/ptcrews/following{/other_user}","gists_url":"https://api.github.com/users/ptcrews/gists{/gist_id}","starred_url":"https://api.github.com/users/ptcrews/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ptcrews/subscriptions","organizations_url":"https://api.github.com/users/ptcrews/orgs","repos_url":"https://api.github.com/users/ptcrews/repos","events_url":"https://api.github.com/users/ptcrews/events{/privacy}","received_events_url":"https://api.github.com/users/ptcrews/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ptcrews/tock","description":"A secure embedded operating system for Cortex-M based microcontrollers","fork":true,"url":"https://api.github.com/repos/ptcrews/tock","forks_url":"https://api.github.com/repos/ptcrews/tock/forks","keys_url":"https://api.github.com/repos/ptcrews/tock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ptcrews/tock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ptcrews/tock/teams","hooks_url":"https://api.github.com/repos/ptcrews/tock/hooks","issue_events_url":"https://api.github.com/repos/ptcrews/tock/issues/events{/number}","events_url":"https://api.github.com/repos/ptcrews/tock/events","assignees_url":"https://api.github.com/repos/ptcrews/tock/assignees{/user}","branches_url":"https://api.github.com/repos/ptcrews/tock/branches{/branch}","tags_url":"https://api.github.com/repos/ptcrews/tock/tags","blobs_url":"https://api.github.com/repos/ptcrews/tock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ptcrews/tock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ptcrews/tock/git/refs{/sha}","trees_url":"https://api.github.com/repos/ptcrews/tock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ptcrews/tock/statuses/{sha}","languages_url":"https://api.github.com/repos/ptcrews/tock/languages","stargazers_url":"https://api.github.com/repos/ptcrews/tock/stargazers","contributors_url":"https://api.github.com/repos/ptcrews/tock/contributors","subscribers_url":"https://api.github.com/repos/ptcrews/tock/subscribers","subscription_url":"https://api.github.com/repos/ptcrews/tock/subscription","commits_url":"https://api.github.com/repos/ptcrews/tock/commits{/sha}","git_commits_url":"https://api.github.com/repos/ptcrews/tock/git/commits{/sha}","comments_url":"https://api.github.com/repos/ptcrews/tock/comments{/number}","issue_comment_url":"https://api.github.com/repos/ptcrews/tock/issues/comments{/number}","contents_url":"https://api.github.com/repos/ptcrews/tock/contents/{+path}","compare_url":"https://api.github.com/repos/ptcrews/tock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ptcrews/tock/merges","archive_url":"https://api.github.com/repos/ptcrews/tock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ptcrews/tock/downloads","issues_url":"https://api.github.com/repos/ptcrews/tock/issues{/number}","pulls_url":"https://api.github.com/repos/ptcrews/tock/pulls{/number}","milestones_url":"https://api.github.com/repos/ptcrews/tock/milestones{/number}","notifications_url":"https://api.github.com/repos/ptcrews/tock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ptcrews/tock/labels{/name}","releases_url":"https://api.github.com/repos/ptcrews/tock/releases{/id}","deployments_url":"https://api.github.com/repos/ptcrews/tock/deployments","created_at":"2017-04-10T02:12:09Z","updated_at":"2018-06-12T07:37:10Z","pushed_at":"2018-08-02T00:36:08Z","git_url":"git://github.com/ptcrews/tock.git","ssh_url":"git@github.com:ptcrews/tock.git","clone_url":"https://github.com/ptcrews/tock.git","svn_url":"https://github.com/ptcrews/tock","homepage":"https://www.tockos.org","size":135802,"stargazers_count":1,"watchers_count":1,"language":"Rust","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"tock:master","ref":"master","sha":"21060a7f34164c2726e1f08cc1730b54a477c922","user":{"login":"tock","id":34076064,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0MDc2MDY0","avatar_url":"https://avatars1.githubusercontent.com/u/34076064?v=4","gravatar_id":"","url":"https://api.github.com/users/tock","html_url":"https://github.com/tock","followers_url":"https://api.github.com/users/tock/followers","following_url":"https://api.github.com/users/tock/following{/other_user}","gists_url":"https://api.github.com/users/tock/gists{/gist_id}","starred_url":"https://api.github.com/users/tock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tock/subscriptions","organizations_url":"https://api.github.com/users/tock/orgs","repos_url":"https://api.github.com/users/tock/repos","events_url":"https://api.github.com/users/tock/events{/privacy}","received_events_url":"https://api.github.com/users/tock/received_events","type":"Organization","site_admin":false},"repo":{"id":36428094,"node_id":"MDEwOlJlcG9zaXRvcnkzNjQyODA5NA==","name":"tock","full_name":"tock/tock","owner":{"login":"tock","id":34076064,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0MDc2MDY0","avatar_url":"https://avatars1.githubusercontent.com/u/34076064?v=4","gravatar_id":"","url":"https://api.github.com/users/tock","html_url":"https://github.com/tock","followers_url":"https://api.github.com/users/tock/followers","following_url":"https://api.github.com/users/tock/following{/other_user}","gists_url":"https://api.github.com/users/tock/gists{/gist_id}","starred_url":"https://api.github.com/users/tock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tock/subscriptions","organizations_url":"https://api.github.com/users/tock/orgs","repos_url":"https://api.github.com/users/tock/repos","events_url":"https://api.github.com/users/tock/events{/privacy}","received_events_url":"https://api.github.com/users/tock/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tock/tock","description":"A secure embedded operating system for Cortex-M based microcontrollers","fork":false,"url":"https://api.github.com/repos/tock/tock","forks_url":"https://api.github.com/repos/tock/tock/forks","keys_url":"https://api.github.com/repos/tock/tock/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tock/tock/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tock/tock/teams","hooks_url":"https://api.github.com/repos/tock/tock/hooks","issue_events_url":"https://api.github.com/repos/tock/tock/issues/events{/number}","events_url":"https://api.github.com/repos/tock/tock/events","assignees_url":"https://api.github.com/repos/tock/tock/assignees{/user}","branches_url":"https://api.github.com/repos/tock/tock/branches{/branch}","tags_url":"https://api.github.com/repos/tock/tock/tags","blobs_url":"https://api.github.com/repos/tock/tock/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tock/tock/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tock/tock/git/refs{/sha}","trees_url":"https://api.github.com/repos/tock/tock/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tock/tock/statuses/{sha}","languages_url":"https://api.github.com/repos/tock/tock/languages","stargazers_url":"https://api.github.com/repos/tock/tock/stargazers","contributors_url":"https://api.github.com/repos/tock/tock/contributors","subscribers_url":"https://api.github.com/repos/tock/tock/subscribers","subscription_url":"https://api.github.com/repos/tock/tock/subscription","commits_url":"https://api.github.com/repos/tock/tock/commits{/sha}","git_commits_url":"https://api.github.com/repos/tock/tock/git/commits{/sha}","comments_url":"https://api.github.com/repos/tock/tock/comments{/number}","issue_comment_url":"https://api.github.com/repos/tock/tock/issues/comments{/number}","contents_url":"https://api.github.com/repos/tock/tock/contents/{+path}","compare_url":"https://api.github.com/repos/tock/tock/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tock/tock/merges","archive_url":"https://api.github.com/repos/tock/tock/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tock/tock/downloads","issues_url":"https://api.github.com/repos/tock/tock/issues{/number}","pulls_url":"https://api.github.com/repos/tock/tock/pulls{/number}","milestones_url":"https://api.github.com/repos/tock/tock/milestones{/number}","notifications_url":"https://api.github.com/repos/tock/tock/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tock/tock/labels{/name}","releases_url":"https://api.github.com/repos/tock/tock/releases{/id}","deployments_url":"https://api.github.com/repos/tock/tock/deployments","created_at":"2015-05-28T09:26:47Z","updated_at":"2018-08-01T21:15:44Z","pushed_at":"2018-08-02T00:36:09Z","git_url":"git://github.com/tock/tock.git","ssh_url":"git@github.com:tock/tock.git","clone_url":"https://github.com/tock/tock.git","svn_url":"https://github.com/tock/tock","homepage":"https://www.tockos.org","size":136182,"stargazers_count":953,"watchers_count":953,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":120,"mirror_url":null,"archived":false,"open_issues_count":65,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":120,"open_issues":65,"watchers":953,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tock/tock/pulls/1134"},"html":{"href":"https://github.com/tock/tock/pull/1134"},"issue":{"href":"https://api.github.com/repos/tock/tock/issues/1134"},"comments":{"href":"https://api.github.com/repos/tock/tock/issues/1134/comments"},"review_comments":{"href":"https://api.github.com/repos/tock/tock/pulls/1134/comments"},"review_comment":{"href":"https://api.github.com/repos/tock/tock/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tock/tock/pulls/1134/commits"},"statuses":{"href":"https://api.github.com/repos/tock/tock/statuses/117261e5074f0623155efa90ae45328ef89b0f50"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"hudson-ayers"}}