goircd

package
v0.0.0-...-5306db9 Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2022 License: GPL-3.0, GPL-3.0 Imports: 12 Imported by: 0

README

     goircd -- minimalistic simple Internet Relay Chat (IRC) server
     ==============================================================

DESCRIPTION

goircd is very simple IRC server, written on Go.
It was heavily inspired by miniircd daemon written on Python.
goircd is free software: see the file COPYING for copying conditions.
It does not aim to replace full featured mass scalable IRC networks:

* It can not connect to other servers. Just standalone installation
* It has few basic IRC commands
* There is no support for channel operators, modes, votes, invites
* No ident lookups

But it has some convincing features:

* Only standard Go libraries, no external requirements
* Single executable binary
* No configuration file, just few command line arguments
* IPv6 out-of-box support
* Ability to listen on TLS-capable ports
* Optional channel logging to plain text files
* Optional permanent channel's state saving in plain text files
  (so you can reload daemon and all channels topics and keys won't
  disappear)
* Optional ability to authenticate users by nickname and password

Some remarks and recommendations related to it's simplicity:

* Use either nohup or similar tools to daemonize it
* Just plain logging on stderr, without syslog support

SUPPORTED IRC COMMANDS

* PASS/NICK/USER during registration workflow
* PING/PONGs
* NOTICE/PRIVMSG, ISON
* AWAY, MOTD, LUSERS, WHO, WHOIS, VERSION, QUIT
* LIST, JOIN, TOPIC, +k/-k channel MODE

USAGE

Just execute goircd daemon. It has following optional arguments:

   -hostname: hostname to show for client's connections
       -bind: address to bind to (:6667 by default)
       -motd: absolute path to MOTD file. It is reread every time
              MOTD is requested
     -logdir: directory where all channels messages will be saved. If
              omitted, then no logs will be kept
   -statedir: directory where all channels states will be saved and
              loaded during startup. If omitted, then states will be
              lost after daemon termination
    -tlsbind: enable TLS, specify address to listen on and path
     -tlspem  to PEM file with certificate and private key
  -passwords: enable client authentication and specify path to
              passwords file
          -v: increase verbosity

TLS

If you specify -bind and -tlsbind simultaneously, then you will have
both raw and encrypted listening sockets. You can use -bind "" to
disable raw socket.

AUTHENTICATION

You can turn on optional client authentication by preparing passwords
file and using the -passwords argument. Format of passwords file is:

    login1:password1\n
    login2:password2\n
    ...

LOG FILES

Log files are not opened all the time, but only during each message
saving. That is why you can safely rename them for rotation purposes.

STATE FILES

Each state file has the name equals to room's one. It contains two plain
text lines: room's topic and room's authentication key (empty if none
specified). For example:

    % cat states/meinroom
    This is meinroom's topic
    secretkey

LICENCE

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

Documentation

Index

Constants

View Source
const (
	BufSize   = 1500
	MaxOutBuf = 1 << 12
)
View Source
const (
	// Max deadline time of client's unresponsiveness
	PingTimeout = time.Second * 180
	// Max idle client's time before PING are sent
	PingThreshold = time.Second * 90
)
View Source
const (
	EventNew   = iota
	EventDel   = iota
	EventMsg   = iota
	EventTopic = iota
	EventWho   = iota
	EventMode  = iota
	EventTerm  = iota
	EventTick  = iota
	FormatMsg  = "[%s] <%s> %s\n"
	FormatMeta = "[%s] * %s %s\n"
)

Variables

View Source
var (
	LogSink   = logSink
	StateSink = stateSink
)
View Source
var (
	CRLF []byte = []byte{'\x0d', '\x0a'}
)
View Source
var (
	HitFunc func()
)
View Source
var (
	RENickname = regexp.MustCompile("^[a-zA-Z0-9-]{1,24}$")
)
View Source
var (
	RERoom = regexp.MustCompile("^#[^\x00\x07\x0a\x0d ,:/]{1,200}$")
)

Functions

func ClientRegister

func ClientRegister(client *Client, cmd string, cols []string)

