smallnetinformationservices

package module
v0.0.0-...-e7aa579 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 24, 2024 License: BSD-3-Clause Imports: 47 Imported by: 0

README

Smallnet Information Services (SIS)

SIS provides a suite of servers from the Gemini and Small/Smol internet ecosystem, including Gemini, Gopher, Nex/NPS, Spartan, Misfin, and Titan. The configuration file allows you to define multiple servers and which service they provide and on which bind address (and port). This means one can configure multiple gemini, nex, misfin, or gopher servers. Each manual configuration change requires either a restart of the server or clicking the update config link in the gemini admin interface. However, if you use the admin gemini interface, then the servers should auto-restart when needed. During startup, the server will read the configuration to determine the number of servers and start up each server in their own lightweight execution threads (i.e. goroutines). Each server starts a lightweight thread for every incoming connection. You can configure the max number of connections for each server if desired, as well as rate limiting.

SIS also comes with an API to extend a server or create a custom server, as well as support for CGI and SCGI applications. Note that SCGI is significantly more performant and secure than CGI. (FastCGI?)

The Gemini and Misfin servers let you configure the minimum TLS version. TLS 1.3 is highly recommended for servers that intend to utilize client certificates (especially misfin) as it offers better privacy for users. However, note that TLS 1.3 is harder to support for clients of older Operating Systems, like Windows Vista and below.

You can dynamically create and run servers while SIS is running by using the admin gemini interface or the cli tool. These dynamically created servers do not persist when SIS is restarted. To make them persist, save them (or manually add them) to the SIS configuration file

The default max concurrent connections for a listener on a bind address + port is 2000, but this can be configured to something else. Connections that come in at the cap will be delayed until there's an open spot rather than rejected. A client could close the connection before the server has a chance to accept it if the server is taking too long with all of the other requests.

For servers that support or require TLS, the certificate is created on server creation via the admin gemini interface, or configured in the configuration file. Certificates are stored in the configured SIS directory using the configured name of the server and appending the .pem extension.

Port Listeners, Virtual Hosting, and Limitations

SIS is structured so that multiple servers of different hostnames can be provided on the same bind address and port. The server will start up a "port listener" on each bind address + port combination. This port listener will then multiplex all requests to the correct server based on the provided hostname (via SNI or in the request) and based on the request type (which protocol it uses).

Port Listeners can only support TLS or non-TLS, but not both. This means you cannot currently host spartan and gemini servers on the same port.

Because Nex and Gopher do not use hostnames in their requests, you cannot host these servers with other servers of different hostnames on the same port listener. Additionally, Misfin servers expect that every server on the port with the same hostname use the misfin server's root CA certificate. This means that one can host multiple servers along with a misfin server on the same port listener only if the misfin server uses it's own unique hostname.

Many of the above restrictions are easily avoided because most protocols use different ports, but the protocols that support virtual hosting allow for multiple servers of different hosts on the same port.

Gemini Server

For users of ..., you can transfer by ....

Titan

Titan can be enabled on a Gemini server and provides multiple functionalities: You can set up specific upload routes for services that you provide, and you can also set it to allow uploads of any static file on the site, which provides an easy mechanism for admins to update their static files via Titan.

CGI and SCGI applications can also utilize Titan.

Misfin Server (Unimplemented)

Users can receive mail through multiple methods: a user on the host system, via the Geminimail interface (if enabled), or through the Gemini-Misfin Access Protocol (GMAP) using supported clients. GMAP offers two different mechanisms that intend to mimic IMAP and POP3, respectively. GMAP's Fetch Address is provided to mimic POP3 and can be configured to delete on fetch or not. The Fetch Address can also be given a query of a start date (in ISO-8601 format) to fetch messages from. This can be used by clients to only get the latest messages that have not been fetched before.

The Misfin Server also allows you to create newsletters, mailinglists, and CGI Mailboxes. CGI Mailboxes are mailboxes that call out to a CGI script when a message has been received.

For users that use my misfinserver project, you can quickly transfer over to SIS by ...

For users of the reference implementation, you can import by ...

Finally, for users of Cipres's fork of the reference implementation, you can transfer over to SIS by ...

Misfin Geminimail Interface (Unimplemented)

You can set a misfin server to provide a geminimail interface for easy mail access to users. This is usually served over the same port as the misfin server. However, you can instead serve it over a route of one of your Gemini servers.

