github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/gp/stream.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package gp 4 5 import ( 6 etime "../earth-time" 7 "../protocol" 8 ) 9 10 // Stream use to send or receive data on specific connection. 11 // It can pass to logic layer to give data access to developer! 12 // Data flow can be up to down (parse raw income data) or down to up (encode app data with respect MTU) 13 // If OutcomePayload not present stream is UnidirectionalStream otherwise it is BidirectionalStream! 14 type Stream struct { 15 id uint32 // Even number for Peer(who start connection). Odd number for server(who accept connection). 16 connection *Connection 17 protocolID protocol.NetworkApplicationProtocolID 18 service protocol.Service 19 incomeData protocol.Codec 20 outcomeData protocol.Codec 21 22 /* State */ 23 status protocol.ConnectionState // States locate in const of this file. 24 state chan protocol.ConnectionState // States locate in const of this file. 25 Weight protocol.ConnectionWeight // 16 queue for priority weight of the streams exist. 26 27 /* Metrics */ 28 TotalPacket uint32 // Expected packets count that must received! 29 PacketReceived uint32 // Count of packets received! 30 LastPacketID uint32 // Last send or received Packet use to know order of packets! 31 PacketDropCount uint8 // Count drop packets to prevent some attacks type! 32 } 33 34 func (st *Stream) ID() uint32 { return st.id } 35 func (st *Stream) Connection() protocol.Connection { return st.connection } 36 func (st *Stream) Service() protocol.Service { return st.service } 37 func (st *Stream) ProtocolID() protocol.NetworkApplicationProtocolID { return st.protocolID } 38 func (st *Stream) Status() protocol.ConnectionState { return st.status } 39 func (st *Stream) State() chan protocol.ConnectionState { return st.state } 40 func (st *Stream) IncomeData() protocol.Codec { return st.incomeData } 41 func (st *Stream) OutcomeData() protocol.Codec { return st.outcomeData } 42 func (st *Stream) SetIncomeData(codec protocol.Codec) { st.incomeData = codec } 43 func (st *Stream) SetOutcomeData(codec protocol.Codec) { st.outcomeData = codec } 44 45 // SetService check and if it is first time register given service for the stream. 46 func (st *Stream) SetService(service protocol.Service) { 47 if st.service != nil { 48 st.service = service 49 } 50 } 51 52 53 // SendRequest use for default and empty switch port due to non of ports can be nil! 54 // SendAndWait register stream in send pool and block caller until response ready to read. 55 func (st *Stream) SendRequest() (err protocol.Error) { 56 57 var outcomeData = stream.OutcomeData() 58 if outcomeData != nil { 59 } 60 61 // st.Send() 62 63 // Listen to response stream and decode error ID and return it to caller 64 var responseStatus protocol.ConnectionState = <-st.State() 65 if responseStatus == protocol.ConnectionStateReady { 66 67 } else { 68 69 } 70 71 // Last Close response stream! 72 st.Close() 73 return 74 } 75 76 // SendResponse register stream in send pool. Usually use to send response stream. 77 func (st *Stream) SendResponse() (err protocol.Error) { 78 // First Check st.Connection.Status to ability send stream over it 79 80 // TODO::: remove this check when remove IP support 81 // if st.Connection.IPAddr != [16]byte{} { 82 // Send by IP 83 // } else { 84 // Send stream by GP 85 // } 86 87 // send stream by weight 88 89 /* Metrics data */ 90 // c.BytesSent += uint64(len(st.OutcomePayload)) 91 92 // Last Close stream! 93 st.Close() 94 return 95 } 96 97 // CloseStream delete given Stream from pool 98 func (st *Stream) Close() { 99 sp.mutex.Lock() 100 delete(st.connection.StreamPool.p, st.id) 101 sp.mutex.Unlock() 102 } 103 104 // SetState change state of stream and send notification on stream StateChannel. 105 func (st *Stream) SetState(state protocol.ConnectionState) { 106 // atomic.StoreUInt64(&st.State, state) 107 st.State = state 108 // notify stream listener that stream state has been changed! 109 st.StateChannel <- state 110 } 111 112 // Authorize authorize request by data in related stream and connection. 113 func (st *Stream) Authorize() (err protocol.Error) { 114 // if st.Connection().UserID() != protocol.OS.AppManifest().AppUUID() { 115 // // TODO::: Attack?? 116 // err = ErrNotAuthorizeRequest 117 // return 118 // } 119 120 err = st.Service.Authorization.UserType.Check(st.Connection.UserType) 121 if err != nil { 122 return 123 } 124 125 err = st.Connection.AccessControl.AuthorizeWhen(etime.Now().Weekdays(), etime.Now().DayHours()) 126 if err != nil { 127 return 128 } 129 err = st.Connection.AccessControl.AuthorizeWhich(st.Service.ID, st.Service.Authorization.CRUD) 130 if err != nil { 131 return 132 } 133 err = st.Connection.AccessControl.AuthorizeWhere(st.Connection.GPAddr.GetSocietyID(), st.Connection.GPAddr.GetRouterID()) 134 if err != nil { 135 return 136 } 137 return 138 } 139 140 // MakeNewStream use to make new stream without any connection exist yet! 141 // TODO::: due to IPv4&&IPv6 support we need this func! Remove it when remove those support! 142 func MakeNewStream() (st *Stream, err protocol.Error) { 143 // TODO::: check server allow make new connection and has enough resource 144 145 st = &Stream{ 146 // ID: 0, 147 State: protocol.ConnectionStateOpening, 148 StateChannel: make(chan protocol.ConnectionState), 149 } 150 return 151 }