created proxy and listeners to connect recorder and server-client cross writing

This commit is contained in:
amit bezalel 2017-07-09 09:51:17 +03:00
parent d40b7670d5
commit 86938a8d76
18 changed files with 1224 additions and 950 deletions

View File

@ -2,12 +2,19 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="a5d84862-9821-4d30-9a77-6235b55d6727" name="Default" comment=""> <list default="true" id="a5d84862-9821-4d30-9a77-6235b55d6727" name="Default" comment="">
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/misc.xml" afterPath="$PROJECT_DIR$/.idea/misc.xml" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/debug.test" afterPath="$PROJECT_DIR$/server/debug.test" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/client/client-conn.go" afterPath="$PROJECT_DIR$/client/client-conn.go" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/client/client-conn.go" afterPath="$PROJECT_DIR$/client/client-conn.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/client/client_auth.go" afterPath="$PROJECT_DIR$/client/client_auth.go" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/common/client-message.go" afterPath="$PROJECT_DIR$/common/client-message.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/encodings/enc-tight.go" afterPath="$PROJECT_DIR$/encodings/enc-tight.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/main.go" afterPath="$PROJECT_DIR$/main.go" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/main.go" afterPath="$PROJECT_DIR$/main.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/client-messages.go" afterPath="$PROJECT_DIR$/server/client-messages.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/handlers.go" afterPath="$PROJECT_DIR$/server/handlers.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/security.go" afterPath="$PROJECT_DIR$/server/security.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/server-conn.go" afterPath="$PROJECT_DIR$/server/server-conn.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/server.go" afterPath="$PROJECT_DIR$/server/server.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/server_test.go" afterPath="$PROJECT_DIR$/server/server_test.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/server/ws-server-go.go" afterPath="$PROJECT_DIR$/server/ws-server-go.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/tee-listeners/recorder.go" afterPath="$PROJECT_DIR$/tee-listeners/recorder.go" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/tee-listeners/write-to.go" afterPath="$PROJECT_DIR$/tee-listeners/write-to.go" />
</list> </list>
<ignored path="$PROJECT_DIR$/out/" /> <ignored path="$PROJECT_DIR$/out/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
@ -38,107 +45,11 @@
</component> </component>
<component name="FileEditorManager"> <component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="color.go" pinned="false" current-in-tab="false"> <file leaf-file-name="client-message.go" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/client/color.go"> <entry file="file://$PROJECT_DIR$/common/client-message.go">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0"> <state relative-caret-position="243">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> <caret line="36" column="26" lean-forward="true" selection-start-line="36" selection-start-column="26" selection-end-line="36" selection-end-column="26" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="server-conn.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/server/server-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15">
<caret line="51" column="4" lean-forward="false" selection-start-line="51" selection-start-column="4" selection-end-line="51" selection-end-column="4" />
<folding>
<element signature="e#16#59#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="server.go" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/server/server.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="readers.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/common/readers.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="27" column="5" lean-forward="false" selection-start-line="27" selection-start-column="5" selection-end-line="27" selection-end-column="5" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="main.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="122">
<caret line="21" column="0" lean-forward="false" selection-start-line="21" selection-start-column="0" selection-end-line="21" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="client_auth.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/client/client_auth.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="285">
<caret line="19" column="31" lean-forward="false" selection-start-line="19" selection-start-column="31" selection-end-line="19" selection-end-column="31" />
<folding>
<element signature="e#16#65#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="enc-corre.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/encodings/enc-corre.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="12" column="1" lean-forward="false" selection-start-line="12" selection-start-column="1" selection-end-line="12" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="client_test.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/client/client_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="10" column="19" lean-forward="true" selection-start-line="10" selection-start-column="19" selection-end-line="10" selection-end-column="19" />
<folding>
<element signature="e#16#51#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="client-conn.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/client/client-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="27" column="27" lean-forward="true" selection-start-line="27" selection-start-column="27" selection-end-line="27" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="security.go" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/server/security.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding /> <folding />
</state> </state>
</provider> </provider>
@ -210,11 +121,12 @@
<option value="$PROJECT_DIR$/server/security.go" /> <option value="$PROJECT_DIR$/server/security.go" />
<option value="$PROJECT_DIR$/server/server_test.go" /> <option value="$PROJECT_DIR$/server/server_test.go" />
<option value="$PROJECT_DIR$/server/ws-server-go.go" /> <option value="$PROJECT_DIR$/server/ws-server-go.go" />
<option value="$PROJECT_DIR$/server/server.go" />
<option value="$PROJECT_DIR$/encodings/enc-tight.go" /> <option value="$PROJECT_DIR$/encodings/enc-tight.go" />
<option value="$PROJECT_DIR$/main.go" /> <option value="$PROJECT_DIR$/main.go" />
<option value="$PROJECT_DIR$/client/client_auth.go" /> <option value="$PROJECT_DIR$/client/client_auth.go" />
<option value="$PROJECT_DIR$/client/client-conn.go" /> <option value="$PROJECT_DIR$/client/client-conn.go" />
<option value="$PROJECT_DIR$/server/server.go" />
<option value="$PROJECT_DIR$/common/client-message.go" />
</list> </list>
</option> </option>
</component> </component>
@ -284,58 +196,37 @@
<foldersAlwaysOnTop value="true" /> <foldersAlwaysOnTop value="true" />
</navigator> </navigator>
<panes> <panes>
<pane id="Scope">
<subPane subId="Project Files">
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
<PATH_ELEMENT USER_OBJECT="vncproxy">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
<PATH_ELEMENT USER_OBJECT="vncproxy">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
<PATH_ELEMENT USER_OBJECT="client">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="Scratches" />
<pane id="ProjectPane"> <pane id="ProjectPane">
<subPane> <subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="External Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ExternalLibrariesNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="External Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ExternalLibrariesNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Go SDK 1.8.3" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.SyntheticLibraryElementNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="External Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ExternalLibrariesNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Go SDK 1.8.3" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.SyntheticLibraryElementNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="net" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH> <PATH>
<PATH_ELEMENT> <PATH_ELEMENT>
<option name="myItemId" value="vncproxy" /> <option name="myItemId" value="vncproxy" />
@ -360,20 +251,6 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT> </PATH_ELEMENT>
</PATH> </PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="encodings" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH> <PATH>
<PATH_ELEMENT> <PATH_ELEMENT>
<option name="myItemId" value="vncproxy" /> <option name="myItemId" value="vncproxy" />
@ -388,52 +265,9 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT> </PATH_ELEMENT>
</PATH> </PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="vncproxy" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="client" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="Scope">
<subPane subId="Project Files">
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
<PATH_ELEMENT USER_OBJECT="vncproxy">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
<PATH_ELEMENT USER_OBJECT="vncproxy">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
<PATH_ELEMENT USER_OBJECT="client">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
</subPane> </subPane>
</pane> </pane>
<pane id="PackagesPane" /> <pane id="PackagesPane" />
<pane id="Scratches" />
</panes> </panes>
</component> </component>
<component name="PropertiesComponent"> <component name="PropertiesComponent">
@ -933,6 +767,7 @@
<workItem from="1498938338650" duration="581000" /> <workItem from="1498938338650" duration="581000" />
<workItem from="1499416638508" duration="21000" /> <workItem from="1499416638508" duration="21000" />
<workItem from="1499416701375" duration="1802000" /> <workItem from="1499416701375" duration="1802000" />
<workItem from="1499522471716" duration="431000" />
</task> </task>
<servers /> <servers />
</component> </component>
@ -969,7 +804,7 @@
</history-entry> </history-entry>
</component> </component>
<component name="TimeTrackingManager"> <component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="33981000" /> <option name="totallyTimeSpent" value="34412000" />
</component> </component>
<component name="TodoView"> <component name="TodoView">
<todo-panel id="selected-file"> <todo-panel id="selected-file">
@ -982,37 +817,38 @@
</component> </component>
<component name="ToolWindowManager"> <component name="ToolWindowManager">
<frame x="0" y="0" width="1280" height="800" extended-state="0" /> <frame x="0" y="0" width="1280" height="800" extended-state="0" />
<editor active="true" />
<layout> <layout>
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Nl-Palette" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.115068495" sideWeight="0.5323102" order="8" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32956383" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32956383" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3029079" sideWeight="0.48367348" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.24959612" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33972603" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.49030694" order="7" side_tool="false" content_ui="tabs" /> <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.49030694" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" /> <window_info id="Nl-Palette" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Palette&#9;" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Palette&#9;" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" /> <window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.30136988" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.39863014" sideWeight="0.509693" order="8" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32956383" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.4676898" order="10" side_tool="false" content_ui="tabs" /> <window_info id="Version Control" active="false" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.4676898" order="10" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.30136988" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.49030694" order="11" side_tool="false" content_ui="tabs" /> <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32876712" sideWeight="0.49030694" order="11" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="true" anchor="left" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2714055" sideWeight="0.6718266" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Problems" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.21506849" sideWeight="0.49676898" order="0" side_tool="false" content_ui="tabs" /> <window_info id="Problems" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.21506849" sideWeight="0.49676898" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32981783" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.19547658" sideWeight="0.6718266" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32956383" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.39863014" sideWeight="0.49030694" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3029079" sideWeight="0.48367348" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.24959612" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2714055" sideWeight="0.32817337" order="5" side_tool="true" content_ui="tabs" /> <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.2714055" sideWeight="0.32817337" order="5" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33972603" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" /> <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" /> <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" /> <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Dynamic Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Dynamic Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" /> <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Coverage" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" /> <window_info id="Coverage" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
</layout> </layout>
@ -1054,68 +890,33 @@
<breakpoints> <breakpoints>
<line-breakpoint type="DlvLineBreakpoint"> <line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/main.go</url> <url>file://$PROJECT_DIR$/main.go</url>
<line>12</line> <line>13</line>
</line-breakpoint> </line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint"> <line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/main.go</url> <url>file://$PROJECT_DIR$/main.go</url>
<line>15</line> <line>16</line>
<option name="timeStamp" value="1" /> <option name="timeStamp" value="1" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint"> <line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/main.go</url> <url>file://$PROJECT_DIR$/main.go</url>
<line>19</line> <line>20</line>
<option name="timeStamp" value="2" /> <option name="timeStamp" value="2" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint"> <line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server_test.go</url> <url>file://$PROJECT_DIR$/server/server_test.go</url>
<line>30</line> <line>35</line>
<option name="timeStamp" value="5" /> <option name="timeStamp" value="5" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint"> <line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server_test.go</url> <url>file://$PROJECT_DIR$/server/server_test.go</url>
<line>31</line> <line>36</line>
<option name="timeStamp" value="6" /> <option name="timeStamp" value="6" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>222</line>
<option name="timeStamp" value="8" />
</line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>226</line>
<option name="timeStamp" value="9" />
</line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint"> <line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/common/encoding.go</url> <url>file://$PROJECT_DIR$/common/encoding.go</url>
<line>162</line> <line>162</line>
<option name="timeStamp" value="31" /> <option name="timeStamp" value="31" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>169</line>
<option name="timeStamp" value="32" />
</line-breakpoint>
<line-breakpoint type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>202</line>
<option name="timeStamp" value="44" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>200</line>
<option name="timeStamp" value="45" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>213</line>
<option name="timeStamp" value="46" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>173</line>
<option name="timeStamp" value="52" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/ws-server-gorilla.go</url> <url>file://$PROJECT_DIR$/server/ws-server-gorilla.go</url>
<line>98</line> <line>98</line>
@ -1128,12 +929,12 @@
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/ws-server-go.go</url> <url>file://$PROJECT_DIR$/server/ws-server-go.go</url>
<line>35</line> <line>43</line>
<option name="timeStamp" value="62" /> <option name="timeStamp" value="62" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/ws-server-go.go</url> <url>file://$PROJECT_DIR$/server/ws-server-go.go</url>
<line>23</line> <line>31</line>
<option name="timeStamp" value="63" /> <option name="timeStamp" value="63" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
@ -1141,54 +942,24 @@
<line>113</line> <line>113</line>
<option name="timeStamp" value="64" /> <option name="timeStamp" value="64" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>207</line>
<option name="timeStamp" value="67" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>205</line>
<option name="timeStamp" value="68" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>185</line>
<option name="timeStamp" value="69" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>190</line>
<option name="timeStamp" value="70" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>209</line>
<option name="timeStamp" value="71" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/server/server.go</url>
<line>211</line>
<option name="timeStamp" value="73" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/tee-listeners/recorder.go</url> <url>file://$PROJECT_DIR$/tee-listeners/recorder.go</url>
<line>115</line> <line>171</line>
<option name="timeStamp" value="77" /> <option name="timeStamp" value="77" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/tee-listeners/recorder.go</url> <url>file://$PROJECT_DIR$/tee-listeners/recorder.go</url>
<line>22</line> <line>26</line>
<option name="timeStamp" value="78" /> <option name="timeStamp" value="78" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/client/client-conn.go</url> <url>file://$PROJECT_DIR$/client/client-conn.go</url>
<line>450</line> <line>467</line>
<option name="timeStamp" value="79" /> <option name="timeStamp" value="79" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint"> <line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/tee-listeners/recorder.go</url> <url>file://$PROJECT_DIR$/tee-listeners/recorder.go</url>
<line>27</line> <line>31</line>
<option name="timeStamp" value="80" /> <option name="timeStamp" value="80" />
</line-breakpoint> </line-breakpoint>
</breakpoints> </breakpoints>
@ -1214,104 +985,6 @@
<option name="FILTER_TARGETS" value="false" /> <option name="FILTER_TARGETS" value="false" />
</component> </component>
<component name="editorHistoryManager"> <component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/encodings/enc-corre.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="12" column="1" lean-forward="false" selection-start-line="12" selection-start-column="1" selection-end-line="12" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/client-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="6750">
<caret line="450" column="0" lean-forward="false" selection-start-line="450" selection-start-column="0" selection-end-line="450" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/server/server-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="765">
<caret line="51" column="4" lean-forward="false" selection-start-line="51" selection-start-column="4" selection-end-line="51" selection-end-column="4" />
<folding>
<element signature="e#16#59#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/server-messages.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="900">
<caret line="60" column="30" lean-forward="false" selection-start-line="60" selection-start-column="30" selection-end-line="60" selection-end-column="30" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tee-listeners/recorder.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="21" column="27" lean-forward="true" selection-start-line="21" selection-start-column="27" selection-end-line="21" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/common/readers.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="27" column="5" lean-forward="false" selection-start-line="27" selection-start-column="5" selection-end-line="27" selection-end-column="5" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="28" column="10" lean-forward="true" selection-start-line="28" selection-start-column="10" selection-end-line="28" selection-end-column="10" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/server-messages.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="795">
<caret line="60" column="30" lean-forward="false" selection-start-line="60" selection-start-column="30" selection-end-line="60" selection-end-column="30" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tee-listeners/recorder.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="21" column="27" lean-forward="false" selection-start-line="21" selection-start-column="27" selection-end-line="21" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/common/readers.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="27" column="5" lean-forward="false" selection-start-line="27" selection-start-column="5" selection-end-line="27" selection-end-column="5" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="122">
<caret line="21" column="0" lean-forward="false" selection-start-line="21" selection-start-column="0" selection-end-line="21" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file:///usr/local/Cellar/go/1.8.3/libexec/src/net/net.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="70">
<caret line="116" column="5" lean-forward="false" selection-start-line="116" selection-start-column="5" selection-end-line="116" selection-end-column="5" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/color.go"> <entry file="file://$PROJECT_DIR$/client/color.go">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0"> <state relative-caret-position="0">
@ -1320,9 +993,65 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/server/server-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="765">
<caret line="51" column="4" lean-forward="false" selection-start-line="51" selection-start-column="4" selection-end-line="51" selection-end-column="4" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/common/readers.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="405">
<caret line="27" column="5" lean-forward="false" selection-start-line="27" selection-start-column="5" selection-end-line="27" selection-end-column="5" />
<folding>
<marker date="1499422201000" expanded="true" signature="95:177" ph="(...)" />
<marker date="1499422201000" expanded="true" signature="468:499" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="527:567" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="629:650" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="722:891" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="743:816" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="983:1162" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1004:1088" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1217:1349" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1238:1275" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1409:1722" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1460:1480" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1558:1595" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1618:1638" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1785:1979" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1864:1959" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2032:2194" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2248:2411" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2465:2628" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2683:3095" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2797:2987" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2899:2984" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="3206:3246" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="3346:3368" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="21" column="0" lean-forward="false" selection-start-line="21" selection-start-column="0" selection-end-line="21" selection-end-column="0" />
<folding>
<marker date="1499516504000" expanded="false" signature="21:57" ph="..." />
<marker date="1499516504000" expanded="true" signature="864:915" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1534:1563" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1577:1779" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1585:1776" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1672:1734" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/client_auth.go"> <entry file="file://$PROJECT_DIR$/client/client_auth.go">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="285"> <state relative-caret-position="225">
<caret line="19" column="31" lean-forward="false" selection-start-line="19" selection-start-column="31" selection-end-line="19" selection-end-column="31" /> <caret line="19" column="31" lean-forward="false" selection-start-line="19" selection-start-column="31" selection-end-line="19" selection-end-column="31" />
<folding> <folding>
<element signature="e#16#65#0" expanded="true" /> <element signature="e#16#65#0" expanded="true" />
@ -1340,7 +1069,7 @@
</entry> </entry>
<entry file="file://$PROJECT_DIR$/client/client_test.go"> <entry file="file://$PROJECT_DIR$/client/client_test.go">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150"> <state relative-caret-position="90">
<caret line="10" column="19" lean-forward="true" selection-start-line="10" selection-start-column="19" selection-end-line="10" selection-end-column="19" /> <caret line="10" column="19" lean-forward="true" selection-start-line="10" selection-start-column="19" selection-end-line="10" selection-end-column="19" />
<folding> <folding>
<element signature="e#16#51#0" expanded="true" /> <element signature="e#16#51#0" expanded="true" />
@ -1352,7 +1081,14 @@
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270"> <state relative-caret-position="270">
<caret line="27" column="27" lean-forward="true" selection-start-line="27" selection-start-column="27" selection-end-line="27" selection-end-column="27" /> <caret line="27" column="27" lean-forward="true" selection-start-line="27" selection-start-column="27" selection-end-line="27" selection-end-column="27" />
<folding /> <folding>
<marker date="1499522819000" expanded="true" signature="11754:11874" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="11913:11945" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="11982:12067" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12030:12064" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12235:12286" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12462:12476" ph="{...}" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
@ -1364,20 +1100,269 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/server/server.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<marker date="1499522819000" expanded="false" signature="23:27" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/encodings/enc-corre.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="12" column="1" lean-forward="false" selection-start-line="12" selection-start-column="1" selection-end-line="12" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/client-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="6750">
<caret line="450" column="0" lean-forward="false" selection-start-line="450" selection-start-column="0" selection-end-line="450" selection-end-column="0" />
<folding>
<marker date="1499522819000" expanded="true" signature="11754:11874" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="11913:11945" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="11982:12067" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12030:12064" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12235:12286" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12462:12476" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/server/server-conn.go"> <entry file="file://$PROJECT_DIR$/server/server-conn.go">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15"> <state relative-caret-position="765">
<caret line="51" column="4" lean-forward="false" selection-start-line="51" selection-start-column="4" selection-end-line="51" selection-end-column="4" /> <caret line="51" column="4" lean-forward="false" selection-start-line="51" selection-start-column="4" selection-end-line="51" selection-end-column="4" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/server-messages.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="900">
<caret line="60" column="30" lean-forward="false" selection-start-line="60" selection-start-column="30" selection-end-line="60" selection-end-column="30" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tee-listeners/recorder.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="21" column="27" lean-forward="true" selection-start-line="21" selection-start-column="27" selection-end-line="21" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/common/readers.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="27" column="5" lean-forward="false" selection-start-line="27" selection-start-column="5" selection-end-line="27" selection-end-column="5" />
<folding> <folding>
<element signature="e#16#59#0" expanded="true" /> <marker date="1499422201000" expanded="true" signature="95:177" ph="(...)" />
<marker date="1499422201000" expanded="true" signature="468:499" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="527:567" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="629:650" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="722:891" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="743:816" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="983:1162" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1004:1088" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1217:1349" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1238:1275" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1409:1722" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1460:1480" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1558:1595" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1618:1638" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1785:1979" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1864:1959" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2032:2194" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2248:2411" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2465:2628" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2683:3095" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2797:2987" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2899:2984" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="3206:3246" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="3346:3368" ph="{...}" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="28" column="10" lean-forward="true" selection-start-line="28" selection-start-column="10" selection-end-line="28" selection-end-column="10" />
<folding>
<marker date="1499516504000" expanded="false" signature="21:57" ph="..." />
<marker date="1499516504000" expanded="true" signature="864:915" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1534:1563" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1577:1779" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1585:1776" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1672:1734" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/server-messages.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="795">
<caret line="60" column="30" lean-forward="false" selection-start-line="60" selection-start-column="30" selection-end-line="60" selection-end-column="30" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tee-listeners/recorder.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="21" column="27" lean-forward="false" selection-start-line="21" selection-start-column="27" selection-end-line="21" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/common/readers.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="32" column="5" lean-forward="false" selection-start-line="32" selection-start-column="5" selection-end-line="32" selection-end-column="5" />
<folding>
<marker date="1499422201000" expanded="true" signature="95:177" ph="(...)" />
<marker date="1499422201000" expanded="true" signature="468:499" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="527:567" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="629:650" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="722:891" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="743:816" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="983:1162" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1004:1088" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1217:1349" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1238:1275" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1409:1722" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1460:1480" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1558:1595" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1618:1638" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1785:1979" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="1864:1959" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2032:2194" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2248:2411" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2465:2628" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2683:3095" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2797:2987" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="2899:2984" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="3206:3246" ph="{...}" />
<marker date="1499422201000" expanded="true" signature="3346:3368" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="22" column="0" lean-forward="false" selection-start-line="22" selection-start-column="0" selection-end-line="22" selection-end-column="0" />
<folding>
<marker date="1499516504000" expanded="false" signature="21:57" ph="..." />
<marker date="1499516504000" expanded="true" signature="864:915" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1534:1563" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1577:1779" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1585:1776" ph="{...}" />
<marker date="1499516504000" expanded="true" signature="1672:1734" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file:///usr/local/Cellar/go/1.8.3/libexec/src/net/net.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="70">
<caret line="116" column="5" lean-forward="false" selection-start-line="116" selection-start-column="5" selection-end-line="116" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/color.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/client_auth.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="19" column="31" lean-forward="false" selection-start-line="19" selection-start-column="31" selection-end-line="19" selection-end-column="31" />
<folding>
<element signature="e#16#65#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/encodings/enc-corre.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="12" column="1" lean-forward="false" selection-start-line="12" selection-start-column="1" selection-end-line="12" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/client_test.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="10" column="19" lean-forward="false" selection-start-line="10" selection-start-column="19" selection-end-line="10" selection-end-column="19" />
<folding>
<element signature="e#16#51#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/client/client-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="26" column="27" lean-forward="false" selection-start-line="26" selection-start-column="27" selection-end-line="26" selection-end-column="27" />
<folding>
<marker date="1499522819000" expanded="true" signature="11754:11874" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="11913:11945" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="11982:12067" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12030:12064" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12235:12286" ph="{...}" />
<marker date="1499522819000" expanded="true" signature="12462:12476" ph="{...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/server/security.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/server/server.go"> <entry file="file://$PROJECT_DIR$/server/server.go">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0"> <state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" /> <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<marker date="1499522819000" expanded="false" signature="23:27" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/server/server-conn.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15">
<caret line="80" column="4" lean-forward="false" selection-start-line="80" selection-start-column="4" selection-end-line="80" selection-end-column="4" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/server/client-messages.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="138">
<caret line="81" column="14" lean-forward="false" selection-start-line="81" selection-start-column="14" selection-end-line="81" selection-end-column="14" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/common/client-message.go">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="243">
<caret line="36" column="26" lean-forward="true" selection-start-line="36" selection-start-column="26" selection-end-line="36" selection-end-column="26" />
<folding /> <folding />
</state> </state>
</provider> </provider>

