proxyConn sets up a bidirectional copy between two open connections
(inst string, client, server net.Conn)
| 1004 | |
| 1005 | // proxyConn sets up a bidirectional copy between two open connections |
| 1006 | func (c *Client) proxyConn(inst string, client, server net.Conn) { |
| 1007 | // only allow the first side to give an error for terminating a connection |
| 1008 | var o sync.Once |
| 1009 | cleanup := func(errDesc string, isErr bool) { |
| 1010 | o.Do(func() { |
| 1011 | _ = client.Close() |
| 1012 | _ = server.Close() |
| 1013 | if isErr { |
| 1014 | c.logger.Errorf(errDesc) |
| 1015 | } else { |
| 1016 | c.logger.Infof(errDesc) |
| 1017 | } |
| 1018 | }) |
| 1019 | } |
| 1020 | |
| 1021 | // copy bytes from client to server |
| 1022 | go func() { |
| 1023 | buf := make([]byte, 8*1024) // 8kb |
| 1024 | for { |
| 1025 | n, cErr := client.Read(buf) |
| 1026 | var sErr error |
| 1027 | if n > 0 { |
| 1028 | _, sErr = server.Write(buf[:n]) |
| 1029 | } |
| 1030 | switch { |
| 1031 | case cErr == io.EOF: |
| 1032 | cleanup(fmt.Sprintf("[%s] client closed the connection", inst), false) |
| 1033 | return |
| 1034 | case cErr != nil: |
| 1035 | cleanup(fmt.Sprintf("[%s] connection aborted - error reading from client: %v", inst, cErr), true) |
| 1036 | return |
| 1037 | case sErr == io.EOF: |
| 1038 | cleanup(fmt.Sprintf("[%s] instance closed the connection", inst), false) |
| 1039 | return |
| 1040 | case sErr != nil: |
| 1041 | cleanup(fmt.Sprintf("[%s] connection aborted - error writing to instance: %v", inst, sErr), true) |
| 1042 | return |
| 1043 | } |
| 1044 | } |
| 1045 | }() |
| 1046 | |
| 1047 | // copy bytes from server to client |
| 1048 | buf := make([]byte, 8*1024) // 8kb |
| 1049 | for { |
| 1050 | n, sErr := server.Read(buf) |
| 1051 | var cErr error |
| 1052 | if n > 0 { |
| 1053 | _, cErr = client.Write(buf[:n]) |
| 1054 | } |
| 1055 | switch { |
| 1056 | case sErr == io.EOF: |
| 1057 | cleanup(fmt.Sprintf("[%s] instance closed the connection", inst), false) |
| 1058 | return |
| 1059 | case sErr != nil: |
| 1060 | cleanup(fmt.Sprintf("[%s] connection aborted - error reading from instance: %v", inst, sErr), true) |
| 1061 | return |
| 1062 | case cErr == io.EOF: |
| 1063 | cleanup(fmt.Sprintf("[%s] client closed the connection", inst), false) |
no test coverage detected