Compare commits

...

10 Commits

Author SHA1 Message Date
eleksir
39ac09f82a Implement ban by nick regexp (in MUCs)
* Move ban action to separate function
* Implement ban by nick regexp
2023-08-20 10:55:18 -07:00
eleksir
939ceaebfb Move some functions to go-xmpp, update deps, more lining 2023-08-20 09:33:56 -07:00
eleksir
9235329b37 Add comment about given rotation period in sample config, fix json format 2023-08-18 09:44:39 -07:00
eleksir
fb5e203bc9 Add status rotation and ban reason description to Design.txt 2023-08-17 11:04:35 -07:00
eleksir
75e7a22c95 Implement optional reason in room' banlist 2023-08-17 11:02:53 -07:00
eleksir
257f489172 Fix typo in config parser 2023-08-17 10:15:09 -07:00
eleksir
6b91648666 Implement random phrase before ban action 2023-08-17 10:08:04 -07:00
eleksir
8a67a91ffb Implement random startup/runtime status, cosmetic fixes
* Implement random startup status from array in config
* Implement random runtime status from array in config
* Implement runtime status rotation
* Remove noecho option from config and from code
* Use separate goroutine to set statuses
2023-08-17 09:48:57 -07:00
eleksir
ce9561b488 Fix comments and typos in black and white lists 2023-08-13 10:20:18 -07:00
eleksir
84f7f21217 More lint fixes
* Correctly wrap errors
* Fix comments
* Add blank strings before continue, where it missing
* Reduce allocations
2023-08-13 08:40:50 -07:00
59 changed files with 956 additions and 398 deletions

View File

@@ -49,3 +49,15 @@ Cуществует несколько видов пинга:
* Component-to-Client Pings * Component-to-Client Pings
Явным образом я реализовываю с2s. Плюс частично Component-to-Client в рамках N.B. по xep-0410. Явным образом я реализовываю с2s. Плюс частично Component-to-Client в рамках N.B. по xep-0410.
Ротация статусов
------------------------------------------------------------------------------------------------------------------------
Ротирование статуса реализовано через заддержки time.sleep, На каждый чат таким образом порождается по горутине. Если
чатов много, это может вызвать проблемы.
Причина бана
------------------------------------------------------------------------------------------------------------------------
Причину бана можно только включить или выключить в конфиге на per-chat основе. Фразу настроить невозможно. (не хотелось
реализовывать парсинг темплейтов, как минимум даты-времени)

178
buny.go
View File

@@ -1,17 +1,17 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/eleksir/go-xmpp" "github.com/eleksir/go-xmpp"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
func buny(v xmpp.Presence) error { //nolint:gocognit func buny(v xmpp.Presence) error { //nolint:gocognit,gocyclo
var err error var err error
// Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном // Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном
@@ -54,6 +54,12 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
} }
evilJid := strings.SplitN(v.JID, "/", 2)[0] evilJid := strings.SplitN(v.JID, "/", 2)[0]
evilNick := ""
evilNicks := strings.SplitN(v.From, "/", 2)
// Давайте-ка похэндлим нонсенс - когда у нас в строке нету разделителя
if len(evilNicks) > 1 {
evilNick = evilNicks[1]
}
// Обрабатываем правила чёрного списка // Обрабатываем правила чёрного списка
for _, cRoom := range roomsConnected { for _, cRoom := range roomsConnected {
@@ -70,27 +76,39 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
continue continue
} }
if re.Match([]byte(evilJid)) { if re.MatchString(evilJid) {
log.Infof("Hammer falls on %s", v.JID) if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением err := fmt.Errorf(
ban := "<item affiliation='outcast' jid='" + evilJid + "'>" "unable to ban user: id=%s, err=%w",
ban += "<reason />" id,
ban += "</item>" err,
)
if id, err := talk.RawInformationQuery(
talk.JID(), gTomb.Kill(err)
room,
"ban1", continue
xmpp.IQTypeSet, }
"http://jabber.org/protocol/muc#admin",
ban, return err
); err != nil { }
err := errors.New( }
fmt.Sprintf(
"Unable to ban user: id=%s, err=%s", for _, nickRegexp := range bEntry.NickRe {
re, err := regexp.Compile(nickRegexp)
if err != nil {
log.Errorf("Incorrect regexp in blacklist: %s, skipping", nickRegexp)
continue
}
if re.MatchString(evilNick) {
// Баним именно jid
if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
err := fmt.Errorf(
"unable to ban user: id=%s, err=%w",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -116,27 +134,12 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
continue continue
} }
if re.Match([]byte(evilJid)) { if re.MatchString(evilJid) {
log.Infof("Hammer falls on %s", v.JID) if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением err := fmt.Errorf(
ban := "<item affiliation='outcast' jid='" + evilJid + "'>" "unable to ban user: id=%s, err=%w",
ban += "<reason />"
ban += "</item>"
if id, err := talk.RawInformationQuery(
talk.JID(),
room,
"ban1",
xmpp.IQTypeSet,
"http://jabber.org/protocol/muc#admin",
ban,
); err != nil {
err := errors.New(
fmt.Sprintf(
"Unable to ban user: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -148,6 +151,35 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
} }
} }
if bEntry.RoomName == room {
for _, nickRegexp := range bEntry.NickRe {
re, err := regexp.Compile(nickRegexp)
if err != nil {
log.Errorf("Incorrect regexp in blacklist: %s, skipping", nickRegexp)
continue
}
if re.MatchString(evilNick) {
// Баним именно jid
if id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type); err != nil {
err := fmt.Errorf(
"unable to ban user: id=%s, err=%w",
id,
err,
)
gTomb.Kill(err)
continue
}
return err
}
}
}
continue continue
} }
} }
@@ -158,4 +190,70 @@ func buny(v xmpp.Presence) error { //nolint:gocognit
return err return err
} }
// squash банит указанный jid в указанной комнате.
// reasonEnable указывает, надо ли писать дату автобана в банлисте в поле reason (это единственная причина, в которую
// умеет бот).
func squash(room, jid string, reasonEnable bool, vType string) (string, error) {
var (
id string
err error
)
log.Infof("Hammer falls on %s", jid)
if config.Jabber.BanPhrasesEnable {
phrase := randomPhrase(config.Jabber.BanPhrases)
if _, err = talk.Send(
xmpp.Chat{ //nolint:exhaustruct
Remote: room,
Text: phrase,
Type: vType,
},
); err != nil {
err = fmt.Errorf("unable to send phrase to room %s: %w", room, err)
// Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше
return id, err
}
}
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
ban := "<item affiliation='outcast' jid='" + jid + "'>"
if reasonEnable {
var t = time.Now()
ban += fmt.Sprintf(
"<reason>autoban at %04d.%02d.%02d %02d:%02d:%02d</reason>",
t.Year(),
t.Month(),
t.Day(),
t.Hour(),
t.Minute(),
t.Second(),
)
} else {
ban += "<reason />"
}
ban += "</item>"
if id, err = talk.RawInformationQuery(
talk.JID(),
room,
"ban1",
xmpp.IQTypeSet,
"http://jabber.org/protocol/muc#admin",
ban,
); err != nil {
err = fmt.Errorf(
"unable to ban user: id=%s, err=%w",
id,
err,
)
}
return id, err
}
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */

View File