Nex Server

Gopher Server

For users of gophernicus, you can transfer to SIS by ...

Spartan Server

HTTP Proxy (Unimplemented)

You can configure an HTTP proxy for any Gemini or Nex server you have configured by setting the http-proxy field to the port you want to serve it over.

Proxy Between Protocols (WIP)

You can proxy between any of the file-serving protocols (gemini, gopher, nex, and spartan). When a request is made to a proxy route, it will proxy the request to the desired server and convert the output to the expected output for the proxy server. For example, one could proxy all routes on a gemini server to gopher and the output will be converted to gophermaps if needed.

Internationalization

None of the supported small internet protocols supports specifying a language in a request. To get around this, one can set up routes specific to certain languages.

For responses, the server will try to detect the mimetype and language of the static document being sent back for the protocols that support these features. One can also manually specify these attributes in CGI/SCGI scripts and with the API.

TLS

You can use the same or different TLS certificates for each server. If using one for multiple servers, make sure that the hostnames for each server is provided in the SAN field. Note that misfin servers always use their own separate server certificate because they act as Certificate Authorities to their respective mailbox certificates.

SNI and ALPN

SNI is used to support virtual hosting. When a client doesn't use SNI, the server will default to the certificate of the first added server on a bind address + port listener, unless a misfin server is provided on the listener, then the misfin server's certificate is used.

Most clients do not currently use ALPN (Application-Layer Protocol Negotiation) within the smallnet, but SIS does provide a list of protocols to allow for ALPN when available. ALPN will allow the TLS connection to quickly and explicitly negotiate the desired protocol for the incoming request. ALPN values sent over in the list include "gemini", "titan", and "misfin".

Reverse Proxying (Unimplemented)

You can use SIS to reverse proxy to other servers.

Gemini Admin Interface (WIP)

SIS provides a gemini interface to allow admins to manage each server, including stopping or restarting a particular server, creating servers, setting routes, configuring proxies, etc.

Streaming Support

Documentation

Index

Constants

This section is empty.

Variables

View Source
var OID_CN = asn1.ObjectIdentifier{2, 5, 4, 3}
View Source
var OID_USER_ID = asn1.ObjectIdentifier{0, 9, 2342, 19200300, 100, 1, 1}
View Source
var TOFUMap map[string]string

Maps address to fingerprint. Shared between all servers

View Source
var Version string = "0.1"

Functions

func ArchiveMimetype

func ArchiveMimetype(mimetype string) bool

func AudioMimetype

func AudioMimetype(mimetype string) bool

func CalendarMimetype

func CalendarMimetype(mimetype string) bool

func CertFilename

func CertFilename(filename string) bool

func CertMimetype

func CertMimetype(mimetype string) bool

func ContainsCensorWords

func ContainsCensorWords(str string) bool

func CutAny

func CutAny(s string, chars string) (before string, after string, found bool)

CutAny slices s around any Unicode code point from chars, returning the text before and after it. The found result reports whether any Unicode code point was appears in s. If it does not appear in s, CutAny returns s, "", false.

func DirFS

func DirFS(name string) fs.FS

func DocumentMimetype

func DocumentMimetype(mimetype string) bool

Where do markup language files get placed?

func DotFilename

func DotFilename(filename string) bool

func FilenameToGopherItemtype

func FilenameToGopherItemtype(filename string) rune

Use when you cannot get the file's mimetype, like if converting URLs

func GetTitleFromGemtext

func GetTitleFromGemtext(reader io.Reader) string

Scans until it sees a level-1 heading, and then stops scanning and returns it Works with gemtext, scrolltext, and markdown

func InsertParamsIntoRouteString

func InsertParamsIntoRouteString(route string, params map[string]string, globString string, reverse bool) string

Reverse will insert params into components starting with ":". Otherwise, params will be inserted into components starting with "$"

func MimetypeGetsLangParam

func MimetypeGetsLangParam(mt_string string) bool

func MimetypeToGopherItemtype

func MimetypeToGopherItemtype(mt_string string, mt_parent_string string) rune

func PrintRoute

func PrintRoute(node *RouteNode, indent int)

func PrivacySensitiveFilename

func PrivacySensitiveFilename(filename string) bool

func PrivacySensitiveMimetype

func PrivacySensitiveMimetype(mimetype string) bool

func ProtocolIsTLS