View File

@ -26,7 +26,7 @@ type ClientAuth interface {
type ClientConn struct { type ClientConn struct {
conn io.ReadWriteCloser conn io.ReadWriteCloser
//c net.Conn //c net.ServerConn
config *ClientConfig config *ClientConfig
// If the pixel format uses a color map, then this is the color // If the pixel format uses a color map, then this is the color
@ -51,6 +51,8 @@ type ClientConn struct {
// be modified. If you wish to set a new pixel format, use the // be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method. // SetPixelFormat method.
PixelFormat common.PixelFormat PixelFormat common.PixelFormat
Listener common.SegmentConsumer
} }
// A ClientConfig structure is used to configure a ClientConn. After // A ClientConfig structure is used to configure a ClientConn. After
@ -76,7 +78,6 @@ type ClientConfig struct {
// This only needs to contain NEW server messages, and doesn't // This only needs to contain NEW server messages, and doesn't
// need to explicitly contain the RFC-required messages. // need to explicitly contain the RFC-required messages.
ServerMessages []common.ServerMessage ServerMessages []common.ServerMessage
Listener common.SegmentConsumer
} }
func Client(c net.Conn, cfg *ClientConfig) (*ClientConn, error) { func Client(c net.Conn, cfg *ClientConfig) (*ClientConn, error) {
@ -107,6 +108,14 @@ func (c *ClientConn) CurrentPixelFormat() *common.PixelFormat {
return &c.PixelFormat return &c.PixelFormat
} }
func (c *ClientConn) Write(bytes []byte) (n int, err error) {
return c.conn.Write(bytes)
}
func (c *ClientConn) Read(bytes []byte) (n int, err error) {
return c.conn.Read(bytes)
}
func (c *ClientConn) CurrentColorMap() *common.ColorMap { func (c *ClientConn) CurrentColorMap() *common.ColorMap {
return &c.ColorMap return &c.ColorMap
} }
@ -446,7 +455,7 @@ FindAuth:
PixelFormat: c.PixelFormat, PixelFormat: c.PixelFormat,
} }
rfbSeg := &common.RfbSegment{SegmentType: common.SegmentServerInitMessage, Message: &srvInit} rfbSeg := &common.RfbSegment{SegmentType: common.SegmentServerInitMessage, Message: &srvInit}
c.config.Listener.Consume(rfbSeg) c.Listener.Consume(rfbSeg)
return nil return nil
} }
@ -456,7 +465,7 @@ FindAuth:
func (c *ClientConn) mainLoop() { func (c *ClientConn) mainLoop() {
defer c.Close() defer c.Close()
reader := &common.RfbReadHelper{Reader: c.conn, Listener: c.config.Listener} reader := &common.RfbReadHelper{Reader: c.conn, Listener: c.Listener}
// Build the map of available server messages // Build the map of available server messages
typeMap := make(map[uint8]common.ServerMessage) typeMap := make(map[uint8]common.ServerMessage)

View File

@ -1,55 +1,56 @@
package common package common
import "io" import "io"
type ClientMessageType uint8 type ClientMessageType uint8
//go:generate stringer -type=ClientMessageType //go:generate stringer -type=ClientMessageType
// Client-to-Server message types. // Client-to-Server message types.
const ( const (
SetPixelFormatMsgType ClientMessageType = iota SetPixelFormatMsgType ClientMessageType = iota
_ _
SetEncodingsMsgType SetEncodingsMsgType
FramebufferUpdateRequestMsgType FramebufferUpdateRequestMsgType
KeyEventMsgType KeyEventMsgType
PointerEventMsgType PointerEventMsgType
ClientCutTextMsgType ClientCutTextMsgType
) )
// Color represents a single color in a color map. // Color represents a single color in a color map.
type Color struct { type Color struct {
pf *PixelFormat pf *PixelFormat
cm *ColorMap cm *ColorMap
cmIndex uint32 // Only valid if pf.TrueColor is false. cmIndex uint32 // Only valid if pf.TrueColor is false.
R, G, B uint16 R, G, B uint16
} }
type ColorMap [256]Color type ColorMap [256]Color
type Conn interface { type ServerConn interface {
io.ReadWriter io.ReadWriter
Conn() io.ReadWriter //ServerConn() io.ReadWriter
Protocol() string Protocol() string
PixelFormat() *PixelFormat CurrentPixelFormat() *PixelFormat
SetPixelFormat(*PixelFormat) error SetPixelFormat(*PixelFormat) error
ColorMap() *ColorMap //ColorMap() *ColorMap
SetColorMap(*ColorMap) SetColorMap(*ColorMap)
Encodings() []Encoding Encodings() []Encoding
SetEncodings([]EncodingType) error SetEncodings([]EncodingType) error
Width() uint16 Width() uint16
Height() uint16 Height() uint16
SetWidth(uint16) SetWidth(uint16)
SetHeight(uint16) SetHeight(uint16)
DesktopName() string DesktopName() string
SetDesktopName(string) SetDesktopName(string)
//Flush() error //Flush() error
SetProtoVersion(string) SetProtoVersion(string)
} // Write([]byte) (int, error)
}
// ClientMessage is the interface
type ClientMessage interface { // ClientMessage is the interface
Type() ClientMessageType type ClientMessage interface {
Read(Conn) (ClientMessage, error) Type() ClientMessageType
Write(Conn) error Read(io.Reader) (ClientMessage, error)
} Write(io.Writer) error
}

View File

@ -33,9 +33,9 @@ func main() {
Auth: authArr, Auth: authArr,
ServerMessageCh: vncSrvMessagesChan, ServerMessageCh: vncSrvMessagesChan,
Exclusive: true, Exclusive: true,
Listener: split,
}) })
clientConn.Listener = split
if err != nil { if err != nil {
fmt.Printf("error creating client: %s", err) fmt.Printf("error creating client: %s", err)
} }

