func main() { lsplog.SetVerbose(3) lsplog.Vlogf(3, "[Request] Request has started") lsplog.Vlogf(3, "[Request] Args: %s", os.Args) port, _ := strconv.Atoi(os.Args[1]) srv, _ = lsp12.NewLspServer(port, &lsp12.LspParams{5, 2000}) clients = make(map[uint16]*client) workers = make(map[uint16]*worker) requestBuffer = abuf.NewBuf() workersAvailable = abuf.NewBuf() go networkHandler() //Scheduler for { workerConnId := workersAvailable.Remove().(uint16) req := requestBuffer.Remove().(*request) for clients[req.connId] == nil { req = requestBuffer.Remove().(*request) } freeWorker := workers[workerConnId] freeWorker.worksForClient = req.connId freeWorker.command = req.crackRequest srv.Write(workerConnId, []byte(req.crackRequest)) } }
// Wait until server has signaled it is done func (ts *SynchTestSystem) WaitServer() { lsplog.Vlogf(6, "Waiting for server\n") select { case d := <-ts.TChan: ts.Tester.Logf("Test reached time limit of %d waiting for server", d) ts.Tester.FailNow() case <-ts.S2MChan: } lsplog.Vlogf(6, "Got signal from server\n") }
func UDPResolve(hostport string) (*lspnet.UDPAddr, error) { lsplog.Vlogf(3, "Attempting to resolve address of %s", hostport) a, e := lspnet.ResolveUDPAddr(NET, hostport) if e != nil { lsplog.CheckFatal(e) return nil, e } lsplog.Vlogf(3, "Address %s resolved", hostport) return a, nil }
func (srv *LspServer) lspListen() error { lsplog.Vlogf(1, "[Server] Attempting to listen to port to %d", srv.udpAddr.Port) conn, e := lspnet.ListenUDP(NET, srv.udpAddr) if e != nil { lsplog.CheckFatal(e) return e } lsplog.Vlogf(1, "[Server] Listening to port %d", srv.udpAddr.Port) srv.udpConn = conn return nil }
func (cli *LspClient) udpConnect() error { lsplog.Vlogf(1, "[Client] Attempting to connect to %s:%d", cli.udpAddr.IP, cli.udpAddr.Port) b, e := lspnet.DialUDP(NET, nil, cli.udpAddr) if e != nil { lsplog.CheckFatal(e) return e } lsplog.Vlogf(6, "[Client] Connected to %s:%d", cli.udpAddr.IP, cli.udpAddr.Port) cli.udpConn = b return nil }
func (srv *LspServer) lspSend(m *LspMessage, c *clientRepresenter) { if m == nil || c == nil { lsplog.Vlogf(6, "[Server] Got a send request for m: %+v c:%+v Ignoring message", m, c) return } marshalled, err := json.Marshal(m) if err != nil { lsplog.CheckFatal(err) } lsplog.Vlogf(6, "[Server] Marshalled message: %s", marshalled) srv.udpConn.WriteToUDP(marshalled, c.addr) }
// Enable network & then Wait until it signals that it is done func (ts *SynchTestSystem) SynchNetwork() { lsplog.Vlogf(6, "Enabling Network\n") ts.M2NChan <- true lsplog.Vlogf(6, "Waiting for network\n") select { case d := <-ts.TChan: ts.Tester.Logf("Test reached time limit of %d waiting for network", d) ts.Tester.FailNow() case <-ts.N2MChan: } lsplog.Vlogf(6, "Got signal from network\n") }
// Wait until clients have that they're done func (ts *SynchTestSystem) WaitClients() { lsplog.Vlogf(6, "Waiting for clients\n") for i := 0; i < ts.Nclients; i++ { select { case d := <-ts.TChan: ts.Tester.Logf("Test reached time limit of %d waiting for client", d) ts.Tester.FailNow() case <-ts.C2MChan: } } lsplog.Vlogf(6, "Got signals from all clients\n") }
func (srv *LspServer) networkHandler() { lsplog.Vlogf(3, "[Server] Started the network handler") for { // Should loop only if the connection is still on. lsplog.Vlogf(6, "[Server] Going to read a packet") m, addr, err := srv.readPacket() if err != nil { lsplog.CheckReport(3, err) lsplog.Vlogf(6, "[Server] Ignoring this packet") continue } go srv.packetHandler(m, addr) } }
func (con *UDPConn) Write(b []byte) (int, error) { ncon := con.ncon if dropit(writeDropPercent) { lsplog.Vlogf(5, "UDP: DROPPING written packet of length %v\n", len(b)) // Make it look like write was successful return len(b), nil } else { n, err := ncon.Write(b) lsplog.Vlogf(5, "UDP: Wrote packet of length %v\v", n) return n, err } return 0, nil }
func (srv *LspServer) packetHandler(m *LspMessage, addr *lspnet.UDPAddr) { lsplog.Vlogf(6, "[Server] Packet reading has no problems.") if IsConnection(m) { lsplog.Vlogf(1, "[Server] A new connection request recieved.") srv.handleConnectionRequest(addr) } else if IsDataPacket(m) { lsplog.Vlogf(4, "[Server] A data packet is recieved.") client := srv.getClient(addr) if client != nil { <-client.finished client.epochCount = 0 if m.ConnId == client.connId { if m.SeqNum == client.clientSeqNum { srv.read.Insert(&readRequest{m.ConnId, m.Payload}) ack := CreateDataAck(m.ConnId, m.SeqNum) srv.lspSend(ack, client) client.lastAck = ack client.clientSeqNum = (client.clientSeqNum + 1) % math.MaxInt8 } else { lsplog.Vlogf(5, "[Server] Recieved data packet has an unexpected sequence (Getting: %d) (Expected: %d)", m.SeqNum, client.clientSeqNum) } } else { lsplog.Vlogf(4, "[Server] Recieved data packet has a wrong connId (Getting: %d) (Expected: %d)", m.ConnId, client.connId) } client.finished <- 1 } } else { lsplog.Vlogf(4, "[Server] An acknowledgment packet is recieved.") client := srv.getClient(addr) if client != nil { <-client.finished client.epochCount = 0 if m.ConnId == client.connId { // Make sure that the connId is the same as the client. <-srv.sentLocker deletedElements := list.New() // Delete all the elements that has been acknowledged for e := srv.sent.Front(); e != nil; e = e.Next() { request := e.Value.(*sentRequest) if request.message.SeqNum <= m.SeqNum { // If a higher sequence is recieved, that means that all previous were acknowleged. deletedElements.PushBack(e) } } for e := deletedElements.Front(); e != nil; e = e.Next() { srv.sent.Remove(e.Value.(*list.Element)) client.closable-- } srv.sentLocker <- 1 if client.closeConnection == true && client.closable == 0 { //Remove client from map key := client.addr.IP.String() + ":" + strconv.Itoa(client.addr.Port) srv.clients[key] = nil } } else { lsplog.Vlogf(4, "[Server] Recieved data packet has a wrong connId (Getting: %d) (Expected: %d)", m.ConnId, client.connId) } client.finished <- 1 } else { lsplog.Vlogf(4, "[Server] Recieved an Acknowledgment packet from an unknown client.") } } }
func (con *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { ncon := con.ncon naddr := &net.UDPAddr{addr.IP, addr.Port} if dropit(writeDropPercent) { lsplog.Vlogf(5, "UDP: DROPPING written packet of length %v\n", len(b)) // Make it look like write was successful return len(b), nil } else { n, err := ncon.WriteToUDP(b, naddr) lsplog.Vlogf(5, "UDP: Wrote packet of length %v", n) return n, err } return 0, nil }
func (ts *TestSystem) runtest(timeoutms int) { lspnet.SetWriteDropPercent(ts.DropPercent) if ts.Description != "" { fmt.Printf("Testing: %s\n", ts.Description) } go ts.runserver() for i := 0; i < ts.NClients; i++ { go ts.runclient(i) } go ts.runtimeout(timeoutms) for i := 0; i < ts.NClients; i++ { v := <-ts.CChan if v < 0 { ts.RunFlag = false ts.Tester.Logf("Test timed out after %f secs\n", float64(timeoutms)/1000.0) ts.Tester.FailNow() } } ts.RunFlag = false lsplog.Vlogf(0, "Passed: %d clients, %d messages/client, %.2f maxsleep, %.2f drop rate\n", ts.NClients, ts.NMessages, float64(ts.MaxSleepMilliseconds)/1000.0, float64(ts.DropPercent)/100.0) lsplog.SetVerbose(DefaultVerbosity) lspnet.SetWriteDropPercent(0) }
// Have client generate n messages and check that they are echoed. func (ts *TestSystem) runclient(clienti int) { if clienti > ts.NClients { ts.Tester.Logf("Invalid client number %d\n", clienti) ts.Tester.FailNow() } cli := ts.Clients[clienti] for i := 0; i < ts.NMessages && ts.RunFlag; i++ { wt := ts.Rgen.Intn(100) werr := cli.Write(i2b(i + wt)) if werr != nil { ts.Tester.Logf("Client write got error '%s'\n", werr.Error()) ts.RunFlag = false ts.Tester.FailNow() } b, rerr := cli.Read() if rerr != nil { ts.Tester.Logf("Client read got error '%s'\n", rerr.Error()) ts.RunFlag = false ts.Tester.FailNow() } v := b2i(b) if v != wt+i { ts.Tester.Logf("Client got %d. Expected %d\n", v, i+wt) ts.RunFlag = false ts.Tester.FailNow() } } cli.Close() lsplog.Vlogf(0, "Client #%d completed %d messages\n", clienti, ts.NMessages) ts.CChan <- 0 }
// Shutting down network communications func (cli *LspClient) stopNetwork() { cli.lspConn.stopNetworkFlag = true err := cli.udpConn.Close() if lsplog.CheckReport(4, err) { lsplog.Vlogf(6, "Client Continuing\n") } }
// Function to coordinate tests func (ts *SynchTestSystem) Master() { // Wait until server and all clients are ready ts.WaitServer() ts.WaitClients() lsplog.Vlogf(4, "Server + all clients started. Shut off network\n") ts.SynchNetwork() // Network Off // Enable client writes if ts.Mode != doservertoclient { ts.ReadyClients() ts.WaitClients() } // Do fast close of client. The calls will not be able to complete if ts.Mode == doclienttoserver { ts.ReadyClients() } if ts.Mode != doservertoclient { // Turn on network and delay ts.SynchNetwork() if ts.Mode == doclienttoserver { ts.WaitClients() } ts.SynchNetwork() // Network off // Enable server reads ts.ReadyServer() ts.WaitServer() } // Do server writes if ts.Mode != doclienttoserver { ts.ReadyServer() ts.WaitServer() } // Do fast close of server. The calls will not be able to complete if ts.Mode != doroundtrip { ts.ReadyServer() } if ts.Mode != doclienttoserver { // Turn on network ts.SynchNetwork() if ts.Mode != doroundtrip { // If did quick close, should get responses from server ts.WaitServer() } // Network off again ts.SynchNetwork() // Enable client reads ts.ReadyClients() ts.WaitClients() // Enable client closes ts.ReadyClients() ts.WaitClients() } // Final close by server if ts.Mode == doroundtrip { ts.ReadyServer() ts.WaitServer() } // Made it! }
// Shut down all network activity func (srv *LspServer) stopGlobalNetwork() { srv.stopGlobalNetworkFlag = true err := srv.udpConn.Close() if lsplog.CheckReport(4, err) { lsplog.Vlogf(6, "Server Continuing\n") } }
func (cli *LspClient) iWrite(payload []byte) error { lsplog.Vlogf(2, "[Client] Application is attempting to write") if cli.connectionAlive { go cli.iWriteHandler(payload) // Defers reading to the write handler so the application don't get blocked. return nil } return lsplog.MakeErr("Connection is no alive. Payload is ignored.") }
func (cli *LspClient) lspSend(message *LspMessage) { marshalled, err := json.Marshal(message) if err != nil { lsplog.CheckFatal(err) } lsplog.Vlogf(6, "[Client] Marshalled message: %s", marshalled) cli.udpConn.Write(marshalled) }
func (cli *LspClient) lspConnect() { e := cli.udpConnect() if e != nil { lsplog.CheckFatal(e) panic("[Client] Unable to establish a connection.") } connectMessage := CreateConnectionPacket() lsplog.Vlogf(5, "[Client] Inserting connection message into sent buffer.") <-cli.sentLocker cli.sent.PushBack(connectMessage) cli.sentLocker <- 1 cli.lspSend(connectMessage) go cli.networkHandler() // Starts the network handler for reading. Making sure it is fired after a UDP is issued. go cli.epochHandler() <-cli.connectedSyncer // Wait for the connection to be established. lsplog.Vlogf(1, "[Client] Connection established completely.") }
func (cli *LspClient) epochHandler() { lsplog.Vlogf(3, "[Client] Started the epoch handler") for cli.epochCounter < cli.params.EpochLimit { epoch := time.Duration(cli.params.EpochMilliseconds) * time.Millisecond time.Sleep(epoch) lsplog.Vlogf(3, "[Client] Epoch has awaken.") <-cli.sentLocker for e := cli.sent.Front(); e != nil; e = e.Next() { m := e.Value.(*LspMessage) lsplog.Vlogf(5, "[Client] Epoch is sending: %+v", m) cli.lspSend(m) } if cli.closeConnection && cli.sent.Len() == 0 { lsplog.Vlogf(3, "[Client] Exiting the network handler") cli.sentLocker <- 1 break } cli.sentLocker <- 1 lsplog.Vlogf(6, "[Client] Sending last recieved ack to server %+v", cli.lastAck) if cli.lastAck != nil { cli.lspSend(cli.lastAck) } <-cli.epochLocker cli.epochCounter++ lsplog.Vlogf(6, "[Client] Increased server epoch counter %d", cli.epochCounter) cli.epochLocker <- 1 } cli.terminateConnection() lsplog.Vlogf(1, "[Client] Connection is terminated.") }
func (con *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { var buffer [2000]byte ncon := con.ncon var naddr *net.UDPAddr n, naddr, err = ncon.ReadFromUDP(buffer[0:]) if dropit(readDropPercent) { lsplog.Vlogf(5, "UDP: DROPPING read packet of length %v\n", n) } else { lsplog.Vlogf(6, "UDP: Read packet of length %v\n", n) copy(b, buffer[0:]) } if naddr == nil { addr = nil } else { addr = &UDPAddr{naddr.IP, naddr.Port} } return n, addr, err }
// Close only specified connection func (srv *LspServer) iCloseConn(connId uint16) { lsplog.Vlogf(3, "[Server] Application closed %d", connId) for _, v := range srv.clients { if v.connId == connId { v.closeConnection = true return } } }
// Turn network off and on func (ts *SynchTestSystem) RunNetwork() { // Network initially on lspnet.SetWriteDropPercent(0) for ts.RunFlag { lsplog.Vlogf(4, "Network running. Waiting for master\n") <-ts.M2NChan lsplog.Vlogf(4, "Turning off network\n") lspnet.SetWriteDropPercent(100) ts.N2MChan <- true lsplog.Vlogf(4, "Network off. Waiting for master\n") <-ts.M2NChan lsplog.Vlogf(4, "Turning network on and delaying\n") lspnet.SetWriteDropPercent(0) ts.N2MChan <- true ts.synchdelay(2.0) } lsplog.Vlogf(4, "Network handler exiting\n") }
func (cli *LspClient) iRead() ([]byte, error) { lsplog.Vlogf(2, "[Client] Application is attempting to read") if cli.connectionAlive { element := cli.read.Remove() if element == nil { return nil, lsplog.MakeErr("Connection is lost with server") } return element.([]byte), nil } return nil, lsplog.MakeErr("Connection is lost. Cannot read.") }
// Write message to specified client func (srv *LspServer) iWrite(connId uint16, payload []byte) error { lsplog.Vlogf(2, "[Server] Application is writing") for _, v := range srv.clients { // Looks for the client to send if v.connId == connId { m := CreateDataPacket(connId, v.serverSeqNum, payload) go srv.iWriteHandler(m, v) return nil } } return lsplog.MakeErr("Could not find specified connId") }
func (cli *LspClient) iWrite(payload []byte) error { // Will fill in ID & sequence number later m := GenDataMessage(0, 0, payload) cli.appWriteChan <- m rm := <-cli.writeReplyChan lsplog.Vlogf(5, "Completed write of %s", string(payload)) if rm != nil { // Recycle so that subsequent writes will get error cli.writeReplyChan <- rm } return rm }
func main() { lsplog.SetVerbose(3) lsplog.Vlogf(3, "[Request] Request has started") lsplog.Vlogf(3, "[Request] Args: %s", os.Args) hostport := os.Args[1] var e error client, e = lsp12.NewLspClient(hostport, &lsp12.LspParams{5, 2000}) if e != nil { lsplog.Vlogf(3, "[Worker] Connection to server failed.") } joinRequest := "J" lsplog.Vlogf(3, "[worker] Sending: %s", joinRequest) client.Write([]byte(joinRequest)) for { response, err := client.Read() if err != nil { return } lsplog.Vlogf(3, "[Worker] Recieved: %s", string(response)) responseParts := strings.Split(string(response), " ") if len(responseParts) == 4 { hash := responseParts[1] lsplog.Vlogf(3, "[Worker] Hash: %s", hash) lower, _ := strconv.Atoi(responseParts[2]) upper, _ := strconv.Atoi(responseParts[3]) go getPassword(hash, lower, upper) } else { suspended = true } } }
func (cli *LspClient) readPacket() (m *LspMessage, addr *lspnet.UDPAddr, e error) { b := make([]byte, 1000) n, addr, err := cli.udpConn.ReadFromUDP(b) if addr == nil || n == 0 { lsplog.Vlogf(3, "[Client] Recieved a terminating packet.") return nil, addr, lsplog.ConnectionClosed() } else { lsplog.Vlogf(5, "[Client] Recieved a packet from %s:%d", addr.IP.String(), addr.Port) } if err != nil { lsplog.CheckFatal(err) return nil, nil, err } recieved := CreateEmptyPacket() err = json.Unmarshal(b[0:n], recieved) if err != nil { lsplog.CheckReport(3, err) return nil, addr, err } lsplog.Vlogf(6, "[Client] Recieved packet %+v", recieved) return recieved, addr, err }
func (srv *LspServer) handleConnectionRequest(addr *lspnet.UDPAddr) { key := addr.IP.String() + ":" + strconv.Itoa(addr.Port) var client *clientRepresenter if srv.clients[key] == nil { lsplog.Vlogf(6, "[Server] A new client is being connected %s", key) client = new(clientRepresenter) srv.idGenerator++ client.connId = srv.idGenerator client.seq = 1 client.addr = addr client.finished = make(chan int, 1) client.finished <- 1 client.clientSeqNum = 1 client.serverSeqNum = 1 srv.clients[key] = client lsplog.Vlogf(3, "[Server] A new client is connected %+v", client) } else { client = srv.clients[key] } m := CreateConnnectionAckPacket(client.connId) srv.lspSend(m, client) client.lastAck = m }