Unregistered client workflow processor. Unregistered client: * is not PINGed * only QUIT, NICK and USER commands are processed * other commands are quietly ignored When client finishes NICK/USER workflow, then MOTD and LUSERS are send to him.

func HandlerJoin

func HandlerJoin(client *Client, cmd string)

func HitCallback

func HitCallback(fn func())

func Logger

func Logger(logdir string, events <-chan LogEvent)

Logging events logger itself Each room's events are written to separate file in logdir Events include messages, topic and keys changes, joining and leaving

func Processor

func Processor(events chan ClientEvent, finished chan struct{})

func RoomNameValid

func RoomNameValid(name string) bool

Sanitize room's name. It can consist of 1 to 50 ASCII symbols with some exclusions. All room names will have "#" prefix.

func SendList

func SendList(client *Client, cols []string)

func SendLusers

func SendLusers(client *Client)

func SendMotd

func SendMotd(client *Client)

func SendWhois

func SendWhois(client *Client, nicknames []string)

func SetSettings

func SetSettings(settings Settings)

func StateKeeper

func StateKeeper(statedir string, events <-chan StateEvent)

Room state events saver Room states shows that either topic or key has been changed Each room's state is written to separate file in statedir

Types

type Client

type Client struct {
	sync.Mutex
	// contains filtered or unexported fields
}

func NewClient

func NewClient(conn net.Conn) *Client

func (*Client) Close

func (c *Client) Close()

func (*Client) Host

func (c *Client) Host() string

func (*Client) Msg

func (c *Client) Msg(text string)

Send message as is with CRLF appended.

func (*Client) MsgSender

func (c *Client) MsgSender()

func (*Client) Processor

func (c *Client) Processor(sink chan ClientEvent)

Client processor blockingly reads everything remote client sends, splits messages by CRLF and send them to Daemon gorouting for processing it futher. Also it can signalize that client is unavailable (disconnected).

func (*Client) Reply

func (c *Client) Reply(text string)

Send message from server. It has ": servername" prefix.

func (*Client) ReplyNicknamed

func (c *Client) ReplyNicknamed(code string, text ...string)

Send nicknamed server message. After servername it always has target client's nickname. The last part is prefixed with ":".

func (*Client) ReplyNoChannel

func (c *Client) ReplyNoChannel(channel string)

Reply "403 no such channel" error for specified channel.

func (*Client) ReplyNoNickChan

func (c *Client) ReplyNoNickChan(channel string)

func (*Client) ReplyNotEnoughParameters

func (c *Client) ReplyNotEnoughParameters(command string)

Reply "461 not enough parameters" error for given command.

func (*Client) ReplyParts

func (c *Client) ReplyParts(code string, text ...string)

Send server message, concatenating all provided text parts and prefix the last one with ":".

func (*Client) SetDead

func (c *Client) SetDead()

func (*Client) String

func (c *Client) String() string

type ClientEvent

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

Client events going from each of client They can be either NEW, DEL or unparsed MSG

func (ClientEvent) String

func (m ClientEvent) String() string

type LogEvent

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

Logging in-room events Intended to tell when, where and who send a message or meta command

type Room

type Room struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

func NewRoom

func NewRoom(name string) *Room

func RoomRegister

func RoomRegister(name string) (*Room, chan ClientEvent)

Register new room in Daemon. Create an object, events sink, save pointers to corresponding daemon's places and start room's processor goroutine.

func (*Room) Broadcast

func (room *Room) Broadcast(msg string, clientToIgnore ...*Client)

Send message to all room's subscribers, possibly excluding someone.

func (*Room) Processor

func (room *Room) Processor(events <-chan ClientEvent)

func (*Room) SendTopic

func (room *Room) SendTopic(client *Client)

func (*Room) StateSave

func (room *Room) StateSave()

func (*Room) String

func (room *Room) String() (name string)

type Settings

type Settings struct {
	Hostname  string
	Bind      string
	Motd      string
	Logdir    string
	Statedir  string
	Passwords string
	TlsBind   string
	TlsPEM    string
	Verbose   bool
}

type StateEvent

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

Jump to

Keyboard shortcuts

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