161
proxy/proxy.go Normal file
View File

@ -0,0 +1,161 @@
package proxy
import (
"fmt"
"log"
"net"
"path"
"strconv"
"time"
"vncproxy/client"
"vncproxy/common"
"vncproxy/encodings"
"vncproxy/server"
listeners "vncproxy/tee-listeners"
)
type VncProxy struct {
tcpListeningUrl string // empty = not listening on tcp
wsListeningUrl string // empty = not listening on ws
recordingDir string // empty = no recording
proxyPassword string // empty = no auth
targetServersPassword string //empty = no auth
singleSession *VncSession // to be used when not using sessions
usingSessions bool //false = single session - defined in the var above
sessionManager *SessionManager
}
func (vp *VncProxy) connectToVncServer(targetServerUrl string) (*client.ClientConn, error) {
nc, err := net.Dial("tcp", targetServerUrl)
if err != nil {
fmt.Printf("error connecting to vnc server: %s", err)
return nil, err
}
var noauth client.ClientAuthNone
authArr := []client.ClientAuth{&client.PasswordAuth{Password: vp.targetServersPassword}, &noauth}
vncSrvMessagesChan := make(chan common.ServerMessage)
//rec := listeners.NewRecorder("recording.rbs")
// split := &listeners.MultiListener{}
// for _, listener := range rfbListeners {
// split.AddListener(listener)
// }
clientConn, err := client.Client(nc,
&client.ClientConfig{
Auth: authArr,
ServerMessageCh: vncSrvMessagesChan,
Exclusive: true,
})
//clientConn.Listener = split
if err != nil {
fmt.Printf("error creating client: %s", err)
return nil, err
}
tight := encodings.TightEncoding{}
tightPng := encodings.TightPngEncoding{}
rre := encodings.RREEncoding{}
zlib := encodings.ZLibEncoding{}
zrle := encodings.ZRLEEncoding{}
cpyRect := encodings.CopyRectEncoding{}
coRRE := encodings.CoRREEncoding{}
hextile := encodings.HextileEncoding{}
clientConn.SetEncodings([]common.Encoding{&cpyRect, &tightPng, &tight, &hextile, &coRRE, &rre, &zlib, &zrle})
return clientConn, nil
}
// if sessions not enabled, will always return the configured target server (only one)
func (vp *VncProxy) getTargetServerFromSession(sessionId string) (*VncSession, error) {
if !vp.usingSessions {
return vp.singleSession, nil
}
return vp.sessionManager.GetSession(sessionId)
}
func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server.ServerConn, rfbListeners []common.SegmentConsumer) error {
recFile := "recording" + strconv.FormatInt(time.Now().Unix(), 10) + ".rbs"
recPath := path.Join(vp.recordingDir, recFile)
rec := listeners.NewRecorder(recPath)
session, err := vp.getTargetServerFromSession(sconn.SessionId)
if err != nil {
fmt.Printf("Proxy.newServerConnHandler can't get session: %d\n", sconn.SessionId)
return err
}
serverSplitter := &listeners.MultiListener{}
for _, l := range rfbListeners {
serverSplitter.AddListener(l)
}
serverSplitter.AddListener(rec)
sconn.Listener = serverSplitter
clientSplitter := &listeners.MultiListener{}
clientSplitter.AddListener(rec)
cconn, err := vp.connectToVncServer(session.TargetHostname + ":" + session.TargetPort)
cconn.Listener = clientSplitter
//creating cross-listeners between server and client parts to pass messages through the proxy:
// gets the bytes from the actual vnc server on the env (client part of the proxy)
// and writes them through the server socket to the vnc-client
serverMsgRepeater := &listeners.WriteTo{sconn, "vnc-client bound"}
clientSplitter.AddListener(serverMsgRepeater)
// gets the messages from the server part (from vnc-client),
// and write through the client to the actual vnc-server
clientMsgRepeater := &listeners.WriteTo{cconn, "vnc-server bound"}
serverSplitter.AddListener(clientMsgRepeater)
return nil
}
func (vp *VncProxy) StartListening(rfbListeners []common.SegmentConsumer) {
//chServer := make(chan common.ClientMessage)
chClient := make(chan common.ServerMessage)
secHandlers := []server.SecurityHandler{&server.ServerAuthNone{}}
if vp.proxyPassword != "" {
secHandlers = []server.SecurityHandler{&server.ServerAuthVNC{vp.proxyPassword}}
}
cfg := &server.ServerConfig{
SecurityHandlers: secHandlers,
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
PixelFormat: common.NewPixelFormat(32),
ServerMessageCh: chClient,
ClientMessages: server.DefaultClientMessages,
DesktopName: []byte("workDesk"),
Height: uint16(768),
Width: uint16(1024),
NewConnHandler: func(cfg *server.ServerConfig, conn *server.ServerConn) error {
vp.newServerConnHandler(cfg, conn, rfbListeners)
return nil
},
}
if vp.wsListeningUrl != "" {
go server.WsServe(vp.wsListeningUrl, cfg)
}
if vp.tcpListeningUrl != "" {
go server.TcpServe(vp.tcpListeningUrl, cfg)
}
// Process messages coming in on the ClientMessage channel.
for {
msg := <-chClient
switch msg.Type() {
default:
log.Printf("Received message type:%v msg:%v\n", msg.Type(), msg)
}
}
}