func ProtocolIsTLS(protocol ProtocolType) bool

func ProtocolToName

func ProtocolToName(protocol ProtocolType) string

func VideoMimetype

func VideoMimetype(mimetype string) bool

Types

type BindPortHostnameCertificate

type BindPortHostnameCertificate struct {
	// contains filtered or unexported fields
}

A certificate for a given BindAddr+Port+Hostname Pair

type CertInfo

type CertInfo struct {
	IsCA bool
	// contains filtered or unexported fields
}

type Log

type Log struct {
	// contains filtered or unexported fields
}

type PortListener

type PortListener struct {
	SIS                      *SISContext
	BindAddress              string
	Port                     string
	MaxConcurrentConnections int
	// contains filtered or unexported fields
}

func NewPortListener

func NewPortListener(SIS *SISContext, BindAddress string, Port string) *PortListener

Create new PortListener

func (*PortListener) AddCertificate

func (l *PortListener) AddCertificate(Hostname string, certFilepath string)

Adds and loads the certificate into the respective PortListener

func (*PortListener) GetCertificate

func (l *PortListener) GetCertificate(Hostname string) BindPortHostnameCertificate

func (*PortListener) HasCertificate

func (l *PortListener) HasCertificate(Hostname string) bool

func (*PortListener) Start

func (l *PortListener) Start(wg *sync.WaitGroup)

type PortListenerKey

type PortListenerKey struct {
	BindAddress string
	Port        string
}

type ProtocolType

type ProtocolType int
const ProtocolType_Gemini ProtocolType = 1
const ProtocolType_Gopher ProtocolType = 4
const ProtocolType_Gopher_SSL ProtocolType = 5 // TODO
const ProtocolType_Misfin_A ProtocolType = 6 // Deprecated
const ProtocolType_Misfin_B ProtocolType = 7
const ProtocolType_Misfin_C ProtocolType = 8
const ProtocolType_NPS ProtocolType = 3
const ProtocolType_Nex ProtocolType = 2
const ProtocolType_Scroll ProtocolType = 11
const ProtocolType_Spartan ProtocolType = 10
const ProtocolType_Titan ProtocolType = 9
const ProtocolType_Unknown ProtocolType = 0

type RateLimitListItem

type RateLimitListItem struct {
	// contains filtered or unexported fields
}

type Request

type Request struct {
	// Request Data
	Type   ServerType // TODO: Change this to ProtocolType instead
	Upload bool       // true if request supports reading uploaded data

	GlobString string // Set to the path components of the glob part of the route

	// Upload Data
	DataSize int64 // Expected Size for upload (-1 for any size until connection close)

	DataMime string // Used for Titan and other protocols that support upload with mimetype. For Spartan, it is usually empty or "text/plain" if proxying to Spartan servers from servers that use queries.

	// More Request Data
	UserCert *x509.Certificate // Used for protocols that support TLS Client Certs (Misfin and Gemini)
	IP       string

	Proxied bool
	Server  ServerHandle

	// Used for Scroll Protocol
	ScrollMetadataRequested  bool
	ScrollRequestedLanguages []string
	// contains filtered or unexported fields
}

func (*Request) Abstract

func (r *Request) Abstract(mimetype string, data string) error

For sending an Abstract file. Will parse data to get Author metadata.

func (*Request) BadRequest

func (r *Request) BadRequest(format string, elem ...any) error

func (*Request) Bytes

func (r *Request) Bytes(mimetype string, data []byte) error

func (*Request) ClearScrollMetadataResponse

func (r *Request) ClearScrollMetadataResponse()

func (*Request) ClientCertNotAuthorized

func (r *Request) ClientCertNotAuthorized(format string, elem ...any) error

func (*Request) DisableConvertMode

func (r *Request) DisableConvertMode()

func (*Request) EnableConvertMode

func (r *Request) EnableConvertMode()

func (*Request) File

func (r *Request) File(filePath string) error

Reads whole file into memory, automatically determins the correct mimetype, and sends it over (converting if in convert mode). If file not found or error on opening file, returns with error without sending anything back to the connection. Prefer FileMimetype() if you know the mimetype beforehand.

func (*Request) FileMimetype

func (r *Request) FileMimetype(mimetype string, filePath string) error

func (*Request) Fragment

func (r *Request) Fragment() string

NOTE: Should almost never be used

func (*Request) Gemini

