// UpsertForm upserts the provided form into the MongoDB database collection and // creates a gallery based on it. func UpsertForm(context interface{}, db *db.DB, f *form.Form) error { log.Dev(context, "UpsertForm", "Started : Form[%s]", f.ID.Hex()) var isNewForm bool // If there was no ID provided, we should set one. UpsertForm might optionally add // a form ID to ensure that we don't duplicate the FormGallery. if f.ID.Hex() == "" { isNewForm = true } if err := form.Upsert(context, db, f); err != nil { log.Error(context, "UpsertForm", err, "Completed") return err } if isNewForm { // Create the new gallery that we will create that is based on the current // form ID. g := gallery.Gallery{ FormID: f.ID, } if err := gallery.Create(context, db, &g); err != nil { log.Error(context, "UpsertForm", err, "Completed") return err } } log.Dev(context, "UpsertForm", "Completed") return nil }
// Mongo handles session management. func Mongo(h app.Handler) app.Handler { // Check if mongodb is configured. dbName, err := cfg.String(cfgMongoDB) if err != nil { return func(c *app.Context) error { log.Dev(c.SessionID, "Mongo", "******> Mongo Not Configured") return h(c) } } // Wrap the handlers inside a session copy/close. return func(c *app.Context) error { mgoDB, err := db.NewMGO("Mongo", dbName) if err != nil { log.Error(c.SessionID, "Mongo", err, "Method[%s] URL[%s] RADDR[%s]", c.Request.Method, c.Request.URL.Path, c.Request.RemoteAddr) return app.ErrDBNotConfigured } log.Dev(c.SessionID, "Mongo", "******> Capture Mongo Session") c.DB = mgoDB defer func() { log.Dev(c.SessionID, "Mongo", "******> Release Mongo Session") mgoDB.CloseMGO("Mongo") }() return h(c) } }
// newClient creates a new client for an incoming connection. func newClient(context string, t *TCP, conn net.Conn) *client { ipAddress := conn.RemoteAddr().String() log.Dev(context, "newClient", "Started : IPAddress[%s]", ipAddress) // Ask the user to bind the reader and writer they want to // use for this connection. r, w := t.ConnHandler.Bind(context, conn) c := client{ context: context, t: t, conn: conn, ipAddress: ipAddress, reader: r, writer: w, } // Check to see if this connection is ipv6. if raddr := conn.RemoteAddr().(*net.TCPAddr); raddr.IP.To4() == nil { c.isIPv6 = true } // Launch a goroutine for this connection. c.wg.Add(1) go c.read() log.Dev(context, "newClient", "Completed") return &c }
// DeleteSubmission deletes a submission as well as updating a form's stats. func DeleteSubmission(context interface{}, db *db.DB, id, formID string) error { log.Dev(context, "DeleteSubmission", "Started : Submission[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "DeleteSubmission", ErrInvalidID, "Completed") return ErrInvalidID } if !bson.IsObjectIdHex(formID) { log.Error(context, "Delete", ErrInvalidID, "Completed") return ErrInvalidID } if err := submission.Delete(context, db, id); err != nil { log.Error(context, "DeleteSubmission", err, "Completed") return err } if _, err := form.UpdateStats(context, db, formID); err != nil { log.Error(context, "DeleteSubmission", err, "Completed") return err } log.Dev(context, "DeleteSubmission", "Started") return nil }
// New creates a new Pool. func New(context interface{}, name string, cfg Config) (*Pool, error) { log.Dev(context, "New", "Started : Name[%s]", name) if cfg.MinRoutines == nil { return nil, ErrNilMinRoutines } if cfg.MinRoutines() <= 0 { return nil, ErrInvalidMinRoutines } if cfg.MaxRoutines == nil { return nil, ErrNilMaxRoutines } if cfg.MaxRoutines() < cfg.MinRoutines() { return nil, ErrInvalidMaxRoutines } p := Pool{ Config: cfg, Name: name, tasks: make(chan doWork), control: make(chan int), kill: make(chan struct{}), shutdown: make(chan struct{}), } p.manager(context) p.add(context, cfg.MinRoutines()) log.Dev(context, "New", "Completed") return &p, nil }
// GetByName retrieves the document for the specified query mask. func GetByName(context interface{}, db *db.DB, collection string, field string) (Mask, error) { log.Dev(context, "GetByName", "Started : Collection[%s] Field[%s]", collection, field) key := "gbn" + collection + field if v, found := cache.Get(key); found { mask := v.(Mask) log.Dev(context, "GetByName", "Completed : CACHE : Mask[%+v]", mask) return mask, nil } var mask Mask f := func(c *mgo.Collection) error { q := bson.M{"collection": collection, "field": field} log.Dev(context, "GetByName", "MGO : db.%s.findOne(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&mask) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByName", err, "Completed") return Mask{}, err } cache.Set(key, mask, gc.DefaultExpiration) log.Dev(context, "GetByName", "Completed : Mask[%+v]", mask) return mask, nil }
// GetByIDs retrieves items by ID from Mongo. func GetByIDs(context interface{}, db *db.DB, ids []string) ([]Item, error) { log.Dev(context, "GetByIDs", "Started : IDs%v", ids) // Get the items from Mongo. var items []Item f := func(c *mgo.Collection) error { q := bson.M{"item_id": bson.M{"$in": ids}} log.Dev(context, "Find", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&items) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByIDs", err, "Completed") return items, err } // If we got an unexpected number of items, throw an error. if len(ids) < len(items) { return nil, fmt.Errorf("Expected %d items, got %d: ", len(ids), len(items)) } log.Dev(context, "GetByIDs", "Completed") return items, nil }
// Midware handles databse session management and manages a MongoDB session. func Midware(mongoURI *url.URL) web.Middleware { // Create the middleware that we can use to create MongoDB sessions with. m := func(next web.Handler) web.Handler { // Create the handler that will be attached in the middleware chain. h := func(c *web.Context) error { // Pull in the mongo session from the master session so we can load it // onto the request context. It is keyed by the path on the uri. db, err := kitdb.NewMGO(c.SessionID, mongoURI.Path) if err != nil { log.Error(c.SessionID, "mongo : Midware", err, "Method[%s] URL[%s] RADDR[%s]", c.Request.Method, c.Request.URL.Path, c.Request.RemoteAddr) return web.ErrDBNotConfigured } // Load the mongo database onto the request context. c.Ctx["DB"] = db log.Dev(c.SessionID, "mongo : Midware", "Capture Mongo Session") // Close the MongoDB session when the handler returns. defer func() { log.Dev(c.SessionID, "mongo : Midware", "Release Mongo Session") db.CloseMGO(c.SessionID) }() return next(c) } return h } return m }
// Update updates the form gallery in the MongoDB database // collection. func Update(context interface{}, db *db.DB, id string, gallery *Gallery) error { log.Dev(context, "Update", "Started : Gallery[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "Update", ErrInvalidID, "Completed") return ErrInvalidID } if err := gallery.Validate(); err != nil { log.Error(context, "Update", err, "Completed") return err } objectID := bson.ObjectIdHex(id) gallery.DateUpdated = time.Now() f := func(c *mgo.Collection) error { log.Dev(context, "Update", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(gallery)) return c.UpdateId(objectID, gallery) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Update", err, "Completed") return err } log.Dev(context, "Update", "Completed") return nil }
// Auth handles token authentication. func Auth(h app.Handler) app.Handler { // Check if authentication is turned off. on, err := cfg.Bool(cfgAuth) if err == nil && !on { return func(c *app.Context) error { log.Dev(c.SessionID, "Auth", "******> Authentication Off") return h(c) } } // Turn authentication on. return func(c *app.Context) error { token := c.Request.Header.Get("Authorization") log.Dev(c.SessionID, "Auth", "Started : Token[%s]", token) if len(token) < 5 || token[0:5] != "Basic" { log.Error(c.SessionID, "Auth", app.ErrNotAuthorized, "Validating token") return app.ErrNotAuthorized } var err error if c.User, err = auth.ValidateWebToken(c.SessionID, c.DB, token[6:]); err != nil { log.Error(c.SessionID, "Auth", err, "Validating token") return app.ErrNotAuthorized } log.Dev(c.SessionID, "Auth", "Completed") return h(c) } }
// GetAll retrieves a list of regexs. func GetAll(context interface{}, db *db.DB, tags []string) ([]Regex, error) { log.Dev(context, "GetAll", "Started : Tags[%v]", tags) key := "grs" + strings.Join(tags, "-") if v, found := cache.Get(key); found { rgxs := v.([]Regex) log.Dev(context, "GetAll", "Completed : CACHE : Rgxs[%d]", len(rgxs)) return rgxs, nil } var rgxs []Regex f := func(c *mgo.Collection) error { log.Dev(context, "GetAll", "MGO : db.%s.find({}).sort([\"name\"])", c.Name) return c.Find(nil).All(&rgxs) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetAll", err, "Completed") return nil, err } if rgxs == nil { log.Error(context, "GetAll", ErrNotFound, "Completed") return nil, ErrNotFound } cache.Set(key, rgxs, gc.DefaultExpiration) log.Dev(context, "GetAll", "Completed : Rgxs[%d]", len(rgxs)) return rgxs, nil }
// Remove removes an item into the items collection and remove any // corresponding quads from the graph database. func Remove(context interface{}, db *db.DB, graph *cayley.Handle, itemID string) error { log.Dev(context, "Remove", "Started : ID[%s]", itemID) // Get the item from the items collection. items, err := item.GetByIDs(context, db, []string{itemID}) if err != nil { log.Error(context, "Remove", err, "Completed") return err } // Prepare the item map data. itmMap := map[string]interface{}{ "item_id": items[0].ID, "type": items[0].Type, "version": items[0].Version, "data": items[0].Data, } // Remove the corresponding relationships from the graph. if err := wire.RemoveFromGraph(context, db, graph, itmMap); err != nil { log.Error(context, "Remove", err, "Completed") return err } // Delete the item. if err := item.Delete(context, db, itemID); err != nil { log.Error(context, "Remove", err, "Completed") return err } log.Dev(context, "Remove", "Completed") return nil }
// Count returns the count of current submissions for a given // form id in the Form Submissions MongoDB database collection. func Count(context interface{}, db *db.DB, formID string) (int, error) { log.Dev(context, "Count", "Completed : Form[%s]", formID) if !bson.IsObjectIdHex(formID) { log.Error(context, "Count", ErrInvalidID, "Completed") return 0, ErrInvalidID } formObjectID := bson.ObjectIdHex(formID) var count int f := func(c *mgo.Collection) error { var err error q := bson.M{ "form_id": formObjectID, } log.Dev(context, "Count", "MGO : db.%s.find(%s).count()", c.Name, mongo.Query(q)) count, err = c.Find(q).Count() return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Count", err, "Completed") return 0, err } log.Dev(context, "Count", "Completed") return count, nil }
// RetrieveMany retrieves a list of Submission's from the MongoDB database collection. func RetrieveMany(context interface{}, db *db.DB, ids []string) ([]Submission, error) { log.Dev(context, "RetrieveMany", "Started") var objectIDs = make([]bson.ObjectId, len(ids)) for i, id := range ids { if !bson.IsObjectIdHex(id) { log.Error(context, "RetrieveMany", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectIDs[i] = bson.ObjectIdHex(id) } var submissions []Submission f := func(c *mgo.Collection) error { q := bson.M{ "_id": bson.M{ "$in": objectIDs, }, } log.Dev(context, "RetrieveMany", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&submissions) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "RetrieveMany", err, "Completed") return nil, err } log.Dev(context, "RetrieveMany", "Started") return submissions, nil }
// UpdateStatus updates a form submissions status inside the MongoDB database // collection. func UpdateStatus(context interface{}, db *db.DB, id, status string) (*Submission, error) { log.Dev(context, "UpdateStatus", "Started : Submission[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "UpdateStatus", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) f := func(c *mgo.Collection) error { u := bson.M{ "$set": bson.M{ "status": status, "date_updated": time.Now(), }, } log.Dev(context, "UpdateStatus", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(u)) return c.UpdateId(objectID, u) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "UpdateStatus", err, "Completed") return nil, err } submission, err := Retrieve(context, db, id) if err != nil { log.Error(context, "UpdateStatus", err, "Completed") return nil, err } log.Dev(context, "UpdateStatus", "Completed") return submission, nil }
// Do will post the request to be sent by the client worker pool. func (t *TCP) Do(context interface{}, r *Response) error { log.Dev(context, "Do", "Started : Local[ %s ] Remote[ %s ]", join(t.ipAddress, t.port), r.TCPAddr.String()) // Find the client connection for this IPAddress. var c *client t.clientsMu.Lock() { // If this ipaddress and socket does not exist, report an error. var ok bool if c, ok = t.clients[r.TCPAddr.String()]; !ok { err := fmt.Errorf("IP Address disconnected [ %s ]", r.TCPAddr.String()) log.Error(context, "Do", err, "Completed") t.clientsMu.Unlock() return err } } t.clientsMu.Unlock() // Set the unexported fields. r.tcp = t r.client = c r.context = context // Send this to the client work pool for processing. t.send.Do(context, r) log.Dev(context, "Do", "Completed") return nil }
// Create adds a new Submission based on a given Form into // the MongoDB database collection. func Create(context interface{}, db *db.DB, formID string, submission *Submission) error { log.Dev(context, "Create", "Started : Form[%s]", formID) if !bson.IsObjectIdHex(formID) { log.Error(context, "Create", ErrInvalidID, "Completed") return ErrInvalidID } if err := submission.Validate(); err != nil { return err } // FIXME: handle Number field maybe with https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/ to resolve race condition count, err := Count(context, db, formID) if err != nil { log.Error(context, "Create", err, "Completed") return err } submission.Number = count + 1 f := func(c *mgo.Collection) error { log.Dev(context, "Create", "MGO : db.%s.insert(%s)", c.Name, mongo.Query(submission)) return c.Insert(submission) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Create", err, "Completed") return err } log.Dev(context, "Create", "Completed") return nil }
// DecodeWebToken breaks a web token into its parts. func DecodeWebToken(context interface{}, webToken string) (sessionID string, token string, err error) { log.Dev(context, "DecodeWebToken", "Started : WebToken[%s]", webToken) // Decode the web token to break it into its parts. data, err := base64.StdEncoding.DecodeString(webToken) if err != nil { log.Error(context, "DecodeWebToken", err, "Completed") return "", "", err } // Split the web token. str := strings.Split(string(data), ":") if len(str) != 2 { err := errors.New("Invalid token") log.Error(context, "DecodeWebToken", err, "Completed") return "", "", err } // Pull out the session and token. sessionID = str[0] token = str[1] log.Dev(context, "DecodeWebToken", "Completed : SessionID[%s] Token[%s]", sessionID, token) return sessionID, token, nil }
// Midware handles the Cayley session management. func Midware(mongoURI *url.URL) web.Middleware { // Create the middleware that we can use to create Cayley sessions with. m := func(next web.Handler) web.Handler { // Create the handler that will be attached in the middleware chain. h := func(c *web.Context) error { // Load the mongo db from the request context. db := c.Ctx["DB"].(*db.DB) // Create the new cayley session based on the mongo connection credentials // which will add it to the db object itself. if err := db.NewCayley(c.SessionID, mongoURI.Path); err != nil { return web.ErrDBNotConfigured } log.Dev(c.SessionID, "cayley : Midware", "Capture Cayley Session") // Close the Cayley session when the handler returns. defer func() { log.Dev(c.SessionID, "cayley : Midware", "Release Cayley Session") db.CloseCayley(c.SessionID) }() return next(c) } return h } return m }
// UpdateUserPassword updates an existing user's password and token in the database. func UpdateUserPassword(context interface{}, db *db.DB, u *User, password string) error { log.Dev(context, "UpdateUserPassword", "Started : PublicID[%s]", u.PublicID) if err := u.Validate(); err != nil { log.Error(context, "UpdateUserPassword", err, "Completed") return err } if len(password) < 8 { err := errors.New("Invalid password length") log.Error(context, "UpdateUserPassword", err, "Completed") return err } newPassHash, err := crypto.BcryptPassword(u.PrivateID + password) if err != nil { log.Error(context, "UpdateUserPassword", err, "Completed") return err } f := func(c *mgo.Collection) error { q := bson.M{"public_id": u.PublicID} upd := bson.M{"$set": bson.M{"password": newPassHash, "modified_at": time.Now().UTC()}} log.Dev(context, "UpdateUserPassword", "MGO : db.%s.Update(%s, CAN'T SHOW)", c.Name, mongo.Query(q)) return c.Update(q, upd) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "UpdateUserPassword", err, "Completed") return err } log.Dev(context, "UpdateUserPassword", "Completed") return nil }
// CreateWebToken return a token and session that can be used to authenticate a user. func CreateWebToken(context interface{}, db *db.DB, u *User, expires time.Duration) (string, error) { log.Dev(context, "CreateWebToken", "Started : PublicID[%s]", u.PublicID) // Do we have a valid session right now? s, err := session.GetByLatest(context, db, u.PublicID) if err != nil && err != mgo.ErrNotFound { log.Error(context, "CreateUser", err, "Completed") return "", err } // If we don't have one or it has been expired create // a new one. if err == mgo.ErrNotFound || s.IsExpired(context) { if s, err = session.Create(context, db, u.PublicID, expires); err != nil { log.Error(context, "CreateUser", err, "Completed") return "", err } } // Set the return arguments though we will explicitly // return them. Don't want any confusion. token, err := u.WebToken(s.SessionID) if err != nil { log.Error(context, "CreateUser", err, "Completed") return "", err } log.Dev(context, "CreateWebToken", "Completed : WebToken[%s]", token) return token, nil }
// GetUserWebToken return a token if one exists and is valid. func GetUserWebToken(context interface{}, db *db.DB, publicID string) (string, error) { log.Dev(context, "GetUserWebToken", "Started : PublicID[%s]", publicID) // Do we have a valid session right now? s, err := session.GetByLatest(context, db, publicID) if err != nil { log.Error(context, "GetUserWebToken", err, "Completed") return "", err } // If it is expired return failure. if s.IsExpired(context) { err := errors.New("Session expired.") log.Error(context, "GetUserWebToken", err, "Completed") return "", err } // Pull the user information. u, err := GetUserByPublicID(context, db, publicID, true) if err != nil { log.Error(context, "GetUserWebToken", err, "Completed") return "", err } // Generate a token that works right now. token, err := u.WebToken(s.SessionID) if err != nil { log.Error(context, "GetUserWebToken", err, "Completed") return "", err } log.Dev(context, "GetUserWebToken", "Completed : WebToken[%s]", token) return token, nil }
// List retrives the form galleries for a given form from the MongoDB database // collection. func List(context interface{}, db *db.DB, formID string) ([]Gallery, error) { log.Dev(context, "List", "Started") if !bson.IsObjectIdHex(formID) { log.Error(context, "List", ErrInvalidID, "Completed") return nil, ErrInvalidID } formObjectID := bson.ObjectIdHex(formID) var galleries = make([]Gallery, 0) f := func(c *mgo.Collection) error { q := bson.M{ "form_id": formObjectID, } log.Dev(context, "List", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&galleries) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "List", err, "Completed") return nil, err } if err := hydrateMany(context, db, galleries); err != nil { log.Error(context, "List", err, "Completed") return nil, err } log.Dev(context, "List", "Completed") return galleries, nil }
// remove deletes a connection from the manager. func (t *TCP) remove(context interface{}, conn net.Conn) { ipAddress := conn.RemoteAddr().String() log.Dev(context, "remove", "Started : IPAddress[ %s ]", ipAddress) t.clientsMu.Lock() { // If this ipaddress and socket does not exist, we have a probler. if _, ok := t.clients[ipAddress]; !ok { err := fmt.Errorf("IP Address already removed [ %s ]", ipAddress) log.Error(context, "remove", err, "Completed") t.clientsMu.Unlock() return } // Remove the client connection from the map. delete(t.clients, ipAddress) } t.clientsMu.Unlock() // Close the connection for safe keeping. conn.Close() log.Dev(context, "remove", "Completed") }
// RemoveFlag removes a flag from a given Submission in // the MongoDB database collection. func RemoveFlag(context interface{}, db *db.DB, id, flag string) (*Submission, error) { log.Dev(context, "RemoveFlag", "Started : Submission[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "RemoveFlag", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) f := func(c *mgo.Collection) error { u := bson.M{ "$pull": bson.M{ "flags": flag, }, } log.Dev(context, "RemoveFlag", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(u)) return c.UpdateId(objectID, u) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "RemoveFlag", err, "Completed") return nil, err } submission, err := Retrieve(context, db, id) if err != nil { log.Error(context, "RemoveFlag", err, "Completed") return nil, err } log.Dev(context, "RemoveFlag", "Completed") return submission, nil }
// GetByName retrieves the document for the specified Set. func GetByName(context interface{}, db *db.DB, name string) (*Set, error) { log.Dev(context, "GetByName", "Started : Name[%s]", name) key := "gbn" + name if v, found := cache.Get(key); found { set := v.(Set) log.Dev(context, "GetByName", "Completed : CACHE : Set[%+v]", &set) return &set, nil } var set Set f := func(c *mgo.Collection) error { q := bson.M{"name": name} log.Dev(context, "GetByName", "MGO : db.%s.findOne(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&set) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByName", err, "Completed") return nil, err } // Fix the set so it can be used for processing. set.PrepareForUse() cache.Set(key, set, gc.DefaultExpiration) log.Dev(context, "GetByName", "Completed : Set[%+v]", &set) return &set, nil }
// Retrieve retrieves a form gallery from the MongoDB database // collection as well as hydrating the form gallery with form submissions. func Retrieve(context interface{}, db *db.DB, id string) (*Gallery, error) { log.Dev(context, "Retrieve", "Started : Gallery[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "Retrieve", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) var gallery Gallery f := func(c *mgo.Collection) error { log.Dev(context, "Retrieve", "MGO : db.%s.find(%s)", c.Name, mongo.Query(objectID)) return c.FindId(objectID).One(&gallery) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Retrieve", err, "Completed") return nil, err } if err := hydrate(context, db, &gallery); err != nil { log.Error(context, "Retrieve", err, "Completed") return nil, err } log.Dev(context, "Retrieve", "Completed") return &gallery, nil }
// Write is provided the user-defined writer and the data to write. func (udpRespHandler) Write(context interface{}, r *udp.Response, writer io.Writer) { log.Dev(context, "Write", "Started") listener := writer.(*net.UDPConn) listener.WriteToUDP(r.Data, r.UDPAddr) log.Dev(context, "Write", "Completed") }
// Stop shuts down the manager and closes all connections. func (t *TCP) Stop(context interface{}) error { log.Dev(context, "Stop", "Started : IPAddress[ %s ]", join(t.ipAddress, t.port)) t.listenerMu.Lock() { // If the listener has been stopped already, return an error. if t.listener == nil { err := errors.New("This TCP has already been stopped") log.Error(context, "Stop", err, "Completed") t.listenerMu.Unlock() return err } } t.listenerMu.Unlock() // Mark that we are shutting down. atomic.StoreInt32(&t.shuttingDown, 1) // Don't accept anymore client connections. t.listenerMu.Lock() { t.listener.Close() } t.listenerMu.Unlock() // Stop processing all the work. if !t.userPools { t.recv.Shutdown(context) t.send.Shutdown(context) } else { log.Dev(context, "Stop", "User pools being used, not shutting them down.") } // Make a copy of all the connections. We need to do this // since we have to lock the map to read it. Dropping a // connection requires locks as well. var clients map[string]*client t.clientsMu.Lock() { clients = make(map[string]*client) for k, v := range t.clients { clients[k] = v } } t.clientsMu.Unlock() // Drop all the existing connections. for _, c := range clients { // This waits for each routine to terminate. c.drop() } // Wait for the accept routine to terminate. t.wg.Wait() log.Dev(context, "Stop", "Completed") return nil }
// Write is provided the user-defined writer and the data to write. func (tcpRespHandler) Write(context interface{}, r *tcp.Response, writer io.Writer) { log.Dev(context, "Write", "Started : Length[%d]", len(r.Data)) bufWriter := writer.(*bufio.Writer) bufWriter.WriteString(string(r.Data)) bufWriter.Flush() log.Dev(context, "Write", "Completed") }