19
proxy/session-manager.go Normal file
View File

@ -0,0 +1,19 @@
package proxy
type SessionManager struct {
sessions map[string]*VncSession
}
func (s *SessionManager) GetSession(sessionId string) (*VncSession, error) {
return s.sessions[sessionId], nil
}
func (s *SessionManager) SetSession(sessionId string, session *VncSession) error {
s.sessions[sessionId] = session
return nil
}
func (s *SessionManager) DeleteSession(sessionId string) error {
delete(s.sessions, sessionId)
return nil
}

24
proxy/vnc-session.go Normal file
View File

@ -0,0 +1,24 @@
package proxy
type SessionStatus int
type SessionType int
const (
SessionStatusInit SessionStatus = iota
SessionStatusActive
)
const (
SessionTypeRecordingProxy SessionType = iota
SessionTypeReplayServer
SessionTypeProxyPass
)
type VncSession struct {
TargetHostname string
TargetPort string
TargetPassword string
ID string
Status SessionStatus
Type SessionType
}

View File

@ -2,6 +2,7 @@ package server
import ( import (
"encoding/binary" "encoding/binary"
"io"
"vncproxy/common" "vncproxy/common"
) )
@ -24,7 +25,7 @@ func (*SetPixelFormat) Type() common.ClientMessageType {
return common.SetPixelFormatMsgType return common.SetPixelFormatMsgType
} }
func (msg *SetPixelFormat) Write(c common.Conn) error { func (msg *SetPixelFormat) Write(c io.Writer) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil { if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err return err
} }
@ -33,16 +34,16 @@ func (msg *SetPixelFormat) Write(c common.Conn) error {
return err return err
} }
pf := c.PixelFormat() //pf := c.CurrentPixelFormat()
// Invalidate the color map. // Invalidate the color map.
if pf.TrueColor { // if pf.TrueColor {
c.SetColorMap(&common.ColorMap{}) // c.SetColorMap(&common.ColorMap{})
} // }
return nil return nil
} }
func (*SetPixelFormat) Read(c common.Conn) (common.ClientMessage, error) { func (*SetPixelFormat) Read(c io.Reader) (common.ClientMessage, error) {
msg := SetPixelFormat{} msg := SetPixelFormat{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil { if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err return nil, err
@ -61,7 +62,7 @@ func (*SetEncodings) Type() common.ClientMessageType {
return common.SetEncodingsMsgType return common.SetEncodingsMsgType
} }
func (*SetEncodings) Read(c common.Conn) (common.ClientMessage, error) { func (*SetEncodings) Read(c io.Reader) (common.ClientMessage, error) {
msg := SetEncodings{} msg := SetEncodings{}
var pad [1]byte var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil { if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
@ -78,11 +79,11 @@ func (*SetEncodings) Read(c common.Conn) (common.ClientMessage, error) {
} }
msg.Encodings = append(msg.Encodings, enc) msg.Encodings = append(msg.Encodings, enc)
} }
c.SetEncodings(msg.Encodings) c.(common.ServerConn).SetEncodings(msg.Encodings)
return &msg, nil return &msg, nil
} }
func (msg *SetEncodings) Write(c common.Conn) error { func (msg *SetEncodings) Write(c io.Writer) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil { if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err return err
} }
@ -117,7 +118,7 @@ func (*FramebufferUpdateRequest) Type() common.ClientMessageType {
return common.FramebufferUpdateRequestMsgType return common.FramebufferUpdateRequestMsgType
} }
func (*FramebufferUpdateRequest) Read(c common.Conn) (common.ClientMessage, error) { func (*FramebufferUpdateRequest) Read(c io.Reader) (common.ClientMessage, error) {
msg := FramebufferUpdateRequest{} msg := FramebufferUpdateRequest{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil { if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err return nil, err
@ -125,7 +126,7 @@ func (*FramebufferUpdateRequest) Read(c common.Conn) (common.ClientMessage, erro
return &msg, nil return &msg, nil
} }
func (msg *FramebufferUpdateRequest) Write(c common.Conn) error { func (msg *FramebufferUpdateRequest) Write(c io.Writer) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil { if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err return err
} }
@ -146,7 +147,7 @@ func (*KeyEvent) Type() common.ClientMessageType {
return common.KeyEventMsgType return common.KeyEventMsgType
} }
func (*KeyEvent) Read(c common.Conn) (common.ClientMessage, error) { func (*KeyEvent) Read(c io.Reader) (common.ClientMessage, error) {
msg := KeyEvent{} msg := KeyEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil { if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err return nil, err
@ -154,7 +155,7 @@ func (*KeyEvent) Read(c common.Conn) (common.ClientMessage, error) {
return &msg, nil return &msg, nil
} }
func (msg *KeyEvent) Write(c common.Conn) error { func (msg *KeyEvent) Write(c io.Writer) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil { if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err return err
} }
@ -174,7 +175,7 @@ func (*PointerEvent) Type() common.ClientMessageType {
return common.PointerEventMsgType return common.PointerEventMsgType
} }
func (*PointerEvent) Read(c common.Conn) (common.ClientMessage, error) { func (*PointerEvent) Read(c io.Reader) (common.ClientMessage, error) {
msg := PointerEvent{} msg := PointerEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil { if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err return nil, err
@ -182,7 +183,7 @@ func (*PointerEvent) Read(c common.Conn) (common.ClientMessage, error) {
return &msg, nil return &msg, nil
} }
func (msg *PointerEvent) Write(c common.Conn) error { func (msg *PointerEvent) Write(c io.Writer) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil { if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err return err
} }
@ -203,7 +204,7 @@ func (*ClientCutText) Type() common.ClientMessageType {
return common.ClientCutTextMsgType return common.ClientCutTextMsgType
} }
func (*ClientCutText) Read(c common.Conn) (common.ClientMessage, error) { func (*ClientCutText) Read(c io.Reader) (common.ClientMessage, error) {
msg := ClientCutText{} msg := ClientCutText{}
var pad [3]byte var pad [3]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil { if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
@ -221,7 +222,7 @@ func (*ClientCutText) Read(c common.Conn) (common.ClientMessage, error) {
return &msg, nil return &msg, nil
} }
func (msg *ClientCutText) Write(c common.Conn) error { func (msg *ClientCutText) Write(c io.Writer) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil { if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err return err
} }

Binary file not shown.

View File

@ -130,7 +130,7 @@ func ServerServerInitHandler(cfg *ServerConfig, c *ServerConn) error {
srvInit := &common.ServerInit{ srvInit := &common.ServerInit{
FBWidth: c.Width(), FBWidth: c.Width(),
FBHeight: c.Height(), FBHeight: c.Height(),
PixelFormat: *c.PixelFormat(), PixelFormat: *c.CurrentPixelFormat(),
NameLength: uint32(len(cfg.DesktopName)), NameLength: uint32(len(cfg.DesktopName)),
NameText: []byte(cfg.DesktopName), NameText: []byte(cfg.DesktopName),
} }

View File

@ -1,335 +1,335 @@
package server package server
import ( import (
"bytes" "bytes"
"crypto/des" "crypto/des"
"crypto/rand" "crypto/rand"
"errors" "errors"
"log" "log"
"vncproxy/common" "vncproxy/common"
) )
type SecurityType uint8 type SecurityType uint8
const ( const (
SecTypeUnknown = SecurityType(0) SecTypeUnknown = SecurityType(0)
SecTypeNone = SecurityType(1) SecTypeNone = SecurityType(1)
SecTypeVNC = SecurityType(2) SecTypeVNC = SecurityType(2)
SecTypeVeNCrypt = SecurityType(19) SecTypeVeNCrypt = SecurityType(19)
) )
type SecuritySubType uint32 type SecuritySubType uint32
const ( const (
SecSubTypeUnknown = SecuritySubType(0) SecSubTypeUnknown = SecuritySubType(0)
) )
const ( const (
SecSubTypeVeNCrypt01Unknown = SecuritySubType(0) SecSubTypeVeNCrypt01Unknown = SecuritySubType(0)
SecSubTypeVeNCrypt01Plain = SecuritySubType(19) SecSubTypeVeNCrypt01Plain = SecuritySubType(19)
SecSubTypeVeNCrypt01TLSNone = SecuritySubType(20) SecSubTypeVeNCrypt01TLSNone = SecuritySubType(20)
SecSubTypeVeNCrypt01TLSVNC = SecuritySubType(21) SecSubTypeVeNCrypt01TLSVNC = SecuritySubType(21)
SecSubTypeVeNCrypt01TLSPlain = SecuritySubType(22) SecSubTypeVeNCrypt01TLSPlain = SecuritySubType(22)
SecSubTypeVeNCrypt01X509None = SecuritySubType(23) SecSubTypeVeNCrypt01X509None = SecuritySubType(23)
SecSubTypeVeNCrypt01X509VNC = SecuritySubType(24) SecSubTypeVeNCrypt01X509VNC = SecuritySubType(24)
SecSubTypeVeNCrypt01X509Plain = SecuritySubType(25) SecSubTypeVeNCrypt01X509Plain = SecuritySubType(25)
) )
const ( const (
SecSubTypeVeNCrypt02Unknown = SecuritySubType(0) SecSubTypeVeNCrypt02Unknown = SecuritySubType(0)
SecSubTypeVeNCrypt02Plain = SecuritySubType(256) SecSubTypeVeNCrypt02Plain = SecuritySubType(256)
SecSubTypeVeNCrypt02TLSNone = SecuritySubType(257) SecSubTypeVeNCrypt02TLSNone = SecuritySubType(257)
SecSubTypeVeNCrypt02TLSVNC = SecuritySubType(258) SecSubTypeVeNCrypt02TLSVNC = SecuritySubType(258)
SecSubTypeVeNCrypt02TLSPlain = SecuritySubType(259) SecSubTypeVeNCrypt02TLSPlain = SecuritySubType(259)
SecSubTypeVeNCrypt02X509None = SecuritySubType(260) SecSubTypeVeNCrypt02X509None = SecuritySubType(260)
SecSubTypeVeNCrypt02X509VNC = SecuritySubType(261) SecSubTypeVeNCrypt02X509VNC = SecuritySubType(261)
SecSubTypeVeNCrypt02X509Plain = SecuritySubType(262) SecSubTypeVeNCrypt02X509Plain = SecuritySubType(262)
) )
type SecurityHandler interface { type SecurityHandler interface {
Type() SecurityType Type() SecurityType
SubType() SecuritySubType SubType() SecuritySubType
Auth(common.Conn) error Auth(common.ServerConn) error
} }
// type ClientAuthNone struct{} // type ClientAuthNone struct{}
// func (*ClientAuthNone) Type() SecurityType { // func (*ClientAuthNone) Type() SecurityType {
// return SecTypeNone // return SecTypeNone
// } // }
// func (*ClientAuthNone) SubType() SecuritySubType { // func (*ClientAuthNone) SubType() SecuritySubType {
// return SecSubTypeUnknown // return SecSubTypeUnknown
// } // }
// func (*ClientAuthNone) Auth(conn common.Conn) error { // func (*ClientAuthNone) Auth(conn common.ServerConn) error {
// return nil // return nil
// } // }
// ServerAuthNone is the "none" authentication. See 7.2.1. // ServerAuthNone is the "none" authentication. See 7.2.1.
type ServerAuthNone struct{} type ServerAuthNone struct{}
func (*ServerAuthNone) Type() SecurityType { func (*ServerAuthNone) Type() SecurityType {
return SecTypeNone return SecTypeNone
} }
func (*ServerAuthNone) Auth(c common.Conn) error { func (*ServerAuthNone) Auth(c common.ServerConn) error {
return nil return nil
} }
func (*ServerAuthNone) SubType() SecuritySubType { func (*ServerAuthNone) SubType() SecuritySubType {
return SecSubTypeUnknown return SecSubTypeUnknown
} }
// func (*ClientAuthVeNCrypt02Plain) Type() SecurityType { // func (*ClientAuthVeNCrypt02Plain) Type() SecurityType {
// return SecTypeVeNCrypt // return SecTypeVeNCrypt
// } // }
// func (*ClientAuthVeNCrypt02Plain) SubType() SecuritySubType { // func (*ClientAuthVeNCrypt02Plain) SubType() SecuritySubType {
// return SecSubTypeVeNCrypt02Plain // return SecSubTypeVeNCrypt02Plain
// } // }
// // ClientAuthVeNCryptPlain see https://www.berrange.com/~dan/vencrypt.txt // // ClientAuthVeNCryptPlain see https://www.berrange.com/~dan/vencrypt.txt
// type ClientAuthVeNCrypt02Plain struct { // type ClientAuthVeNCrypt02Plain struct {
// Username []byte // Username []byte
// Password []byte // Password []byte
// } // }
// func (auth *ClientAuthVeNCrypt02Plain) Auth(c common.Conn) error { // func (auth *ClientAuthVeNCrypt02Plain) Auth(c common.ServerConn) error {
// if err := binary.Write(c, binary.BigEndian, []uint8{0, 2}); err != nil { // if err := binary.Write(c, binary.BigEndian, []uint8{0, 2}); err != nil {
// return err // return err
// } // }
// if err := c.Flush(); err != nil { // if err := c.Flush(); err != nil {
// return err // return err
// } // }
// var ( // var (
// major, minor uint8 // major, minor uint8
// ) // )
// if err := binary.Read(c, binary.BigEndian, &major); err != nil { // if err := binary.Read(c, binary.BigEndian, &major); err != nil {
// return err // return err
// } // }
// if err := binary.Read(c, binary.BigEndian, &minor); err != nil { // if err := binary.Read(c, binary.BigEndian, &minor); err != nil {
// return err // return err
// } // }
// res := uint8(1) // res := uint8(1)
// if major == 0 && minor == 2 { // if major == 0 && minor == 2 {
// res = uint8(0) // res = uint8(0)
// } // }
// if err := binary.Write(c, binary.BigEndian, res); err != nil { // if err := binary.Write(c, binary.BigEndian, res); err != nil {
// return err // return err
// } // }
// c.Flush() // c.Flush()
// if err := binary.Write(c, binary.BigEndian, uint8(1)); err != nil { // if err := binary.Write(c, binary.BigEndian, uint8(1)); err != nil {
// return err // return err
// } // }
// if err := binary.Write(c, binary.BigEndian, auth.SubType()); err != nil { // if err := binary.Write(c, binary.BigEndian, auth.SubType()); err != nil {
// return err // return err
// } // }
// if err := c.Flush(); err != nil { // if err := c.Flush(); err != nil {
// return err // return err
// } // }
// var secType SecuritySubType // var secType SecuritySubType
// if err := binary.Read(c, binary.BigEndian, &secType); err != nil { // if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
// return err // return err
// } // }
// if secType != auth.SubType() { // if secType != auth.SubType() {
// binary.Write(c, binary.BigEndian, uint8(1)) // binary.Write(c, binary.BigEndian, uint8(1))
// c.Flush() // c.Flush()
// return fmt.Errorf("invalid sectype") // return fmt.Errorf("invalid sectype")
// } // }
// if len(auth.Password) == 0 || len(auth.Username) == 0 { // if len(auth.Password) == 0 || len(auth.Username) == 0 {
// return fmt.Errorf("Security Handshake failed; no username and/or password provided for VeNCryptAuth.") // return fmt.Errorf("Security Handshake failed; no username and/or password provided for VeNCryptAuth.")
// } // }
// /* // /*
// if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Username))); err != nil { // if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Username))); err != nil {
// return err // return err
// } // }
// if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Password))); err != nil { // if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Password))); err != nil {
// return err // return err
// } // }
// if err := binary.Write(c, binary.BigEndian, auth.Username); err != nil { // if err := binary.Write(c, binary.BigEndian, auth.Username); err != nil {
// return err // return err
// } // }
// if err := binary.Write(c, binary.BigEndian, auth.Password); err != nil { // if err := binary.Write(c, binary.BigEndian, auth.Password); err != nil {
// return err // return err
// } // }
// */ // */
// var ( // var (
// uLength, pLength uint32 // uLength, pLength uint32
// ) // )
// if err := binary.Read(c, binary.BigEndian, &uLength); err != nil { // if err := binary.Read(c, binary.BigEndian, &uLength); err != nil {
// return err // return err
// } // }
// if err := binary.Read(c, binary.BigEndian, &pLength); err != nil { // if err := binary.Read(c, binary.BigEndian, &pLength); err != nil {
// return err // return err
// } // }
// username := make([]byte, uLength) // username := make([]byte, uLength)
// password := make([]byte, pLength) // password := make([]byte, pLength)
// if err := binary.Read(c, binary.BigEndian, &username); err != nil { // if err := binary.Read(c, binary.BigEndian, &username); err != nil {
// return err // return err
// } // }
// if err := binary.Read(c, binary.BigEndian, &password); err != nil { // if err := binary.Read(c, binary.BigEndian, &password); err != nil {
// return err // return err
// } // }
// if !bytes.Equal(auth.Username, username) || !bytes.Equal(auth.Password, password) { // if !bytes.Equal(auth.Username, username) || !bytes.Equal(auth.Password, password) {
// return fmt.Errorf("invalid username/password") // return fmt.Errorf("invalid username/password")
// } // }
// return nil // return nil
// } // }
// ServerAuthVNC is the standard password authentication. See 7.2.2. // ServerAuthVNC is the standard password authentication. See 7.2.2.
type ServerAuthVNC struct { type ServerAuthVNC struct {
pass string Pass string
} }
func (*ServerAuthVNC) Type() SecurityType { func (*ServerAuthVNC) Type() SecurityType {
return SecTypeVNC return SecTypeVNC
} }
func (*ServerAuthVNC) SubType() SecuritySubType { func (*ServerAuthVNC) SubType() SecuritySubType {
return SecSubTypeUnknown return SecSubTypeUnknown
} }
const AUTH_FAIL = "Authentication Failure" const AUTH_FAIL = "Authentication Failure"
func (auth *ServerAuthVNC) Auth(c common.Conn) error { func (auth *ServerAuthVNC) Auth(c common.ServerConn) error {
buf := make([]byte, 8+len([]byte(AUTH_FAIL))) buf := make([]byte, 8+len([]byte(AUTH_FAIL)))
rand.Read(buf[:16]) // Random 16 bytes in buf rand.Read(buf[:16]) // Random 16 bytes in buf
sndsz, err := c.Write(buf[:16]) sndsz, err := c.Write(buf[:16])
if err != nil { if err != nil {
log.Printf("Error sending challenge to client: %s\n", err.Error()) log.Printf("Error sending challenge to client: %s\n", err.Error())
return errors.New("Error sending challenge to client:" + err.Error()) return errors.New("Error sending challenge to client:" + err.Error())
} }
if sndsz != 16 { if sndsz != 16 {
log.Printf("The full 16 byte challenge was not sent!\n") log.Printf("The full 16 byte challenge was not sent!\n")
return errors.New("The full 16 byte challenge was not sent") return errors.New("The full 16 byte challenge was not sent")
} }
//c.Flush() //c.Flush()
buf2 := make([]byte, 16) buf2 := make([]byte, 16)
_, err = c.Read(buf2) _, err = c.Read(buf2)
if err != nil { if err != nil {
log.Printf("The authentication result was not read: %s\n", err.Error()) log.Printf("The authentication result was not read: %s\n", err.Error())
return errors.New("The authentication result was not read" + err.Error()) return errors.New("The authentication result was not read" + err.Error())
} }
AuthText := auth.pass AuthText := auth.Pass
bk, err := des.NewCipher([]byte(fixDesKey(AuthText))) bk, err := des.NewCipher([]byte(fixDesKey(AuthText)))
if err != nil { if err != nil {
log.Printf("Error generating authentication cipher: %s\n", err.Error()) log.Printf("Error generating authentication cipher: %s\n", err.Error())
return errors.New("Error generating authentication cipher") return errors.New("Error generating authentication cipher")
} }
buf3 := make([]byte, 16) buf3 := make([]byte, 16)
bk.Encrypt(buf3, buf) //Encrypt first 8 bytes bk.Encrypt(buf3, buf) //Encrypt first 8 bytes
bk.Encrypt(buf3[8:], buf[8:]) // Encrypt second 8 bytes bk.Encrypt(buf3[8:], buf[8:]) // Encrypt second 8 bytes
if bytes.Compare(buf2, buf3) != 0 { // If the result does not decrypt correctly to what we sent then a problem if bytes.Compare(buf2, buf3) != 0 { // If the result does not decrypt correctly to what we sent then a problem
SetUint32(buf, 0, 1) SetUint32(buf, 0, 1)
SetUint32(buf, 4, uint32(len([]byte(AUTH_FAIL)))) SetUint32(buf, 4, uint32(len([]byte(AUTH_FAIL))))
copy(buf[8:], []byte(AUTH_FAIL)) copy(buf[8:], []byte(AUTH_FAIL))
c.Write(buf) c.Write(buf)
//c.Flush() //c.Flush()
return errors.New("Authentication failed") return errors.New("Authentication failed")
} }
return nil return nil
} }
// SetUint32 set 4 bytes at pos in buf to the val (in big endian format) // SetUint32 set 4 bytes at pos in buf to the val (in big endian format)
// A test is done to ensure there are 4 bytes available at pos in the buffer // A test is done to ensure there are 4 bytes available at pos in the buffer
func SetUint32(buf []byte, pos int, val uint32) { func SetUint32(buf []byte, pos int, val uint32) {
if pos+4 > len(buf) { if pos+4 > len(buf) {
return return
} }
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
buf[3-i+pos] = byte(val) buf[3-i+pos] = byte(val)
val >>= 8 val >>= 8
} }
} }
// fixDesKeyByte is used to mirror a byte's bits // fixDesKeyByte is used to mirror a byte's bits
// This is not clearly indicated by the document, but is in actual fact used // This is not clearly indicated by the document, but is in actual fact used
func fixDesKeyByte(val byte) byte { func fixDesKeyByte(val byte) byte {
var newval byte = 0 var newval byte = 0
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
newval <<= 1 newval <<= 1
newval += (val & 1) newval += (val & 1)
val >>= 1 val >>= 1
} }
return newval return newval
} }
// fixDesKey will make sure that exactly 8 bytes is used either by truncating or padding with nulls // fixDesKey will make sure that exactly 8 bytes is used either by truncating or padding with nulls
// The bytes are then bit mirrored and returned // The bytes are then bit mirrored and returned
func fixDesKey(key string) []byte { func fixDesKey(key string) []byte {
tmp := []byte(key) tmp := []byte(key)
buf := make([]byte, 8) buf := make([]byte, 8)
if len(tmp) <= 8 { if len(tmp) <= 8 {
copy(buf, tmp) copy(buf, tmp)
} else { } else {
copy(buf, tmp[:8]) copy(buf, tmp[:8])
} }
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
buf[i] = fixDesKeyByte(buf[i]) buf[i] = fixDesKeyByte(buf[i])
} }
return buf return buf
} }
// // ClientAuthVNC is the standard password authentication. See 7.2.2. // // ClientAuthVNC is the standard password authentication. See 7.2.2.
// type ClientAuthVNC struct { // type ClientAuthVNC struct {
// Challenge [16]byte // Challenge [16]byte
// Password []byte // Password []byte
// } // }
// func (*ClientAuthVNC) Type() SecurityType { // func (*ClientAuthVNC) Type() SecurityType {
// return SecTypeVNC // return SecTypeVNC
// } // }
// func (*ClientAuthVNC) SubType() SecuritySubType { // func (*ClientAuthVNC) SubType() SecuritySubType {
// return SecSubTypeUnknown // return SecSubTypeUnknown
// } // }
// func (auth *ClientAuthVNC) Auth(c common.Conn) error { // func (auth *ClientAuthVNC) Auth(c common.ServerConn) error {
// if len(auth.Password) == 0 { // if len(auth.Password) == 0 {
// return fmt.Errorf("Security Handshake failed; no password provided for VNCAuth.") // return fmt.Errorf("Security Handshake failed; no password provided for VNCAuth.")
// } // }
// if err := binary.Read(c, binary.BigEndian, auth.Challenge); err != nil { // if err := binary.Read(c, binary.BigEndian, auth.Challenge); err != nil {
// return err // return err
// } // }
// auth.encode() // auth.encode()
// // Send the encrypted challenge back to server // // Send the encrypted challenge back to server
// if err := binary.Write(c, binary.BigEndian, auth.Challenge); err != nil { // if err := binary.Write(c, binary.BigEndian, auth.Challenge); err != nil {
// return err // return err
// } // }
// return c.Flush() // return c.Flush()
// } // }
// func (auth *ClientAuthVNC) encode() error { // func (auth *ClientAuthVNC) encode() error {
// // Copy password string to 8 byte 0-padded slice // // Copy password string to 8 byte 0-padded slice
// key := make([]byte, 8) // key := make([]byte, 8)
// copy(key, auth.Password) // copy(key, auth.Password)
// // Each byte of the password needs to be reversed. This is a // // Each byte of the password needs to be reversed. This is a
// // non RFC-documented behaviour of VNC clients and servers // // non RFC-documented behaviour of VNC clients and servers
// for i := range key { // for i := range key {
// key[i] = (key[i]&0x55)<<1 | (key[i]&0xAA)>>1 // Swap adjacent bits // key[i] = (key[i]&0x55)<<1 | (key[i]&0xAA)>>1 // Swap adjacent bits
// key[i] = (key[i]&0x33)<<2 | (key[i]&0xCC)>>2 // Swap adjacent pairs // key[i] = (key[i]&0x33)<<2 | (key[i]&0xCC)>>2 // Swap adjacent pairs
// key[i] = (key[i]&0x0F)<<4 | (key[i]&0xF0)>>4 // Swap the 2 halves // key[i] = (key[i]&0x0F)<<4 | (key[i]&0xF0)>>4 // Swap the 2 halves
// } // }
// // Encrypt challenge with key. // // Encrypt challenge with key.
// cipher, err := des.NewCipher(key) // cipher, err := des.NewCipher(key)
// if err != nil { // if err != nil {
// return err // return err
// } // }
// for i := 0; i < len(auth.Challenge); i += cipher.BlockSize() { // for i := 0; i < len(auth.Challenge); i += cipher.BlockSize() {
// cipher.Encrypt(auth.Challenge[i:i+cipher.BlockSize()], auth.Challenge[i:i+cipher.BlockSize()]) // cipher.Encrypt(auth.Challenge[i:i+cipher.BlockSize()], auth.Challenge[i:i+cipher.BlockSize()])
// } // }
// return nil // return nil
// } // }