func (r *Request) Gemini(text string) error

TODO: Add a way to configure nex width in Request (or Nex Server)

func (*Request) GetParam

func (r *Request) GetParam(name string) string

Returns empty string if param not in route

func (*Request) GetUploadData

func (r *Request) GetUploadData() ([]byte, error)

Get Titan or Spartan raw data.

func (*Request) Gophermap

func (r *Request) Gophermap(text string) error

TODO: make sure all lines end in CRLF

func (*Request) GophermapLine

func (r *Request) GophermapLine(linetype string, name string, selector string, hostname string, port string) error

Enter empty strings for hostname and port to use the server's hostname and port. TODO: Handle URL: links and cross-server links

func (*Request) Host

func (r *Request) Host() string

Hostname + Port. Port is excluded if it's the default of the protocol.

func (*Request) Hostname

func (r *Request) Hostname() string

TODO: Reconsider how this works... Gets the requested hostname for protocols that use those in requests If not used in request, then gets the hostname of the server.

func (*Request) IPHash

func (r *Request) IPHash() string

Takes checksum hash of IP and returns it in a hex string

func (*Request) Markdown

func (r *Request) Markdown(text string) error

func (*Request) NexListing

func (r *Request) NexListing(text string) error

Send Next text. TODO: This is unfinished.

func (*Request) NotFound

func (r *Request) NotFound(format string, elem ...any) error

func (*Request) Path

func (r *Request) Path() string

Gets the requested path, removing hostname and scheme information for protocols that use those in requests Path is unescaped if part of URL (for protocols that use URL requests). Unescaping is unnecessary for Nex and Gopher.

func (*Request) PlainText

func (r *Request) PlainText(format string, elem ...any) error

func (*Request) PromptLine

func (r *Request) PromptLine(link string, text string) error

Uses a regular link linetype for Gemini and Nex, and a prompt/search linetype for Spartan and Gopher. The link should be in standard url format, even for gopher servers.

func (*Request) Query

func (r *Request) Query() (string, error)

Gets the query for protocols that support queries in requests. The returned query is unescaped. If Spartan, it gets the *raw* uploaded data (if there is any) as text. To get it query escaped, use request.RawQuery() If data is longer than Spartan Query Limit, then this method will return an error.

func (*Request) RawFragment

func (r *Request) RawFragment() string

NOTE: Should almost never be used

func (*Request) RawPath

func (r *Request) RawPath() string

Gets the requested path, removing hostname and scheme information for protocols that use those in requests Path is escaped if part of URL (for protocols that use URL requests). NOTE: Nex and Gopher requests are not escaped.

func (*Request) RawQuery

func (r *Request) RawQuery() (string, error)

Gets the escaped query for protocols that support queries in requests. If Spartan, it gets the uploaded data (if there is any) as text and escapes it. If data is longer than Spartan Query Limit, then this method will return an error.

func (*Request) Redirect

func (r *Request) Redirect(format string, elem ...any)

func (*Request) RequestClientCert

func (r *Request) RequestClientCert(format string, elem ...any) error

func (*Request) RequestInput

func (r *Request) RequestInput(format string, elem ...any) error

TODO: When proxying gopher to gemini, translate the gopher input requested message/error to a gemini input request.

func (r *Request) RouteLink(route string, name string) error

Sends a link to a particular route on the given server. Route links can reference other servers by prefixing the route path with "$ServerName". You can reference the current request's params by prefixing them with "$" in the route path.

func (*Request) Scroll

func (r *Request) Scroll(text string) error

TODO: Add a way to configure nex width in Request (or Nex Server)

func (*Request) SendAbstract

func (r *Request) SendAbstract(mimetype string) error

Will send the abstract that is already stored in the scroll metadata

func (*Request) ServerUnavailable

func (r *Request) ServerUnavailable(format string, elem ...any) error

func (*Request) SetLanguage

func (r *Request) SetLanguage(lang string)

Used for all protocols that send a mimetype in the response

func (*Request) SetNoLanguage

func (r *Request) SetNoLanguage()

Forces the response to have no lang parameter

func (*Request) SetScrollMetadataResponse

func (r *Request) SetScrollMetadataResponse(metadata ScrollMetadata)

func (*Request) SetSpartanQueryLimit

func (r *Request) SetSpartanQueryLimit(bytesize int64)

