github.com/braveheart12/insolar-09-08-19@v0.8.7/network/transport/base.go (about) 1 /* 2 * The Clear BSD License 3 * 4 * Copyright (c) 2019 Insolar Technologies 5 * 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met: 9 * 10 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 * Neither the name of Insolar Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 * 14 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 * 16 */ 17 18 package transport 19 20 import ( 21 "context" 22 "io" 23 "sync" 24 25 "github.com/insolar/insolar/instrumentation/inslogger" 26 "github.com/insolar/insolar/metrics" 27 "github.com/insolar/insolar/network" 28 "github.com/insolar/insolar/network/transport/packet" 29 "github.com/insolar/insolar/network/transport/relay" 30 "github.com/pkg/errors" 31 ) 32 33 type transportSerializer interface { 34 SerializePacket(q *packet.Packet) ([]byte, error) 35 DeserializePacket(conn io.Reader) (*packet.Packet, error) 36 } 37 38 type baseSerializer struct{} 39 40 func (b *baseSerializer) SerializePacket(q *packet.Packet) ([]byte, error) { 41 return packet.SerializePacket(q) 42 } 43 44 func (b *baseSerializer) DeserializePacket(conn io.Reader) (*packet.Packet, error) { 45 return packet.DeserializePacket(conn) 46 } 47 48 type baseTransport struct { 49 futureManager futureManager 50 serializer transportSerializer 51 proxy relay.Proxy 52 packetHandler packetHandler 53 54 disconnectStarted chan bool 55 disconnectFinished chan bool 56 57 mutex *sync.RWMutex 58 59 publicAddress string 60 sendFunc func(recvAddress string, data []byte) error 61 } 62 63 func newBaseTransport(proxy relay.Proxy, publicAddress string) baseTransport { 64 futureManager := newFutureManager() 65 return baseTransport{ 66 futureManager: futureManager, 67 packetHandler: newPacketHandler(futureManager), 68 proxy: proxy, 69 serializer: &baseSerializer{}, 70 71 mutex: &sync.RWMutex{}, 72 73 disconnectStarted: make(chan bool, 1), 74 disconnectFinished: make(chan bool, 1), 75 76 publicAddress: publicAddress, 77 } 78 } 79 80 // SendRequest sends request packet and returns future. 81 func (t *baseTransport) SendRequest(ctx context.Context, msg *packet.Packet) (Future, error) { 82 future := t.futureManager.Create(msg) 83 err := t.SendPacket(ctx, msg) 84 if err != nil { 85 future.Cancel() 86 return nil, errors.Wrap(err, "Failed to send transport packet") 87 } 88 metrics.NetworkPacketSentTotal.WithLabelValues(msg.Type.String()).Inc() 89 return future, nil 90 } 91 92 // SendResponse sends response packet. 93 func (t *baseTransport) SendResponse(ctx context.Context, requestID network.RequestID, msg *packet.Packet) error { 94 msg.RequestID = requestID 95 96 return t.SendPacket(ctx, msg) 97 } 98 99 // Close closes packet channels. 100 func (t *baseTransport) Close() { 101 t.mutex.Lock() 102 defer t.mutex.Unlock() 103 104 close(t.disconnectFinished) 105 } 106 107 // Packets returns incoming packets channel. 108 func (t *baseTransport) Packets() <-chan *packet.Packet { 109 return t.packetHandler.Received() 110 } 111 112 // Stopped checks if networking is stopped already. 113 func (t *baseTransport) Stopped() <-chan bool { 114 t.mutex.RLock() 115 defer t.mutex.RUnlock() 116 117 return t.disconnectStarted 118 } 119 120 func (t *baseTransport) prepareDisconnect() { 121 t.disconnectStarted <- true 122 close(t.disconnectStarted) 123 } 124 125 // PublicAddress returns transport public ip address 126 func (t *baseTransport) PublicAddress() string { 127 return t.publicAddress 128 } 129 130 func (t *baseTransport) SendPacket(ctx context.Context, p *packet.Packet) error { 131 var recvAddress string 132 if t.proxy.ProxyHostsCount() > 0 { 133 recvAddress = t.proxy.GetNextProxyAddress() 134 } 135 if len(recvAddress) == 0 { 136 recvAddress = p.Receiver.Address.String() 137 } 138 139 data, err := t.serializer.SerializePacket(p) 140 if err != nil { 141 return errors.Wrap(err, "Failed to serialize packet") 142 } 143 144 inslogger.FromContext(ctx).Debugf("Send %s packet to %s with RequestID = %d", p.Type, recvAddress, p.RequestID) 145 return t.sendFunc(recvAddress, data) 146 }