1 Commits

Author SHA1 Message Date
James Mills
d06f3eac27 Added contributors guideline (CONTRIBUTING.md) 2017-11-24 16:43:02 -08:00
56 changed files with 189 additions and 5391 deletions

View File

@@ -1,8 +0,0 @@
version: 1
update_configs:
- package_manager: "go:modules"
directory: "/"
update_schedule: "daily"
- package_manager: "docker"
directory: "/"
update_schedule: "weekly"

30
.drone.yml Normal file
View File

@@ -0,0 +1,30 @@
workspace:
base: /go
path: src/github.com/prologic/eris
pipeline:
build:
image: golang
commands:
- go get -d
- go build .
docker:
image: plugins/docker
repo: r.mills.io/prologic/eris
registry: r.mills.io
secrets: [ docker_username, docker_password ]
notify:
image: drillster/drone-email
host: mail.mills.io
from: drone@mills.io
skip_verify: true
when:
status: [ success, changed, failure ]
secrets:
registry_username:
external: true
registry_password:
external: true

View File

@@ -1,35 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,17 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,35 +0,0 @@
---
name: Build
on:
push:
branches:
- master
pull_request:
jobs:
build:
name: Build
strategy:
matrix:
go-version:
- "1.12.x"
- "1.13.x"
- "1.14.x"
os:
- "ubuntu-latest"
- "macos-latest"
- "windows-latest"
runs-on: ${{ matrix.os }}
steps:
- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v1
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: |
go build -v .
- name: Test
run: |
go test -v -race .

4
.gitignore vendored
View File

@@ -1,8 +1,6 @@
*~*
bin
dist
*.db
*.pem
./coverage.txt
./eris
eris

45
.gitmodules vendored Normal file
View File

@@ -0,0 +1,45 @@
[submodule "vendor/github.com/sirupsen/logrus"]
path = vendor/github.com/sirupsen/logrus
url = https://github.com/sirupsen/logrus
[submodule "vendor/golang.org/x/crypto"]
path = vendor/golang.org/x/crypto
url = https://go.googlesource.com/crypto
[submodule "vendor/golang.org/x/sys"]
path = vendor/golang.org/x/sys
url = https://go.googlesource.com/sys
[submodule "vendor/github.com/DanielOaks/girc-go"]
path = vendor/github.com/DanielOaks/girc-go
url = https://github.com/DanielOaks/girc-go
[submodule "vendor/github.com/goshuirc/e-nfa"]
path = vendor/github.com/goshuirc/e-nfa
url = https://github.com/goshuirc/e-nfa
[submodule "vendor/github.com/imdario/mergo"]
path = vendor/github.com/imdario/mergo
url = https://github.com/imdario/mergo
[submodule "vendor/golang.org/x/text"]
path = vendor/golang.org/x/text
url = https://go.googlesource.com/text
[submodule "vendor/gopkg.in/yaml.v2"]
path = vendor/gopkg.in/yaml.v2
url = https://gopkg.in/yaml.v2
[submodule "vendor/github.com/prometheus/client_golang"]
path = vendor/github.com/prometheus/client_golang
url = https://github.com/prometheus/client_golang
[submodule "vendor/github.com/beorn7/perks"]
path = vendor/github.com/beorn7/perks
url = https://github.com/beorn7/perks
[submodule "vendor/github.com/golang/protobuf"]
path = vendor/github.com/golang/protobuf
url = https://github.com/golang/protobuf
[submodule "vendor/github.com/prometheus/client_model"]
path = vendor/github.com/prometheus/client_model
url = https://github.com/prometheus/client_model
[submodule "vendor/github.com/prometheus/common"]
path = vendor/github.com/prometheus/common
url = https://github.com/prometheus/common
[submodule "vendor/github.com/matttproud/golang_protobuf_extensions"]
path = vendor/github.com/matttproud/golang_protobuf_extensions
url = https://github.com/matttproud/golang_protobuf_extensions
[submodule "vendor/github.com/prometheus/procfs"]
path = vendor/github.com/prometheus/procfs
url = https://github.com/prometheus/procfs

View File

@@ -1,31 +0,0 @@
builds:
- binary: eris
flags: -tags "static_build"
ldflags: -w -X mail.Version={{.Version}} -X main.Commit={{.Commit}}
env:
- CGO_ENABLED=0
goos:
- darwin
- freebsd
- linux
- windows
goarch:
- i386
- amd64
- arm
- amd64
goarm:
- 6
- 7
sign:
artifacts: checksum
archive:
wrap_in_directory: true
format_overrides:
- goos: windows
format: zip
files:
- "*.pem"
- "*.yml"
- "LICENSE"
- "README.md"

View File

@@ -1,29 +0,0 @@
---
yaml-files:
- '*.yaml'
- '*.yml'
- '.yamllint'
rules:
braces: enable
brackets: enable
colons: enable
commas: enable
comments: disable
comments-indentation: disable
document-end: disable
document-start:
level: warning
empty-lines: enable
empty-values: disable
hyphens: enable
indentation: enable
key-duplicates: enable
key-ordering: disable
line-length: disable
new-line-at-end-of-file: enable
new-lines: enable
octal-values: enable
quoted-strings: disable
trailing-spaces: enable
truthy: disable

View File

@@ -1,46 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at prologic@shortcircuit.net.au. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -46,4 +46,4 @@ $ git push -u origin my-feature
When describing your bug report; please be concise and as detailed as you can
so we can easily work out what the problem is. It's also very helpful if you
are able to provide a test case that repeatedly demonstrates the bug at hand.
are able to provide a test case that repeatedly demonstrates the bug at hand:

View File

@@ -2,6 +2,7 @@
FROM golang:alpine AS build
ARG TAG
ARG BUILD
ENV APP eris
ENV REPO prologic/$APP
@@ -11,7 +12,7 @@ RUN apk add --update git make build-base && \
WORKDIR /go/src/github.com/$REPO
COPY . /go/src/github.com/$REPO
RUN make TAG=$TAG build
RUN make TAG=$TAG BUILD=$BUILD build
# Runtime
FROM alpine

View File

@@ -6,6 +6,7 @@ APP=eris
PACKAGE=irc
REPO?=prologic/$(APP)
TAG?=latest
BUILD?=-dev
all: dev
@@ -16,24 +17,17 @@ deps:
@go get ./...
build: clean deps
@echo "github.com/$(REPO)/${PACKAGE}.GitCommit=$(COMMIT)"
@echo " -> Building $(REPO) $(TAG)@$(COMMIT)"
@echo " -> Building $(TAG)$(BUILD)"
@go build -tags "netgo static_build" -installsuffix netgo \
-ldflags "-w -X github.com/$(REPO)/${PACKAGE}.GitCommit=$(COMMIT)"
-ldflags "-w -X github.com/$(REPO)/${PACKAGE}.GitCommit=$(COMMIT) -X github.com/$(REPO)/${PACKAGE}.Build=$(BUILD)" .
@echo "Built $$(./$(APP) -v)"
image:
@docker build --build-arg TAG=$(TAG) -t $(REPO):$(TAG) .
@docker build --build-arg TAG=$(TAG) --build-arg BUILD=$(BUILD) -t $(REPO):$(TAG) .
@echo "Image created: $(REPO):$(TAG)"
profile:
@go test -cpuprofile cpu.prof -memprofile mem.prof -v -bench ./...
bench:
@go test -v -bench ./...
test:
@go test -v -cover -coverprofile=coverage.txt -covermode=atomic -coverpkg=./... -race ./...
@go test -v -cover -race $(TEST_ARGS)
clean:
@git clean -f -d -X
@rm -rf $(APP)