View File

@ -1,6 +1,8 @@
package server package server
import ( import (
"encoding/binary"
"fmt"
"io" "io"
"sync" "sync"
"vncproxy/common" "vncproxy/common"
@ -37,6 +39,11 @@ type ServerConn struct {
// SetPixelFormat method. // SetPixelFormat method.
pixelFormat *common.PixelFormat pixelFormat *common.PixelFormat
// a consumer for the parsed messages, to allow for recording and proxy
Listener common.SegmentConsumer
SessionId string
quit chan struct{} quit chan struct{}
} }
@ -44,6 +51,28 @@ type ServerConn struct {
// return c.br.UnreadByte() // return c.br.UnreadByte()
// } // }
func NewServerConn(c io.ReadWriter, cfg *ServerConfig) (*ServerConn, error) {
// if cfg.ClientMessageCh == nil {
// return nil, fmt.Errorf("ClientMessageCh nil")
// }
if len(cfg.ClientMessages) == 0 {
return nil, fmt.Errorf("ClientMessage 0")
}
return &ServerConn{
c: c,
//br: bufio.NewReader(c),
//bw: bufio.NewWriter(c),
cfg: cfg,
quit: make(chan struct{}),
encodings: cfg.Encodings,
pixelFormat: cfg.PixelFormat,
fbWidth: cfg.Width,
fbHeight: cfg.Height,
}, nil
}
func (c *ServerConn) Conn() io.ReadWriter { func (c *ServerConn) Conn() io.ReadWriter {
return c.c return c.c
} }
@ -72,7 +101,7 @@ func (c *ServerConn) SetProtoVersion(pv string) {
// } // }
func (c *ServerConn) Close() error { func (c *ServerConn) Close() error {
return c.c.(io.ReadWriteCloser).Close() return c.c.(io.ReadWriteCloser).Close()
} }
/* /*
@ -104,7 +133,7 @@ func (c *ServerConn) SetColorMap(cm *common.ColorMap) {
func (c *ServerConn) DesktopName() string { func (c *ServerConn) DesktopName() string {
return c.desktopName return c.desktopName
} }
func (c *ServerConn) PixelFormat() *common.PixelFormat { func (c *ServerConn) CurrentPixelFormat() *common.PixelFormat {
return c.pixelFormat return c.pixelFormat
} }
func (c *ServerConn) SetDesktopName(name string) { func (c *ServerConn) SetDesktopName(name string) {
@ -134,3 +163,71 @@ func (c *ServerConn) SetWidth(w uint16) {
func (c *ServerConn) SetHeight(h uint16) { func (c *ServerConn) SetHeight(h uint16) {
c.fbHeight = h c.fbHeight = h
} }
func (c *ServerConn) handle() error {
//var err error
//var wg sync.WaitGroup
//defer c.Close()
//create a map of all message types
clientMessages := make(map[common.ClientMessageType]common.ClientMessage)
for _, m := range c.cfg.ClientMessages {
clientMessages[m.Type()] = m
}
//wg.Add(2)
// server
go func() error {
//defer wg.Done()
for {
select {
case msg := <-c.cfg.ServerMessageCh:
fmt.Printf("%v", msg)
// if err = msg.Write(c); err != nil {
// return err
// }
case <-c.quit:
c.Close()
return nil
}
}
}()
// client
//go func() error {
//defer wg.Done()
for {
select {
case <-c.quit:
return nil
default:
var messageType common.ClientMessageType
if err := binary.Read(c, binary.BigEndian, &messageType); err != nil {
fmt.Printf("Error: %v\n", err)
return err
}
msg, ok := clientMessages[messageType]
if !ok {
return fmt.Errorf("unsupported message-type: %v", messageType)
}
parsedMsg, err := msg.Read(c)
seg := &common.RfbSegment{
SegmentType: common.SegmentFullyParsedClientMessage,
Message: parsedMsg,
}
c.Listener.Consume(seg)
if err != nil {
fmt.Printf("srv err %s\n", err.Error())
return err
}
fmt.Printf("message:%s, %v\n", parsedMsg.Type(), parsedMsg)
//c.cfg.ClientMessageCh <- parsedMsg
}
}
//}()
//wg.Wait()
//return nil
}

View File

@ -1,8 +1,6 @@
package server package server
import ( import (
"context"
"encoding/binary"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -19,9 +17,7 @@ var DefaultClientMessages = []common.ClientMessage{
&ClientCutText{}, &ClientCutText{},
} }
//var _ ServerConn = (*ServerConn)(nil)
//var _ Conn = (*ServerConn)(nil)
// ServerMessage represents a Client-to-Server RFB message type. // ServerMessage represents a Client-to-Server RFB message type.
// type ServerMessageType uint8 // type ServerMessageType uint8
@ -55,60 +51,43 @@ type ServerConfig struct {
SecurityHandlers []SecurityHandler SecurityHandlers []SecurityHandler
//ClientInitHandler ServerHandler //ClientInitHandler ServerHandler
//ServerInitHandler ServerHandler //ServerInitHandler ServerHandler
Encodings []common.Encoding Encodings []common.Encoding
PixelFormat *common.PixelFormat PixelFormat *common.PixelFormat
ColorMap *common.ColorMap ColorMap *common.ColorMap
ClientMessageCh chan common.ClientMessage //ClientMessageCh chan common.ClientMessage
ServerMessageCh chan common.ServerMessage ServerMessageCh chan common.ServerMessage
ClientMessages []common.ClientMessage ClientMessages []common.ClientMessage
DesktopName []byte DesktopName []byte
Height uint16 Height uint16
Width uint16 Width uint16
//handler to allow for registering for messages, this can't be a channel
//because of the websockets handler function which will kill the connection on exit if conn.handle() is run on another thread
NewConnHandler ServerHandler
} }
func newServerConn(c io.ReadWriter, cfg *ServerConfig) (*ServerConn, error) { func wsHandlerFunc(ws io.ReadWriter, cfg *ServerConfig, sessionId string) {
if cfg.ClientMessageCh == nil {
return nil, fmt.Errorf("ClientMessageCh nil")
}
if len(cfg.ClientMessages) == 0 {
return nil, fmt.Errorf("ClientMessage 0")
}
return &ServerConn{
c: c,
//br: bufio.NewReader(c),
//bw: bufio.NewWriter(c),
cfg: cfg,
quit: make(chan struct{}),
encodings: cfg.Encodings,
pixelFormat: cfg.PixelFormat,
fbWidth: cfg.Width,
fbHeight: cfg.Height,
}, nil
}
func wsHandlerFunc(ws io.ReadWriter, cfg *ServerConfig) {
// header := ws.Request().Header // header := ws.Request().Header
// url := ws.Request().URL // url := ws.Request().URL
// //stam := header.Get("Origin") // //stam := header.Get("Origin")
// fmt.Printf("header: %v\nurl: %v\n", header, url) // fmt.Printf("header: %v\nurl: %v\n", header, url)
// io.Copy(ws, ws) // io.Copy(ws, ws)
err := attachNewServerConn(ws, cfg) err := attachNewServerConn(ws, cfg, sessionId)
if err != nil { if err != nil {
log.Fatalf("Error attaching new connection. %v", err) log.Fatalf("Error attaching new connection. %v", err)
} }
} }
func WsServe(url string, ctx context.Context, cfg *ServerConfig) error { func WsServe(url string, cfg *ServerConfig) error {
//server := WsServer1{cfg} //server := WsServer1{cfg}
server := WsServer{cfg} server := WsServer{cfg}
server.Listen(url, WsHandler(wsHandlerFunc)) server.Listen(url, WsHandler(wsHandlerFunc))
return nil return nil
} }
func TcpServe(url string, ctx context.Context, cfg *ServerConfig) error { func TcpServe(url string, cfg *ServerConfig) error {
ln, err := net.Listen("tcp", ":5903") ln, err := net.Listen("tcp", url)
if err != nil { if err != nil {
log.Fatalf("Error listen. %v", err) log.Fatalf("Error listen. %v", err)
} }
@ -117,7 +96,7 @@ func TcpServe(url string, ctx context.Context, cfg *ServerConfig) error {
if err != nil { if err != nil {
return err return err
} }
go attachNewServerConn(c, cfg) go attachNewServerConn(c, cfg, "tcpDummySession")
// if err != nil { // if err != nil {
// return err // return err
// } // }
@ -125,9 +104,9 @@ func TcpServe(url string, ctx context.Context, cfg *ServerConfig) error {
return nil return nil
} }
func attachNewServerConn(c io.ReadWriter, cfg *ServerConfig) error { func attachNewServerConn(c io.ReadWriter, cfg *ServerConfig, sessionId string) error {
conn, err := newServerConn(c, cfg) conn, err := NewServerConn(c, cfg)
if err != nil { if err != nil {
return err return err
} }
@ -152,72 +131,11 @@ func attachNewServerConn(c io.ReadWriter, cfg *ServerConfig) error {
conn.Close() conn.Close()
return err return err
} }
conn.SessionId = sessionId
cfg.NewConnHandler(cfg, conn)
//go //go here will kill ws connections
conn.handle() conn.handle()
return nil return nil
} }
func (c *ServerConn) handle() error {
//var err error
//var wg sync.WaitGroup
//defer c.Close()
//create a map of all message types
clientMessages := make(map[common.ClientMessageType]common.ClientMessage)
for _, m := range c.cfg.ClientMessages {
clientMessages[m.Type()] = m
}
//wg.Add(2)
// server
// go func() error {
// defer wg.Done()
// for {
// select {
// case msg := <-c.cfg.ServerMessageCh:
// fmt.Printf("%v", msg)
// // if err = msg.Write(c); err != nil {
// // return err
// // }
// case <-c.quit:
// c.Close()
// return nil
// }
// }
// }()
// client
//go func() error {
//defer wg.Done()
for {
select {
case <-c.quit:
return nil
default:
var messageType common.ClientMessageType
if err := binary.Read(c, binary.BigEndian, &messageType); err != nil {
fmt.Printf("Error: %v\n", err)
return err
}
msg, ok := clientMessages[messageType]
if !ok {
return fmt.Errorf("unsupported message-type: %v", messageType)
}
parsedMsg, err := msg.Read(c)
if err != nil {
fmt.Printf("srv err %s\n", err.Error())
return err
}
fmt.Printf("message:%s, %v\n", parsedMsg.Type(), parsedMsg)
//c.cfg.ClientMessageCh <- parsedMsg
}
}
//}()
//wg.Wait()
//return nil
}

View File

@ -1,16 +1,20 @@
package server package server
import ( import (
"context"
"log" "log"
"testing" "testing"
"vncproxy/common" "vncproxy/common"
"vncproxy/encodings" "vncproxy/encodings"
) )
func newServerConnHandler(cfg *ServerConfig, conn *ServerConn) error {
return nil
}
func TestServer(t *testing.T) { func TestServer(t *testing.T) {
chServer := make(chan common.ClientMessage) //chServer := make(chan common.ClientMessage)
chClient := make(chan common.ServerMessage) chClient := make(chan common.ServerMessage)
cfg := &ServerConfig{ cfg := &ServerConfig{
@ -18,16 +22,17 @@ func TestServer(t *testing.T) {
SecurityHandlers: []SecurityHandler{&ServerAuthVNC{"Ch_#!T@8"}}, SecurityHandlers: []SecurityHandler{&ServerAuthVNC{"Ch_#!T@8"}},
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}}, Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
PixelFormat: common.NewPixelFormat(32), PixelFormat: common.NewPixelFormat(32),
ClientMessageCh: chServer, //ClientMessageCh: chServer,
ServerMessageCh: chClient, ServerMessageCh: chClient,
ClientMessages: DefaultClientMessages, ClientMessages: DefaultClientMessages,
DesktopName: []byte("workDesk"), DesktopName: []byte("workDesk"),
Height: uint16(768), Height: uint16(768),
Width: uint16(1024), Width: uint16(1024),
NewConnHandler: newServerConnHandler,
} }
url := "http://localhost:8091/" url := "http://localhost:8091/"
go WsServe(url, context.Background(), cfg) go WsServe(url, cfg)
go TcpServe(":5903", context.Background(), cfg) go TcpServe(":5903", cfg)
// Process messages coming in on the ClientMessage channel. // Process messages coming in on the ClientMessage channel.
for { for {
msg := <-chClient msg := <-chClient

View File

@ -13,7 +13,15 @@ type WsServer struct {
cfg *ServerConfig cfg *ServerConfig
} }
type WsHandler func(io.ReadWriter, *ServerConfig) type WsHandler func(io.ReadWriter, *ServerConfig, string)
// func checkOrigin(config *websocket.Config, req *http.Request) (err error) {
// config.Origin, err = websocket.Origin(config, req)
// if err == nil && config.Origin == nil {
// return fmt.Errorf("null origin")
// }
// return err
// }
// This example demonstrates a trivial echo server. // This example demonstrates a trivial echo server.
func (wsServer *WsServer) Listen(urlStr string, handlerFunc WsHandler) { func (wsServer *WsServer) Listen(urlStr string, handlerFunc WsHandler) {
@ -26,15 +34,28 @@ func (wsServer *WsServer) Listen(urlStr string, handlerFunc WsHandler) {
fmt.Println("error while parsing url: ", err) fmt.Println("error while parsing url: ", err)
} }
http.Handle(url.Path, websocket.Handler(func(ws *websocket.Conn) { // http.HandleFunc(url.Path,
// header := ws.Request().Header // func(w http.ResponseWriter, req *http.Request) {
// url := ws.Request().URL // sessionId := req.URL.Query().Get("sessionId")
// //stam := header.Get("Origin") // s := websocket.Server{Handshake: checkOrigin, Handler: websocket.Handler(
// fmt.Printf("header: %v\nurl: %v\n", header, url) // func(ws *websocket.ServerConn) {
// io.Copy(ws, ws) // ws.PayloadType = websocket.BinaryFrame
ws.PayloadType = websocket.BinaryFrame // handlerFunc(ws, wsServer.cfg, sessionId)
handlerFunc(ws, wsServer.cfg) // })}
})) // s.ServeHTTP(w, req)
// })
http.Handle(url.Path, websocket.Handler(
func(ws *websocket.Conn) {
path := ws.Request().URL.Path
var sessionId string
if path != "" {
sessionId = path[1:]
}
ws.PayloadType = websocket.BinaryFrame
handlerFunc(ws, wsServer.cfg, sessionId)
}))
err = http.ListenAndServe(url.Host, nil) err = http.ListenAndServe(url.Host, nil)
if err != nil { if err != nil {

View File

@ -116,6 +116,7 @@ func (r *Recorder) writeStartSession(initMsg *common.ServerInit) error {
func (r *Recorder) Consume(data *common.RfbSegment) error { func (r *Recorder) Consume(data *common.RfbSegment) error {
//using async writes so if chan buffer overflows, proxy will not be affected
select { select {
case r.segmentChan <- data: case r.segmentChan <- data:
default: default:

View File

@ -6,20 +6,43 @@ import (
"vncproxy/common" "vncproxy/common"
) )
type WriteToListener struct { type WriteTo struct {
io.Writer Writer io.Writer
Name string
} }
func (p *WriteToListener) Consume(seg *common.RfbSegment) error { func (p *WriteTo) Consume(seg *common.RfbSegment) error {
switch seg.SegmentType { switch seg.SegmentType {
case common.SegmentMessageSeparator: case common.SegmentMessageSeparator:
case common.SegmentRectSeparator: case common.SegmentRectSeparator:
case common.SegmentBytes: case common.SegmentBytes:
_, err := p.Writer.Write(seg.Bytes) _, err := p.Writer.Write(seg.Bytes)
return err return err
case common.SegmentFullyParsedClientMessage:
clientMsg := seg.Message.(common.ClientMessage)
clientMsg.Write(p.Writer)
default: default:
return errors.New("undefined RfbSegment type") return errors.New("undefined RfbSegment type")
} }
return nil return nil
} }
// type SendToClientMessageChan struct {
// Channel chan *common.ClientMessage
// }
// func (p *SendToClientMessageChan) Consume(seg *common.RfbSegment) error {
// switch seg.SegmentType {
// case common.SegmentMessageSeparator:
// case common.SegmentRectSeparator:
// case common.SegmentBytes:
// case common.SegmentFullyParsedClientMessage:
// p.Channel <- seg.Message.(*common.ClientMessage)
// //_, err := p.Writer.Write(seg.Bytes)
// //return err
// default:
// //return errors.New("undefined RfbSegment type")
// }
// return nil
// }

9
todo.md Normal file
View File

@ -0,0 +1,9 @@
#TODO:
* test proxy flow
* create replay flow
* set correct status for each flow
* have splitter logic on the connection objects
* move encodings to be on the framebufferupdate message object
* clear all messages read functions from updating stuff, move modification logic to another listener
* message read function should accept only an io.Reader, move read helper logic (readuint8) to an actual helper class