reformat passing of connhost to instead now use FileSystemRequest

Signed-off-by: kim (grufwub) <grufwub@gmail.com>
master
kim (grufwub) 4 years ago
parent e8eb848a05
commit 13878b4310

@ -49,7 +49,6 @@ func checkCacheFreshness() {
Config.FileCache.CacheMutex.Unlock()
}
/* TODO: see if there is more efficienct setup */
type FileCache struct {
CacheMap *FixedMap
CacheMutex sync.RWMutex
@ -62,26 +61,26 @@ func (fc *FileCache) Init(size int, fileSizeMax float64) {
fc.FileSizeMax = int64(BytesInMegaByte * fileSizeMax)
}
func (fc *FileCache) FetchRegular(path string, connHost ConnHost) ([]byte, *GophorError) {
return fc.Fetch(path, func(path string) FileContents {
func (fc *FileCache) FetchRegular(request *FileSystemRequest) ([]byte, *GophorError) {
return fc.Fetch(request, func(path string) FileContents {
contents := new(RegularFileContents)
contents.path = path
return contents
}, connHost)
})
}
func (fc *FileCache) FetchGophermap(path string, connHost ConnHost) ([]byte, *GophorError) {
return fc.Fetch(path, func(path string) FileContents {
func (fc *FileCache) FetchGophermap(request *FileSystemRequest) ([]byte, *GophorError) {
return fc.Fetch(request, func(path string) FileContents {
contents := new(GophermapContents)
contents.path = path
return contents
}, connHost)
})
}
func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContents, connHost ConnHost) ([]byte, *GophorError) {
func (fc *FileCache) Fetch(request *FileSystemRequest, newFileContents func(string) FileContents) ([]byte, *GophorError) {
/* Get cache map read lock then check if file in cache map */
fc.CacheMutex.RLock()
file := fc.CacheMap.Get(path)
file := fc.CacheMap.Get(request.Path)
/* TODO: work on efficiency */
if file != nil {
@ -109,7 +108,7 @@ func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContent
}
} else {
/* Before we do ANYTHING, we need to check file-size on disk */
stat, err := os.Stat(path)
stat, err := os.Stat(request.Path)
if err != nil {
/* Error stat'ing file, unlock read mutex then return error */
fc.CacheMutex.RUnlock()
@ -117,7 +116,7 @@ func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContent
}
/* Create new file contents object using supplied function */
contents := newFileContents(path)
contents := newFileContents(request.Path)
/* Create new file wrapper around contents */
file = NewFile(contents)
@ -136,7 +135,7 @@ func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContent
* contents, unlock all mutex and don't bother caching.
*/
if stat.Size() > fc.FileSizeMax {
b := file.Contents(connHost)
b := file.Contents(request)
fc.CacheMutex.RUnlock()
return b, nil
}
@ -146,7 +145,7 @@ func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContent
fc.CacheMutex.Lock()
/* Put file in the FixedMap */
fc.CacheMap.Put(path, file)
fc.CacheMap.Put(request.Path, file)
/* Before unlocking cache mutex, lock file read for upcoming call to .Contents() */
file.RLock()
@ -157,7 +156,7 @@ func (fc *FileCache) Fetch(path string, newFileContents func(string) FileContent
}
/* Read file contents into new variable for return, then unlock file read lock */
b := file.Contents(connHost)
b := file.Contents(request)
file.RUnlock()
/* Finally we can unlock the cache map read lock, we are done :) */

@ -17,12 +17,12 @@ type ConnHost struct {
*/
type GophorListener struct {
Listener net.Listener
Host ConnHost
Host *ConnHost
}
func BeginGophorListen(bindAddr, hostname, port string) (*GophorListener, error) {
gophorListener := new(GophorListener)
gophorListener.Host = ConnHost{ hostname, port }
gophorListener.Host = &ConnHost{ hostname, port }
var err error
gophorListener.Listener, err = net.Listen("tcp", bindAddr+":"+port)
@ -41,7 +41,7 @@ func (l *GophorListener) Accept() (*GophorConn, error) {
gophorConn := new(GophorConn)
gophorConn.Conn = conn
gophorConn.Host = l.Host
gophorConn.Host = &ConnHost{ l.Host.Name, l.Host.Port }
return gophorConn, nil
}
@ -54,7 +54,7 @@ func (l *GophorListener) Addr() net.Addr {
*/
type GophorConn struct {
Conn net.Conn
Host ConnHost
Host *ConnHost
}
func (c *GophorConn) Read(b []byte) (int, error) {

@ -16,7 +16,7 @@ type RegularFileContents struct {
contents []byte
}
func (fc *RegularFileContents) Render(connHost ConnHost) []byte {
func (fc *RegularFileContents) Render(request *FileSystemRequest) []byte {
return fc.contents
}
@ -41,13 +41,13 @@ type GophermapContents struct {
sections []GophermapSection
}
func (gc *GophermapContents) Render(connHost ConnHost) []byte {
func (gc *GophermapContents) Render(request *FileSystemRequest) []byte {
/* We don't just want to read the contents, but also
* execute any included gophermap execute lines
*/
returnContents := make([]byte, 0)
for _, line := range gc.sections {
content, gophorErr := line.Render(connHost)
content, gophorErr := line.Render(request)
if gophorErr != nil {
content = buildInfoLine(GophermapRenderErrorStr)
}
@ -75,7 +75,7 @@ func (gc *GophermapContents) Clear() {
* upon each file cache request.
*/
type GophermapSection interface {
Render(ConnHost) ([]byte, *GophorError)
Render(*FileSystemRequest) ([]byte, *GophorError)
}
/* GophermapText:
@ -92,8 +92,8 @@ func NewGophermapText(contents []byte) *GophermapText {
return s
}
func (s *GophermapText) Render(connHost ConnHost) ([]byte, *GophorError) {
return replaceStrings(string(s.contents), connHost), nil
func (s *GophermapText) Render(request *FileSystemRequest) ([]byte, *GophorError) {
return replaceStrings(string(s.contents), request.Host), nil
}
/* GophermapDirListing:
@ -113,8 +113,11 @@ func NewGophermapDirListing(path string) *GophermapDirListing {
return s
}
func (s *GophermapDirListing) Render(connHost ConnHost) ([]byte, *GophorError) {
return listDir(s.path, s.Hidden, connHost)
func (s *GophermapDirListing) Render(request *FileSystemRequest) ([]byte, *GophorError) {
/* We could just pass the request directly, but in case the request
* path happens to differ for whatever reason we create a new one
*/
return listDir(&FileSystemRequest{ s.path, request.Host }, s.Hidden)
}
func readGophermap(path string) ([]GophermapSection, *GophorError) {
@ -282,7 +285,7 @@ func minWidth(w int) int {
}
}
func replaceStrings(str string, connHost ConnHost) []byte {
func replaceStrings(str string, connHost *ConnHost) []byte {
str = strings.Replace(str, ReplaceStrHostname, connHost.Name, -1)
str = strings.Replace(str, ReplaceStrPort, connHost.Port, -1)
return []byte(str)

65
fs.go

@ -11,6 +11,19 @@ import (
"bufio"
)
/* FileSystemRequest:
* Makes a request to the filesystem either through
* the FileCache or directly to a function like listDir().
* It carries the requested filesystem path and any extra
* needed information, for the moment just a set of details
* about the virtual host.. Opens things up a lot more for
* the future :)
*/
type FileSystemRequest struct {
Path string
Host *ConnHost
}
/* File:
* Wraps around the cached contents of a file and
* helps with management of this content by the
@ -32,8 +45,8 @@ func NewFile(contents FileContents) *File {
return f
}
func (f *File) Contents(connHost ConnHost) []byte {
return f.contents.Render(connHost)
func (f *File) Contents(request *FileSystemRequest) []byte {
return f.contents.Render(request)
}
func (f *File) LoadContents() *GophorError {
@ -89,8 +102,8 @@ func (f *File) RUnlock() {
* are requested.
*/
type FileContents interface {
Render(ConnHost) []byte
Load() *GophorError
Render(*FileSystemRequest) []byte
Load() *GophorError
Clear()
}
@ -196,10 +209,10 @@ func unixLineEndSplitter(data []byte, atEOF bool) (advance int, token []byte, er
* This negates need to check if RestrictedFilesRegex is nil every
* single call.
*/
var listDir func(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte, *GophorError)
var listDir func(request *FileSystemRequest, hidden map[string]bool) ([]byte, *GophorError)
func _listDir(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte, *GophorError) {
return _listDirBase(dirPath, func(dirContents *[]byte, file os.FileInfo, host ConnHost) {
func _listDir(request *FileSystemRequest, hidden map[string]bool) ([]byte, *GophorError) {
return _listDirBase(request, func(dirContents *[]byte, file os.FileInfo) {
/* If requested hidden */
if _, ok := hidden[file.Name()]; ok {
return
@ -209,23 +222,23 @@ func _listDir(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte
switch {
case file.Mode() & os.ModeDir != 0:
/* Directory -- create directory listing */
itemPath := path.Join(dirPath, file.Name())
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, connHost.Name, connHost.Port)...)
itemPath := path.Join(request.Path, file.Name())
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
case file.Mode() & os.ModeType == 0:
/* Regular file -- find item type and creating listing */
itemPath := path.Join(dirPath, file.Name())
itemPath := path.Join(request.Path, file.Name())
itemType := getItemType(itemPath)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, connHost.Name, connHost.Port)...)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
default:
/* Ignore */
}
}, connHost)
})
}
func _listDirRegexMatch(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte, *GophorError) {
return _listDirBase(dirPath, func(dirContents *[]byte, file os.FileInfo, host ConnHost) {
func _listDirRegexMatch(request *FileSystemRequest, hidden map[string]bool) ([]byte, *GophorError) {
return _listDirBase(request, func(dirContents *[]byte, file os.FileInfo) {
/* If regex match in restricted files || requested hidden */
if isRestrictedFile(file.Name()) {
return
@ -237,33 +250,33 @@ func _listDirRegexMatch(dirPath string, hidden map[string]bool, connHost ConnHos
switch {
case file.Mode() & os.ModeDir != 0:
/* Directory -- create directory listing */
itemPath := path.Join(dirPath, file.Name())
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, host.Name, host.Port)...)
itemPath := path.Join(request.Path, file.Name())
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
case file.Mode() & os.ModeType == 0:
/* Regular file -- find item type and creating listing */
itemPath := path.Join(dirPath, file.Name())
itemPath := path.Join(request.Path, file.Name())
itemType := getItemType(itemPath)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, host.Name, host.Port)...)
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
default:
/* Ignore */
}
}, connHost)
})
}
func _listDirBase(dirPath string, iterFunc func(dirContents *[]byte, file os.FileInfo, connHost ConnHost), connHost ConnHost) ([]byte, *GophorError) {
func _listDirBase(request *FileSystemRequest, iterFunc func(dirContents *[]byte, file os.FileInfo)) ([]byte, *GophorError) {
/* Open directory file descriptor */
fd, err := os.Open(dirPath)
fd, err := os.Open(request.Path)
if err != nil {
Config.LogSystemError("failed to open %s: %s\n", dirPath, err.Error())
Config.LogSystemError("failed to open %s: %s\n", request.Path, err.Error())
return nil, &GophorError{ FileOpenErr, err }
}
/* Read files in directory */
files, err := fd.Readdir(-1)
if err != nil {
Config.LogSystemError("failed to enumerate dir %s: %s\n", dirPath, err.Error())
Config.LogSystemError("failed to enumerate dir %s: %s\n", request.Path, err.Error())
return nil, &GophorError{ DirListErr, err }
}
@ -274,14 +287,14 @@ func _listDirBase(dirPath string, iterFunc func(dirContents *[]byte, file os.Fil
dirContents := make([]byte, 0)
/* First add a title + a space */
dirContents = append(dirContents, buildLine(TypeInfo, "[ "+Config.Hostname+dirPath+" ]", "TITLE", NullHost, NullPort)...)
dirContents = append(dirContents, buildLine(TypeInfo, "[ "+request.Host.Name+request.Path+" ]", "TITLE", NullHost, NullPort)...)
dirContents = append(dirContents, buildInfoLine("")...)
/* Add a 'back' entry. GoLang Readdir() seems to miss this */
dirContents = append(dirContents, buildLine(TypeDirectory, "..", path.Join(fd.Name(), ".."), Config.Hostname, Config.Port)...)
dirContents = append(dirContents, buildLine(TypeDirectory, "..", path.Join(fd.Name(), ".."), request.Host.Name, request.Host.Port)...)
/* Walk through files :D */
for _, file := range files { iterFunc(&dirContents, file, connHost) }
for _, file := range files { iterFunc(&dirContents, file) }
return dirContents, nil
}

@ -173,10 +173,10 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
case FileTypeDir:
/* First try to serve gopher map */
gophermapPath := path.Join(requestPath, "/"+GophermapFileStr)
fileContents, gophorErr := Config.FileCache.FetchGophermap(gophermapPath, worker.Conn.Host)
fileContents, gophorErr := Config.FileCache.FetchGophermap(&FileSystemRequest{ gophermapPath, worker.Conn.Host })
if gophorErr != nil {
/* Get directory listing instead */
fileContents, gophorErr = listDir(requestPath, map[string]bool{}, worker.Conn.Host)
fileContents, gophorErr = listDir(&FileSystemRequest{ requestPath, worker.Conn.Host }, map[string]bool{})
if gophorErr != nil {
return gophorErr
}
@ -196,7 +196,7 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
/* Regular file */
case FileTypeRegular:
/* Read file contents */
fileContents, gophorErr := Config.FileCache.FetchRegular(requestPath, worker.Conn.Host)
fileContents, gophorErr := Config.FileCache.FetchRegular(&FileSystemRequest{ requestPath, worker.Conn.Host })
if gophorErr != nil {
return gophorErr
}

Loading…
Cancel
Save