Limits the number of bytes of uploaded data to read when you call request.Query() or request.RawQuery(). The default is 1024 to (somewhat) match Gemini. This only applies to .RawQuery() and .Query() calls. It does not apply to .GetUploadData() calls.

func (*Request) Spartan

func (r *Request) Spartan(text string) error

func (*Request) Stream

func (r *Request) Stream(mimetype string, reader io.Reader) error

TODO: Use a buffer bool and provide a 32KB buffer from the pool. Streams a file, using a 32KB buffer by default. If you want to control the buffer size, use StreamBuffer.

func (*Request) StreamBuffer

func (r *Request) StreamBuffer(mimetype string, reader io.Reader, buf []byte) error

Provide a buffer to handle the copy. This allows you to control your own buffer size to increase performance. For big files, create a big buffer (at the cost of memory). For small files, create a smaller buffer.

func (*Request) TemporaryFailure

func (r *Request) TemporaryFailure(format string, elem ...any) error

func (*Request) TextWithMimetype

func (r *Request) TextWithMimetype(mimetype string, text string) error

TODO

func (*Request) UserCertHash_Gemini

func (r *Request) UserCertHash_Gemini() string

func (*Request) UserCertHash_Misfin

func (r *Request) UserCertHash_Misfin() string

func (*Request) UserCert_MD5Hash

func (r *Request) UserCert_MD5Hash() string

MD5 Hash of User Cert - usually used for Gemini and Titan. Returns empty string when there's no user cert.

func (*Request) UserCert_SHA256Hash

func (r *Request) UserCert_SHA256Hash() string

SHA256 Hash of User Cert - usually used for Misfin. Returns empty string when there's no user cert.

type RequestHandler

type RequestHandler func(request Request)

TODO: Ability to return errors (especially NotFound, which redirects to the NotFoundHandler)

type RequestHeader

type RequestHeader struct {
	Protocol        ProtocolType
	Request         string            // The Selector/Path or URL that is requested
	Hostname        string            // Used for Gemini, Misfin, and Titan
	ContentLength   int64             // Used for Titan, Misfin, and Spartan. If Titan protocol and 0, it's a titan delete request. If Spartan and 0, no upload data is expected.
	Token           string            // Used for Titan
	Mime            string            // Used for Titan
	UserCert        *x509.Certificate // For TLS protocols
	MetadataRequest bool              // Used for Scroll protocol
	Languages       []string          // Used for Scroll protocol
}

type RouteListItem

type RouteListItem struct {
	// contains filtered or unexported fields
}

type RouteNode

type RouteNode struct {
	Component string         // If equal to "*", then it's a blob and matches with everything.
	Handler   RequestHandler // If nil, no handler

	Parent   *RouteNode
	Children *RouteNode // Linked List of Children

	// Linked List Info
	Next *RouteNode
	// contains filtered or unexported fields
}

func (*RouteNode) ChildrenLength

func (node *RouteNode) ChildrenLength() int

func (*RouteNode) GetRouteAncestry

func (node *RouteNode) GetRouteAncestry() []*RouteNode

Gets array of route nodes from root to last component

func (*RouteNode) GetRoutePath

func (node *RouteNode) GetRoutePath() string

Gets the route path string

type Router

type Router struct {
	NotFoundHandler RequestHandler
	// contains filtered or unexported fields
}

Uses a tree to store routes, and matches using a breadth-first search algorithm.

func (*Router) GetRoutesList

func (router *Router) GetRoutesList() []RouteListItem

Flattens routes tree into a list of routes. Returns an array of strings.

func (*Router) PrintRouteTree

func (router *Router) PrintRouteTree()

func (*Router) Search

func (router *Router) Search(p string) (*RouteNode, string, map[string]string)

Uses breadth-first search. Returns node, globString (if exists), and params map TODO: Make sure to collect list of params TODO: Differentiate between "/blah/" and "/blah"?

type SISContext

type SISContext struct {
	// contains filtered or unexported fields
}

func InitSIS

func InitSIS(directory string) (*SISContext, error)

func (*SISContext) AddServer

func (context *SISContext) AddServer(server Server) ServerHandle

TODO: Make loadSISConfig use this function? When directory is empty, creates subdirectory under SIS directory named with the server's name.

func (*SISContext) AddServerRoute

func (context *SISContext) AddServerRoute(BindAddress string, Port string, Protocol ProtocolType, Hostname string, server ServerHandle)

