// poolMan is run in a go routine by new. It moves clients from the inPool // back to the outPool as long as the version string matches the current. It // also clears out the outPool when a new version string is recieved on the // version channel. func poolMan(pool *Pool, versionStr string) { for { // TODO: Do I need to break? I think I do select { case str := <-pool.versionChan: if str != versionStr { gslog.Debug("POOL: flushing pool because versionStr changed") versionStr = str flushPool(pool.outPool) } continue case client := <-pool.inPool: if client.versionStr == versionStr { gslog.Debug("POOL: poolMan added client back to pool") select { case pool.outPool <- client: continue default: gslog.Warn("POOL: out pool is full") } continue } client.Close() gslog.Debug("POOL: poolMan discarded client") continue } } }
func PostHordeGob(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: PostHordeGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) params := r.URL.Query() hordeName := params.Get(":horde") if !validHordeName(hordeName) { returnHTTPError(w, "PostHordeGob", "horde name can only contain up to "+strconv.Itoa(HORDE_MAX_LEN)+" alphanumeric characters", http.StatusNotFound) return } gobData := getGobData(w, r) if len(gobData) == 0 { returnHTTPError(w, "PostHordeGob", "gob empty", http.StatusBadRequest) return } ip := getIpAddress(r) uid, token, err := store.PutHordeGob(hordeName, gobData, ip) gslog.Debug("HANDLER: uid: %s, ip: %s", uid, ip) if err != nil { gslog.Error("HANDLER: put horde gob failed with error: %s", err.Error()) returnHTTPError(w, "PostHordeGob", "failed to save gob", http.StatusInternalServerError) return } pageType := getPageType(r) pageBytes, err := templ.GetURLPage(getScheme(r), pageType, uid, token) w.Write(pageBytes) }
func PostGob(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: PostGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) gobData := getGobData(w, r) if len(gobData) == 0 { returnHTTPError(w, "PostGob", "gob empty", http.StatusBadRequest) return } ip := getIpAddress(r) uid, token, err := store.PutGob(gobData, ip) gslog.Debug("HANDLER: PostGob uid: %s, ip: %s, token: %s", uid, ip, token) if err != nil { gslog.Error("HANDLER: post gob failed with error: %s", err.Error()) returnHTTPError(w, "PostGob", "failed to save gob", http.StatusInternalServerError) return } pageType := getPageType(r) pageBytes, err := templ.GetURLPage(getScheme(r), pageType, uid, token) if err != nil { gslog.Error("HANDLER: post gob failed with error: %s", err.Error()) returnHTTPError(w, "GetHorde", "failed to save gob", http.StatusInternalServerError) return } w.Write(pageBytes) }
func Initialize(htmlTemplatesPath string, textTemplatesPath string, confDomain string, confPygmentizePath string) error { var err error htmlTemplates, err = htmlTemplate.ParseFiles(htmlTemplatesPath) if err != nil { return err } textTemplates, err = textTemplate.ParseFiles(textTemplatesPath) gslog.Debug("TEMPL: loaded htmlTemplates from %s", htmlTemplatesPath) gslog.Debug("TEMPL: loaded textTemplates from %s", textTemplatesPath) domain = confDomain pygmentizePath = confPygmentizePath return err }
func DelGob(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: DelGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) params := r.URL.Query() token := params.Get(":token") if !validToken(token) { returnHTTPError(w, "DelGob", token+" not found", http.StatusNotFound) return } uid, err := store.TokenToUID(token) if err != nil { gslog.Error("HANDLER: delete gob failed with error: %s", err.Error()) returnHTTPError(w, "DelGob", "failed to delete gob", http.StatusInternalServerError) return } if uid == "" { returnHTTPError(w, "DelGob", token+" not found", http.StatusNotFound) return } err = store.DelGob(uid) if err != nil { gslog.Error("HANDLER: delete gob failed with error: %s", err.Error()) returnHTTPError(w, "DelGob", "failed to delete gob", http.StatusInternalServerError) return } pageType := getPageType(r) pageBytes, err := templ.GetMessPage(pageType, "successfully deleted "+uid) w.Write(pageBytes) }
func GetHorde(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: GetHorde called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) params := r.URL.Query() hordeName := params.Get(":horde") if !validHordeName(hordeName) { returnHTTPError(w, "GetHorde", hordeName+" not found", http.StatusNotFound) return } horde, err := store.GetHorde(hordeName) if err != nil { gslog.Error("HANDLER: failed to get horde with error: %s", err.Error()) returnHTTPError(w, "GetHorde", "failed to get horde", http.StatusInternalServerError) return } if len(horde) == 0 { returnHTTPError(w, "GetHorde", hordeName+" not found", http.StatusNotFound) return } pageType := getPageType(r) pageBytes, err := templ.GetHordePage(getScheme(r), pageType, hordeName, horde) if err != nil { gslog.Error("HANDLER: failed to get horde with error: %s", err.Error()) returnHTTPError(w, "GetHorde", "failed to get horde", http.StatusInternalServerError) return } w.Write(pageBytes) }
// Get a *Client from the pool or create a new one if there are none available. func (p *Pool) Get() (*Client, error) { select { // TODO: Should I be getting the ok also an verifying that the channel wasn't closed case r := <-p.outPool: gslog.Debug("POOL: got client from outPool") return r, nil default: } versionStr := buildVersionStr(p.network, p.addr) r, err := redis.Dial(p.network, p.addr) if err != nil { return nil, err } // TODO: learn how to use a mix of named and unamed fields gslog.Debug("POOL: created new client") return &Client{r, versionStr}, nil }
func (memoryStore *MemoryStore) GetHorde(hordeName string) (storage.Horde, error) { memoryStore.lock.RLock() defer memoryStore.lock.RUnlock() if horde, ok := memoryStore.hordes[hordeName]; ok { gslog.Debug("%+v", horde) return horde, nil } return storage.Horde{}, nil }
func GetForm(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: GetForm called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) pageBytes, err := templ.GetFormPage(getScheme(r)) if err != nil { gslog.Error("HANDLER: failed to get form with error: %s", err.Error()) returnHTTPError(w, "GetRoot", "failed to get form", http.StatusInternalServerError) return } w.Write(pageBytes) }
// TODO: Possibly return client to pool on some errors? func (redisStore *RedisStore) AppendGob(uid string, data []byte) error { client, err := redisStore.Get() if err != nil { return err } // Get gobInfo reply := client.Cmd("GET", gobInfoKey(uid)) if reply.Err != nil { return reply.Err } gobInfoBytes, _ := reply.Bytes() gobInfo, err := gobInfoDecode(gobInfoBytes) if err != nil { return err } // Append or set depending on if length of old + new data > MAX_LEN length, err := getStrLen(client, gobKey(uid)) if err != nil { return err } length += len(data) if length > MAX_LEN { gslog.Debug("REDIS: tuncating gob length %d MAX_LEN %d", length, MAX_LEN) reply := client.Cmd("GET", gobKey(uid)) if reply.Err != nil { return reply.Err } oldData, _ := reply.Bytes() // TODO: Best way to do this? data = bytes.Join([][]byte{oldData[length-MAX_LEN : len(oldData)], data}, []byte{}) if reply := client.Cmd("SET", gobKey(uid), data); reply.Err != nil { return reply.Err } } else { gslog.Debug("REDIS: appending gob length %d MAX_LEN %d", length, MAX_LEN) if reply := client.Cmd("APPEND", gobKey(uid), data); reply.Err != nil { return reply.Err } } go redisStore.setTTLRoutine(client, gobInfo, data) return nil }
func GetGob(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: GetGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) params := r.URL.Query() uid := params.Get(":uid") if !validUID(uid) { returnHTTPError(w, "GetGob", uid+" not found", http.StatusNotFound) return } data, _, err := store.GetGob(uid) if err != nil { gslog.Error("HANDLER: failed to get gob with error: " + err.Error()) returnHTTPError(w, "GetGob", "failed to get gob", http.StatusInternalServerError) return } if len(data) == 0 { returnHTTPError(w, "GetGob", uid+" not found", http.StatusNotFound) return } // Firgure out language parameter lang := getLanguage(r) if lang == "" { gslog.Debug("HANDLER: GetGob writing data") w.Write(data) return } contentType := http.DetectContentType(data) // If data is a valid content type for syntax highlighting if textContentTypeReg.MatchString(contentType) { data, err = templ.GetGobPage(lang, data) if err != nil { gslog.Error("HANDLER: failed to get gob page with error: %s", err.Error()) returnHTTPError(w, "GetGob", "failed to get gob", http.StatusInternalServerError) return } } w.Write(data) }
func AppendGob(w http.ResponseWriter, r *http.Request) { gslog.Debug("HANDLER: AppendGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr) params := r.URL.Query() token := params.Get(":token") if !validToken(token) { returnHTTPError(w, "AppendGob", token+" not found", http.StatusNotFound) return } gobData := getGobData(w, r) if len(gobData) == 0 { returnHTTPError(w, "AppendGob", "gob empty", http.StatusBadRequest) return } ip := getIpAddress(r) uid, err := store.TokenToUID(token) gslog.Debug("HANDLER: AppendGob uid: %s, ip: %s, token: %s", uid, ip, token) if err != nil { gslog.Error("HANDLER: append gob failed with error: %s", err.Error()) returnHTTPError(w, "AppendGob", "failed to append gob", http.StatusInternalServerError) return } if uid == "" { returnHTTPError(w, "AppendGob", token+" not found", http.StatusNotFound) return } err = store.AppendGob(uid, gobData) if err != nil { gslog.Error("HANDLER: append gob failed with error: %s", err.Error()) returnHTTPError(w, "AppendGob", "failed to append gob", http.StatusInternalServerError) return } pageType := getPageType(r) // TODO: Should I tell them what gob they appended? Maybe a security flaw pageBytes, err := templ.GetMessPage(pageType, "successfully appended "+uid) w.Write(pageBytes) }
func Reload(htmlTemplatesPath string, textTemplatesPath string, confDomain string, confPygmentizePath string) error { if htmlTemplatesTemp, err := htmlTemplate.ParseFiles(htmlTemplatesPath); err != nil { return err } else { htmlTemplates = htmlTemplatesTemp gslog.Debug("htmlTemplates loaded") } if textTemplatesTemp, err := textTemplate.ParseFiles(textTemplatesPath); err != nil { return err } else { textTemplates = textTemplatesTemp gslog.Info("textTemplates loaded") } domain = confDomain pygmentizePath = confPygmentizePath return nil }
func returnHTTPError(w http.ResponseWriter, funcName string, errMessage string, status int) { gslog.Debug("HANDLER: %s returned error to user: %s", funcName, errMessage) http.Error(w, "Error: "+errMessage, http.StatusInternalServerError) }
// Must be called before any other functions are called // TODO: should I just called it SetUIDLen ? func Initialize(uidLength int, tokenLength int) { uidLen = uidLength tokenLen = tokenLength gslog.Debug("HANDLER: initialized with uid length: %d, token length: %d", uidLen, tokenLen) }