func (srv *LspServer) iRead() (uint16, []byte, error) { m := <-srv.appReadChan switch m.Type { case MsgDATA: return m.ConnId, m.Payload, nil case MsgINVALID: // Indicates that read should fail. return m.ConnId, nil, lsplog.ConnectionClosed() } return m.ConnId, nil, lsplog.ConnectionClosed() }
func (cli *LspClient) iRead() ([]byte, error) { m := <-cli.appReadChan switch m.Type { case MsgDATA: return m.Payload, nil case MsgINVALID: // Indicates that read should fail // Recycle message so that future reads will also fail cli.appReadChan <- m return nil, lsplog.ConnectionClosed() } return nil, lsplog.ConnectionClosed() }
func (cli *LspClient) iRead() ([]byte, error) { select { case <-cli.eventHandClosedChan: cli.eventHandClosed = true return nil, lsplog.ConnectionClosed() default: if cli.eventHandClosed { return nil, lsplog.ConnectionClosed() } <-cli.Rchan msg := <-cli.RBchan if msg == nil { return nil, lsplog.ConnectionClosed() } return msg.Payload, nil } return nil, lsplog.ConnectionClosed() }
// Read next message received by server, return connection ID + contents func (srv *LspServer) iRead() (uint16, []byte, error) { select { case <-srv.eventHandClosedChan: srv.eventHandClosed = true return 0, nil, lsplog.ConnectionClosed() default: if srv.eventHandClosed { return 0, nil, lsplog.ConnectionClosed() } <-srv.Rchan msg := <-srv.RBchan if msg == nil { return 0, nil, lsplog.ConnectionClosed() } if msg.Type == MsgINVALID { return msg.ConnId, nil, lsplog.ConnectionClosed() } return msg.ConnId, msg.Payload, nil } return 0, nil, lsplog.ConnectionClosed() }
// Main client loop func (cli *LspClient) clientLoop() { for !(cli.stopAppFlag && cli.lspConn.stopNetworkFlag) { if cli.readBuf.Empty() { select { case netm := <-cli.netInChan: cli.handleNetMessage(netm) case appm := <-cli.appWriteChan: cli.handleAppWrite(appm) case <-cli.epochChan: cli.handleEpoch() } } else { v := cli.readBuf.Front() rm := v.(*LspMessage) if rm.Type == MsgINVALID { // Have completed all reads. Stop applications cli.stopAppFlag = true } select { case netm := <-cli.netInChan: cli.handleNetMessage(netm) case appm := <-cli.appWriteChan: cli.handleAppWrite(appm) case <-cli.epochChan: cli.handleEpoch() case cli.appReadChan <- rm: cli.readBuf.Remove() } } cli.checkToSend() } // Make sure any subsequent operations fail cli.closeReplyChan <- nil cli.writeReplyChan <- lsplog.ConnectionClosed() cm := GenInvalidMessage(0, 0) cli.appReadChan <- cm }
// go routine to handle writing and epochs events func EventHandlerClient(cli *LspClient) { for cli.running || cli.readList.Len() != 0 || cli.NbWrite != 0 { if cli.readList.Len() == 0 { select { case msg, _ := <-cli.WBchan: if !cli.running { cli.errChan <- lsplog.ConnectionClosed() continue } cli.errChan <- nil msg.SeqNum = cli.sn cli.sn++ if cli.sn == 0 { cli.sn = 1 } if cli.AckWrite && cli.writeList.Len() == 0 { select { case cli.Wchan <- 1: default: } } cli.writeList.PushBack(msg) cli.NbWrite++ case msg, _ := <-cli.Nchan: cli.epochCount = 0 switch msg.Type { case MsgACK: if cli.id == 0 && msg.SeqNum == 0 { cli.NbWrite-- cli.id = msg.ConnId cli.established <- 1 cli.AckWrite = true if cli.writeList.Len() != 0 { select { case cli.Wchan <- 1: default: } } } else if msg.ConnId == cli.id && msg.SeqNum == cli.lastWrite.SeqNum && !cli.AckWrite { cli.NbWrite-- cli.AckWrite = true if cli.writeList.Len() != 0 { select { case cli.Wchan <- 1: default: } } } case MsgDATA: if !cli.running { continue } if msg.SeqNum == cli.rcvn { cli.rcvn++ if cli.rcvn == 0 { cli.rcvn = 1 } //cli.epochCount = 0 cli.readList.PushBack(msg) cli.lastRead = msg // send an ACK ack, _ := buildMSG(MsgACK, msg.ConnId, msg.SeqNum, nil) msgAck, _ := marshalMSG(ack) cli.conn.Write(msgAck) } } case <-cli.Wchan: cli.AckWrite = false cli.lastWrite = (cli.writeList.Remove(cli.writeList.Front())).(*LspMessage) b, _ := marshalMSG(cli.lastWrite) cli.conn.Write(b) case <-cli.Echan: if !cli.AckWrite { b, _ := marshalMSG(cli.lastWrite) cli.conn.Write(b) } if cli.lastRead != nil { ack, _ := buildMSG(MsgACK, cli.lastRead.ConnId, cli.lastRead.SeqNum, nil) msgAck, _ := marshalMSG(ack) cli.conn.Write(msgAck) } else { ack, _ := buildMSG(MsgACK, cli.id, 0, nil) msgAck, _ := marshalMSG(ack) cli.conn.Write(msgAck) } cli.epochCount++ if cli.epochCount == cli.params.EpochLimit { cli.exitEpochHandler <- 1 } else { <-cli.continueEpochHandler } cli.EchanBack <- 1 case <-cli.CloseChanEpoch: cli.writeList = new(list.List) cli.running = false cli.AckWrite = true cli.NbWrite = 0 cli.conn.Close() cli.CloseNetworkChan <- 1 case <-cli.CloseChan: cli.readList = new(list.List) cli.running = false } } else { select { case msg, _ := <-cli.WBchan: if !cli.running { cli.errChan <- lsplog.ConnectionClosed() continue } cli.errChan <- nil msg.SeqNum = cli.sn cli.sn++ if cli.sn == 0 { cli.sn = 1 } if cli.AckWrite && cli.writeList.Len() == 0 { select { case cli.Wchan <- 1: default: } } cli.writeList.PushBack(msg) cli.NbWrite++ case cli.Rchan <- 1: cli.RBchan <- (cli.readList.Remove(cli.readList.Front())).(*LspMessage) case msg, _ := <-cli.Nchan: cli.epochCount = 0 switch msg.Type { case MsgACK: if cli.id == 0 && msg.SeqNum == 0 { cli.NbWrite-- cli.id = msg.ConnId cli.established <- 1 cli.AckWrite = true if cli.writeList.Len() != 0 { select { case cli.Wchan <- 1: default: } } } else if msg.ConnId == cli.id && msg.SeqNum == cli.lastWrite.SeqNum && !cli.AckWrite { cli.NbWrite-- cli.AckWrite = true if cli.writeList.Len() != 0 { select { case cli.Wchan <- 1: default: } } } case MsgDATA: if !cli.running { continue } if msg.SeqNum == cli.rcvn { cli.rcvn++ if cli.rcvn == 0 { cli.rcvn = 1 } //cli.epochCount = 0 cli.readList.PushBack(msg) cli.lastRead = msg // send an ACK ack, _ := buildMSG(MsgACK, msg.ConnId, msg.SeqNum, nil) msgAck, _ := marshalMSG(ack) cli.conn.Write(msgAck) } } case <-cli.Wchan: cli.AckWrite = false cli.lastWrite = (cli.writeList.Remove(cli.writeList.Front())).(*LspMessage) b, _ := marshalMSG(cli.lastWrite) cli.conn.Write(b) case <-cli.Echan: if !cli.AckWrite { b, _ := marshalMSG(cli.lastWrite) cli.conn.Write(b) } if cli.lastRead != nil { ack, _ := buildMSG(MsgACK, cli.lastRead.ConnId, cli.lastRead.SeqNum, nil) msgAck, _ := marshalMSG(ack) cli.conn.Write(msgAck) } else { ack, _ := buildMSG(MsgACK, cli.id, 0, nil) msgAck, _ := marshalMSG(ack) cli.conn.Write(msgAck) } cli.epochCount++ if cli.epochCount == cli.params.EpochLimit { cli.exitEpochHandler <- 1 } else { <-cli.continueEpochHandler } cli.EchanBack <- 1 case <-cli.CloseChanEpoch: cli.writeList = new(list.List) cli.AckWrite = true cli.running = false cli.NbWrite = 0 cli.conn.Close() cli.CloseNetworkChan <- 1 case <-cli.CloseChan: cli.readList = new(list.List) cli.running = false } } } cli.eventHandClosedChan <- 1 cli.CloseNetworkChan <- 1 cli.exitEpochHandler <- 1 cli.conn.Close() cli.writeEnded <- 1 select { case cli.Rchan <- 1: cli.RBchan <- nil default: } }
// go routine to handle writing and epochs events func EventHandlerServer(srv *LspServer) { for srv.running || srv.NbWrite != 0 || srv.readList.Len() != 0 { if srv.readList.Len() == 0 { select { case msg, _ := <-srv.WBchan: if !srv.running || !srv.ClientDict[msg.ConnId].readClient { srv.errChan <- lsplog.ConnectionClosed() continue } srv.errChan <- nil msg.SeqNum = srv.ClientDict[msg.ConnId].sn srv.ClientDict[msg.ConnId].sn++ if srv.ClientDict[msg.ConnId].sn == 0 { srv.ClientDict[msg.ConnId].sn = 1 } select { case srv.Wchan <- 1: default: } srv.ClientDict[msg.ConnId].writeList.PushBack(msg) srv.NbWrite++ case msg, _ := <-srv.Nchan: if !srv.running && srv.NbWrite == 0 { continue } srv.epochCount = 0 if msg.ConnId != 0 { srv.ClientDict[msg.ConnId].epochCount = 0 } switch msg.Type { case MsgCONNECT: if msg.SeqNum == 0 && msg.ConnId == 0 { // connect request newcli := new(iClient) newcli.id = srv.connId newcli.readClient = true newcli.writeClient = true newcli.sn = 1 newcli.epochCount = 0 newcli.rcvn = 1 newcli.lastSeqAcked = 0 newcli.AckWrite = true newcli.writeList = new(list.List) newcli.clientAddr = <-srv.Addrchan newcli.lastRead = msg srv.ClientDict[srv.connId] = newcli ack, _ := buildMSG(MsgACK, srv.connId, 0, nil) msgAck, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgAck, newcli.clientAddr) srv.connId++ } case MsgACK: if msg.SeqNum == 0 { continue } front := srv.ClientDict[msg.ConnId].lastWrite if msg.SeqNum == front.SeqNum && msg.SeqNum != srv.ClientDict[msg.ConnId].lastSeqAcked { //srv.epochCount = 0 srv.ClientDict[msg.ConnId].lastSeqAcked = msg.SeqNum srv.ClientDict[msg.ConnId].AckWrite = true srv.NbWrite-- if srv.ClientDict[msg.ConnId].writeList.Len() != 0 { select { case srv.Wchan <- 1: default: } } } case MsgDATA: if !srv.running { continue } if srv.ClientDict[msg.ConnId].readClient && msg.SeqNum == srv.ClientDict[msg.ConnId].rcvn { //srv.epochCount = 0 srv.readList.PushBack(msg) srv.ClientDict[msg.ConnId].lastRead = msg srv.ClientDict[msg.ConnId].rcvn++ if srv.ClientDict[msg.ConnId].rcvn == 0 { srv.ClientDict[msg.ConnId].rcvn = 1 } // send an ACK ack, _ := buildMSG(MsgACK, msg.ConnId, msg.SeqNum, nil) msgAck, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgAck, srv.ClientDict[msg.ConnId].clientAddr) } } case <-srv.Wchan: for _, v := range srv.ClientDict { if !v.AckWrite || v.writeList.Len() == 0 { continue } if !v.writeClient { v.writeList.Remove(v.writeList.Front()) srv.NbWrite-- continue } v.lastWrite = (v.writeList.Remove(v.writeList.Front())).(*LspMessage) v.AckWrite = false msgW, _ := marshalMSG(v.lastWrite) srv.conn.WriteToUDP(msgW, v.clientAddr) } case <-srv.Echan: for _, v := range srv.ClientDict { if !v.writeClient { continue } if !v.readClient && v.writeList.Len() == 0 { v.writeClient = false continue } v.epochCount++ if v.epochCount == srv.params.EpochLimit { msgDisconnect, _ := buildMSG(MsgINVALID, v.id, 0, nil) srv.readList.PushBack(msgDisconnect) v.readClient = false v.writeClient = false continue } if !v.AckWrite { msgW, _ := marshalMSG(v.lastWrite) srv.conn.WriteToUDP(msgW, v.clientAddr) } if v.lastRead != nil { ack, _ := buildMSG(MsgACK, v.id, v.lastRead.SeqNum, nil) msgR, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgR, v.clientAddr) } else { ack, _ := buildMSG(MsgACK, v.id, 0, nil) msgR, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgR, v.clientAddr) } } srv.epochCount++ if srv.epochCount == srv.params.EpochLimit { srv.exitEpochHandler <- 1 } else { <-srv.continueEpochHandler } srv.EchanBack <- 1 case <-srv.CloseChan: srv.running = false srv.readList = new(list.List) for _, cli := range srv.ClientDict { cli.readClient = false } case <-srv.CloseChanEpoch: srv.NbWrite = 0 srv.CloseNetworkChan <- 1 srv.conn.Close() srv.running = false for id, cli := range srv.ClientDict { msgDisconnect, _ := buildMSG(MsgINVALID, id, 0, nil) srv.readList.PushBack(msgDisconnect) cli.readClient = false cli.writeClient = false } case id, _ := <-srv.CloseConnChan: srv.ClientDict[id].readClient = false msgDisconnect, _ := buildMSG(MsgINVALID, id, 0, nil) srv.readList.PushBack(msgDisconnect) } } else { select { case srv.Rchan <- 1: srv.RBchan <- (srv.readList.Remove(srv.readList.Front())).(*LspMessage) case msg, _ := <-srv.WBchan: if !srv.running || !srv.ClientDict[msg.ConnId].readClient { srv.errChan <- lsplog.ConnectionClosed() continue } srv.errChan <- nil msg.SeqNum = srv.ClientDict[msg.ConnId].sn srv.ClientDict[msg.ConnId].sn++ if srv.ClientDict[msg.ConnId].sn == 0 { srv.ClientDict[msg.ConnId].sn = 1 } select { case srv.Wchan <- 1: default: } srv.ClientDict[msg.ConnId].writeList.PushBack(msg) srv.NbWrite++ case msg, _ := <-srv.Nchan: if !srv.running && srv.NbWrite == 0 { continue } srv.epochCount = 0 if msg.ConnId != 0 { srv.ClientDict[msg.ConnId].epochCount = 0 } switch msg.Type { case MsgCONNECT: if msg.SeqNum == 0 && msg.ConnId == 0 { // connect request newcli := new(iClient) newcli.id = srv.connId newcli.readClient = true newcli.writeClient = true newcli.sn = 1 newcli.rcvn = 1 newcli.epochCount = 0 newcli.AckWrite = true newcli.lastSeqAcked = 0 newcli.writeList = new(list.List) newcli.clientAddr = <-srv.Addrchan srv.ClientDict[srv.connId] = newcli ack, _ := buildMSG(MsgACK, srv.connId, 0, nil) msgAck, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgAck, newcli.clientAddr) srv.connId++ } case MsgACK: if msg.SeqNum == 0 { continue } front := srv.ClientDict[msg.ConnId].lastWrite if msg.SeqNum == front.SeqNum && msg.SeqNum != srv.ClientDict[msg.ConnId].lastSeqAcked { //srv.epochCount = 0 srv.ClientDict[msg.ConnId].lastSeqAcked = msg.SeqNum srv.ClientDict[msg.ConnId].AckWrite = true srv.NbWrite-- if srv.ClientDict[msg.ConnId].writeList.Len() != 0 { select { case srv.Wchan <- 1: default: } } } case MsgDATA: if !srv.running { continue } if srv.ClientDict[msg.ConnId].readClient && msg.SeqNum == srv.ClientDict[msg.ConnId].rcvn { //srv.epochCount = 0 srv.readList.PushBack(msg) srv.ClientDict[msg.ConnId].lastRead = msg srv.ClientDict[msg.ConnId].rcvn++ if srv.ClientDict[msg.ConnId].rcvn == 0 { srv.ClientDict[msg.ConnId].rcvn = 1 } // send an ACK ack, _ := buildMSG(MsgACK, msg.ConnId, msg.SeqNum, nil) msgAck, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgAck, srv.ClientDict[msg.ConnId].clientAddr) } } case <-srv.Wchan: for _, v := range srv.ClientDict { if !v.AckWrite || v.writeList.Len() == 0 { continue } if !v.writeClient { v.writeList.Remove(v.writeList.Front()) srv.NbWrite-- continue } v.lastWrite = (v.writeList.Remove(v.writeList.Front())).(*LspMessage) v.AckWrite = false msgW, _ := marshalMSG(v.lastWrite) srv.conn.WriteToUDP(msgW, v.clientAddr) } case <-srv.Echan: for _, v := range srv.ClientDict { if !v.writeClient { continue } if !v.readClient && v.writeList.Len() == 0 { v.writeClient = false continue } v.epochCount++ if v.epochCount == srv.params.EpochLimit { msgDisconnect, _ := buildMSG(MsgINVALID, v.id, 0, nil) srv.readList.PushBack(msgDisconnect) v.readClient = false v.writeClient = false continue } if !v.AckWrite { msgW, _ := marshalMSG(v.lastWrite) srv.conn.WriteToUDP(msgW, v.clientAddr) } if v.lastRead != nil { ack, _ := buildMSG(MsgACK, v.id, v.lastRead.SeqNum, nil) msgR, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgR, v.clientAddr) } else { ack, _ := buildMSG(MsgACK, v.id, 0, nil) msgR, _ := marshalMSG(ack) srv.conn.WriteToUDP(msgR, v.clientAddr) } } srv.epochCount++ if srv.epochCount == srv.params.EpochLimit { srv.exitEpochHandler <- 1 } else { <-srv.continueEpochHandler } srv.EchanBack <- 1 case <-srv.CloseChan: srv.running = false srv.readList = new(list.List) for _, cli := range srv.ClientDict { cli.readClient = false } case <-srv.CloseChanEpoch: srv.NbWrite = 0 srv.CloseNetworkChan <- 1 srv.conn.Close() srv.running = false for id, cli := range srv.ClientDict { msgDisconnect, _ := buildMSG(MsgINVALID, id, 0, nil) srv.readList.PushBack(msgDisconnect) cli.readClient = false cli.writeClient = false } case id, _ := <-srv.CloseConnChan: srv.ClientDict[id].readClient = false msgDisconnect, _ := buildMSG(MsgINVALID, id, 0, nil) srv.readList.PushBack(msgDisconnect) } } } srv.eventHandClosedChan <- 1 srv.conn.Close() srv.exitEpochHandler <- 1 srv.CloseNetworkChan <- 1 srv.writeEnded <- 1 select { case srv.Rchan <- 1: srv.RBchan <- nil default: } }