func (*SISContext) AdminServer

func (context *SISContext) AdminServer() *Server

Get the Admin server, which will let you customize it (like by adding routes and handlers).

func (*SISContext) AllowIP

func (context *SISContext) AllowIP(ip string)

func (*SISContext) BlockIP

func (context *SISContext) BlockIP(ip string)

func (*SISContext) EnterMaintenanceMode_All

func (context *SISContext) EnterMaintenanceMode_All()

Enters maintenance mode for all portListeners

func (*SISContext) FindServerByName

func (context *SISContext) FindServerByName(name string) ServerHandle

func (*SISContext) FullRestart

func (context *SISContext) FullRestart()

func (*SISContext) GetOrCreatePortListener

func (context *SISContext) GetOrCreatePortListener(BindAddress string, Port string) *PortListener

func (*SISContext) GetPortListener

func (context *SISContext) GetPortListener(BindAddress string, Port string) *PortListener

func (*SISContext) IsIPBlocked

func (context *SISContext) IsIPBlocked(ip string) bool

func (*SISContext) Log

func (context *SISContext) Log(serverType ServerType, label string, msgFormat string, args ...any)

Concurrent-safe

func (*SISContext) SaveConfiguration

func (context *SISContext) SaveConfiguration() error

Saves SIS Config File TODO: Mutex?

func (context *SISContext) SetUpdateLink(link string)

Set a gemini link to update the server

func (*SISContext) ShutdownPortListeners

func (context *SISContext) ShutdownPortListeners()

Shuts down all Port Listeners, but does not shut down SIS

func (*SISContext) ShutdownSIS

func (context *SISContext) ShutdownSIS()

Shuts down all of SIS

func (*SISContext) Start

func (context *SISContext) Start()

Starts GIS. Must call InitSIS first.

func (*SISContext) UpdateAndRestart

func (context *SISContext) UpdateAndRestart(data []byte) string

You must have the new subprocess delete the renamed filename (which is returned by the function). You can do this by redirecting to a route that deletes the old file. By the time the redirect happens, the server would have been updated. You can pass in the data of the executable instead of downloading the data from the update link.

type ScrollMetadata

type ScrollMetadata struct {
	Author      string
	PublishDate time.Time // Should be in UTC
	UpdateDate  time.Time // Should be in UTC
	Language    string    // Should use BCP47
	Abstract    string
}

type Server

type Server struct {
	Name                     string
	Type                     ServerType
	BindAddress              string
	Port                     string
	UploadPort               string // Port to listen on for uploads (usually the same port for gemini+titan, misfin+titan+gemini, and Spartan). Used internally for Nex+NPS.
	MaxConcurrentConnections int    // -1 for unlimited
	Directory                string // Defaults to SIS Directory, unless configured to elsewhere via sis.conf file in code.
	FS                       ServerFS

	ServerHandler   ServerHandlerFunc // For custom servers
	DefaultLanguage string

	Hostname              string // TODO
	Pubnix                bool
	ServerTLSCertFilename string
	ServerTLSCert         []byte // TODO: Unused
	Router                Router // For Downloads
	UploadRouter          Router // For Uploads (if applicable)

	RateLimitDuration time.Duration

	SIS *SISContext
	// contains filtered or unexported fields
}

NOTE: Usually accessed through a ServerHandle. See server_handle.go

func (*Server) AddCertificate

func (s *Server) AddCertificate(filepath string)

func (*Server) AddDirectory

func (s *Server) AddDirectory(p string, directoryPath string)

AddDirectory adds a directory that's either absolute, or relative to the server's directory Remember that a server's directory, when not specified, defaults to a subdirectory named after the server's name under the SIS directory.

func (*Server) AddEmbedDirectory

func (s *Server) AddEmbedDirectory(p string, content embed.FS, directoryPath string)

func (*Server) AddEmbedFile

func (s *Server) AddEmbedFile(p string, content embed.FS, filePath string)

func (*Server) AddFile

func (s *Server) AddFile(p string, filePath string)

Adds a file that's either absolute, or relative to the server's directory

func (*Server) AddProxyRoute

func (s *Server) AddProxyRoute(p string, proxyRoute string, gopherItemType rune)

Proxy routes will proxy the handler from a different server to this server and will automatically set the request to convert mode.

func (*Server) AddRoute

func (s *Server) AddRoute(p string, handler RequestHandler)