View File

@@ -1,3 +0,0 @@
<one line description here>
Fixes #xx

View File

@@ -1,10 +1,4 @@
eris - IRC Server / Daemon written in Go
[![Build Status](https://cloud.drone.io/api/badges/prologic/eris/status.svg)](https://cloud.drone.io/prologic/eris)
[![CodeCov](https://codecov.io/gh/prologic/eris/branch/master/graph/badge.svg)](https://codecov.io/gh/prologic/eris)
[![Go Report Card](https://goreportcard.com/badge/prologic/eris)](https://goreportcard.com/report/prologic/eris)
[![GoDoc](https://godoc.org/github.com/prologic/eris?status.svg)](https://godoc.org/github.com/prologic/eris)
[![Sourcegraph](https://sourcegraph.com/github.com/prologic/eris/-/badge.svg)](https://sourcegraph.com/github.com/prologic/eris?badge)
# eris - IRC Server / Daemon written in Go
> This project and repository is based off of [ergonomadic](https://github.com/edmund-huber/ergonomadic)
> and much of my original contributions were made in my [fork of ergonomadic](https://github.com/prologic/ergonomadic)
@@ -25,7 +19,7 @@ The connotation here is that IRC (*Internet Relay Chat*) is a place of chaos,
strife and discord. IRC is a place where you argue and get into arguments for
the sake of argument.
So `eris` is an IRC daemon written from scratch in Go to facilitate discord
So `eris` is an IRC daemon written from scratch in Go to factiliate discord
and have arguments for the sake of argument!
Pull requests and issues are welcome.
@@ -35,9 +29,9 @@ Discussion at:
* /server irc.mills.io +6697 (*use TLS/SSL*)
* /join #lobby
Or (**not recommended**):
Or (*not recommended*)P
* /server irc.mills.io (*default port 6667, non-TLS*)
* /server irc.mills.io (*default port 6667, non-TLS)
* /join #lobby
## Features
@@ -54,41 +48,6 @@ Or (**not recommended**):
* Simple IRC operator privileges (*overrides most things*)
* Secure connection tracking (+z) and SecureOnly user mode (+Z)
* Secure channels (+Z)
* Three layers of channel privacy, Public, Private (+p) and Secret (s)
## Quick Start
```#!bash
$ go get github.com/prologic/eris
$ cat > ircd.yml <<EOF
network:
name: Test
server:
name: Test
listen:
- ":6667"
EOF
$ eris
```
If you want TLS (**recommended**) then:
```#!bash
$ go get github.com/prologic/mksslcert
$ mksslcert
```
This generates a self-signed cert `cert.pem` and `key.pem` into the `$PWD`.
Then add a `tlslisten` block to your config:
```#!yaml
server:
tlslisten:
":6697":
key: key.pem
cert: cert.pem
```
## Installation
@@ -108,14 +67,6 @@ $ go install github.com/prologic/mkpasswd
$ mkpasswd
```
Self-signed certificates can also be generated using the `mksslcert` tool
from [prologic/mksslcert](https://github.com/prologic/mksslcert):
```#!bash
$ go install github.com/prologic/mksslcert
$ mksslcert
```
## Deployment
To run simply run the `eris` binary (*assuming a `ircd.yml` in the current directory*):
@@ -136,44 +87,14 @@ You may want to customize the configuration however and create your own image ba
$ docker stack deploy -c docker-compose.yml eris
```
Which assumes a `ircd.yml` coniguration file in the current directory which Docker will use to distribute as the configuration. The `docker-compose.yml` (*Docker Stackfile*) is available at the root of this repository.
Which assumes a `ircd.yml` coniguration fiel int he current directory which Docker will use to distribute as the configuration. The `docker-compose.yml` (*Docker Stackfile*) is available at the root of this repository.
## Related Projects
## Related Proejcts
There are a number of supported accompanying services that are being developed alongside Eris:
* [Soter](https://github.com/prologic/soter) -- An IRC Bot that persists channel modes and topics.
* [Cadmus](https://github.com/prologic/cadmus) -- An IRC Bot that logs channels and provides an interface for viewing and searching logs
## Recommended Clients
### CLI / Terminal
* [irccat](https://github.com/prologic/irccat)
* [irssi](https://irssi.org/)
### Cloud
* [IRCCloud](https://www.irccloud.com/)
### Desktop
* [HexChat (Linux)](https://hexchat.github.io/)
* [Textual (OSX)](https://www.codeux.com/textual/)
* [mIRC (Windows)](https://www.mirc.com/)
### Mobile
* [Palaver (iOS)](https://palaverapp.com/) -- SASL, TLS, Server Password, Push Notifications, IRCv3 (*Also supports custom image upload service(s) for better privacy of shared photos/images over IRC*)
### Web
* [Dispatch](https://github.com/khlieng/dispatch) -- TLS, Multiple Servers and Users, Client Certificates
## Related Projects
* [cadmus](https://github.com/prologic/cadmus) -- an IRC Bot written in Go that logs IRC Channels and provides an interface to view and search those logs
* [soter](https://github.com/prologic/soter) -- an IRC Bot written in Go that protects IRC Channels by persisting channel modes and topics
* [Cadmus](https://github.com/prologic/cadmus) -- An IRC Bot that logs channels and provides an interface for viewing and searching logs (*Coming soon...*)
## License

View File

@@ -1 +0,0 @@
theme: jekyll-theme-architect

File diff suppressed because it is too large Load Diff

BIN
eris

Binary file not shown.

17
go.mod
View File

@@ -1,17 +0,0 @@
module github.com/prologic/eris
require (
github.com/DanielOaks/girc-go v0.0.0-20180430075055-8d136c4f9287
github.com/google/uuid v1.1.0 // indirect
github.com/goshuirc/e-nfa v0.0.0-20160917075329-7071788e3940 // indirect
github.com/imdario/mergo v0.3.9
github.com/mmcloughlin/professor v0.0.0-20170922221822-6b97112ab8b3
github.com/prometheus/client_golang v0.9.4
github.com/renstrom/shortuuid v3.0.0+incompatible
github.com/sirupsen/logrus v1.6.0
github.com/stretchr/testify v1.6.0
github.com/thoj/go-ircevent v0.0.0-20180816043103-14f3614f28c3
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
golang.org/x/text v0.3.2
gopkg.in/yaml.v2 v2.3.0
)

103
go.sum
View File

@@ -1,103 +0,0 @@
github.com/DanielOaks/girc-go v0.0.0-20180430075055-8d136c4f9287 h1:xOE8jDDulcwdPG+coLps6seNn6yERt5xgKSATNqWUM0=
github.com/DanielOaks/girc-go v0.0.0-20180430075055-8d136c4f9287/go.mod h1:nn+Gr++RLey8iGwfvI84UO5oZal6Muz7qPxDII0BsQ8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s=
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/goshuirc/e-nfa v0.0.0-20160917075329-7071788e3940 h1:KmRLPRstEJiE/9OjumKqI8Rccip8Qmyw2FwyTFxtVqs=
github.com/goshuirc/e-nfa v0.0.0-20160917075329-7071788e3940/go.mod h1:VOmrX6cmj7zwUeexC9HzznUdTIObHqIXUrWNYS+Ik7w=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mmcloughlin/professor v0.0.0-20170922221822-6b97112ab8b3 h1:2YMbJ6WbdQI9K73chxh9OWMDsZ2PNjAIRGTonp3T0l0=
github.com/mmcloughlin/professor v0.0.0-20170922221822-6b97112ab8b3/go.mod h1:LQkXsHRSPIEklPCq8OMQAzYNS2NGtYStdNE/ej1oJU8=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.4 h1:Y8E/JaaPbmFSW2V81Ab/d8yZFYQQGbni1b1jPcG9Y6A=
github.com/prometheus/client_golang v0.9.4/go.mod h1:oCXIBxdI62A4cR6aTRJCgetEjecSIYzOEaeAn4iYEpM=
github.com/prometheus/client_golang v1.6.0 h1:YVPodQOcK15POxhgARIvnDRVpLcuK8mglnMrWfyrw6A=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/renstrom/shortuuid v3.0.0+incompatible h1:F6T1U7bWlI3FTV+JE8HyeR7bkTeYZJntqQLA9ST4HOQ=
github.com/renstrom/shortuuid v3.0.0+incompatible/go.mod h1:n18Ycpn8DijG+h/lLBQVnGKv1BCtTeXo8KKSbBOrQ8c=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/thoj/go-ircevent v0.0.0-20180816043103-14f3614f28c3 h1:389FrrKIAlxqQMTscCQ7VH3JAVuxb/pe53v2LBiA7z8=
github.com/thoj/go-ircevent v0.0.0-20180816043103-14f3614f28c3/go.mod h1:QYOctLs5qEsaIrA/PKEc4YqAv2SozbxNEX0vMPs84p4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

File diff suppressed because it is too large Load Diff

View File

@@ -155,16 +155,16 @@ func (channel *Channel) Join(client *Client, key Text) {
return
}
isInvited := channel.lists[InviteMask].Match(client.UserHost(false))
isInvited := channel.lists[InviteMask].Match(client.UserHost())
if !isOperator && channel.flags.Has(InviteOnly) && !isInvited {
client.ErrInviteOnlyChan(channel)
return
}
if channel.lists[BanMask].Match(client.UserHost(false)) &&
if channel.lists[BanMask].Match(client.UserHost()) &&
!isInvited &&
!isOperator &&
!channel.lists[ExceptMask].Match(client.UserHost(false)) {
!channel.lists[ExceptMask].Match(client.UserHost()) {
client.ErrBannedFromChan(channel)
return
}
@@ -374,7 +374,7 @@ func (channel *Channel) applyMode(client *Client, change *ChannelModeChange) boo
return channel.applyModeMask(client, change.mode, change.op,
NewName(change.arg))
case InviteOnly, Moderated, NoOutside, OpOnlyTopic, Private, Secret, SecureChan:
case InviteOnly, Moderated, NoOutside, OpOnlyTopic, Private, SecureChan:
return channel.applyModeFlag(client, change.mode, change.op)
case Key:
@@ -508,7 +508,7 @@ func (channel *Channel) Invite(invitee *Client, inviter *Client) {
}
if channel.flags.Has(InviteOnly) {
channel.lists[InviteMask].Add(invitee.UserHost(false))
channel.lists[InviteMask].Add(invitee.UserHost())
}
inviter.RplInviting(invitee, channel.name)

View File

@@ -4,7 +4,6 @@ import (
"crypto/tls"
"fmt"
"net"
"sync"
"time"
log "github.com/sirupsen/logrus"
@@ -15,30 +14,6 @@ const (
QUIT_TIMEOUT = time.Minute // how long after idle before a client is kicked
)
type SyncBool struct {
sync.RWMutex
value bool
}
func NewSyncBool(value bool) *SyncBool {
return &SyncBool{value: value}
}
func (sb *SyncBool) Get() bool {
sb.RLock()
defer sb.RUnlock()
return sb.value
}
func (sb *SyncBool) Set(value bool) {
sb.Lock()
defer sb.Unlock()
sb.value = value
}
type Client struct {
atime time.Time
authorized bool
@@ -48,10 +23,9 @@ type Client struct {
channels *ChannelSet
ctime time.Time
flags map[UserMode]bool
hasQuit *SyncBool
hasQuit bool
hops uint
hostname Name
hostmask Name // Cloacked hostname (SHA256)
pingTime time.Time
idleTimer *time.Timer
nick Name
@@ -75,7 +49,6 @@ func NewClient(server *Server, conn net.Conn) *Client {
channels: NewChannelSet(),
ctime: now,
flags: make(map[UserMode]bool),
hasQuit: NewSyncBool(false),
sasl: NewSaslState(),
server: server,
socket: NewSocket(conn),
@@ -98,14 +71,8 @@ func NewClient(server *Server, conn net.Conn) *Client {
//
func (client *Client) writeloop() {
for {
select {
case reply, ok := <-client.replies:
if !ok || reply == "" || client.socket == nil {
return
}
client.socket.Write(reply)
}
for reply := range client.replies {
client.socket.Write(reply)
}
}
@@ -116,7 +83,6 @@ func (client *Client) readloop() {
// Set the hostname for this client.
client.hostname = AddrLookupHostname(client.socket.conn.RemoteAddr())
client.hostmask = NewName(SHA256(client.hostname.String()))
for err == nil {
if line, err = client.socket.Read(); err != nil {
@@ -151,6 +117,13 @@ func (client *Client) readloop() {
}
func (client *Client) processCommand(cmd Command) {
client.server.metrics.Counter("client", "commands").Inc()
defer func(t time.Time) {
v := client.server.metrics.SummaryVec("client", "command_duration_seconds")
v.WithLabelValues(cmd.Code().String()).Observe(time.Now().Sub(t).Seconds())
}(time.Now())
cmd.SetClient(client)
if !client.registered {
@@ -169,13 +142,6 @@ func (client *Client) processCommand(cmd Command) {
return
}
client.server.metrics.Counter("client", "commands").Inc()
defer func(t time.Time) {
v := client.server.metrics.SummaryVec("client", "command_duration_seconds")
v.WithLabelValues(cmd.Code().String()).Observe(time.Now().Sub(t).Seconds())
}(time.Now())
switch srvCmd.(type) {
case *PingCommand, *PongCommand:
client.Touch()
@@ -241,7 +207,6 @@ func (client *Client) Register() {
return
}
client.registered = true
client.flags[HostMask] = true
client.Touch()
}
@@ -255,12 +220,6 @@ func (client *Client) destroy() {
// clean up server
if _, ok := client.socket.conn.(*tls.Conn); ok {
client.server.metrics.GaugeVec("server", "clients").WithLabelValues("secure").Dec()
} else {
client.server.metrics.GaugeVec("server", "clients").WithLabelValues("insecure").Dec()
}
client.server.connections.Dec()
client.server.clients.Remove(client)
@@ -320,14 +279,11 @@ func (c *Client) ModeString() (str string) {
return
}
func (c *Client) UserHost(cloacked bool) Name {
func (c *Client) UserHost() Name {
username := "*"
if c.HasUsername() {
username = c.username.String()
}
if cloacked {
return Name(fmt.Sprintf("%s!%s@%s", c.Nick(), username, c.hostmask))
}
return Name(fmt.Sprintf("%s!%s@%s", c.Nick(), username, c.hostname))
}
@@ -347,7 +303,7 @@ func (c *Client) Nick() Name {
}
func (c *Client) Id() Name {
return c.UserHost(true)
return c.UserHost()
}
func (c *Client) String() string {
@@ -390,17 +346,15 @@ func (client *Client) ChangeNickname(nickname Name) {
}
func (client *Client) Reply(reply string) {
if !client.hasQuit.Get() {
client.replies <- reply
}
client.replies <- reply
}
func (client *Client) Quit(message Text) {
if client.hasQuit.Get() {
if client.hasQuit {
return
}
client.hasQuit.Set(true)
client.hasQuit = true
client.Reply(RplError("quit"))
client.server.whoWas.Append(client)
friends := client.Friends()

View File

@@ -4,7 +4,9 @@ import (
"errors"
"regexp"
"strings"
"sync"
//"sync"
sync "github.com/sasha-s/go-deadlock"
"github.com/DanielOaks/girc-go/ircmatch"
)
@@ -103,7 +105,7 @@ func (clients *ClientLookupSet) FindAll(userhost Name) *ClientSet {
var casemappedNickMask string
for _, client := range clients.nicks {
casemappedNickMask = client.UserHost(false).String()
casemappedNickMask = client.UserHost().String()
if matcher.Match(casemappedNickMask) {
set.Add(client)
}
@@ -121,7 +123,7 @@ func (clients *ClientLookupSet) Find(userhost Name) *Client {
var casemappedNickMask string
for _, client := range clients.nicks {
casemappedNickMask = client.UserHost(false).String()
casemappedNickMask = client.UserHost().String()
if matcher.Match(casemappedNickMask) {
return client
}

View File

@@ -4,7 +4,9 @@ import (
"errors"
"io/ioutil"
"log"
"sync"
//"sync"
sync "github.com/sasha-s/go-deadlock"
"github.com/imdario/mergo"
"gopkg.in/yaml.v2"
@@ -31,10 +33,6 @@ type Config struct {
sync.Mutex
filename string
Network struct {
Name string
}
Server struct {
PassConfig `yaml:",inline"`
Listen []string
@@ -99,10 +97,6 @@ func LoadConfig(filename string) (config *Config, err error) {
config.filename = filename
if config.Network.Name == "" {
return nil, errors.New("Network name missing")
}
if config.Server.Name == "" {
return nil, errors.New("Server name missing")
}

View File

@@ -3,7 +3,6 @@ package irc
import (
"fmt"
"net/http"
"sync"
log "github.com/sirupsen/logrus"
@@ -11,7 +10,6 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// DefObjectives ...
var DefObjectives = map[float64]float64{
0.50: 0.05,
0.90: 0.01,
@@ -19,27 +17,20 @@ var DefObjectives = map[float64]float64{
0.99: 0.001,
}
// Metrics ...
type Metrics struct {
sync.RWMutex
namespace string
metrics map[string]prometheus.Metric
guagevecs map[string]*prometheus.GaugeVec
sumvecs map[string]*prometheus.SummaryVec
}
// NewMetrics ...
func NewMetrics(namespace string) *Metrics {
return &Metrics{
namespace: namespace,
metrics: make(map[string]prometheus.Metric),
guagevecs: make(map[string]*prometheus.GaugeVec),
sumvecs: make(map[string]*prometheus.SummaryVec),
}
}
// NewCounter ...
func (m *Metrics) NewCounter(subsystem, name, help string) prometheus.Counter {
counter := prometheus.NewCounter(
prometheus.CounterOpts{
@@ -51,15 +42,12 @@ func (m *Metrics) NewCounter(subsystem, name, help string) prometheus.Counter {
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.metrics[key] = counter
m.Unlock()
prometheus.MustRegister(counter)
return counter
}
// NewCounterFunc ...
func (m *Metrics) NewCounterFunc(subsystem, name, help string, f func() float64) prometheus.CounterFunc {
counter := prometheus.NewCounterFunc(
prometheus.CounterOpts{
@@ -72,15 +60,12 @@ func (m *Metrics) NewCounterFunc(subsystem, name, help string, f func() float64)
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.metrics[key] = counter
m.Unlock()
prometheus.MustRegister(counter)
return counter
}
// NewGauge ...
func (m *Metrics) NewGauge(subsystem, name, help string) prometheus.Gauge {
guage := prometheus.NewGauge(
prometheus.GaugeOpts{
@@ -92,15 +77,12 @@ func (m *Metrics) NewGauge(subsystem, name, help string) prometheus.Gauge {
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.metrics[key] = guage
m.Unlock()
prometheus.MustRegister(guage)
return guage
}
// NewGaugeFunc ...
func (m *Metrics) NewGaugeFunc(subsystem, name, help string, f func() float64) prometheus.GaugeFunc {
guage := prometheus.NewGaugeFunc(
prometheus.GaugeOpts{
@@ -113,36 +95,12 @@ func (m *Metrics) NewGaugeFunc(subsystem, name, help string, f func() float64) p
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.metrics[key] = guage
m.Unlock()
prometheus.MustRegister(guage)
return guage
}
// NewGaugeVec ...
func (m *Metrics) NewGaugeVec(subsystem, name, help string, labels []string) *prometheus.GaugeVec {
guagevec := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: subsystem,
Name: name,
Help: help,
},
labels,
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.guagevecs[key] = guagevec
m.Unlock()
prometheus.MustRegister(guagevec)
return guagevec
}
// NewSummary ...
func (m *Metrics) NewSummary(subsystem, name, help string) prometheus.Summary {
summary := prometheus.NewSummary(
prometheus.SummaryOpts{
@@ -155,15 +113,12 @@ func (m *Metrics) NewSummary(subsystem, name, help string) prometheus.Summary {
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.metrics[key] = summary
m.Unlock()
prometheus.MustRegister(summary)
return summary
}
// NewSummaryVec ...
func (m *Metrics) NewSummaryVec(subsystem, name, help string, labels []string) *prometheus.SummaryVec {
sumvec := prometheus.NewSummaryVec(
prometheus.SummaryOpts{
@@ -177,58 +132,36 @@ func (m *Metrics) NewSummaryVec(subsystem, name, help string, labels []string) *
)
key := fmt.Sprintf("%s_%s", subsystem, name)
m.Lock()
m.sumvecs[key] = sumvec
m.Unlock()
prometheus.MustRegister(sumvec)
return sumvec
}
// Counter ...
func (m *Metrics) Counter(subsystem, name string) prometheus.Counter {
key := fmt.Sprintf("%s_%s", subsystem, name)
return m.metrics[key].(prometheus.Counter)
}
// Gauge ...
func (m *Metrics) Gauge(subsystem, name string) prometheus.Gauge {
key := fmt.Sprintf("%s_%s", subsystem, name)
m.RLock()
defer m.RUnlock()
return m.metrics[key].(prometheus.Gauge)
}
// GaugeVec ...
func (m *Metrics) GaugeVec(subsystem, name string) *prometheus.GaugeVec {
key := fmt.Sprintf("%s_%s", subsystem, name)
m.RLock()
defer m.RUnlock()
return m.guagevecs[key]
}
// Summary ...
func (m *Metrics) Summary(subsystem, name string) prometheus.Summary {
key := fmt.Sprintf("%s_%s", subsystem, name)
m.RLock()
defer m.RUnlock()
return m.metrics[key].(prometheus.Summary)
}
// SummaryVec ...
func (m *Metrics) SummaryVec(subsystem, name string) *prometheus.SummaryVec {
key := fmt.Sprintf("%s_%s", subsystem, name)
m.RLock()
defer m.RUnlock()
return m.sumvecs[key]
}
// Handler ...
func (m *Metrics) Handler() http.Handler {
return promhttp.Handler()
}
// Run ...
func (m *Metrics) Run(addr string) {
http.Handle("/", m.Handler())
log.Infof("metrics endpoint listening on %s", addr)

View File

@@ -1,51 +0,0 @@
package irc
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestMetrics(t *testing.T) {
assert := assert.New(t)
m := NewMetrics("test")
m.NewCounter("foo", "counter", "help")
m.NewCounterFunc("foo", "counter_func", "help", func() float64 { return 1.0 })
m.NewGauge("foo", "gauge", "help")
m.NewGaugeFunc("foo", "gauge_func", "help", func() float64 { return 1.0 })
m.NewGaugeVec("foo", "gauge_vec", "help", []string{"test"})
m.Counter("foo", "counter").Inc()
m.Gauge("foo", "gauge").Add(1)
m.GaugeVec("foo", "gauge_vec").WithLabelValues("test").Add(1)
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/", nil)
m.Handler().ServeHTTP(w, r)
assert.Equal(w.Code, http.StatusOK)
assert.Regexp(
`
# HELP test_foo_counter help
# TYPE test_foo_counter counter
test_foo_counter 1
# HELP test_foo_counter_func help
# TYPE test_foo_counter_func counter
test_foo_counter_func 1
# HELP test_foo_gauge help
# TYPE test_foo_gauge gauge
test_foo_gauge 1
# HELP test_foo_gauge_func help
# TYPE test_foo_gauge_func gauge
test_foo_gauge_func 1
# HELP test_foo_gauge_vec help
# TYPE test_foo_gauge_vec gauge
test_foo_gauge_vec{test="test"} 1
`,
w.Body.String(),
)
}

View File

@@ -58,12 +58,11 @@ const (
Registered UserMode = 'r' // not a real user mode (flag)
SecureConn UserMode = 'z'
SecureOnly UserMode = 'Z'
HostMask UserMode = 'x'
)
var (
SupportedUserModes = UserModes{
Invisible, Operator, HostMask,
Invisible, Operator,
}
DefaultChannelModes = ChannelModes{
NoOutside, OpOnlyTopic,
@@ -71,6 +70,7 @@ var (
)
const (
Anonymous ChannelMode = 'a' // flag
BanMask ChannelMode = 'b' // arg
ChannelCreator ChannelMode = 'O' // flag
ChannelOperator ChannelMode = 'o' // arg
@@ -82,6 +82,8 @@ const (
NoOutside ChannelMode = 'n' // flag
OpOnlyTopic ChannelMode = 't' // flag
Private ChannelMode = 'p' // flag
Quiet ChannelMode = 'q' // flag
ReOp ChannelMode = 'r' // flag
Secret ChannelMode = 's' // flag, deprecated
UserLimit ChannelMode = 'l' // flag arg
Voice ChannelMode = 'v' // arg
@@ -91,7 +93,7 @@ const (
var (
SupportedChannelModes = ChannelModes{
BanMask, ExceptMask, InviteMask, InviteOnly, Key, NoOutside,
OpOnlyTopic, Private, UserLimit, Secret, SecureChan,
OpOnlyTopic, Private, UserLimit, SecureChan,
}
)
@@ -117,7 +119,7 @@ func (m *ModeCommand) HandleServer(s *Server) {
for _, change := range m.changes {
switch change.mode {
case Invisible, HostMask, WallOps, SecureOnly:
case Invisible, WallOps, SecureOnly:
switch change.op {
case Add:
if target.flags[change.mode] {

View File

@@ -4,8 +4,9 @@ import (
"encoding/base64"
"fmt"
"golang.org/x/crypto/bcrypt"
"sync"
//"sync"
sync "github.com/sasha-s/go-deadlock"
log "github.com/sirupsen/logrus"
)
@@ -67,7 +68,7 @@ func (store *MemoryPasswordStore) Verify(username, password string) error {
hash, ok := store.Get(username)
if !ok {
log.Debugf("username %s not found", username)
return fmt.Errorf("account not found: %s", username)
return fmt.Errorf("account not found: %S", username)
}
return store.hasher.Compare(hash, []byte(password))

View File

@@ -1,22 +0,0 @@
package irc
func CanSeeChannel(client *Client, channel *Channel) bool {
isPrivate := channel.flags.Has(Private)
isSecret := channel.flags.Has(Secret)
isMember := channel.members.Has(client)
isOperator := client.flags[Operator]
isRegistered := client.flags[Registered]
isSecure := client.flags[SecureConn]
if !(isSecret || isPrivate) {
return true
}
if isSecret && (isMember || isOperator) {
return true
}
if isPrivate && (isMember || isOperator || (isRegistered && isSecure)) {
return true
}
return false
}

View File

@@ -173,12 +173,8 @@ func RplCap(client *Client, subCommand CapSubCommand, arg interface{}) string {
// numeric replies
func (target *Client) RplWelcome() {
target.NumericReply(
RPL_WELCOME,
":Welcome to the %s Internet Relay Network %s",
target.server.Network(),
target.Id(),
)
target.NumericReply(RPL_WELCOME,
":Welcome to the Internet Relay Network %s", target.Id())
}
func (target *Client) RplYourHost() {
@@ -260,26 +256,13 @@ func (target *Client) RplWhois(client *Client) {
}
target.RplWhoisServer(client)
target.RplWhoisLoggedIn(client)
target.RplEndOfWhois(client)
target.RplEndOfWhois()
}
func (target *Client) RplWhoisUser(client *Client) {
var clientHost Name
if target.flags[Operator] || !client.flags[HostMask] {
clientHost = client.hostname
} else {
clientHost = client.hostmask
}
target.NumericReply(
RPL_WHOISUSER,
"%s %s %s * :%s",
client.Nick(),
client.username,
clientHost,
client.realname,
)
target.NumericReply(RPL_WHOISUSER,
"%s %s %s * :%s", client.Nick(), client.username, client.hostname,
client.realname)
}
func (target *Client) RplWhoisOperator(client *Client) {
@@ -324,12 +307,9 @@ func (target *Client) RplWhoisServer(client *Client) {
)
}
func (target *Client) RplEndOfWhois(client *Client) {
target.NumericReply(
RPL_ENDOFWHOIS,
"%s :End of WHOIS list",
client.Nick(),
)
func (target *Client) RplEndOfWhois() {
target.NumericReply(RPL_ENDOFWHOIS,
":End of WHOIS list")
}
func (target *Client) RplChannelModeIs(channel *Channel) {
@@ -340,14 +320,6 @@ func (target *Client) RplChannelModeIs(channel *Channel) {
// <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
// :<hopcount> <real name>
func (target *Client) RplWhoReply(channel *Channel, client *Client) {
var clientHost Name
if target.flags[Operator] || !client.flags[HostMask] {
clientHost = client.hostname
} else {
clientHost = client.hostmask
}
channelName := "*"
flags := ""
@@ -377,18 +349,9 @@ func (target *Client) RplWhoReply(channel *Channel, client *Client) {
}
}
}
target.NumericReply(
RPL_WHOREPLY,
"%s %s %s %s %s %s :%d %s",
channelName,
client.username,
clientHost,
client.server.name,
client.Nick(),
flags,
client.hops,
client.realname,
)
target.NumericReply(RPL_WHOREPLY,
"%s %s %s %s %s %s :%d %s", channelName, client.username, client.hostname,
client.server.name, client.Nick(), flags, client.hops, client.realname)
}
// <name> :End of WHO list
@@ -489,13 +452,8 @@ func (target *Client) RplMOTDEnd() {
}
func (target *Client) RplList(channel *Channel) {
target.NumericReply(
RPL_LIST,
"%s %d :%s",
channel,
channel.members.Count(),
channel.topic,
)
target.NumericReply(RPL_LIST,
"%s %d :%s", channel, channel.members.Count(), channel.topic)
}
func (target *Client) RplListEnd(server *Server) {
@@ -509,12 +467,8 @@ func (target *Client) RplNamReply(channel *Channel) {
}
func (target *Client) RplWhoisChannels(client *Client) {
target.MultilineReply(
client.WhoisChannelsNames(target),
RPL_WHOISCHANNELS,
"%s :%s",
client.Nick(),
)
target.MultilineReply(client.WhoisChannelsNames(), RPL_WHOISCHANNELS,
"%s :%s", client.Nick())
}
func (target *Client) RplVersion() {
@@ -608,22 +562,9 @@ func (target *Client) RplLUserMe() {
}
func (target *Client) RplWhoWasUser(whoWas *WhoWas) {
var whoWasHost Name
if target.flags[Operator] {
whoWasHost = whoWas.hostname
} else {
whoWasHost = whoWas.hostmask
}
target.NumericReply(
RPL_WHOWASUSER,
target.NumericReply(RPL_WHOWASUSER,
"%s %s %s * :%s",
whoWas.nickname,
whoWas.username,
whoWasHost,
whoWas.realname,
)
whoWas.nickname, whoWas.username, whoWas.hostname, whoWas.realname)
}
func (target *Client) RplEndOfWhoWas(nickname Name) {

View File

@@ -2,7 +2,9 @@ package irc
import (
"bytes"
"sync"
//"sync"
sync "github.com/sasha-s/go-deadlock"
)
type SaslState struct {

View File

@@ -37,23 +37,19 @@ type Server struct {
idle chan *Client
motdFile string
name Name
network Name
description string
newConns chan net.Conn
operators map[Name][]byte
accounts PasswordStore
password []byte
signals chan os.Signal
done chan bool
whoWas *WhoWasList
ids map[string]*Identity
}
var (
SERVER_SIGNALS = []os.Signal{
syscall.SIGINT,
syscall.SIGTERM,
}
SERVER_SIGNALS = []os.Signal{syscall.SIGINT, syscall.SIGHUP,
syscall.SIGTERM, syscall.SIGQUIT}
)
func NewServer(config *Config) *Server {
@@ -67,20 +63,18 @@ func NewServer(config *Config) *Server {
idle: make(chan *Client),
motdFile: config.Server.MOTD,
name: NewName(config.Server.Name),
network: NewName(config.Network.Name),
description: config.Server.Description,
newConns: make(chan net.Conn),
operators: config.Operators(),
accounts: NewMemoryPasswordStore(config.Accounts(), PasswordStoreOpts{}),
signals: make(chan os.Signal, len(SERVER_SIGNALS)),
done: make(chan bool),
whoWas: NewWhoWasList(100),
ids: make(map[string]*Identity),
}
log.Debugf("accounts: %v", config.Accounts())
// TODO: Make this configureable?
// TODO: Make this configurabel?
server.ids["global"] = NewIdentity(config.Server.Name, "global")
if config.Server.Password != "" {
@@ -127,22 +121,15 @@ func NewServer(config *Config) *Server {
},
)
// server registered (clients) gauge
// server clients gauge
server.metrics.NewGaugeFunc(
"server", "registered",
"server", "clients",
"Number of registered clients connected",
func() float64 {
return float64(server.clients.Count())
},
)
// server clients gauge (by secure/insecure)
server.metrics.NewGaugeVec(
"server", "clients",
"Number of registered clients connected (by secure/insecure)",
[]string{"secure"},
)
// server channels gauge
server.metrics.NewGaugeFunc(
"server", "channels",
@@ -202,22 +189,13 @@ func (server *Server) Shutdown() {
server.Global("shutting down...")
}
func (server *Server) Stop() {
server.done <- true
}
func (server *Server) Run() {
for {
done := false
for !done {
select {
case <-server.done:
return
case <-server.signals:
server.Shutdown()
// Give at least 1s for clients to see the shutdown
go func() {
time.Sleep(1 * time.Second)
server.Stop()
}()
done = true
case conn := <-server.newConns:
go NewClient(server, conn)
@@ -237,12 +215,6 @@ func (s *Server) acceptor(listener net.Listener) {
}
log.Debugf("%s accept: %s", s, conn.RemoteAddr())
if _, ok := conn.(*tls.Conn); ok {
s.metrics.GaugeVec("server", "clients").WithLabelValues("secure").Inc()
} else {
s.metrics.GaugeVec("server", "clients").WithLabelValues("insecure").Inc()
}
s.connections.Inc()
s.newConns <- conn
}
@@ -342,7 +314,6 @@ func (s *Server) Rehash() error {
s.motdFile = s.config.Server.MOTD
s.name = NewName(s.config.Server.Name)
s.network = NewName(s.config.Network.Name)
s.description = s.config.Server.Description
s.operators = s.config.Operators()
@@ -353,10 +324,6 @@ func (s *Server) Id() Name {
return s.name
}
func (s *Server) Network() Name {
return s.network
}
func (s *Server) String() string {
return s.name.String()
}
@@ -629,14 +596,10 @@ func (msg *PrivMsgCommand) HandleServer(server *Server) {
}
}
func (client *Client) WhoisChannelsNames(target *Client) []string {
func (client *Client) WhoisChannelsNames() []string {
chstrs := make([]string, client.channels.Count())
index := 0
client.channels.Range(func(channel *Channel) bool {
if !CanSeeChannel(target, channel) {
return true
}
switch {
case channel.members.Get(client).Has(ChannelOperator):
chstrs[index] = "@" + channel.name.String()
@@ -843,7 +806,7 @@ func (msg *ListCommand) HandleServer(server *Server) {
if len(msg.channels) == 0 {
server.channels.Range(func(name Name, channel *Channel) bool {
if !CanSeeChannel(client, channel) {
if !client.flags[Operator] && channel.flags.Has(Private) {
return true
}
client.RplList(channel)
@@ -852,7 +815,7 @@ func (msg *ListCommand) HandleServer(server *Server) {
} else {
for _, chname := range msg.channels {
channel := server.channels.Get(chname)
if channel == nil || !CanSeeChannel(client, channel) {
if channel == nil || (!client.flags[Operator] && channel.flags.Has(Private)) {
client.ErrNoSuchChannel(chname)
continue
}

View File

@@ -3,7 +3,9 @@ package irc
import (
"fmt"
"strings"
"sync"
//"sync"
sync "github.com/sasha-s/go-deadlock"
)
//

View File

@@ -1,11 +0,0 @@
package irc
import (
"crypto/sha256"
"fmt"
)
func SHA256(data string) string {
hash := sha256.Sum256([]byte(data))
return fmt.Sprintf("%x", hash)
}

View File

@@ -1,15 +1,14 @@
package irc
import (
"fmt"
)
var (
// Package package name
//PackageName package name
Package = "eris"
// Version release version
Version = "1.6.4"
Version = "1.6.0"
// Build will be overwritten automatically by the build system
Build = "-dev"
// GitCommit will be overwritten automatically by the build system
GitCommit = "HEAD"
@@ -17,5 +16,5 @@ var (
// FullVersion display the full version and build
func FullVersion() string {
return fmt.Sprintf("%s-%s@%s", Package, Version, GitCommit)
return Package + " v" + Version + Build + " (" + GitCommit + ")"
}

View File

@@ -1,7 +1,9 @@
package irc
import (
"sync"
//"sync"
sync "github.com/sasha-s/go-deadlock"
)
type WhoWasList struct {
@@ -15,7 +17,6 @@ type WhoWas struct {
nickname Name
username Name
hostname Name
hostmask Name
realname Text
}
@@ -32,7 +33,6 @@ func (list *WhoWasList) Append(client *Client) {
nickname: client.Nick(),
username: client.username,
hostname: client.hostname,
hostmask: client.hostmask,
realname: client.realname,
}
list.end = (list.end + 1) % len(list.buffer)

View File

@@ -1,7 +1,3 @@
network:
# network name
name: Local
server:
# server name
name: localhost.localdomain

View File

@@ -7,7 +7,6 @@ import (
log "github.com/sirupsen/logrus"
"github.com/mmcloughlin/professor"
"github.com/prologic/eris/irc"
)
@@ -34,10 +33,6 @@ func main() {
log.SetLevel(log.WarnLevel)
}
if debug {
go professor.Launch(":6060")
}
config, err := irc.LoadConfig(configfile)
if err != nil {
log.Fatal("Config file did not load successfully:", err.Error())

View File

@@ -1,577 +0,0 @@
package main
import (
"crypto/sha256"
"flag"
"fmt"
"os"
"strings"
"testing"
"time"
log "github.com/sirupsen/logrus"
"github.com/renstrom/shortuuid"
"github.com/stretchr/testify/assert"
"github.com/thoj/go-ircevent"
eris "github.com/prologic/eris/irc"
)
const (
TIMEOUT = 3 * time.Second
)
var (
server *eris.Server
debug = flag.Bool("d", false, "enable debug logging")
)
func setupServer() *eris.Server {
config := &eris.Config{}
config.Network.Name = "Test"
config.Server.Name = "test"
config.Server.Description = "Test"
config.Server.Listen = []string{":6667"}
// SASL
config.Account = map[string]*eris.PassConfig{
"admin": &eris.PassConfig{"JDJhJDA0JGtUU1JVc1JOUy9DbEh1WEdvYVlMdGVnclp6YnA3NDBOZGY1WUZhdTZtRzVmb1VKdXQ5ckZD"},
}
server := eris.NewServer(config)
go server.Run()
return server
}
func randomValidName() string {
var name eris.Name
for {
name = eris.NewName(shortuuid.New())
if name.IsNickname() {
break
}
}
return name.String()
}
func newClient(start bool) *irc.Connection {
name := randomValidName()
client := irc.IRC(name, name)
client.RealName = fmt.Sprintf("Test Client: %s", name)
err := client.Connect("localhost:6667")
if err != nil {
log.Fatalf("error setting up test client: %s", err)
}
if start {
go client.Loop()
}
return client
}
func TestMain(m *testing.M) {
flag.Parse()
if *debug {
log.SetLevel(log.DebugLevel)
} else {
log.SetLevel(log.WarnLevel)
}
server = setupServer()
result := m.Run()
server.Stop()
os.Exit(result)
}
func TestConnection(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client := newClient(false)
client.AddCallback("001", func(e *irc.Event) {
actual <- true
})
defer client.Quit()
go client.Loop()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestSASL(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client := newClient(false)
client.SASLLogin = "admin"
client.SASLPassword = "admin"
client.AddCallback("001", func(e *irc.Event) {
actual <- true
})
defer client.Quit()
go client.Loop()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestRplWelcome(t *testing.T) {
assert := assert.New(t)
expected := "Welcome to the .* Internet Relay Network .*!.*@.*"
actual := make(chan string)
client := newClient(false)
client.AddCallback("001", func(e *irc.Event) {
actual <- e.Message()
})
defer client.Quit()
go client.Loop()
select {
case res := <-actual:
assert.Regexp(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestUser_JOIN(t *testing.T) {
assert := assert.New(t)
client := newClient(false)
expected := []string{client.GetNick(), "=", "#join", fmt.Sprintf("@%s", client.GetNick())}
actual := make(chan string)
client.AddCallback("353", func(e *irc.Event) {
for i := range e.Arguments {
actual <- e.Arguments[i]
}
})
defer client.Quit()
go client.Loop()
client.Join("#join")
client.SendRaw("NAMES #join")
for i := range expected {
select {
case res := <-actual:
assert.Equal(expected[i], res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
}
func TestChannel_InviteOnly(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(false)
client2 := newClient(false)
client1.AddCallback("324", func(e *irc.Event) {
if strings.Contains(e.Arguments[2], "i") {
client2.Join("#inviteonly")
} else {
client1.Mode("#inviteonly")
}
})
client2.AddCallback("473", func(e *irc.Event) {
actual <- true
})
client2.AddCallback("JOIN", func(e *irc.Event) {
actual <- false
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
client1.Join("#inviteonly")
client1.Mode("#inviteonly", "+i")
client1.Mode("#inviteonly")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestUser_WithHostMask(t *testing.T) {
assert := assert.New(t)
client1 := newClient(false)
client2 := newClient(false)
expected := fmt.Sprintf("%x", sha256.Sum256([]byte("localhost")))
actual := make(chan string)
client1.AddCallback("001", func(e *irc.Event) {
client1.Mode(client1.GetNick(), "+x")
})
client2.AddCallback("001", func(e *irc.Event) {
client2.Whois(client1.GetNick())
})
client2.AddCallback("401", func(e *irc.Event) {
client2.Whois(client1.GetNick())
})
client2.AddCallback("311", func(e *irc.Event) {
actual <- e.Arguments[3]
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
/* FIXME: This test is racey :/
func TestUser_WithoutHostMask(t *testing.T) {
assert := assert.New(t)
client1 := newClient(false)
client2 := newClient(false)
expected := "localhost"
actual := make(chan string)
client1.AddCallback("001", func(e *irc.Event) {
client1.Mode(client1.GetNick(), "-x")
})
client2.AddCallback("001", func(e *irc.Event) {
client2.Whois(client1.GetNick())
})
client2.AddCallback("401", func(e *irc.Event) {
client2.Whois(client1.GetNick())
})
client2.AddCallback("311", func(e *irc.Event) {
actual <- e.Arguments[3]
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
*/
func TestUser_PRIVMSG(t *testing.T) {
assert := assert.New(t)
expected := "Hello World!"
actual := make(chan string)
client1 := newClient(false)
client2 := newClient(false)
client1.AddCallback("001", func(e *irc.Event) {
client1.Privmsg(client2.GetNick(), expected)
})
client1.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
client2.AddCallback("001", func(e *irc.Event) {
client2.Privmsg(client1.GetNick(), expected)
})
client2.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_PRIVMSG(t *testing.T) {
assert := assert.New(t)
expected := "Hello World!"
actual := make(chan string)
client1 := newClient(false)
client2 := newClient(false)
client1.AddCallback("JOIN", func(e *irc.Event) {
client1.Privmsg(e.Arguments[0], expected)
})
client2.AddCallback("JOIN", func(e *irc.Event) {
client2.Privmsg(e.Arguments[0], expected)
})
client1.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
client2.AddCallback("PRIVMSG", func(e *irc.Event) {
actual <- e.Message()
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
client1.Join("#channelprivmsg")
client2.Join("#channelprivmsg")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_NoExternal(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("JOIN", func(e *irc.Event) {
channel := e.Arguments[0]
if channel == "#noexternal" {
if e.Nick == client1.GetNick() {
client2.Privmsg("#noexternal", "FooBar!")
} else {
assert.Fail(fmt.Sprintf("unexpected user %s joined %s", e.Nick, channel))
}
} else {
assert.Fail(fmt.Sprintf("unexpected channel %s", channel))
}
})
client2.AddCallback("PRIVMSG", func(e *irc.Event) {
if e.Arguments[0] == "#noexternal" {
actual <- false
}
})
client2.AddCallback("404", func(e *irc.Event) {
actual <- true
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
client1.Join("#noexternal")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_SetTopic_InvalidChannel(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(false)
client1.AddCallback("403", func(e *irc.Event) {
actual <- true
})
defer client1.Quit()
go client1.Loop()
client1.SendRaw("TOPIC #invalidchannel :FooBar")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_SetTopic_NotOnChannel(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(false)
client2 := newClient(false)
client1.AddCallback("442", func(e *irc.Event) {
actual <- true
})
client2.AddCallback("JOIN", func(e *irc.Event) {
client1.SendRaw("TOPIC #notonchannel :FooBar")
})
defer client1.Quit()
go client1.Loop()
client2.Join("#notonchannel")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_BadChannelKey(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(false)
client2 := newClient(false)
client1.AddCallback("324", func(e *irc.Event) {
if strings.Contains(e.Arguments[2], "k") {
client2.Join(e.Arguments[1])
} else {
client1.Mode("#badchannelkey")
}
})
client2.AddCallback("JOIN", func(e *irc.Event) {
if e.Nick == client2.GetNick() && e.Arguments[0] == "#badchannelkey" {
actual <- false
}
})
client2.AddCallback("475", func(e *irc.Event) {
actual <- true
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
client1.Join("#badchannelkey")
client1.Mode("#badchannelkey", "+k", "opensesame")
client1.Mode("#badchannelkey")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}
func TestChannel_GoodChannelKey(t *testing.T) {
assert := assert.New(t)
expected := true
actual := make(chan bool)
client1 := newClient(true)
client2 := newClient(true)
client1.AddCallback("324", func(e *irc.Event) {
if strings.Contains(e.Arguments[2], "k") {
client2.SendRawf("JOIN %s :opensesame", e.Arguments[1])
} else {
client1.Mode("#goodchannelkey")
}
})
client2.AddCallback("JOIN", func(e *irc.Event) {
if e.Nick == client2.GetNick() && e.Arguments[0] == "#goodchannelkey" {
actual <- true
}
})
client2.AddCallback("475", func(e *irc.Event) {
actual <- false
})
defer client1.Quit()
defer client2.Quit()
go client1.Loop()
go client2.Loop()
client1.Join("#goodchannelkey")
client1.Mode("#goodchannelkey", "+k", "opensesame")
client1.Mode("#goodchannelkey")
select {
case res := <-actual:
assert.Equal(expected, res)
case <-time.After(TIMEOUT):
assert.Fail("timeout")
}
}

View File

@@ -21,7 +21,7 @@ fi
echo -n "Building binaries ... "
GOOS=linux GOARCH=amd64 go build -o ./bin/eris-Linux-x86_64 .
GOOS=linux GOARCH=arm64 go build -o ./bin/eris-Linux-arm_64 .
GOOS=linux GOARCH=arm64 go build -o ./bin/eris-Linux-x86_64 .
GOOS=darwin GOARCH=amd64 go build -o ./bin/eris-Darwin-x86_64 .
GOOS=windows GOARCH=amd64 go build -o ./bin/eris-Windows-x86_64.exe .

1
vendor/github.com/beorn7/perks generated vendored Submodule

1
vendor/github.com/golang/protobuf generated vendored Submodule

1
vendor/github.com/goshuirc/e-nfa generated vendored Submodule

1
vendor/github.com/imdario/mergo generated vendored Submodule

1
vendor/github.com/prometheus/common generated vendored Submodule

1
vendor/github.com/prometheus/procfs generated vendored Submodule

1
vendor/github.com/sirupsen/logrus generated vendored Submodule

1
vendor/golang.org/x/crypto generated vendored Submodule

1
vendor/golang.org/x/sys generated vendored Submodule

Submodule vendor/golang.org/x/sys added at 0dd5e194bb

1
vendor/golang.org/x/text generated vendored Submodule

1
vendor/gopkg.in/yaml.v2 generated vendored Submodule

Submodule vendor/gopkg.in/yaml.v2 added at 287cf08546