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

@ -27,13 +27,13 @@ type Color struct {
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
@ -45,11 +45,12 @@ type Conn interface {
SetDesktopName(string) SetDesktopName(string)
//Flush() error //Flush() error
SetProtoVersion(string) SetProtoVersion(string)
// Write([]byte) (int, error)
} }
// ClientMessage is the interface // ClientMessage is the interface
type ClientMessage interface { type ClientMessage interface {
Type() ClientMessageType Type() ClientMessageType
Read(Conn) (ClientMessage, error) Read(io.Reader) (ClientMessage, error)
Write(Conn) error Write(io.Writer) error
} }

View File

@ -33,8 +33,8 @@ 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

@ -49,7 +49,7 @@ const (
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{}
@ -62,7 +62,7 @@ type SecurityHandler interface {
// return SecSubTypeUnknown // return SecSubTypeUnknown
// } // }
// func (*ClientAuthNone) Auth(conn common.Conn) error { // func (*ClientAuthNone) Auth(conn common.ServerConn) error {
// return nil // return nil
// } // }
@ -73,7 +73,7 @@ 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
} }
@ -95,7 +95,7 @@ func (*ServerAuthNone) SubType() SecuritySubType {
// 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
// } // }
@ -185,7 +185,7 @@ func (*ServerAuthNone) SubType() SecuritySubType {
// 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 {
@ -198,7 +198,7 @@ func (*ServerAuthVNC) SubType() SecuritySubType {
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])
@ -217,7 +217,7 @@ func (auth *ServerAuthVNC) Auth(c common.Conn) error {
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())
@ -290,7 +290,7 @@ func fixDesKey(key string) []byte {
// 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.")
// } // }

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