func (*Server) AddUploadRoute

func (s *Server) AddUploadRoute(p string, handler RequestHandler)

func (*Server) CleanupRateLimiting

func (s *Server) CleanupRateLimiting()

Removes all IPs that are passed the rate-limit duration. There's no need to call this too often, but do not wait so long that the ip list becomes too big.

func (*Server) GetHandle

func (s *Server) GetHandle() ServerHandle

func (*Server) IPRateLimit_ClearRedirectPath

func (s *Server) IPRateLimit_ClearRedirectPath(ip string)

func (*Server) IPRateLimit_ExpectRedirectPath

func (s *Server) IPRateLimit_ExpectRedirectPath(ip string, redirectPath string)

When a redirection occurs, let server know to expect another request immediately following the previous one so that the rate-limiting can be bypassed

func (*Server) IPRateLimit_IsExpectingRedirect

func (s *Server) IPRateLimit_IsExpectingRedirect(ip string) bool

func (*Server) IpRateLimit_GetExpectedRedirectPath

func (s *Server) IpRateLimit_GetExpectedRedirectPath(ip string) string

func (*Server) IsIPRateLimited

func (s *Server) IsIPRateLimited(ip string) bool

If not rate-limited, set ip to current time and return false. If last access time is within duration, set ip to current time and return true. Otherwise, set ip to current time and return false

func (*Server) LoadRoutes

func (s *Server) LoadRoutes() error

Located in server's directory (which defaults to the SIS directory)

func (*Server) SaveRoutes

func (s *Server) SaveRoutes() error

func (*Server) Scheme

func (s *Server) Scheme() string

Gets the default/download protocol Scheme

func (*Server) UploadScheme

func (s *Server) UploadScheme() string

type ServerDirFS

type ServerDirFS string

func (ServerDirFS) Lstat

func (dir ServerDirFS) Lstat(name string) (fs.FileInfo, error)
func (dir ServerDirFS) MkSymlink(name, target string) error

NOTE: The target is *not* relative to the dirFS

func (ServerDirFS) Mkdir

func (dir ServerDirFS) Mkdir(name string, perm fs.FileMode) error

func (ServerDirFS) Open

func (dir ServerDirFS) Open(name string) (fs.File, error)

func (ServerDirFS) OpenFile

func (dir ServerDirFS) OpenFile(name string, flag int, perm fs.FileMode) (fs.File, error)

func (ServerDirFS) ReadDir

func (dir ServerDirFS) ReadDir(name string) ([]fs.DirEntry, error)

func (ServerDirFS) ReadFile

func (dir ServerDirFS) ReadFile(name string) ([]byte, error)
func (dir ServerDirFS) Readlink(name string) (string, error)

func (ServerDirFS) Stat

func (dir ServerDirFS) Stat(name string) (fs.FileInfo, error)

func (ServerDirFS) WriteFile

func (dir ServerDirFS) WriteFile(name string, data []byte, perm fs.FileMode) error

type ServerFS

type ServerFS interface {
	fs.FS
	fs.ReadFileFS
	fs.ReadDirFS
	fsx.FS
	fsx.FSSupportingWrite
	fsx.FSSupportingMkSymlink
	fsx.FSSupportingReadlink
	fsx.FSSupportingStat
	WriteFile(name string, data []byte, perm fs.FileMode) error
}

Extends go-fsx/osfs to add ReadDir and ReadFile methods

type ServerHandle

type ServerHandle struct {
	// contains filtered or unexported fields
}

Handle value for servers

func (*ServerHandle) AddCertificate

func (handle *ServerHandle) AddCertificate(filePath string)

func (*ServerHandle) AddDirectory

func (handle *ServerHandle) AddDirectory(p string, directoryPath string)

func (*ServerHandle) AddFile

func (handle *ServerHandle) AddFile(p string, filePath string)

func (*ServerHandle) AddProxyRoute

func (handle *ServerHandle) AddProxyRoute(p string, proxyRoute string, gopherItemType rune)

func (*ServerHandle) AddRoute

func (handle *ServerHandle) AddRoute(p string, handler RequestHandler)

func (*ServerHandle) AddUploadRoute

func (handle *ServerHandle) AddUploadRoute(p string, handler RequestHandler)

func (*ServerHandle) BindAddress

func (handle *ServerHandle) BindAddress() string