@@ -24,7 +24,7 @@ func NewCollection() *Collection {
return c return c
} }
// (collection *Collection) Get(key interface{}) (interface{}, bool) достаёт данные по заданному ключу из коллекции. // Get достаёт данные по заданному ключу из коллекции.
func (collection *Collection) Get(key interface{}) (interface{}, bool) { func (collection *Collection) Get(key interface{}) (interface{}, bool) {
obj, exists := collection.items.Load(key) obj, exists := collection.items.Load(key)
@@ -37,14 +37,14 @@ func (collection *Collection) Get(key interface{}) (interface{}, bool) {
return item.data, true return item.data, true
} }
// (collection *Collection) Set(key interface{}, value interface{}) сохраняет данные с заданным ключом в коллекцию. // Set сохраняет данные с заданным ключом в коллекцию.
func (collection *Collection) Set(key interface{}, value interface{}) { func (collection *Collection) Set(key interface{}, value interface{}) {
collection.items.Store(key, item{ collection.items.Store(key, item{
data: value, data: value,
}) })
} }
// (collection *Collection) Range(f func(key, value interface{}) bool) применяет функцию f ко всем ключам в коллекции. // Range применяет функцию f ко всем ключам в коллекции.
func (collection *Collection) Range(f func(key, value interface{}) bool) { func (collection *Collection) Range(f func(key, value interface{}) bool) {
fn := func(key, value interface{}) bool { fn := func(key, value interface{}) bool {
item := value.(item) item := value.(item)
@@ -55,12 +55,12 @@ func (collection *Collection) Range(f func(key, value interface{}) bool) {
collection.items.Range(fn) collection.items.Range(fn)
} }
// (collection *Collection) Delete(key interface{}) удаляет ключ и значение из коллекции данных. // Delete удаляет ключ и значение из коллекции данных.
func (collection *Collection) Delete(key interface{}) { func (collection *Collection) Delete(key interface{}) {
collection.items.Delete(key) collection.items.Delete(key)
} }
// (collection *Collection) Close() очищает и высвобождает ресурсы, занятые коллекцией. // Close очищает и высвобождает ресурсы, занятые коллекцией.
func (collection *Collection) Close() { func (collection *Collection) Close() {
collection.close <- struct{}{} collection.close <- struct{}{}
collection.items = sync.Map{} collection.items = sync.Map{}

View File

@@ -1,14 +1,22 @@
{ {
"blacklist": [ "blacklist": [
{ {
# Пустой список означет глобальные баны, которые применяются ко всем комнатам, где присутствует бот # Пустой список означает глобальные баны, которые применяются ко всем комнатам, где присутствует бот
"room_name": "", "room_name": "",
# Записывать ли в reason в банлисте комнаты сообщение вида autoban at yyyy.MM.dd hh:mm:ss
# Если не задано, то false
"reason_enable": false,
# Список регулярок JID-ов, которых надо банить # Список регулярок JID-ов, которых надо банить
"jid_re": [ "jid_re": [
"^[Mm]ary@server.tld/resource1$", "^[Mm]ary@server.tld/resource1$",
"^[cC]hris(topher)?@", "^[cC]hris(topher)?@",
"^(his|her)_cat@sweet.home/.*$", "^(his|her)_cat@sweet.home/.*$",
"^(her|his)_dog@.*\\.street/.*" "^(her|his)_dog@.*\\.street/.*"
],
# Список регулярок nick-ов злодеев
"nick_re": [
"^(Annoying_)?[F|f]ly$",
"^Buzzing_Wasp$"
] ]
} }
] ]

View File

@@ -35,7 +35,75 @@
"ping_splay_delay": 3, "ping_splay_delay": 3,
# Ник бота, с которым он будет заходить в комнаты # Ник бота, с которым он будет заходить в комнаты
"nick": "buny", "nick": "buny",
"resource" : "buny bot", # Уникальная часть jid-а, специфичная для клиента
"resource" : "Лунная призма",
# Статус, с которым бот запускается. (если всё нормально, этот статус будет видать только в логах сервера и
# на долю секунды он промелькнёт у всех в ростере, у кого бот в знакомых. Может отсуствовать, тогда статус будет
# пустой строкой
"startup_status": [
"bunny bot is starting"
],
# Статус, который демонстрируется во время работы бота, как xa
# (по задумке - extended away, на практике, к away обычно отношения не имеет)
"runtime_status": {
# Сам текст статуса, может отсустствовать, тогда статус - это пустая строка
"text": [
"Тот, кто не знает силу пешек, не имеет права ходить королевой.",
"Когда ты пройдешь сквозь мрак беспомощности и попадешь в мир надежды, тогда ты преодолеешь все преграды.",
"По-моему, тебе очень хочется стать уткой по-пекински!",
"If a soldier’s pride means hurting one another, I don’t want it.",
"Without the bad times, we wouldn’t appreciate the good times.",
"I’ll just warn you now, I don’t know how to use a computer.",
"Thinking isn’t going to get us anywhere.",
"Вместо того, чтобы произносить речи, лучше бы подумала, что ты будешь делать дальше.",
"Да как ты смела разгадать мой замысел?! Я же целую ночь не спала, пока его придумала. Верни мне мой сон!",
"Не волнуйся, жизнь намного скучнее, чем ты себе её представляешь.",
"Я бы завела котёнка, но у меня уже есть Луна и она жрёт как лошадь.",
"Звезда нашей надежды никогда не исчезнет. Пока она горит, всё будет в порядке. Мы не сможем проиграть",
"Голова с хвостиками… Не вмешивайся в наши дела! Играть в войну — это опасно"
],
# Период смены статуса, сек. Если параметра нет или он выставлен в 0, ротации не будет
# 3 дня
"rotation_time": 259200,
# Рандомная составляющая, добавляемая к периоду смены статуса, сек.
# 4 дня
"rotation_splay_time": 345600
},
# Произносим ли что-то пафосное в момоент бана
"ban_phrases_enable": false,
# Пафосные фраза, произносимые перед баном
"ban_phrases": [
"Во имя Луны, я накажу тебя!",
"Сила Луны, проснись!",
"Мы — воительницы справедливости!",
"Любовь и справедливость победят всегда!",
"Я буду защищать этот мир до последнего вздоха!",
"Мысли о любви делают нас сильнее!",
"Никогда не сдавайся, даже если все кажется безнадежным!",
"Мы можем преодолеть любые трудности, если будем вместе!",
"Любовь — это самая мощная сила во Вселенной!",
"Верь в себя и свою силу!",
"Красавица-воин Сейлор Мун, покоряющая сердца!",
"Мы несем свет и надежду в этот мир!",
"Луна, дай мне силу!",
"Мысли о друзьях дают мне силу!",
"Мы боремся за мир и справедливость!",
"Мы всегда найдем путь к победе!",
"Наша дружба — это наша сила!",
"Мы — защитницы мира, и ничто не остановит нас!",
"Любовь — это то, что делает нас сильнее!",
"Мы сражаемся за будущее всех живых существ!",
"Мы всегда будем вместе, независимо от трудностей!",
"Мы — сестры по духу и воительницы справедливости!",
"Мы несем свет и надежду в этот мир!",
"Любовь — это самое важное чувство во Вселенной!",
"Мы сражаемся за справедливость и защищаем тех, кто слабее!",
"Мы — герои, которые противостоят тьме!",
"Луна, дай мне силу стать красавицей-воином!",
"Мы сражаемся за мир и равенство!",
"Мы — надежда для всех, кто нуждается в защите!",
"Мы — воительницы справедливости, и ничто не остановит нас!"
],
# Имя пользователя для авторизации на сервере # Имя пользователя для авторизации на сервере
"user": "buny@jabber.tld", "user": "buny@jabber.tld",
# Пароль для авторизации # Пароль для авторизации
@@ -52,5 +120,5 @@
"loglevel": "debug", "loglevel": "debug",
# Если не задан, логи идут в STDOUT # Если не задан, логи идут в STDOUT
"log": "/var/log/echo-jabber-bot/echo-jabber-bot.log", "log": "/var/log/buny-jabber-bot/error.log"
} }

View File

@@ -1,8 +1,9 @@
# Пример белого списка # Пример белого списка
{ {
"whitlist": [ "whitelist": [
{ {
# Если room_name пустой или его нет, это список jid-ов, которых мы не баним ни на одном канале, нигде и никогда # Если room_name пустой или его нет, это список jid-ов, которых мы не баним ни на одном канале, нигде и
# никогда. Глобальный белый список.
"room_name": "", "room_name": "",
# Собственно, сам список # Собственно, сам список
"jid": [ "jid": [

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"encoding/xml" "encoding/xml"
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@@ -13,7 +12,8 @@ import (
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
func parseEvent(e interface{}) { //nolint:gocognit,gocyclo // parseEvent парсит ивенты, прилетающие из модуля xmpp (изменения presence, фразы участников, ошибки).
func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
lastServerActivity = time.Now().Unix() lastServerActivity = time.Now().Unix()
switch v := e.(type) { switch v := e.(type) {
@@ -22,10 +22,6 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
log.Debugf("Looks like message, ChatType: %s, From: %s, Subject: %s Text: %s", log.Debugf("Looks like message, ChatType: %s, From: %s, Subject: %s Text: %s",
v.Type, v.Remote, v.Subject, v.Text) v.Type, v.Remote, v.Subject, v.Text)
if config.NoEcho {
return
}
// Топик чятика присылается в виде сообщения с subject, но без text // Топик чятика присылается в виде сообщения с subject, но без text
// В то же время сообщения от людей приходят с пустым subject, но с заполненным text // В то же время сообщения от людей приходят с пустым subject, но с заполненным text
if v.Text != "" { if v.Text != "" {
@@ -98,25 +94,17 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
// Запрос номера версии приложения // Запрос номера версии приложения
case "jabber:iq:version": case "jabber:iq:version":
log.Infof("Got IQ get request for version from %s", v.From) log.Infof("Got IQ get request for version from %s", v.From)
answer := "<query xmlns=\"jabber:iq:version\">" //nolint:wsl
answer += "<name>buny-jabber-bot</name>"
answer += "<version>1.с_чем-то</version>"
answer += "<os>линупс</os>"
answer += "</query>"
if id, err := talk.RawInformation( if id, err := talk.IqVersionResponse(
v.To, v,
v.From, "buny-jabber-bot",
v.ID, "1.с_чем-то",
xmpp.IQTypeResult, "линупс",
answer,
); err != nil { ); err != nil {
err := errors.New( err := fmt.Errorf(
fmt.Sprintf( "unable to send version info to jabber server: id=%s, err=%w",
"Unable to send version info to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -130,19 +118,11 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
case "urn:xmpp:ping": case "urn:xmpp:ping":
log.Infof("Got IQ get request for pong from %s", v.From) log.Infof("Got IQ get request for pong from %s", v.From)
if id, err := talk.RawInformation( if id, err := talk.PingResponse(v); err != nil {
v.To, err := fmt.Errorf(
v.From, "unable to send pong to jabber server: id=%s, err=%w",
v.ID,
xmpp.IQTypeResult,
"",
); err != nil {
err := errors.New(
fmt.Sprintf(
"Unable to send pong to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -153,28 +133,15 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
parseError = false parseError = false
// У нас запросили время последней активности. В нашем случае это либо время запуска клиента, либо время // У нас запросили время последней активности. В нашем случае это либо время запуска клиента, либо время
// последней фразы в чяти. // последней фразы в чяти. Xep-0012.
case "jabber:iq:last": case "jabber:iq:last":
log.Infof("Got IQ get last activity time request from %s", v.From) log.Infof("Got IQ get last activity time request from %s", v.From)
answer := fmt.Sprintf( if id, err := talk.JabberIqLastResponse(v, lastActivity); err != nil {
"<query xmlns=\"jabber:iq:last\" seconds=\"%d\" />", err := fmt.Errorf(
time.Now().Unix()-lastActivity, "unable to send last activity time to jabber server: id=%s, err=%w",
)
if id, err := talk.RawInformation(
v.To,
v.From,
v.ID,
xmpp.IQTypeResult,
answer,
); err != nil {
err := errors.New(
fmt.Sprintf(
"Unable to send last activity time to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -203,12 +170,10 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
xmpp.IQTypeResult, xmpp.IQTypeResult,
answer, answer,
); err != nil { ); err != nil {
err := errors.New( err := fmt.Errorf(
fmt.Sprintf( "unable to send disco#info to jabber server: id=%s, err=%w",
"Unable to send disco#info to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -218,29 +183,19 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
parseError = false parseError = false
// Спрашивают список команд, чтобы поуправлять этим клиентом // Спрашивают список команд, чтобы поуправлять этим клиентом (xep-0030)
case xmpp.XMPPNS_DISCO_ITEMS: case xmpp.XMPPNS_DISCO_ITEMS:
log.Infof("Got IQ get disco#items request from %s, answer service unavailable", v.From) log.Infof("Got IQ get disco#items request from %s, answer service unavailable", v.From)
answer := "<query xmlns=\"http://jabber.org/protocol/disco#info\" " if _, err := talk.ErrorServiceUnavailable(
answer += "node=\"http://jabber.org/protocol/commands\" />" v,
answer += "<error type=\"cancel\">" //nolint:goconst "http://jabber.org/protocol/disco#info",
answer += "<service-unavailable xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />" "http://jabber.org/protocol/commands",
answer += "</error>" //nolint:goconst
if id, err := talk.RawInformation(
v.To,
v.From,
v.ID,
xmpp.IQTypeError,
answer,
); err != nil { ); err != nil {
err := errors.New( err := fmt.Errorf(
fmt.Sprintf( "unable to send disco#items to jabber server: id=%s, err=%w",
"Unable to send disco#items to jabber server: id=%s, err=%s", v.ID,
id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -270,24 +225,11 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
case "urn:xmpp:time": case "urn:xmpp:time":
log.Infof("Got IQ get time request from %s", v.From) log.Infof("Got IQ get time request from %s", v.From)
answer := fmt.Sprintf( if id, err := talk.UrnXmppTimeResponse(v, "+00:00"); err != nil {
"<time xmlns=\"urn:xmpp:time\"><tzo>+00:00</tzo><utc>%s</utc></time>", err := fmt.Errorf(
time.Now().UTC().Format(time.RFC3339), "unable to send urn:xmpp:time to jabber server: id=%s, err=%w",
)
if id, err := talk.RawInformation(
v.To,
v.From,
v.ID,
xmpp.IQTypeResult,
answer,
); err != nil {
err := errors.New(
fmt.Sprintf(
"Unable to send urn:xmpp:time to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -317,24 +259,14 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
case xmpp.XMPPNS_PUBSUB: case xmpp.XMPPNS_PUBSUB:
log.Infof("Got IQ get pubsub request from %s, answer feature unimplemented", v.From) log.Infof("Got IQ get pubsub request from %s, answer feature unimplemented", v.From)
answer := "<error type=\"cancel\">" if id, err := talk.ErrorNotImplemented(
answer += "<feature-not-implemented xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />" v,
answer += "<unsupported xmlns=\"http://jabber.org/protocol/pubsub#errors\" feature=\"subscribe\" />" "http://jabber.org/protocol/pubsub#errors",
answer += "</error>" "subscribe",
if id, err := talk.RawInformation(
v.To,
v.From,
v.ID,
xmpp.IQTypeError,
answer,
); err != nil { ); err != nil {
err := errors.New( err := fmt.Errorf("unable to send pubsub feature unimplemented to jabber server: id=%s, err=%w",
fmt.Sprintf(
"Unable to send pubsub feature unimplemented to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -363,19 +295,11 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil { if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
log.Debugf("Got IQ get request (actually, response) for MUC Self-Ping from %s", v.From) log.Debugf("Got IQ get request (actually, response) for MUC Self-Ping from %s", v.From)
if id, err := talk.RawInformation( if id, err := talk.PingResponse(v); err != nil {
v.To, err := fmt.Errorf(
v.From, "unable to send pong to jabber server: id=%s, err=%w",
v.ID,
xmpp.IQTypeResult,
"",
); err != nil {
err := errors.New(
fmt.Sprintf(
"Unable to send pong to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -448,24 +372,15 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
log.Info("Got an IQ request for set something. Answer not implemented") log.Info("Got an IQ request for set something. Answer not implemented")
answer := "<error type=\"cancel\">" if id, err := talk.ErrorNotImplemented(
answer += "<feature-not-implemented xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />" v,
answer += "<unsupported xmlns=\"http://jabber.org/protocol/commands\" feature=\"set\" />" "http://jabber.org/protocol/commands",
answer += "</error>" xmpp.IQTypeSet,
if id, err := talk.RawInformation(
v.To,
v.From,
v.ID,
xmpp.IQTypeError,
answer,
); err != nil { ); err != nil {
err := errors.New( err := fmt.Errorf(
fmt.Sprintf( "unable to send set feature unimplemented to jabber server: id=%s, err=%w",
"Unable to send set feature unimplemented to jabber server: id=%s, err=%s",
id, id,
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
@@ -520,11 +435,9 @@ func parseEvent(e interface{}) { //nolint:gocognit,gocyclo
time.Sleep(time.Duration(config.Jabber.MucRejoinDelay) * time.Second) time.Sleep(time.Duration(config.Jabber.MucRejoinDelay) * time.Second)
if _, err := talk.JoinMUCNoHistory(iqErrorCancelNotAcceptable.By, nick); err != nil { if _, err := talk.JoinMUCNoHistory(iqErrorCancelNotAcceptable.By, nick); err != nil {
err := errors.New( err := fmt.Errorf(
fmt.Sprintf( "looks like connection to server also lost err=%w",
"Looks like connection to server also lost err=%s",
err, err,
),
) )
gTomb.Kill(err) gTomb.Kill(err)

View File

@@ -63,7 +63,7 @@ var serverPingTimestampTx int64
// Время, когда был принят s2c pong. // Время, когда был принят s2c pong.
var serverPingTimestampRx int64 var serverPingTimestampRx int64
// Объектик для хранения стейта утилизатора горутинок // Объектик для хранения стейта утилизатора горутинок.
var gTomb tomb.Tomb var gTomb tomb.Tomb
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */

8
go.mod
View File

@@ -4,14 +4,14 @@ go 1.20
require ( require (
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/eleksir/go-xmpp v1.4.0 github.com/eleksir/go-xmpp v1.5.0
github.com/hjson/hjson-go v3.3.0+incompatible github.com/hjson/hjson-go v3.3.0+incompatible
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
) )
require ( require (
golang.org/x/crypto v0.11.0 // indirect golang.org/x/crypto v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect golang.org/x/sys v0.11.0 // indirect
) )

16
go.sum
View File

@@ -1,8 +1,8 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eleksir/go-xmpp v1.4.0 h1:CJ91zeoLoV0FqhhcvZnkBjeuaXWbWgRTJ/HrzKugM4s= github.com/eleksir/go-xmpp v1.5.0 h1:kAjpCxuqWiu9LdlCTkQzvczotHONpojwp/mpI4aBVmQ=
github.com/eleksir/go-xmpp v1.4.0/go.mod h1:KnvbXvUpttEVFl8l5eDO2Q7J97ZxtTMvOsDWULD2Rn8= github.com/eleksir/go-xmpp v1.5.0/go.mod h1:KnvbXvUpttEVFl8l5eDO2Q7J97ZxtTMvOsDWULD2Rn8=
github.com/hjson/hjson-go v3.3.0+incompatible h1:Rqr+Ya+0aCJMjaE4s8E9YKvuJLuLVpEvz4ONum52vnI= github.com/hjson/hjson-go v3.3.0+incompatible h1:Rqr+Ya+0aCJMjaE4s8E9YKvuJLuLVpEvz4ONum52vnI=
github.com/hjson/hjson-go v3.3.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio= github.com/hjson/hjson-go v3.3.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -12,13 +12,13 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 h1:/yRP+0AN7mf5DkD3BAI6TOFnd51gEoDEb8o35jIFtgw= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=

136
lib.go
View File

@@ -2,7 +2,6 @@ package main
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"math/rand" "math/rand"
"os" "os"
@@ -16,7 +15,7 @@ import (
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
// sigHandler() Хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения. // sigHandler Хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения.
func sigHandler() { func sigHandler() {
log.Debug("Installing signal handler") log.Debug("Installing signal handler")
@@ -68,7 +67,7 @@ func sigHandler() {
// readConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге // readConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге
// нет. // нет.
func readConfig() { //nolint:gocognit func readConfig() { //nolint:gocognit,gocyclo
configLoaded := false configLoaded := false
executablePath, err := os.Executable() executablePath, err := os.Executable()
@@ -229,6 +228,26 @@ func readConfig() { //nolint:gocognit
// Если sampleConfig.Jabber.Password не задан, то авторизации не будет // Если sampleConfig.Jabber.Password не задан, то авторизации не будет
// Если sampleConfig.Jabber.Sasl не задан, то авторизация происходит через NickServ // Если sampleConfig.Jabber.Sasl не задан, то авторизация происходит через NickServ
// Если sampleConfig.Jabber.BanPhrasesEnable не задан, то он false
// Если список фраз, с которыми банят пустой, то вносим в него одну позицию с пустой строкой
if len(sampleConfig.Jabber.BanPhrases) == 0 {
sampleConfig.Jabber.BanPhrases[0] = ""
}
// Если список фраз с которыми стартует бот пустой, вносим в него 1 запись с пустой строкой
if len(sampleConfig.Jabber.StartupStatus) == 0 {
sampleConfig.Jabber.StartupStatus[0] = ""
}
// Если список статусов, с которыми работает бот пустой, вносим в него 1 запись с пустой строкой
if len(sampleConfig.Jabber.RuntimeStatus.Text) == 0 {
sampleConfig.Jabber.RuntimeStatus.Text[0] = ""
}
// Если sampleConfig.Jabber.RuntimeStatus.RotationTime не задан, то он равен 0
// Если sampleConfig.Jabber.RuntimeStatus.RotationSplayTime не задан, то он равен 0
// Нам бот нужен в каких-то чат-румах, а не "просто так" // Нам бот нужен в каких-то чат-румах, а не "просто так"
if len(sampleConfig.Jabber.Channels) < 1 { if len(sampleConfig.Jabber.Channels) < 1 {
log.Errorf("No jabber channels/rooms defined in config, quitting") log.Errorf("No jabber channels/rooms defined in config, quitting")
@@ -256,7 +275,7 @@ func readConfig() { //nolint:gocognit
} }
} }
// readWhitelist() читает и валидирует белые списки пользователей. // readWhitelist читает и валидирует белые списки пользователей.
func readWhitelist() { func readWhitelist() {
whitelistLoaded := false whitelistLoaded := false
executablePath, err := os.Executable() executablePath, err := os.Executable()
@@ -346,7 +365,7 @@ func readWhitelist() {
} }
} }
// readBlacklist() читает и валидирует чёрные списки пользователей. // readBlacklist читает и валидирует чёрные списки пользователей.
func readBlacklist() { func readBlacklist() {
blacklistLoaded := false blacklistLoaded := false
executablePath, err := os.Executable() executablePath, err := os.Executable()
@@ -437,7 +456,7 @@ func readBlacklist() {
} }
} }
// establishConnection() устанавливает соединение с jabber-сервером. // establishConnection устанавливает соединение с jabber-сервером.
func establishConnection() { func establishConnection() {
var err error var err error
@@ -454,6 +473,7 @@ func establishConnection() {
if err != nil { if err != nil {
gTomb.Kill(err) gTomb.Kill(err)
return return
} }
@@ -471,16 +491,7 @@ func establishConnection() {
go joinMuc(room) go joinMuc(room)
} }
if _, err := talk.SendPresence( go RotateStatus("")
xmpp.Presence{ //nolint:exhaustruct
Status: "Ready to chat",
},
); err != nil {
log.Infof("Unable to send presence to jabber server: %s", err)
gTomb.Kill(err)
return
}
lastActivity = time.Now().Unix() lastActivity = time.Now().Unix()
connecting = false connecting = false
@@ -498,7 +509,7 @@ func establishConnection() {
} }
} }
// joinMuc(room string) джойнится к конференциям/каналам/комнатам в джаббере. // joinMu джойнится к конференциям/каналам/комнатам в джаббере.
func joinMuc(room string) { func joinMuc(room string) {
log.Debugf("Sending disco#info from %s to %s", talk.JID(), room) log.Debugf("Sending disco#info from %s to %s", talk.JID(), room)
@@ -568,20 +579,10 @@ func joinMuc(room string) {
// Вот теперь точно можно слать статус. // Вот теперь точно можно слать статус.
log.Infof("Joined to MUC: %s", room) log.Infof("Joined to MUC: %s", room)
if _, err := talk.SendPresence( go RotateStatus(room)
xmpp.Presence{ //nolint:exhaustruct
To: room,
Status: "Ready to chat",
},
); err != nil {
log.Infof("Unable to send presence to MUC %s: %s", room, err)
gTomb.Kill(err)
return
}
} }
// probeServerLiveness() проверяет живость соединения с сервером. Для многих серверов обязательная штука, без которой // probeServerLiveness проверяет живость соединения с сервером. Для многих серверов обязательная штука, без которой
// они выкидывают клиента через некоторое время неактивности. // они выкидывают клиента через некоторое время неактивности.
func probeServerLiveness() { //nolint:gocognit func probeServerLiveness() { //nolint:gocognit
defer gTomb.Done() defer gTomb.Done()
@@ -634,14 +635,13 @@ func probeServerLiveness() { //nolint:gocognit
switch { switch {
// Давненько мы не получали понгов от сервера, вероятно, соединение с сервером утеряно? // Давненько мы не получали понгов от сервера, вероятно, соединение с сервером утеряно?
case rxTimeAgo > (rxTimeout * 2): case rxTimeAgo > (rxTimeout * 2):
err := errors.New( err := fmt.Errorf( //nolint:goerr113
fmt.Sprintf( "stall connection detected. No c2s pong for %d seconds",
"Stall connection detected. No c2s pong for %d seconds",
rxTimeAgo, rxTimeAgo,
),
) )
gTomb.Kill(err) gTomb.Kill(err)
continue continue
// По-умолчанию, мы отправляем c2s пинг // По-умолчанию, мы отправляем c2s пинг
@@ -650,6 +650,7 @@ func probeServerLiveness() { //nolint:gocognit
if err := talk.PingC2S(talk.JID(), config.Jabber.Server); err != nil { if err := talk.PingC2S(talk.JID(), config.Jabber.Server); err != nil {
gTomb.Kill(err) gTomb.Kill(err)
continue continue
} }
@@ -660,6 +661,7 @@ func probeServerLiveness() { //nolint:gocognit
if err := talk.PingC2S(talk.JID(), config.Jabber.Server); err != nil { if err := talk.PingC2S(talk.JID(), config.Jabber.Server); err != nil {
gTomb.Kill(err) gTomb.Kill(err)
continue continue
} }
@@ -672,6 +674,7 @@ func probeServerLiveness() { //nolint:gocognit
if _, err := talk.SendKeepAlive(); err != nil { if _, err := talk.SendKeepAlive(); err != nil {
gTomb.Kill(err) gTomb.Kill(err)
continue continue
} }
} }
@@ -680,6 +683,7 @@ func probeServerLiveness() { //nolint:gocognit
if _, err := talk.SendKeepAlive(); err != nil { if _, err := talk.SendKeepAlive(); err != nil {
gTomb.Kill(err) gTomb.Kill(err)
continue continue
} }
} }
@@ -688,8 +692,8 @@ func probeServerLiveness() { //nolint:gocognit
} }
} }
// probeMUCLiveness() Пингует MUC-и, нужно для проверки, что клиент ещё находится в MUC-е. // probeMUCLiveness Пингует MUC-и, нужно для проверки, что клиент ещё находится в MUC-е.
func probeMUCLiveness() { func probeMUCLiveness() { //nolint:gocognit
defer gTomb.Done() defer gTomb.Done()
for { for {
@@ -756,4 +760,66 @@ func probeMUCLiveness() {
} }
} }
// RotateStatus периодически изменяет статус бота в MUC-е согласно настройкам из кофига.
func RotateStatus(room string) {
defer gTomb.Done()
for {
select {
case <-gTomb.Dying():
return
default:
// TODO: Переделать на ticker-ы
totalSleepTime := time.Duration(config.Jabber.RuntimeStatus.RotationTime) * time.Second
totalSleepTime += time.Duration(config.Jabber.RuntimeStatus.RotationSplayTime) * time.Second
for {
status := randomPhrase(config.Jabber.RuntimeStatus.Text)
log.Debugf("Set status for MUC: %s to: %s", room, status)
var p xmpp.Presence
if room != "" {
p = xmpp.Presence{ //nolint:exhaustruct
To: room,
Status: status,
}
} else {
p = xmpp.Presence{ //nolint:exhaustruct
Status: status,
}
}
if _, err := talk.SendPresence(p); err != nil {
log.Infof("Unable to send presence to MUC %s: %s", room, err)
gTomb.Kill(err)
return
}
// Если мы не хотим ротировать, то цикл нам тут не нужен, просто выходим.
if config.Jabber.RuntimeStatus.RotationTime == 0 {
gTomb.Done()
return
}
time.Sleep(totalSleepTime)
}
}
}
}
// randomPhrase Выдаёт одну рандомную фразу из даденного списка фраз.
func randomPhrase(list []string) string {
phrase := ""
if listLen := len(list); listLen > 0 {
phrase = list[rand.Intn(listLen)] //nolint:gosec
}
return phrase
}
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */ /* vim: set ft=go noet ai ts=4 sw=4 sts=4: */

17
main.go
View File

@@ -43,7 +43,6 @@ func init() {
default: default:
log.SetLevel(log.InfoLevel) log.SetLevel(log.InfoLevel)
} }
} }
func main() { func main() {
@@ -94,11 +93,11 @@ func main() {
Debug: verboseClient, Debug: verboseClient,
Session: false, Session: false,
Status: "xa", Status: "xa",
StatusMessage: fmt.Sprintf("%s bot is starting up", config.Jabber.Nick), StatusMessage: randomPhrase(config.Jabber.StartupStatus),
DialTimeout: time.Duration(config.Jabber.ConnectionTimeout) * time.Second, DialTimeout: time.Duration(config.Jabber.ConnectionTimeout) * time.Second,
} }
// Через tomb попробуем попробуем сделать выход горутинок управляемым // Через tomb попробуем сделать выход горутинок управляемым
gTomb = tomb.Tomb{} gTomb = tomb.Tomb{}
// Устанавливаем соединение и гребём события, посылаемые сервером // Устанавливаем соединение и гребём события, посылаемые сервером
@@ -161,28 +160,32 @@ func myLoop() {
switch { switch {
// Стрим не читается, он закрылся с той стороны во время чтения // Стрим не читается, он закрылся с той стороны во время чтения
case errors.Is(err, io.EOF): case errors.Is(err, io.EOF):
err := errors.New("Tcp stream closed while reading") err := fmt.Errorf("tcp stream closed while reading, err=%w", err)
gTomb.Kill(err) gTomb.Kill(err)
continue continue
// Пытаемся читать закрытый сокет // Пытаемся читать закрытый сокет
case errors.Is(err, net.ErrClosed): case errors.Is(err, net.ErrClosed):
err := errors.New("Unable to read closed socket") err := fmt.Errorf("unable to read closed socket, err=%w", err)
gTomb.Kill(err) gTomb.Kill(err)
continue continue
// Не смогли записать в сокет // Не смогли записать в сокет
case errors.Is(err, net.ErrWriteToConnected): case errors.Is(err, net.ErrWriteToConnected):
err := errors.New("Unable to write to socket") err := fmt.Errorf("unable to write to socket, err=%w", err)
gTomb.Kill(err) gTomb.Kill(err)
continue continue
// Не сетевая проблема // Не сетевая проблема
default: default:
// Это уже что-то странное. // Это уже что-то странное.
// Вероятно, ошибка парсинга xml. Собственно, баг сервера, тут мы ничего поделать не можем // Вероятно, ошибка парсинга xml. Собственно, баг сервера, тут мы ничего поделать не можем
err := errors.New("error during parsing received message") err := fmt.Errorf("error during parsing received message, err=%w", err)
gTomb.Kill(err) gTomb.Kill(err)
continue continue
} }
} }

View File

@@ -24,12 +24,18 @@ type myConfig struct {
User string `json:"user,omitempty"` User string `json:"user,omitempty"`
Password string `json:"password,omitempty"` Password string `json:"password,omitempty"`
Channels []string `json:"channels"` Channels []string `json:"channels"`
OutcastDomains []string `json:"outcast_domains,omitempty"` StartupStatus []string `json:"startup_status,omitempty"`
} RuntimeStatus struct {
Text []string `json:"text,omitempty"`
RotationTime int64 `json:"rotation_time,omitempty"`
RotationSplayTime int64 `json:"rotation_splay_time,omitempty"`
} `json:"runtime_status,omitempty"`
BanPhrasesEnable bool `json:"ban_phrases_enable,omitempty"`
BanPhrases []string `json:"ban_phrases,omitempty"`
} `json:"jabber,omitempty"`
Loglevel string `json:"loglevel,omitempty"` Loglevel string `json:"loglevel,omitempty"`
Log string `json:"log,omitempty"` Log string `json:"log,omitempty"`
NoEcho bool `json:"noecho,omitempty"`
} }
// myWhiteList прототип структурки с белым списком jid-ов. // myWhiteList прототип структурки с белым списком jid-ов.
@@ -45,7 +51,9 @@ type myWhiteList struct {
type myBlackList struct { type myBlackList struct {
Blacklist []struct { Blacklist []struct {
RoomName string `json:"room_name,omitempty"` RoomName string `json:"room_name,omitempty"`
ReasonEnable bool `json:"reason_enable,omitempty"`
JidRe []string `json:"jid_re,omitempty"` JidRe []string `json:"jid_re,omitempty"`
NickRe []string `json:"nick_re,omitempty"`
} `json:"blacklist,omitempty"` } `json:"blacklist,omitempty"`
} }

57
vendor/github.com/eleksir/go-xmpp/xmpp_error.go generated vendored Normal file
View File

@@ -0,0 +1,57 @@
package xmpp
import (
"fmt"
)
// ErrorServiceUnavailable implements error response about feature that is not available. Currently implemented for
// xep-0030.
// QueryXmlns is about incoming xmlns attribute in query tag.
// Node is about incoming node attribute in query tag (looks like it used only in disco#commands).
//
// If queried feature is not here on purpose, standards suggest answer with this stanza.
func (c *Client) ErrorServiceUnavailable(v IQ, queryXmlns, node string) (string, error) {
query := fmt.Sprintf("<query xmlns=\"%s\" ", queryXmlns)
if node != "" {
query += fmt.Sprintf("node=\"%s\" />", node)
} else {
query += "/>"
}
query += "<error type=\"cancel\">"
query += "<service-unavailable xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />"
query += "</error>"
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeError,
query,
)
}
// ErrorNotImplemented implements error response about feature that is not (yet?) implemented.
// Xmlns is about not implemented feature.
//
// If queried feature is not here because of it under development or for similar reasons, standards suggest answer with
// this stanza.
func (c *Client) ErrorNotImplemented(v IQ, xmlns, feature string) (string, error) {
query := "<error type=\"cancel\">"
query += "<feature-not-implemented xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />"
query += fmt.Sprintf(
"<unsupported xmlns=\"%s\" feature=\"%s\" />",
xmlns,
feature,
)
query += "</error>"
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeError,
query,
)
}

View File

@@ -3,6 +3,7 @@ package xmpp
import ( import (
"fmt" "fmt"
"strconv" "strconv"
"time"
) )
const IQTypeGet = "get" const IQTypeGet = "get"
@@ -16,24 +17,24 @@ func (c *Client) Discovery() (string, error) {
return c.RawInformationQuery(c.jid, c.domain, reqID, IQTypeGet, XMPPNS_DISCO_ITEMS, "") return c.RawInformationQuery(c.jid, c.domain, reqID, IQTypeGet, XMPPNS_DISCO_ITEMS, "")
} }
// Discover information about a node. Empty node queries info about server itself. // DiscoverNodeInfo discovers information about a node. Empty node queries info about server itself.
func (c *Client) DiscoverNodeInfo(node string) (string, error) { func (c *Client) DiscoverNodeInfo(node string) (string, error) {
query := fmt.Sprintf("<query xmlns='%s' node='%s'/>", XMPPNS_DISCO_INFO, node) query := fmt.Sprintf("<query xmlns='%s' node='%s'/>", XMPPNS_DISCO_INFO, node)
return c.RawInformation(c.jid, c.domain, "info3", IQTypeGet, query) return c.RawInformation(c.jid, c.domain, "info3", IQTypeGet, query)
} }
// Discover information about given item from given jid. // DiscoverInfo discovers information about given item from given jid.
func (c *Client) DiscoverInfo(from string, to string) (string, error) { func (c *Client) DiscoverInfo(from string, to string) (string, error) {
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_INFO) query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_INFO)
return c.RawInformation(from, to, "info3", IQTypeGet, query) return c.RawInformation(from, to, "info3", IQTypeGet, query)
} }
// Discover items that the server exposes // DiscoverServerItems discover items that the server exposes
func (c *Client) DiscoverServerItems() (string, error) { func (c *Client) DiscoverServerItems() (string, error) {
return c.DiscoverEntityItems(c.domain) return c.DiscoverEntityItems(c.domain)
} }
// Discover items that an entity exposes // DiscoverEntityItems discovers items that an entity exposes.
func (c *Client) DiscoverEntityItems(jid string) (string, error) { func (c *Client) DiscoverEntityItems(jid string) (string, error) {
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_ITEMS) query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_ITEMS)
return c.RawInformation(c.jid, jid, "info1", IQTypeGet, query) return c.RawInformation(c.jid, jid, "info1", IQTypeGet, query)
@@ -46,9 +47,73 @@ func (c *Client) RawInformationQuery(from, to, id, iqType, requestNamespace, bod
return id, err return id, err
} }
// rawInformation send a IQ request with the payload body to the server // RawInformation sends a IQ request with the payload body to the server.
func (c *Client) RawInformation(from, to, id, iqType, body string) (string, error) { func (c *Client) RawInformation(from, to, id, iqType, body string) (string, error) {
const xmlIQ = "<iq from='%s' to='%s' id='%s' type='%s'>%s</iq>" const xmlIQ = "<iq from='%s' to='%s' id='%s' type='%s'>%s</iq>"
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, body) _, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, body)
return id, err return id, err
} }
// IqVersionResponse responding with software version, according to xep-0092.
func (c *Client) IqVersionResponse(v IQ, name, version, os string) (string, error) {
if name == "" {
name = "go-xmpp"
}
if version == "" {
version = "undefined"
}
query := "<query xmlns=\"jabber:iq:version\">" //nolint:wsl
query += fmt.Sprintf("<name>%s</name>", name)
query += fmt.Sprintf("<version>%s</version>", version)
if os != "" {
query += fmt.Sprintf("<os>%s</os>", os)
}
query += "</query>"
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
query,
)
}
// JabberIqLastResponse responding with relative time since last activity.
// Here lastActivity is unix time stamp when last activity took place since.
func (c *Client) JabberIqLastResponse(v IQ, lastActivity int64) (string, error) {
query := fmt.Sprintf(
"<query xmlns=\"jabber:iq:last\" seconds=\"%d\" />",
time.Now().Unix()-lastActivity,
)
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
query,
)
}
// UrnXmppTimeResponse implements response to query entity's current time (xep-0202).
// TimezoneOffset have format +HH:MM or -HH:MM
func (c *Client) UrnXmppTimeResponse(v IQ, timezoneOffset string) (string, error) {
query := fmt.Sprintf(
"<time xmlns=\"urn:xmpp:time\"><tzo>%s</tzo><utc>%s</utc></time>",
timezoneOffset,
time.Now().UTC().Format(time.RFC3339),
)
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
query,
)
}

View File

@@ -31,3 +31,14 @@ func (c *Client) SendResultPing(id, toServer string) error {
xmlEscape(toServer), xmlEscape(id)) xmlEscape(toServer), xmlEscape(id))
return err return err
} }
// PingResponse responding to ping query according to xep-0199
func (c *Client) PingResponse(v IQ) (string, error) {
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
"",
)
}

View File

@@ -106,28 +106,28 @@ func pubsubUnsubscriptionStanza(node, jid string) string {
return pubsubStanza(body) return pubsubStanza(body)
} }
func (c *Client) PubsubSubscribeNode(node, jid string) { func (c *Client) PubsubSubscribeNode(node, jid string) (string, error) {
c.RawInformation(c.jid, return c.RawInformation(c.jid,
jid, jid,
"sub1", "sub1",
"set", "set",
pubsubSubscriptionStanza(node, c.jid)) pubsubSubscriptionStanza(node, c.jid))
} }
func (c *Client) PubsubUnsubscribeNode(node, jid string) { func (c *Client) PubsubUnsubscribeNode(node, jid string) (string, error) {
c.RawInformation(c.jid, return c.RawInformation(c.jid,
jid, jid,
"unsub1", "unsub1",
"set", "set",
pubsubUnsubscriptionStanza(node, c.jid)) pubsubUnsubscriptionStanza(node, c.jid))
} }
func (c *Client) PubsubRequestLastItems(node, jid string) { func (c *Client) PubsubRequestLastItems(node, jid string) (string, error) {
body := fmt.Sprintf("<items node='%s'/>", node) body := fmt.Sprintf("<items node='%s'/>", node)
c.RawInformation(c.jid, jid, "items1", "get", pubsubStanza(body)) return c.RawInformation(c.jid, jid, "items1", "get", pubsubStanza(body))
} }
func (c *Client) PubsubRequestItem(node, jid, id string) { func (c *Client) PubsubRequestItem(node, jid, id string) (string, error) {
body := fmt.Sprintf("<items node='%s'><item id='%s'/></items>", node, id) body := fmt.Sprintf("<items node='%s'><item id='%s'/></items>", node, id)
c.RawInformation(c.jid, jid, "items3", "get", pubsubStanza(body)) return c.RawInformation(c.jid, jid, "items3", "get", pubsubStanza(body))
} }

View File

@@ -624,7 +624,7 @@ ccflags="$@"
$2 ~ /^MEM/ || $2 ~ /^MEM/ ||
$2 ~ /^WG/ || $2 ~ /^WG/ ||
$2 ~ /^FIB_RULE_/ || $2 ~ /^FIB_RULE_/ ||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE|IOMIN$|IOOPT$|ALIGNOFF$|DISCARD|ROTATIONAL$|ZEROOUT$|GETDISKSEQ$)/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next} $2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}

14
vendor/golang.org/x/sys/unix/mmap_nomremap.go generated vendored Normal file
View File

@@ -0,0 +1,14 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
// +build aix darwin dragonfly freebsd openbsd solaris
package unix
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}

View File

@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build linux //go:build linux || netbsd
// +build linux // +build linux netbsd
package unix package unix
@@ -14,8 +14,17 @@ type mremapMmapper struct {
mremap func(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) mremap func(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
} }
var mapper = &mremapMmapper{
mmapper: mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
},
mremap: mremap,
}
func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) { func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
if newLength <= 0 || len(oldData) == 0 || len(oldData) != cap(oldData) || flags&MREMAP_FIXED != 0 { if newLength <= 0 || len(oldData) == 0 || len(oldData) != cap(oldData) || flags&mremapFixed != 0 {
return nil, EINVAL return nil, EINVAL
} }
@@ -32,9 +41,13 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [
} }
bNew := unsafe.Slice((*byte)(unsafe.Pointer(newAddr)), newLength) bNew := unsafe.Slice((*byte)(unsafe.Pointer(newAddr)), newLength)
pNew := &bNew[cap(bNew)-1] pNew := &bNew[cap(bNew)-1]
if flags&MREMAP_DONTUNMAP == 0 { if flags&mremapDontunmap == 0 {
delete(m.active, pOld) delete(m.active, pOld)
} }
m.active[pNew] = bNew m.active[pNew] = bNew
return bNew, nil return bNew, nil
} }
func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
return mapper.Mremap(oldData, newLength, flags)
}

View File

@@ -535,21 +535,6 @@ func Fsync(fd int) error {
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg
//sys munmap(addr uintptr, length uintptr) (err error) //sys munmap(addr uintptr, length uintptr) (err error)
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
//sys Madvise(b []byte, advice int) (err error) //sys Madvise(b []byte, advice int) (err error)
//sys Mprotect(b []byte, prot int) (err error) //sys Mprotect(b []byte, prot int) (err error)
//sys Mlock(b []byte) (err error) //sys Mlock(b []byte) (err error)

View File

@@ -601,20 +601,6 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
// Gethostuuid(uuid *byte, timeout *Timespec) (err error) // Gethostuuid(uuid *byte, timeout *Timespec) (err error)
// Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error) // Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error)
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
//sys Madvise(b []byte, behav int) (err error) //sys Madvise(b []byte, behav int) (err error)
//sys Mlock(b []byte) (err error) //sys Mlock(b []byte) (err error)
//sys Mlockall(flags int) (err error) //sys Mlockall(flags int) (err error)

View File

@@ -510,6 +510,7 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
return nil, err return nil, err
} }
for {
// Find size. // Find size.
n := uintptr(0) n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil { if err := sysctl(mib, nil, &n, nil, 0); err != nil {
@@ -525,6 +526,10 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
// Read into buffer of that size. // Read into buffer of that size.
buf := make([]KinfoProc, n/SizeofKinfoProc) buf := make([]KinfoProc, n/SizeofKinfoProc)
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil { if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
if err == ENOMEM {
// Process table grew. Try again.
continue
}
return nil, err return nil, err
} }
if n%SizeofKinfoProc != 0 { if n%SizeofKinfoProc != 0 {
@@ -534,6 +539,7 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
// The actual call may return less than the original reported required // The actual call may return less than the original reported required
// size so ensure we deal with that. // size so ensure we deal with that.
return buf[:n/SizeofKinfoProc], nil return buf[:n/SizeofKinfoProc], nil
}
} }
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)

View File

@@ -1885,7 +1885,7 @@ func Getpgrp() (pid int) {
//sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) //sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6 //sys pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error)
//sys read(fd int, p []byte) (n int, err error) //sys read(fd int, p []byte) (n int, err error)
//sys Removexattr(path string, attr string) (err error) //sys Removexattr(path string, attr string) (err error)
//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) //sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)
@@ -2125,28 +2125,6 @@ func writevRacedetect(iovecs []Iovec, n int) {
// mmap varies by architecture; see syscall_linux_*.go. // mmap varies by architecture; see syscall_linux_*.go.
//sys munmap(addr uintptr, length uintptr) (err error) //sys munmap(addr uintptr, length uintptr) (err error)
//sys mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) //sys mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
var mapper = &mremapMmapper{
mmapper: mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
},
mremap: mremap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
return mapper.Mremap(oldData, newLength, flags)
}
//sys Madvise(b []byte, advice int) (err error) //sys Madvise(b []byte, advice int) (err error)
//sys Mprotect(b []byte, prot int) (err error) //sys Mprotect(b []byte, prot int) (err error)
//sys Mlock(b []byte) (err error) //sys Mlock(b []byte) (err error)
@@ -2155,6 +2133,12 @@ func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
//sys Munlock(b []byte) (err error) //sys Munlock(b []byte) (err error)
//sys Munlockall() (err error) //sys Munlockall() (err error)
const (
mremapFixed = MREMAP_FIXED
mremapDontunmap = MREMAP_DONTUNMAP
mremapMaymove = MREMAP_MAYMOVE
)
// Vmsplice splices user pages from a slice of Iovecs into a pipe specified by fd, // Vmsplice splices user pages from a slice of Iovecs into a pipe specified by fd,
// using the specified flags. // using the specified flags.
func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) { func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
@@ -2454,6 +2438,39 @@ func Getresgid() (rgid, egid, sgid int) {
return int(r), int(e), int(s) return int(r), int(e), int(s)
} }
// Pselect is a wrapper around the Linux pselect6 system call.
// This version does not modify the timeout argument.
func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
// Per https://man7.org/linux/man-pages/man2/select.2.html#NOTES,
// The Linux pselect6() system call modifies its timeout argument.
// [Not modifying the argument] is the behavior required by POSIX.1-2001.
var mutableTimeout *Timespec
if timeout != nil {
mutableTimeout = new(Timespec)
*mutableTimeout = *timeout
}
// The final argument of the pselect6() system call is not a
// sigset_t * pointer, but is instead a structure
var kernelMask *sigset_argpack
if sigmask != nil {
wordBits := 32 << (^uintptr(0) >> 63) // see math.intSize
// A sigset stores one bit per signal,
// offset by 1 (because signal 0 does not exist).
// So the number of words needed is ⌈__C_NSIG - 1 / wordBits⌉.
sigsetWords := (_C__NSIG - 1 + wordBits - 1) / (wordBits)
sigsetBytes := uintptr(sigsetWords * (wordBits / 8))
kernelMask = &sigset_argpack{
ss: sigmask,
ssLen: sigsetBytes,
}
}
return pselect6(nfd, r, w, e, mutableTimeout, kernelMask)
}
/* /*
* Unimplemented * Unimplemented
*/ */

View File

@@ -40,7 +40,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil { if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
} }
return Pselect(nfd, r, w, e, ts, nil) return pselect6(nfd, r, w, e, ts, nil)
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

View File

@@ -33,7 +33,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil { if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
} }
return Pselect(nfd, r, w, e, ts, nil) return pselect6(nfd, r, w, e, ts, nil)
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

View File

@@ -28,7 +28,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil { if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
} }
return Pselect(nfd, r, w, e, ts, nil) return pselect6(nfd, r, w, e, ts, nil)
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

View File

@@ -31,7 +31,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil { if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
} }
return Pselect(nfd, r, w, e, ts, nil) return pselect6(nfd, r, w, e, ts, nil)
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)

View File

@@ -32,7 +32,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
if timeout != nil { if timeout != nil {
ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000}
} }
return Pselect(nfd, r, w, e, ts, nil) return pselect6(nfd, r, w, e, ts, nil)
} }
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
@@ -177,3 +177,14 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
} }
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
} }
//sys riscvHWProbe(pairs []RISCVHWProbePairs, cpuCount uintptr, cpus *CPUSet, flags uint) (err error)
func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error) {
var setSize uintptr
if set != nil {
setSize = uintptr(unsafe.Sizeof(*set))
}
return riscvHWProbe(pairs, setSize, set, flags)
}

View File

@@ -360,6 +360,18 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE //sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
const (
mremapFixed = MAP_FIXED
mremapDontunmap = 0
mremapMaymove = 0
)
//sys mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) = SYS_MREMAP
func mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (uintptr, error) {
return mremapNetBSD(oldaddr, oldlength, newaddr, newlength, flags)
}
/* /*
* Unimplemented * Unimplemented
*/ */
@@ -564,7 +576,6 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
// mq_timedreceive // mq_timedreceive
// mq_timedsend // mq_timedsend
// mq_unlink // mq_unlink
// mremap
// msgget // msgget
// msgrcv // msgrcv
// msgsnd // msgsnd

View File

@@ -716,20 +716,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
return return
} }
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
// Event Ports // Event Ports
type fileObjCookie struct { type fileObjCookie struct {

View File

@@ -147,6 +147,14 @@ func (m *mmapper) Munmap(data []byte) (err error) {
return nil return nil
} }
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
func Read(fd int, p []byte) (n int, err error) { func Read(fd int, p []byte) (n int, err error) {
n, err = read(fd, p) n, err = read(fd, p)
if raceenabled { if raceenabled {

View File

@@ -285,25 +285,11 @@ func Close(fd int) (err error) {
return return
} }
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
// Dummy function: there are no semantics for Madvise on z/OS // Dummy function: there are no semantics for Madvise on z/OS
func Madvise(b []byte, advice int) (err error) { func Madvise(b []byte, advice int) (err error) {
return return
} }
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
//sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A //sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
//sysnb Getegid() (egid int) //sysnb Getegid() (egid int)
//sysnb Geteuid() (uid int) //sysnb Geteuid() (uid int)

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80041270 BLKBSZGET = 0x80041270
BLKBSZSET = 0x40041271 BLKBSZSET = 0x40041271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80041272 BLKGETSIZE64 = 0x80041272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80081270 BLKBSZGET = 0x80081270
BLKBSZSET = 0x40081271 BLKBSZSET = 0x40081271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80081272 BLKGETSIZE64 = 0x80081272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80041270 BLKBSZGET = 0x80041270
BLKBSZSET = 0x40041271 BLKBSZSET = 0x40041271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80041272 BLKGETSIZE64 = 0x80041272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80081270 BLKBSZGET = 0x80081270
BLKBSZSET = 0x40081271 BLKBSZSET = 0x40081271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80081272 BLKGETSIZE64 = 0x80081272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80081270 BLKBSZGET = 0x80081270
BLKBSZSET = 0x40081271 BLKBSZSET = 0x40081271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80081272 BLKGETSIZE64 = 0x80081272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40041270 BLKBSZGET = 0x40041270
BLKBSZSET = 0x80041271 BLKBSZSET = 0x80041271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40041272 BLKGETSIZE64 = 0x40041272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40081270 BLKBSZGET = 0x40081270
BLKBSZSET = 0x80081271 BLKBSZSET = 0x80081271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40081272 BLKGETSIZE64 = 0x40081272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40081270 BLKBSZGET = 0x40081270
BLKBSZSET = 0x80081271 BLKBSZSET = 0x80081271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40081272 BLKGETSIZE64 = 0x40081272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40041270 BLKBSZGET = 0x40041270
BLKBSZSET = 0x80041271 BLKBSZSET = 0x80041271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40041272 BLKGETSIZE64 = 0x40041272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x10 B57600 = 0x10
B576000 = 0x15 B576000 = 0x15
B921600 = 0x16 B921600 = 0x16
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40041270 BLKBSZGET = 0x40041270
BLKBSZSET = 0x80041271 BLKBSZSET = 0x80041271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40041272 BLKGETSIZE64 = 0x40041272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1f BOTHER = 0x1f
BS1 = 0x8000 BS1 = 0x8000
BSDLY = 0x8000 BSDLY = 0x8000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x10 B57600 = 0x10
B576000 = 0x15 B576000 = 0x15
B921600 = 0x16 B921600 = 0x16
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40081270 BLKBSZGET = 0x40081270
BLKBSZSET = 0x80081271 BLKBSZSET = 0x80081271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40081272 BLKGETSIZE64 = 0x40081272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1f BOTHER = 0x1f
BS1 = 0x8000 BS1 = 0x8000
BSDLY = 0x8000 BSDLY = 0x8000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x10 B57600 = 0x10
B576000 = 0x15 B576000 = 0x15
B921600 = 0x16 B921600 = 0x16
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40081270 BLKBSZGET = 0x40081270
BLKBSZSET = 0x80081271 BLKBSZSET = 0x80081271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40081272 BLKGETSIZE64 = 0x40081272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1f BOTHER = 0x1f
BS1 = 0x8000 BS1 = 0x8000
BSDLY = 0x8000 BSDLY = 0x8000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80081270 BLKBSZGET = 0x80081270
BLKBSZSET = 0x40081271 BLKBSZSET = 0x40081271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80081272 BLKGETSIZE64 = 0x80081272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -27,22 +27,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x127a
BLKBSZGET = 0x80081270 BLKBSZGET = 0x80081270
BLKBSZSET = 0x40081271 BLKBSZSET = 0x40081271
BLKDISCARD = 0x1277
BLKDISCARDZEROES = 0x127c
BLKFLSBUF = 0x1261 BLKFLSBUF = 0x1261
BLKFRAGET = 0x1265 BLKFRAGET = 0x1265
BLKFRASET = 0x1264 BLKFRASET = 0x1264
BLKGETDISKSEQ = 0x80081280
BLKGETSIZE = 0x1260 BLKGETSIZE = 0x1260
BLKGETSIZE64 = 0x80081272 BLKGETSIZE64 = 0x80081272
BLKIOMIN = 0x1278
BLKIOOPT = 0x1279
BLKPBSZGET = 0x127b BLKPBSZGET = 0x127b
BLKRAGET = 0x1263 BLKRAGET = 0x1263
BLKRASET = 0x1262 BLKRASET = 0x1262
BLKROGET = 0x125e BLKROGET = 0x125e
BLKROSET = 0x125d BLKROSET = 0x125d
BLKROTATIONAL = 0x127e
BLKRRPART = 0x125f BLKRRPART = 0x125f
BLKSECDISCARD = 0x127d
BLKSECTGET = 0x1267 BLKSECTGET = 0x1267
BLKSECTSET = 0x1266 BLKSECTSET = 0x1266
BLKSSZGET = 0x1268 BLKSSZGET = 0x1268
BLKZEROOUT = 0x127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -30,22 +30,31 @@ const (
B57600 = 0x1001 B57600 = 0x1001
B576000 = 0x1006 B576000 = 0x1006
B921600 = 0x1007 B921600 = 0x1007
BLKALIGNOFF = 0x2000127a
BLKBSZGET = 0x40081270 BLKBSZGET = 0x40081270
BLKBSZSET = 0x80081271 BLKBSZSET = 0x80081271
BLKDISCARD = 0x20001277
BLKDISCARDZEROES = 0x2000127c
BLKFLSBUF = 0x20001261 BLKFLSBUF = 0x20001261
BLKFRAGET = 0x20001265 BLKFRAGET = 0x20001265
BLKFRASET = 0x20001264 BLKFRASET = 0x20001264
BLKGETDISKSEQ = 0x40081280
BLKGETSIZE = 0x20001260 BLKGETSIZE = 0x20001260
BLKGETSIZE64 = 0x40081272 BLKGETSIZE64 = 0x40081272
BLKIOMIN = 0x20001278
BLKIOOPT = 0x20001279
BLKPBSZGET = 0x2000127b BLKPBSZGET = 0x2000127b
BLKRAGET = 0x20001263 BLKRAGET = 0x20001263
BLKRASET = 0x20001262 BLKRASET = 0x20001262
BLKROGET = 0x2000125e BLKROGET = 0x2000125e
BLKROSET = 0x2000125d BLKROSET = 0x2000125d
BLKROTATIONAL = 0x2000127e
BLKRRPART = 0x2000125f BLKRRPART = 0x2000125f
BLKSECDISCARD = 0x2000127d
BLKSECTGET = 0x20001267 BLKSECTGET = 0x20001267
BLKSECTSET = 0x20001266 BLKSECTSET = 0x20001266
BLKSSZGET = 0x20001268 BLKSSZGET = 0x20001268
BLKZEROOUT = 0x2000127f
BOTHER = 0x1000 BOTHER = 0x1000
BS1 = 0x2000 BS1 = 0x2000
BSDLY = 0x2000 BSDLY = 0x2000

View File

@@ -1356,7 +1356,7 @@ func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { func pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error) {
r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask))) r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))
n = int(r0) n = int(r0)
if e1 != 0 { if e1 != 0 {

View File

@@ -531,3 +531,19 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f
} }
return return
} }
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func riscvHWProbe(pairs []RISCVHWProbePairs, cpuCount uintptr, cpus *CPUSet, flags uint) (err error) {
var _p0 unsafe.Pointer
if len(pairs) > 0 {
_p0 = unsafe.Pointer(&pairs[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
_, _, e1 := Syscall6(SYS_RISCV_HWPROBE, uintptr(_p0), uintptr(len(pairs)), uintptr(cpuCount), uintptr(unsafe.Pointer(cpus)), uintptr(flags), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -1858,3 +1858,14 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error
} }
return return
} }
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) {
r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0)
xaddr = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -1858,3 +1858,14 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error
} }
return return
} }
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) {
r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0)
xaddr = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -1858,3 +1858,14 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error
} }
return return
} }
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) {
r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0)
xaddr = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -1858,3 +1858,14 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error
} }
return return
} }
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) {
r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0)
xaddr = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}

View File

@@ -251,6 +251,8 @@ const (
SYS_ACCEPT4 = 242 SYS_ACCEPT4 = 242
SYS_RECVMMSG = 243 SYS_RECVMMSG = 243
SYS_ARCH_SPECIFIC_SYSCALL = 244 SYS_ARCH_SPECIFIC_SYSCALL = 244
SYS_RISCV_HWPROBE = 258
SYS_RISCV_FLUSH_ICACHE = 259
SYS_WAIT4 = 260 SYS_WAIT4 = 260
SYS_PRLIMIT64 = 261 SYS_PRLIMIT64 = 261
SYS_FANOTIFY_INIT = 262 SYS_FANOTIFY_INIT = 262

View File

@@ -866,6 +866,11 @@ const (
POLLNVAL = 0x20 POLLNVAL = 0x20
) )
type sigset_argpack struct {
ss *Sigset_t
ssLen uintptr
}
type SignalfdSiginfo struct { type SignalfdSiginfo struct {
Signo uint32 Signo uint32
Errno int32 Errno int32

View File

@@ -718,3 +718,26 @@ type SysvShmDesc struct {
_ uint64 _ uint64
_ uint64 _ uint64
} }
type RISCVHWProbePairs struct {
Key int64
Value uint64
}
const (
RISCV_HWPROBE_KEY_MVENDORID = 0x0
RISCV_HWPROBE_KEY_MARCHID = 0x1
RISCV_HWPROBE_KEY_MIMPID = 0x2
RISCV_HWPROBE_KEY_BASE_BEHAVIOR = 0x3
RISCV_HWPROBE_BASE_BEHAVIOR_IMA = 0x1
RISCV_HWPROBE_KEY_IMA_EXT_0 = 0x4
RISCV_HWPROBE_IMA_FD = 0x1
RISCV_HWPROBE_IMA_C = 0x2
RISCV_HWPROBE_KEY_CPUPERF_0 = 0x5
RISCV_HWPROBE_MISALIGNED_UNKNOWN = 0x0
RISCV_HWPROBE_MISALIGNED_EMULATED = 0x1
RISCV_HWPROBE_MISALIGNED_SLOW = 0x2
RISCV_HWPROBE_MISALIGNED_FAST = 0x3
RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = 0x4
RISCV_HWPROBE_MISALIGNED_MASK = 0x7
)

View File

@@ -135,14 +135,14 @@ func Getpagesize() int { return 4096 }
// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. // NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
// This is useful when interoperating with Windows code requiring callbacks. // This is useful when interoperating with Windows code requiring callbacks.
// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. // The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
func NewCallback(fn interface{}) uintptr { func NewCallback(fn interface{}) uintptr {
return syscall.NewCallback(fn) return syscall.NewCallback(fn)
} }
// NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention. // NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention.
// This is useful when interoperating with Windows code requiring callbacks. // This is useful when interoperating with Windows code requiring callbacks.
// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. // The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
func NewCallbackCDecl(fn interface{}) uintptr { func NewCallbackCDecl(fn interface{}) uintptr {
return syscall.NewCallbackCDecl(fn) return syscall.NewCallbackCDecl(fn)
} }

8
vendor/modules.txt vendored
View File

@@ -1,7 +1,7 @@
# github.com/davecgh/go-spew v1.1.1 # github.com/davecgh/go-spew v1.1.1
## explicit ## explicit
github.com/davecgh/go-spew/spew github.com/davecgh/go-spew/spew
# github.com/eleksir/go-xmpp v1.4.0 # github.com/eleksir/go-xmpp v1.5.0
## explicit; go 1.20 ## explicit; go 1.20
github.com/eleksir/go-xmpp github.com/eleksir/go-xmpp
# github.com/hjson/hjson-go v3.3.0+incompatible # github.com/hjson/hjson-go v3.3.0+incompatible
@@ -10,14 +10,14 @@ github.com/hjson/hjson-go
# github.com/sirupsen/logrus v1.9.3 # github.com/sirupsen/logrus v1.9.3
## explicit; go 1.13 ## explicit; go 1.13
github.com/sirupsen/logrus github.com/sirupsen/logrus
# golang.org/x/crypto v0.11.0 # golang.org/x/crypto v0.12.0
## explicit; go 1.17 ## explicit; go 1.17
golang.org/x/crypto/pbkdf2 golang.org/x/crypto/pbkdf2
# golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 # golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
## explicit; go 1.20 ## explicit; go 1.20
golang.org/x/exp/constraints golang.org/x/exp/constraints
golang.org/x/exp/slices golang.org/x/exp/slices
# golang.org/x/sys v0.10.0 # golang.org/x/sys v0.11.0
## explicit; go 1.17 ## explicit; go 1.17
golang.org/x/sys/internal/unsafeheader golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix golang.org/x/sys/unix