diff --git a/hydrachat/chat_test.go b/hydrachat/chat_test.go new file mode 100644 index 0000000..865a2bd --- /dev/null +++ b/hydrachat/chat_test.go @@ -0,0 +1,140 @@ +package hydrachat + +import ( + "bufio" + "fmt" + "math/rand" + "net" + "strings" + "sync" + "testing" + "time" +) + +/* +func TestRun(t *testing.T) { + go func() { + t.Log("Starting Hydra chat server.. ") + if err := Run(":2301"); err != nil { + t.Error("Could not start chat server ", err) + return + } else { + t.Log("Started Hydra chat server... ") + } + }() + + time.Sleep(1 * time.Second) + + rand.Seed(time.Now().UnixNano()) + name := fmt.Sprintf("Anonymous%d", rand.Intn(400)) + + t.Logf("Hello %s, connecting to the hydra chat system.... \n", name) + conn, err := net.Dial("tcp", "127.0.0.1:2000") + if err != nil { + t.Fatal("Could not connect to hydra chat system", err) + } + t.Log("Connected to hydra chat system") + name += ":" + //name:my chat message + defer conn.Close() + msgCh := make(chan string) + + go func() { + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + recvmsg := scanner.Text() + sentmsg := <-msgCh + if strings.Compare(recvmsg, sentmsg) != 0 { + t.Errorf("Chat message %s does not match %s", recvmsg, sentmsg) + } + } + }() + for i := 0; i <= 10; i++ { + msgbody := fmt.Sprintf("RandomMessage %d", rand.Intn(400)) + msg := name + msgbody + //Anonymous4:RandomMessage 1 + _, err = fmt.Fprintf(conn, msg+"\n") + if err != nil { + t.Error(err) + return + //t.Fatal("error message") + } + msgCh <- msg + } +} +*/ + +var once sync.Once + +func chatServerFunc(t *testing.T) func() { + return func() { + t.Log("Starting Hydra chat server.. ") + if err := Run(":2300"); err != nil { + t.Error("Could not start chat server ", err) + return + } else { + t.Log("Started Hydra chat server...") + } + } +} + +func TestRun(t *testing.T) { + if testing.Short() { + t.Skip("Skipping test in short mode... ") + } + t.Log("Testing hydra chat send and receive... ") + + go once.Do(chatServerFunc(t)) + + //Let's wait for one second assuming the chat server succeeded + time.Sleep(1 * time.Second) + + rand.Seed(time.Now().UnixNano()) + name := fmt.Sprintf("Anonymous%d", rand.Intn(400)) + + t.Logf("Hello %s, connecting to the hydra chat system.... \n", name) + conn, err := net.Dial("tcp", "127.0.0.1:2300") + if err != nil { + t.Fatal("Could not connect to hydra chat system", err) + } + t.Log("Connected to hydra chat system") + name += ":" + defer conn.Close() + msgCh := make(chan string) + + go func() { + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + recvmsg := scanner.Text() + sentmsg := <-msgCh + if strings.Compare(recvmsg, sentmsg) != 0 { + t.Errorf("Chat message %s does not match %s", recvmsg, sentmsg) + } + } + }() + + for i := 0; i <= 10; i++ { + msgbody := fmt.Sprintf("RandomMessage %d", rand.Intn(400)) + msg := name + msgbody + _, err = fmt.Fprintf(conn, msg+"\n") + if err != nil { + t.Error(err) + return + } + msgCh <- msg + } +} + +func TestServerConnection(t *testing.T) { + t.Log("Test hydra chat receive messages... ") + f := chatServerFunc(t) + go once.Do(f) + //Let's wait for one second assuming the chat server succeeded + time.Sleep(1 * time.Second) + + conn, err := net.Dial("tcp", "127.0.0.1:2300") + if err != nil { + t.Fatal("Could not connect to hydra chat system", err) + } + conn.Close() +} diff --git a/hydrachat/clients.go b/hydrachat/clients.go new file mode 100644 index 0000000..59f7364 --- /dev/null +++ b/hydrachat/clients.go @@ -0,0 +1,53 @@ +package hydrachat + +import ( + "bufio" + "io" +) + +type client struct { + *bufio.Reader + *bufio.Writer + wc chan string +} + +func StartClient(msgCh chan<- string, cn io.ReadWriteCloser, quit chan struct{}) (chan<- string, <-chan struct{}) { + c := new(client) + c.Reader = bufio.NewReader(cn) + c.Writer = bufio.NewWriter(cn) + c.wc = make(chan string) + done := make(chan struct{}) + + //setup the reader + go func() { + scanner := bufio.NewScanner(c.Reader) + for scanner.Scan() { + logger.Println(scanner.Text()) + msgCh <- scanner.Text() + } + done <- struct{}{} + }() + + //setup the writer + c.writeMonitor() + + go func() { + select { + case <-quit: + cn.Close() + case <-done: + } + }() + + return c.wc, done +} + +func (c *client) writeMonitor() { + go func() { + for s := range c.wc { + //logger.Println("Sending",s) + c.WriteString(s + "\n") + c.Flush() + } + }() +} diff --git a/hydrachat/fanin/fanin.go b/hydrachat/fanin/fanin.go new file mode 100644 index 0000000..d4f4129 --- /dev/null +++ b/hydrachat/fanin/fanin.go @@ -0,0 +1,15 @@ +package fanin + +func fanin(chs ...<-chan int) <-chan int { + out := make(chan int) + for _, c := range chs { + go registerChannel(c, out) + } + return out +} + +func registerChannel(c <-chan int, out chan<- int) { + for n := range c { + out <- n + } +} diff --git a/hydrachat/hchatclient/chat.conf b/hydrachat/hchatclient/chat.conf new file mode 100644 index 0000000..3bd7a92 --- /dev/null +++ b/hydrachat/hchatclient/chat.conf @@ -0,0 +1,3 @@ +name|Mina;string +remoteip|127.0.0.1:2100;string +tcp|true;bool diff --git a/hydrachat/hchatclient/main.go b/hydrachat/hchatclient/main.go new file mode 100644 index 0000000..6fb7f3d --- /dev/null +++ b/hydrachat/hchatclient/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "math/rand" + "net" + "os" + "time" + //"Hydra/HydraConfigurator" +) + +func main() { + rand.Seed(time.Now().UnixNano()) + name := fmt.Sprintf("Anonymous%d", rand.Intn(400)) + fmt.Println("Starting hydraChatClient....") + fmt.Println("What's your name?") + fmt.Scanln(&name) + + /*confStruct := struct{ + Name string `name:"name"` + RemoteAddr string `name:"remoteip"` + TCP bool `name:"tcp"` + }{} + + HydraConfigurator.GetConfiguration(HydraConfigurator.CUSTOM,&confStruct,"chat.conf") + name = confStruct.Name + proto := "tcp" + if !confStruct.TCP{ + proto = "udp" + } + */ + + fmt.Printf("Hello %s, connecting to the hydra chat system.... \n", name) + conn, err := net.Dial("tcp", "127.0.0.1:2300") + if err != nil { + log.Fatal("Could not connect to hydra chat system", err) + } + fmt.Println("Connected to hydra chat system") + name += ":" + defer conn.Close() + go func() { + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + fmt.Println(scanner.Text()) + } + }() + + /* + for err==nil { + msg := "" + fmt.Print(name) + fmt.Scan(&msg) + msg = name+msg+"\n" + fmt.Println("Duplicate: " + msg) + _,err = fmt.Fprintf(conn,msg) + + } + */ + + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() && err == nil { + msg := scanner.Text() + _, err = fmt.Fprintf(conn, name+msg+"\n") + } +} diff --git a/hydrachat/hchatservertest/hchatservertest.go b/hydrachat/hchatservertest/hchatservertest.go new file mode 100644 index 0000000..6381a38 --- /dev/null +++ b/hydrachat/hchatservertest/hchatservertest.go @@ -0,0 +1,9 @@ +package main + +import ( + "Hydra/hydrachat" +) + +func main() { + hydrachat.Run("127.0.0.1:2300") +} diff --git a/hydrachat/hchatservertest/hydralogger.log b/hydrachat/hchatservertest/hydralogger.log new file mode 100644 index 0000000..03f94df --- /dev/null +++ b/hydrachat/hchatservertest/hydralogger.log @@ -0,0 +1,5 @@ +Hydra rooms.go:62: Starting chat room HydraChat +Hydra hydrachat.go:50: Received request from client 127.0.0.1:50986 +Hydra clients.go:25: Mina:Hello +Hydra rooms.go:47: Removing client +Hydra hydrachat.go:40: Error accepting connection from chat client accept tcp 127.0.0.1:2300: use of closed network connection diff --git a/hydrachat/hydrachat.go b/hydrachat/hydrachat.go new file mode 100644 index 0000000..6f1f4b3 --- /dev/null +++ b/hydrachat/hydrachat.go @@ -0,0 +1,52 @@ +package hydrachat + +import ( + "Hydra/hlogger" + "fmt" + "net" + "os" + "os/signal" + "syscall" +) + +var logger = hlogger.GetInstance() + +//Start hydra chat +func Run(connection string) error { + l, err := net.Listen("tcp", connection) + if err != nil { + logger.Println("Error connecting to chat client", err) + return err + } + r := CreateRoom("HydraChat") + go func() { + // Handle SIGINT and SIGTERM. + ch := make(chan os.Signal) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + <-ch + + l.Close() + fmt.Println("Closing tcp connection") + close(r.Quit) + if r.ClCount() > 0 { + <-r.Msgch + } + os.Exit(0) + }() + + for { + conn, err := l.Accept() + if err != nil { + logger.Println("Error accepting connection from chat client", err) + break + } + go handleConnection(r, conn) + } + + return err +} + +func handleConnection(r *room, c net.Conn) { + logger.Println("Received request from client", c.RemoteAddr()) + r.AddClient(c) +} diff --git a/hydrachat/hydralogger.log b/hydrachat/hydralogger.log new file mode 100644 index 0000000..b8b6d89 --- /dev/null +++ b/hydrachat/hydralogger.log @@ -0,0 +1,15 @@ +Hydra rooms.go:62: Starting chat room HydraChat +Hydra hydrachat.go:51: Received request from client 127.0.0.1:63555 +Hydra clients.go:25: Anonymous132:RandomMessage 109 +Hydra clients.go:25: Anonymous132:RandomMessage 73 +Hydra clients.go:25: Anonymous132:RandomMessage 120 +Hydra clients.go:25: Anonymous132:RandomMessage 144 +Hydra clients.go:25: Anonymous132:RandomMessage 180 +Hydra clients.go:25: Anonymous132:RandomMessage 142 +Hydra clients.go:25: Anonymous132:RandomMessage 113 +Hydra clients.go:25: Anonymous132:RandomMessage 20 +Hydra clients.go:25: Anonymous132:RandomMessage 336 +Hydra clients.go:25: Anonymous132:RandomMessage 180 +Hydra clients.go:25: Anonymous132:RandomMessage 337 +Hydra rooms.go:47: Removing client +Hydra hydrachat.go:51: Received request from client 127.0.0.1:63556 diff --git a/hydrachat/rooms.go b/hydrachat/rooms.go new file mode 100644 index 0000000..32f93eb --- /dev/null +++ b/hydrachat/rooms.go @@ -0,0 +1,79 @@ +package hydrachat + +import ( + "fmt" + "io" + "sync" +) + +type room struct { + name string + Msgch chan string + clients map[chan<- string]struct{} + Quit chan struct{} + *sync.RWMutex +} + +func CreateRoom(name string) *room { + r := &room{ + name: name, + Msgch: make(chan string), + RWMutex: new(sync.RWMutex), + clients: make(map[chan<- string]struct{}), + Quit: make(chan struct{}), + } + r.Run() + return r +} + +func (r *room) AddClient(c io.ReadWriteCloser) { + r.Lock() + wc, done := StartClient(r.Msgch, c, r.Quit) + r.clients[wc] = struct{}{} + r.Unlock() + + //remove client when done is signalled + go func() { + <-done + r.RemoveClient(wc) + }() +} + +func (r *room) ClCount() int { + return len(r.clients) +} + +func (r *room) RemoveClient(wc chan<- string) { + logger.Println("Removing client ") + r.Lock() + close(wc) + delete(r.clients, wc) + r.Unlock() + select { + case <-r.Quit: + if len(r.clients) == 0 { + close(r.Msgch) + } + default: + } +} + +func (r *room) Run() { + logger.Println("Starting chat room", r.name) + go func() { + for msg := range r.Msgch { + r.broadcastMsg(msg) + } + }() +} + +func (r *room) broadcastMsg(msg string) { + r.RLock() + defer r.RUnlock() + fmt.Println("Received message: ", msg) + for wc := range r.clients { + go func(wc chan<- string) { + wc <- msg + }(wc) + } +} diff --git a/mongodbdatafiller/Crews.csv b/mongodbdatafiller/Crews.csv new file mode 100644 index 0000000..6b6d88a --- /dev/null +++ b/mongodbdatafiller/Crews.csv @@ -0,0 +1,18 @@ +#id,Name,SecurityClearance,Title +1,Isis Adcox  ,5,Engineer I +2,Yu Chaloux  ,8,Engineer II +3,Lorette Gee  ,2,Assistant Pilot +4,Telma Rosas  ,5,Mechanic +5,Lynsey Christman  ,3,Technician +6,Shanika Reller  ,5,Biologist +7,Marcus Durkee  ,2,Chemist +8,Orval Barney  ,9,Engineer I +9,Maryanna Militello  ,1,Engineer II +10,Reva Gosser  ,6,Assistant Pilot +11,Noble Luczynski  ,4,Mechanic +12,Cherise Propp  ,2,Technician +13,Nickie Fralick  ,3,Biologist +14,Christel Sample  ,6,Chemist +15,Lynnette Woods  ,4,Engineer I +16,Karma Hennen  ,2,Engineer II +17,Alton Saez  ,1,Assistant Pilot diff --git a/mongodbdatafiller/mongodbdatafiller.go b/mongodbdatafiller/mongodbdatafiller.go new file mode 100644 index 0000000..6dd3e27 --- /dev/null +++ b/mongodbdatafiller/mongodbdatafiller.go @@ -0,0 +1,77 @@ +package main + +import ( + "encoding/csv" + "io" + "log" + "os" + "strconv" + + "flag" + + mgo "gopkg.in/mgo.v2" +) + +type crewMember struct { + ID int `bson:"id"` + Name string `bson:"name"` + SecClearance int `bson:"security clearance"` + Position string `bson:"position"` +} + +type Crew []crewMember + +func main() { + mgoaddress := flag.String("a", "mongodb://127.0.0.1", "Mongodb connection address") + flag.Parse() + //session, err := mgo.Dial("localhost") + session, err := mgo.Dial(*mgoaddress) + if err != nil { + log.Fatal(err) + } + defer session.Close() + + //get collection + personnel := session.DB("Hydra").C("Personnel2") + CSVToMongo(personnel) +} + +func CSVToMongo(c *mgo.Collection) { + file, err := os.Open("Crews.csv") + if err != nil { + log.Fatal(err) + } + defer file.Close() + + r := csv.NewReader(file) + r.Comment = '#' + var crew []interface{} + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + break + } + if len(record) != 4 { + continue + } + id, err := strconv.Atoi(record[0]) + if err != nil { + log.Println(err) + continue + } + sc, err := strconv.Atoi(record[2]) + if err != nil { + log.Println(err) + continue + } + crew = append(crew, crewMember{id, record[1], sc, record[3]}) + } + log.Println("Crew found in CSV: ", crew) + err = c.Insert(crew...) + if err != nil { + log.Fatal(err) + } +}