func (*ServerHandle) CleanupRateLimiting

func (handle *ServerHandle) CleanupRateLimiting()

func (*ServerHandle) DefaultLanguage

func (handle *ServerHandle) DefaultLanguage() string

func (*ServerHandle) Directory

func (handle *ServerHandle) Directory() string

func (*ServerHandle) FS

func (handle *ServerHandle) FS() ServerFS

func (*ServerHandle) GetServer

func (handle *ServerHandle) GetServer() *Server

func (*ServerHandle) Hostname

func (handle *ServerHandle) Hostname() string

func (*ServerHandle) IsIPRateLimited

func (handle *ServerHandle) IsIPRateLimited(ip string) bool

func (*ServerHandle) LoadRoutes

func (handle *ServerHandle) LoadRoutes() error

func (*ServerHandle) MaxConcurrentConnections

func (handle *ServerHandle) MaxConcurrentConnections() int

func (*ServerHandle) Name

func (handle *ServerHandle) Name() string

func (*ServerHandle) Port

func (handle *ServerHandle) Port() string

func (*ServerHandle) Pubnix

func (handle *ServerHandle) Pubnix() bool

func (*ServerHandle) RateLimitDuration

func (handle *ServerHandle) RateLimitDuration() time.Duration

func (*ServerHandle) Router

func (handle *ServerHandle) Router() Router

func (*ServerHandle) SIS

func (handle *ServerHandle) SIS() *SISContext

func (*ServerHandle) SaveRoutes

func (handle *ServerHandle) SaveRoutes() error

func (*ServerHandle) Scheme

func (handle *ServerHandle) Scheme() string

func (*ServerHandle) ServerHandler

func (handle *ServerHandle) ServerHandler() ServerHandlerFunc

func (*ServerHandle) ServerTLSCert

func (handle *ServerHandle) ServerTLSCert() []byte

func (*ServerHandle) ServerTLSCertFilename

func (handle *ServerHandle) ServerTLSCertFilename() string

func (*ServerHandle) SetBindAddress

func (handle *ServerHandle) SetBindAddress(v string)

func (*ServerHandle) SetHostname

func (handle *ServerHandle) SetHostname(v string)

func (*ServerHandle) SetMaxConcurrentConnections

func (handle *ServerHandle) SetMaxConcurrentConnections(v int)

func (*ServerHandle) SetName

func (handle *ServerHandle) SetName(v string)

func (*ServerHandle) SetPort

func (handle *ServerHandle) SetPort(v string)

func (*ServerHandle) SetPubnix

func (handle *ServerHandle) SetPubnix(v bool)

func (*ServerHandle) SetRateLimitDuration

func (handle *ServerHandle) SetRateLimitDuration(v time.Duration)

func (*ServerHandle) SetRouter

func (handle *ServerHandle) SetRouter(v Router)

func (*ServerHandle) SetSIS

func (handle *ServerHandle) SetSIS(v *SISContext)

func (*ServerHandle) SetServerHandler

func (handle *ServerHandle) SetServerHandler(v ServerHandlerFunc)

func (*ServerHandle) SetServerTLSCertFilename

func (handle *ServerHandle) SetServerTLSCertFilename(v string)

func (*ServerHandle) SetType

func (handle *ServerHandle) SetType(v ServerType)

func (*ServerHandle) Type

func (handle *ServerHandle) Type() ServerType

type ServerHandlerFunc

type ServerHandlerFunc func(s *Server)

type ServerRouteMapKey

type ServerRouteMapKey struct {
	Protocol ProtocolType
	Hostname string // Empty for default/none
}

Every Bind Address + Port + Protocol key has one server, but a server can be attached to multiple keys. Servers that use multiple protocols will be registered under multiple keys.

type ServerType

type ServerType int
const ServerType_Admin ServerType = 4 // Gemini + Titan
const ServerType_Gemini ServerType = 0 // Gemini + Titan
const ServerType_Gopher ServerType = 2 // Gopher
const ServerType_Misfin ServerType = 3 // Misfin(B) + Misfin(C) + Gemini
const ServerType_Nex ServerType = 1 // Nex + NPS
const ServerType_Scroll ServerType = 6
const ServerType_Spartan ServerType = 5
const ServerType_Unknown ServerType = 7

Directories

Path Synopsis
The main Smallnet Information Services Server
The main Smallnet Information Services Server

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL