{"action":"created","comment":{"url":"https://api.github.com/repos/eclipse/californium/pulls/comments/69744968","id":69744968,"diff_hunk":"@@ -0,0 +1,170 @@\n+/*******************************************************************************\n+ * Copyright (c) 2016 Amazon Web Services.\n+ *\n+ * All rights reserved. This program and the accompanying materials\n+ * are made available under the terms of the Eclipse Public License v1.0\n+ * and Eclipse Distribution License v1.0 which accompany this distribution.\n+ *\n+ * The Eclipse Public License is available at\n+ *    http://www.eclipse.org/legal/epl-v10.html\n+ * and the Eclipse Distribution License is available at\n+ *    http://www.eclipse.org/org/documents/edl-v10.html.\n+ *\n+ * Contributors:\n+ *    Joe Magerramov (Amazon Web Services) - CoAP over TCP support.\n+ ******************************************************************************/\n+package org.eclipse.californium.elements.tcp;\n+\n+import io.netty.bootstrap.ServerBootstrap;\n+import io.netty.buffer.Unpooled;\n+import io.netty.channel.Channel;\n+import io.netty.channel.ChannelHandlerContext;\n+import io.netty.channel.ChannelInboundHandlerAdapter;\n+import io.netty.channel.ChannelInitializer;\n+import io.netty.channel.ChannelOption;\n+import io.netty.channel.EventLoopGroup;\n+import io.netty.channel.nio.NioEventLoopGroup;\n+import io.netty.channel.socket.SocketChannel;\n+import io.netty.channel.socket.nio.NioServerSocketChannel;\n+import io.netty.handler.timeout.IdleStateHandler;\n+import org.eclipse.californium.elements.Connector;\n+import org.eclipse.californium.elements.RawData;\n+import org.eclipse.californium.elements.RawDataChannel;\n+\n+import java.io.IOException;\n+import java.net.InetSocketAddress;\n+import java.net.SocketAddress;\n+import java.util.concurrent.ConcurrentHashMap;\n+import java.util.concurrent.ConcurrentMap;\n+import java.util.concurrent.TimeUnit;\n+import java.util.logging.Level;\n+import java.util.logging.Logger;\n+\n+/**\n+ * TCP server connection is used by CoapEndpoint when instantiated by the CoapServer. Per RFC the server can both\n+ * send and receive messages, but cannot initiated new outgoing connections.\n+ */\n+public class TcpServerConnector implements Connector {\n+\n+    private final static Logger LOGGER = Logger.getLogger(TcpServerConnector.class.getName());\n+\n+    private final int numberOfThreads;\n+    private final InetSocketAddress localAddress;\n+    private final int connectionIdleTimeoutSeconds;\n+    private final ConcurrentMap<SocketAddress, Channel> activeChannels = new ConcurrentHashMap<>();\n+\n+    private RawDataChannel rawDataChannel;\n+    private EventLoopGroup bossGroup;\n+    private EventLoopGroup workerGroup;\n+\n+    public TcpServerConnector(InetSocketAddress localAddress, int idleTimeout, int numberOfThreads) {\n+        this.numberOfThreads = numberOfThreads;\n+        this.connectionIdleTimeoutSeconds = idleTimeout;\n+        this.localAddress = localAddress;\n+    }\n+\n+    @Override\n+    public void start() throws IOException {\n+        if (rawDataChannel == null) {\n+            throw new IllegalStateException(\"Cannot start without message handler.\");\n+        }\n+        if (bossGroup != null) {\n+            throw new IllegalStateException(\"Connector already started\");\n+        }\n+        if (workerGroup != null) {\n+            throw new IllegalStateException(\"Connector already started\");\n+        }\n+\n+        bossGroup = new NioEventLoopGroup(1);\n+        workerGroup = new NioEventLoopGroup(numberOfThreads);\n+\n+        ServerBootstrap bootstrap = new ServerBootstrap();\n+        bootstrap.group(bossGroup, workerGroup)\n+                .channel(NioServerSocketChannel.class)\n+                .option(ChannelOption.SO_BACKLOG, 100)\n+                .option(ChannelOption.SO_KEEPALIVE, true)\n+                .option(ChannelOption.AUTO_READ, true)\n+                .childHandler(new ChannelRegistry());\n+\n+        // Start the server.\n+        bootstrap.bind(localAddress).syncUninterruptibly();\n+    }\n+\n+    @Override\n+    public void stop() {\n+        bossGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS).syncUninterruptibly();\n+        workerGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS).syncUninterruptibly();\n+\n+        workerGroup = null;\n+        bossGroup = null;\n+    }\n+\n+    @Override\n+    public void destroy() {\n+        stop();\n+    }\n+\n+    @Override\n+    public void send(RawData msg) {\n+        Channel channel = activeChannels.get(msg.getInetSocketAddress());\n+        if (channel == null) {\n+            // TODO: Is it worth allowing opening a new connection when in server mode?\n+            LOGGER.log(Level.WARNING,\n+                    \"Attempting to send message to an address without an active connection {0}\", msg.getAddress());\n+            return;\n+        }\n+\n+        channel.writeAndFlush(Unpooled.wrappedBuffer(msg.getBytes()));\n+    }\n+\n+    @Override\n+    public void setRawDataReceiver(RawDataChannel messageHandler) {\n+        if (rawDataChannel != null) {\n+            throw new IllegalStateException(\"RawDataChannel alrady set\");","path":"element-connector/src/main/java/org/eclipse/californium/elements/tcp/TcpServerConnector.java","position":123,"original_position":123,"commit_id":"1d2bcb1bb87aea879b94df8d19007bf0f6622454","original_commit_id":"1d2bcb1bb87aea879b94df8d19007bf0f6622454","user":{"login":"sophokles73","id":5682135,"avatar_url":"https://avatars.githubusercontent.com/u/5682135?v=3","gravatar_id":"","url":"https://api.github.com/users/sophokles73","html_url":"https://github.com/sophokles73","followers_url":"https://api.github.com/users/sophokles73/followers","following_url":"https://api.github.com/users/sophokles73/following{/other_user}","gists_url":"https://api.github.com/users/sophokles73/gists{/gist_id}","starred_url":"https://api.github.com/users/sophokles73/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sophokles73/subscriptions","organizations_url":"https://api.github.com/users/sophokles73/orgs","repos_url":"https://api.github.com/users/sophokles73/repos","events_url":"https://api.github.com/users/sophokles73/events{/privacy}","received_events_url":"https://api.github.com/users/sophokles73/received_events","type":"User","site_admin":false},"body":"see above","created_at":"2016-07-06T14:49:04Z","updated_at":"2016-07-06T14:49:04Z","html_url":"https://github.com/eclipse/californium/pull/66#discussion_r69744968","pull_request_url":"https://api.github.com/repos/eclipse/californium/pulls/66","_links":{"self":{"href":"https://api.github.com/repos/eclipse/californium/pulls/comments/69744968"},"html":{"href":"https://github.com/eclipse/californium/pull/66#discussion_r69744968"},"pull_request":{"href":"https://api.github.com/repos/eclipse/californium/pulls/66"}}},"pull_request":{"url":"https://api.github.com/repos/eclipse/californium/pulls/66","id":76356403,"html_url":"https://github.com/eclipse/californium/pull/66","diff_url":"https://github.com/eclipse/californium/pull/66.diff","patch_url":"https://github.com/eclipse/californium/pull/66.patch","issue_url":"https://api.github.com/repos/eclipse/californium/issues/66","number":66,"state":"open","locked":false,"title":"Implementation of TCP connector for Californium per CoAP over TCP RFC.","user":{"login":"joemag1","id":16496690,"avatar_url":"https://avatars.githubusercontent.com/u/16496690?v=3","gravatar_id":"","url":"https://api.github.com/users/joemag1","html_url":"https://github.com/joemag1","followers_url":"https://api.github.com/users/joemag1/followers","following_url":"https://api.github.com/users/joemag1/following{/other_user}","gists_url":"https://api.github.com/users/joemag1/gists{/gist_id}","starred_url":"https://api.github.com/users/joemag1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joemag1/subscriptions","organizations_url":"https://api.github.com/users/joemag1/orgs","repos_url":"https://api.github.com/users/joemag1/repos","events_url":"https://api.github.com/users/joemag1/events{/privacy}","received_events_url":"https://api.github.com/users/joemag1/received_events","type":"User","site_admin":false},"body":"    Uses Netty 4.1 for non-blocking IO. Implementation splits into Server and Client TCP connector, with expectation that the client connector does not listen on a port. Still todo:\r\n\r\n    1) Add TLS support to both client and server connector.\r\n    2) Add call back from the TcpConnector when a connection is lost (per RFC all exchanges with that remote endpoint must be closed)\r\n    3) Add ability for TcpServerConnector to open outbound connections. This is desireable when application is reusing the same endpoint between CoapClient and CoapServer\r\n\r\nSigned-off-by: Joe Magerramov <joemag@amazon.com>","created_at":"2016-07-05T23:00:24Z","updated_at":"2016-07-06T14:49:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b8bc554481ee581202d3e5c361721d7689a22c91","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/eclipse/californium/pulls/66/commits","review_comments_url":"https://api.github.com/repos/eclipse/californium/pulls/66/comments","review_comment_url":"https://api.github.com/repos/eclipse/californium/pulls/comments{/number}","comments_url":"https://api.github.com/repos/eclipse/californium/issues/66/comments","statuses_url":"https://api.github.com/repos/eclipse/californium/statuses/1d2bcb1bb87aea879b94df8d19007bf0f6622454","head":{"label":"joemag1:tcp-connector","ref":"tcp-connector","sha":"1d2bcb1bb87aea879b94df8d19007bf0f6622454","user":{"login":"joemag1","id":16496690,"avatar_url":"https://avatars.githubusercontent.com/u/16496690?v=3","gravatar_id":"","url":"https://api.github.com/users/joemag1","html_url":"https://github.com/joemag1","followers_url":"https://api.github.com/users/joemag1/followers","following_url":"https://api.github.com/users/joemag1/following{/other_user}","gists_url":"https://api.github.com/users/joemag1/gists{/gist_id}","starred_url":"https://api.github.com/users/joemag1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joemag1/subscriptions","organizations_url":"https://api.github.com/users/joemag1/orgs","repos_url":"https://api.github.com/users/joemag1/repos","events_url":"https://api.github.com/users/joemag1/events{/privacy}","received_events_url":"https://api.github.com/users/joemag1/received_events","type":"User","site_admin":false},"repo":{"id":61489054,"name":"californium","full_name":"joemag1/californium","owner":{"login":"joemag1","id":16496690,"avatar_url":"https://avatars.githubusercontent.com/u/16496690?v=3","gravatar_id":"","url":"https://api.github.com/users/joemag1","html_url":"https://github.com/joemag1","followers_url":"https://api.github.com/users/joemag1/followers","following_url":"https://api.github.com/users/joemag1/following{/other_user}","gists_url":"https://api.github.com/users/joemag1/gists{/gist_id}","starred_url":"https://api.github.com/users/joemag1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joemag1/subscriptions","organizations_url":"https://api.github.com/users/joemag1/orgs","repos_url":"https://api.github.com/users/joemag1/repos","events_url":"https://api.github.com/users/joemag1/events{/privacy}","received_events_url":"https://api.github.com/users/joemag1/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/joemag1/californium","description":"","fork":true,"url":"https://api.github.com/repos/joemag1/californium","forks_url":"https://api.github.com/repos/joemag1/californium/forks","keys_url":"https://api.github.com/repos/joemag1/californium/keys{/key_id}","collaborators_url":"https://api.github.com/repos/joemag1/californium/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/joemag1/californium/teams","hooks_url":"https://api.github.com/repos/joemag1/californium/hooks","issue_events_url":"https://api.github.com/repos/joemag1/californium/issues/events{/number}","events_url":"https://api.github.com/repos/joemag1/californium/events","assignees_url":"https://api.github.com/repos/joemag1/californium/assignees{/user}","branches_url":"https://api.github.com/repos/joemag1/californium/branches{/branch}","tags_url":"https://api.github.com/repos/joemag1/californium/tags","blobs_url":"https://api.github.com/repos/joemag1/californium/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/joemag1/californium/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/joemag1/californium/git/refs{/sha}","trees_url":"https://api.github.com/repos/joemag1/californium/git/trees{/sha}","statuses_url":"https://api.github.com/repos/joemag1/californium/statuses/{sha}","languages_url":"https://api.github.com/repos/joemag1/californium/languages","stargazers_url":"https://api.github.com/repos/joemag1/californium/stargazers","contributors_url":"https://api.github.com/repos/joemag1/californium/contributors","subscribers_url":"https://api.github.com/repos/joemag1/californium/subscribers","subscription_url":"https://api.github.com/repos/joemag1/californium/subscription","commits_url":"https://api.github.com/repos/joemag1/californium/commits{/sha}","git_commits_url":"https://api.github.com/repos/joemag1/californium/git/commits{/sha}","comments_url":"https://api.github.com/repos/joemag1/californium/comments{/number}","issue_comment_url":"https://api.github.com/repos/joemag1/californium/issues/comments{/number}","contents_url":"https://api.github.com/repos/joemag1/californium/contents/{+path}","compare_url":"https://api.github.com/repos/joemag1/californium/compare/{base}...{head}","merges_url":"https://api.github.com/repos/joemag1/californium/merges","archive_url":"https://api.github.com/repos/joemag1/californium/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/joemag1/californium/downloads","issues_url":"https://api.github.com/repos/joemag1/californium/issues{/number}","pulls_url":"https://api.github.com/repos/joemag1/californium/pulls{/number}","milestones_url":"https://api.github.com/repos/joemag1/californium/milestones{/number}","notifications_url":"https://api.github.com/repos/joemag1/californium/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/joemag1/californium/labels{/name}","releases_url":"https://api.github.com/repos/joemag1/californium/releases{/id}","deployments_url":"https://api.github.com/repos/joemag1/californium/deployments","created_at":"2016-06-19T16:21:57Z","updated_at":"2016-06-19T16:22:00Z","pushed_at":"2016-07-05T23:14:51Z","git_url":"git://github.com/joemag1/californium.git","ssh_url":"git@github.com:joemag1/californium.git","clone_url":"https://github.com/joemag1/californium.git","svn_url":"https://github.com/joemag1/californium","homepage":null,"size":3103,"stargazers_count":0,"watchers_count":0,"language":"Java","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":"eclipse:master","ref":"master","sha":"ff60025f4db12298be9efb27d164423e947f07bf","user":{"login":"eclipse","id":56974,"avatar_url":"https://avatars.githubusercontent.com/u/56974?v=3","gravatar_id":"","url":"https://api.github.com/users/eclipse","html_url":"https://github.com/eclipse","followers_url":"https://api.github.com/users/eclipse/followers","following_url":"https://api.github.com/users/eclipse/following{/other_user}","gists_url":"https://api.github.com/users/eclipse/gists{/gist_id}","starred_url":"https://api.github.com/users/eclipse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eclipse/subscriptions","organizations_url":"https://api.github.com/users/eclipse/orgs","repos_url":"https://api.github.com/users/eclipse/repos","events_url":"https://api.github.com/users/eclipse/events{/privacy}","received_events_url":"https://api.github.com/users/eclipse/received_events","type":"Organization","site_admin":false},"repo":{"id":43075480,"name":"californium","full_name":"eclipse/californium","owner":{"login":"eclipse","id":56974,"avatar_url":"https://avatars.githubusercontent.com/u/56974?v=3","gravatar_id":"","url":"https://api.github.com/users/eclipse","html_url":"https://github.com/eclipse","followers_url":"https://api.github.com/users/eclipse/followers","following_url":"https://api.github.com/users/eclipse/following{/other_user}","gists_url":"https://api.github.com/users/eclipse/gists{/gist_id}","starred_url":"https://api.github.com/users/eclipse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eclipse/subscriptions","organizations_url":"https://api.github.com/users/eclipse/orgs","repos_url":"https://api.github.com/users/eclipse/repos","events_url":"https://api.github.com/users/eclipse/events{/privacy}","received_events_url":"https://api.github.com/users/eclipse/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/eclipse/californium","description":"","fork":false,"url":"https://api.github.com/repos/eclipse/californium","forks_url":"https://api.github.com/repos/eclipse/californium/forks","keys_url":"https://api.github.com/repos/eclipse/californium/keys{/key_id}","collaborators_url":"https://api.github.com/repos/eclipse/californium/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/eclipse/californium/teams","hooks_url":"https://api.github.com/repos/eclipse/californium/hooks","issue_events_url":"https://api.github.com/repos/eclipse/californium/issues/events{/number}","events_url":"https://api.github.com/repos/eclipse/californium/events","assignees_url":"https://api.github.com/repos/eclipse/californium/assignees{/user}","branches_url":"https://api.github.com/repos/eclipse/californium/branches{/branch}","tags_url":"https://api.github.com/repos/eclipse/californium/tags","blobs_url":"https://api.github.com/repos/eclipse/californium/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/eclipse/californium/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/eclipse/californium/git/refs{/sha}","trees_url":"https://api.github.com/repos/eclipse/californium/git/trees{/sha}","statuses_url":"https://api.github.com/repos/eclipse/californium/statuses/{sha}","languages_url":"https://api.github.com/repos/eclipse/californium/languages","stargazers_url":"https://api.github.com/repos/eclipse/californium/stargazers","contributors_url":"https://api.github.com/repos/eclipse/californium/contributors","subscribers_url":"https://api.github.com/repos/eclipse/californium/subscribers","subscription_url":"https://api.github.com/repos/eclipse/californium/subscription","commits_url":"https://api.github.com/repos/eclipse/californium/commits{/sha}","git_commits_url":"https://api.github.com/repos/eclipse/californium/git/commits{/sha}","comments_url":"https://api.github.com/repos/eclipse/californium/comments{/number}","issue_comment_url":"https://api.github.com/repos/eclipse/californium/issues/comments{/number}","contents_url":"https://api.github.com/repos/eclipse/californium/contents/{+path}","compare_url":"https://api.github.com/repos/eclipse/californium/compare/{base}...{head}","merges_url":"https://api.github.com/repos/eclipse/californium/merges","archive_url":"https://api.github.com/repos/eclipse/californium/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/eclipse/californium/downloads","issues_url":"https://api.github.com/repos/eclipse/californium/issues{/number}","pulls_url":"https://api.github.com/repos/eclipse/californium/pulls{/number}","milestones_url":"https://api.github.com/repos/eclipse/californium/milestones{/number}","notifications_url":"https://api.github.com/repos/eclipse/californium/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/eclipse/californium/labels{/name}","releases_url":"https://api.github.com/repos/eclipse/californium/releases{/id}","deployments_url":"https://api.github.com/repos/eclipse/californium/deployments","created_at":"2015-09-24T15:27:15Z","updated_at":"2016-07-06T10:48:14Z","pushed_at":"2016-07-05T23:14:19Z","git_url":"git://github.com/eclipse/californium.git","ssh_url":"git@github.com:eclipse/californium.git","clone_url":"https://github.com/eclipse/californium.git","svn_url":"https://github.com/eclipse/californium","homepage":null,"size":3545,"stargazers_count":51,"watchers_count":51,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":47,"mirror_url":null,"open_issues_count":21,"forks":47,"open_issues":21,"watchers":51,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/eclipse/californium/pulls/66"},"html":{"href":"https://github.com/eclipse/californium/pull/66"},"issue":{"href":"https://api.github.com/repos/eclipse/californium/issues/66"},"comments":{"href":"https://api.github.com/repos/eclipse/californium/issues/66/comments"},"review_comments":{"href":"https://api.github.com/repos/eclipse/californium/pulls/66/comments"},"review_comment":{"href":"https://api.github.com/repos/eclipse/californium/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/eclipse/californium/pulls/66/commits"},"statuses":{"href":"https://api.github.com/repos/eclipse/californium/statuses/1d2bcb1bb87aea879b94df8d19007bf0f6622454"}}}}
{"actor":{"display_login":"sophokles73"}}