mirror of
https://github.com/mumble-voip/grumble.git
synced 2025-12-19 21:59:59 -08:00
Major gofix run.
This commit is contained in:
parent
92e6ac5276
commit
71b8314c2e
28 changed files with 522 additions and 559 deletions
2
args.go
2
args.go
|
|
@ -66,7 +66,7 @@ func init() {
|
||||||
flag.BoolVar(&Args.GenerateCert, "gencert", false, "Generate a self-signed certificate for use with Grumble")
|
flag.BoolVar(&Args.GenerateCert, "gencert", false, "Generate a self-signed certificate for use with Grumble")
|
||||||
|
|
||||||
// SQLite related
|
// SQLite related
|
||||||
if (SQLiteSupport) {
|
if SQLiteSupport {
|
||||||
flag.StringVar(&Args.SQLiteDB, "murmurdb", "", "Path to a Murmur SQLite database to import from")
|
flag.StringVar(&Args.SQLiteDB, "murmurdb", "", "Path to a Murmur SQLite database to import from")
|
||||||
flag.BoolVar(&Args.CleanUp, "cleanup", false, "Clean up Grumble's data directory on launch")
|
flag.BoolVar(&Args.CleanUp, "cleanup", false, "Clean up Grumble's data directory on launch")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func (channel *Channel) AddChild(child *Channel) {
|
||||||
// Remove a child channel from a parent
|
// Remove a child channel from a parent
|
||||||
func (channel *Channel) RemoveChild(child *Channel) {
|
func (channel *Channel) RemoveChild(child *Channel) {
|
||||||
child.parent = nil
|
child.parent = nil
|
||||||
channel.children[child.Id] = nil, false
|
delete(channel.children, child.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add client
|
// Add client
|
||||||
|
|
@ -66,7 +66,7 @@ func (channel *Channel) AddClient(client *Client) {
|
||||||
|
|
||||||
// Remove client
|
// Remove client
|
||||||
func (channel *Channel) RemoveClient(client *Client) {
|
func (channel *Channel) RemoveClient(client *Client) {
|
||||||
channel.clients[client.Session] = nil, false
|
delete(channel.clients, client.Session)
|
||||||
client.Channel = nil
|
client.Channel = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
15
client.go
15
client.go
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"packetdatastream"
|
"packetdatastream"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -196,7 +195,7 @@ func (client *Client) RejectAuth(rejectType mumbleproto.Reject_RejectType, reaso
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a protobuf message from a client
|
// Read a protobuf message from a client
|
||||||
func (client *Client) readProtoMessage() (msg *Message, err os.Error) {
|
func (client *Client) readProtoMessage() (msg *Message, err error) {
|
||||||
var (
|
var (
|
||||||
length uint32
|
length uint32
|
||||||
kind uint16
|
kind uint16
|
||||||
|
|
@ -230,7 +229,7 @@ func (client *Client) readProtoMessage() (msg *Message, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a protobuf-encoded message
|
// Send a protobuf-encoded message
|
||||||
func (c *Client) sendProtoMessage(msg interface{}) (err os.Error) {
|
func (c *Client) sendProtoMessage(msg interface{}) (err error) {
|
||||||
d, err := proto.Marshal(msg)
|
d, err := proto.Marshal(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
@ -277,7 +276,7 @@ func (c *Client) sendPermissionDenied(who *Client, where *Channel, what Permissi
|
||||||
Type: mumbleproto.NewPermissionDenied_DenyType(mumbleproto.PermissionDenied_Permission),
|
Type: mumbleproto.NewPermissionDenied_DenyType(mumbleproto.PermissionDenied_Permission),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Panicf(err.String())
|
c.Panicf(err.Error())
|
||||||
}
|
}
|
||||||
c.msgchan <- &Message{
|
c.msgchan <- &Message{
|
||||||
buf: d,
|
buf: d,
|
||||||
|
|
@ -370,7 +369,7 @@ func (client *Client) sendUdp(msg *Message) {
|
||||||
// This method should only be called from within the client's own
|
// This method should only be called from within the client's own
|
||||||
// sender goroutine, since it serializes access to the underlying
|
// sender goroutine, since it serializes access to the underlying
|
||||||
// buffered writer.
|
// buffered writer.
|
||||||
func (client *Client) sendMessage(msg *Message) os.Error {
|
func (client *Client) sendMessage(msg *Message) error {
|
||||||
// Write message kind
|
// Write message kind
|
||||||
err := binary.Write(client.writer, binary.BigEndian, msg.kind)
|
err := binary.Write(client.writer, binary.BigEndian, msg.kind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -432,7 +431,7 @@ func (client *Client) receiver() {
|
||||||
// Try to read the next message in the pool
|
// Try to read the next message in the pool
|
||||||
msg, err := client.readProtoMessage()
|
msg, err := client.readProtoMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
client.Disconnect()
|
client.Disconnect()
|
||||||
} else {
|
} else {
|
||||||
client.Panicf("%v", err)
|
client.Panicf("%v", err)
|
||||||
|
|
@ -454,7 +453,7 @@ func (client *Client) receiver() {
|
||||||
// Try to read the next message in the pool
|
// Try to read the next message in the pool
|
||||||
msg, err := client.readProtoMessage()
|
msg, err := client.readProtoMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
client.Disconnect()
|
client.Disconnect()
|
||||||
} else {
|
} else {
|
||||||
client.Panicf("%v", err)
|
client.Panicf("%v", err)
|
||||||
|
|
@ -492,7 +491,7 @@ func (client *Client) receiver() {
|
||||||
} else if client.state == StateServerSentVersion {
|
} else if client.state == StateServerSentVersion {
|
||||||
msg, err := client.readProtoMessage()
|
msg, err := client.readProtoMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
client.Disconnect()
|
client.Disconnect()
|
||||||
} else {
|
} else {
|
||||||
client.Panicf("%v", err)
|
client.Panicf("%v", err)
|
||||||
|
|
|
||||||
24
ctlrpc.go
24
ctlrpc.go
|
|
@ -4,9 +4,7 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "errors"
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ControlRPC struct {
|
type ControlRPC struct {
|
||||||
|
|
||||||
|
|
@ -19,30 +17,30 @@ type KeyValuePair struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a server
|
// Start a server
|
||||||
func (c *ControlRPC) Start(Id int64, out *int64) os.Error {
|
func (c *ControlRPC) Start(Id int64, out *int64) error {
|
||||||
server, exists := servers[Id]
|
server, exists := servers[Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return errors.New("no such server")
|
||||||
}
|
}
|
||||||
_ = server
|
_ = server
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop a server
|
// Stop a server
|
||||||
func (c *ControlRPC) Stop(Id int64, out *int) os.Error {
|
func (c *ControlRPC) Stop(Id int64, out *int) error {
|
||||||
server, exists := servers[Id]
|
server, exists := servers[Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return errors.New("no such server")
|
||||||
}
|
}
|
||||||
_ = server
|
_ = server
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set SuperUser password
|
// Set SuperUser password
|
||||||
func (c *ControlRPC) SetSuperUserPassword(in *KeyValuePair, out *int64) os.Error {
|
func (c *ControlRPC) SetSuperUserPassword(in *KeyValuePair, out *int64) error {
|
||||||
server, exists := servers[in.Id]
|
server, exists := servers[in.Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return errors.New("no such server")
|
||||||
}
|
}
|
||||||
server.SetSuperUserPassword(in.Value)
|
server.SetSuperUserPassword(in.Value)
|
||||||
*out = in.Id
|
*out = in.Id
|
||||||
|
|
@ -50,10 +48,10 @@ func (c *ControlRPC) SetSuperUserPassword(in *KeyValuePair, out *int64) os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a config value
|
// Set a config value
|
||||||
func (c *ControlRPC) SetConfig(in *KeyValuePair, out *KeyValuePair) os.Error {
|
func (c *ControlRPC) SetConfig(in *KeyValuePair, out *KeyValuePair) error {
|
||||||
server, exists := servers[in.Id]
|
server, exists := servers[in.Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return errors.New("no such server")
|
||||||
}
|
}
|
||||||
server.cfg.Set(in.Key, in.Value)
|
server.cfg.Set(in.Key, in.Value)
|
||||||
server.cfgUpdate <- in
|
server.cfgUpdate <- in
|
||||||
|
|
@ -64,10 +62,10 @@ func (c *ControlRPC) SetConfig(in *KeyValuePair, out *KeyValuePair) os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a config value
|
// Get a config value
|
||||||
func (c *ControlRPC) GetConfig(in *KeyValuePair, out *KeyValuePair) os.Error {
|
func (c *ControlRPC) GetConfig(in *KeyValuePair, out *KeyValuePair) error {
|
||||||
server, exists := servers[in.Id]
|
server, exists := servers[in.Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return errors.New("no such server")
|
||||||
}
|
}
|
||||||
out.Id = in.Id
|
out.Id = in.Id
|
||||||
out.Key = in.Key
|
out.Key = in.Key
|
||||||
|
|
|
||||||
50
freeze.go
50
freeze.go
|
|
@ -5,11 +5,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"goprotobuf.googlecode.com/hg/proto"
|
"goprotobuf.googlecode.com/hg/proto"
|
||||||
"grumble/ban"
|
"grumble/ban"
|
||||||
"grumble/freezer"
|
"grumble/freezer"
|
||||||
"grumble/mumbleproto"
|
"grumble/mumbleproto"
|
||||||
"grumble/serverconf"
|
"grumble/serverconf"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -20,7 +22,7 @@ import (
|
||||||
|
|
||||||
// Freeze a server to disk, and re-open the log, if needed.
|
// Freeze a server to disk, and re-open the log, if needed.
|
||||||
// This must be called from within the Server's synchronous handler.
|
// This must be called from within the Server's synchronous handler.
|
||||||
func (server *Server) FreezeToFile() (err os.Error) {
|
func (server *Server) FreezeToFile() (err error) {
|
||||||
// Close the log file, if it's open
|
// Close the log file, if it's open
|
||||||
if server.freezelog != nil {
|
if server.freezelog != nil {
|
||||||
err = server.freezelog.Close()
|
err = server.freezelog.Close()
|
||||||
|
|
@ -69,10 +71,10 @@ func (server *Server) FreezeToFile() (err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a new freeze log
|
// Open a new freeze log
|
||||||
func (server *Server) openFreezeLog() (err os.Error) {
|
func (server *Server) openFreezeLog() (err error) {
|
||||||
logfn := filepath.Join(Args.DataDir, strconv.Itoa64(server.Id), "log.fz")
|
logfn := filepath.Join(Args.DataDir, strconv.Itoa64(server.Id), "log.fz")
|
||||||
err = os.Remove(logfn)
|
err = os.Remove(logfn)
|
||||||
if pe, ok := err.(*os.PathError); ok && pe.Error == os.ENOENT {
|
if pe, ok := err.(*os.PathError); ok && pe.Err == os.ENOENT {
|
||||||
// OK. File does not exist...
|
// OK. File does not exist...
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -86,7 +88,7 @@ func (server *Server) openFreezeLog() (err os.Error) {
|
||||||
|
|
||||||
// Freeze a server to a flattened protobuf-based structure ready to
|
// Freeze a server to a flattened protobuf-based structure ready to
|
||||||
// persist to disk.
|
// persist to disk.
|
||||||
func (server *Server) Freeze() (fs *freezer.Server, err os.Error) {
|
func (server *Server) Freeze() (fs *freezer.Server, err error) {
|
||||||
fs = new(freezer.Server)
|
fs = new(freezer.Server)
|
||||||
|
|
||||||
// Freeze all config kv-pairs
|
// Freeze all config kv-pairs
|
||||||
|
|
@ -112,7 +114,7 @@ func (server *Server) Freeze() (fs *freezer.Server, err os.Error) {
|
||||||
for _, c := range server.Channels {
|
for _, c := range server.Channels {
|
||||||
fc, err := c.Freeze()
|
fc, err := c.Freeze()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
channels = append(channels, fc)
|
channels = append(channels, fc)
|
||||||
}
|
}
|
||||||
|
|
@ -123,13 +125,13 @@ func (server *Server) Freeze() (fs *freezer.Server, err os.Error) {
|
||||||
for _, u := range server.Users {
|
for _, u := range server.Users {
|
||||||
fu, err := u.Freeze()
|
fu, err := u.Freeze()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
users = append(users, fu)
|
users = append(users, fu)
|
||||||
}
|
}
|
||||||
fs.Users = users
|
fs.Users = users
|
||||||
|
|
||||||
return
|
return fs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the contents of a freezer.BanList into the server's
|
// Merge the contents of a freezer.BanList into the server's
|
||||||
|
|
@ -180,7 +182,7 @@ func FreezeBan(ban ban.Ban) (fb *freezer.Ban) {
|
||||||
|
|
||||||
// Freeze a channel into a flattened protobuf-based struct
|
// Freeze a channel into a flattened protobuf-based struct
|
||||||
// ready to be persisted to disk.
|
// ready to be persisted to disk.
|
||||||
func (channel *Channel) Freeze() (fc *freezer.Channel, err os.Error) {
|
func (channel *Channel) Freeze() (fc *freezer.Channel, err error) {
|
||||||
fc = new(freezer.Channel)
|
fc = new(freezer.Channel)
|
||||||
|
|
||||||
fc.Id = proto.Uint32(uint32(channel.Id))
|
fc.Id = proto.Uint32(uint32(channel.Id))
|
||||||
|
|
@ -196,7 +198,7 @@ func (channel *Channel) Freeze() (fc *freezer.Channel, err os.Error) {
|
||||||
for _, acl := range channel.ACL {
|
for _, acl := range channel.ACL {
|
||||||
facl, err := acl.Freeze()
|
facl, err := acl.Freeze()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
acls = append(acls, facl)
|
acls = append(acls, facl)
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +209,7 @@ func (channel *Channel) Freeze() (fc *freezer.Channel, err os.Error) {
|
||||||
for _, grp := range channel.Groups {
|
for _, grp := range channel.Groups {
|
||||||
fgrp, err := grp.Freeze()
|
fgrp, err := grp.Freeze()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
groups = append(groups, fgrp)
|
groups = append(groups, fgrp)
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +296,7 @@ func (c *Channel) Unfreeze(fc *freezer.Channel) {
|
||||||
|
|
||||||
// Freeze a User into a flattened protobuf-based structure
|
// Freeze a User into a flattened protobuf-based structure
|
||||||
// ready to be persisted to disk.
|
// ready to be persisted to disk.
|
||||||
func (user *User) Freeze() (fu *freezer.User, err os.Error) {
|
func (user *User) Freeze() (fu *freezer.User, err error) {
|
||||||
fu = new(freezer.User)
|
fu = new(freezer.User)
|
||||||
|
|
||||||
fu.Id = proto.Uint32(user.Id)
|
fu.Id = proto.Uint32(user.Id)
|
||||||
|
|
@ -336,7 +338,7 @@ func (u *User) Unfreeze(fu *freezer.User) {
|
||||||
|
|
||||||
// Freeze a ChannelACL into it a flattened protobuf-based structure
|
// Freeze a ChannelACL into it a flattened protobuf-based structure
|
||||||
// ready to be persisted to disk.
|
// ready to be persisted to disk.
|
||||||
func (acl *ChannelACL) Freeze() (facl *freezer.ACL, err os.Error) {
|
func (acl *ChannelACL) Freeze() (facl *freezer.ACL, err error) {
|
||||||
facl = new(freezer.ACL)
|
facl = new(freezer.ACL)
|
||||||
|
|
||||||
if acl.UserId != -1 {
|
if acl.UserId != -1 {
|
||||||
|
|
@ -354,7 +356,7 @@ func (acl *ChannelACL) Freeze() (facl *freezer.ACL, err os.Error) {
|
||||||
|
|
||||||
// Freeze a Group into a flattened protobuf-based structure
|
// Freeze a Group into a flattened protobuf-based structure
|
||||||
// ready to be persisted to disk.
|
// ready to be persisted to disk.
|
||||||
func (group *Group) Freeze() (fgrp *freezer.Group, err os.Error) {
|
func (group *Group) Freeze() (fgrp *freezer.Group, err error) {
|
||||||
fgrp = new(freezer.Group)
|
fgrp = new(freezer.Group)
|
||||||
|
|
||||||
fgrp.Name = proto.String(group.Name)
|
fgrp.Name = proto.String(group.Name)
|
||||||
|
|
@ -382,7 +384,7 @@ func (group *Group) Freeze() (fgrp *freezer.Group, err os.Error) {
|
||||||
// Once both the full server and the log file has been merged together
|
// Once both the full server and the log file has been merged together
|
||||||
// in memory, a new full seralized server will be written and synced to
|
// in memory, a new full seralized server will be written and synced to
|
||||||
// disk, and the existing log file will be removed.
|
// disk, and the existing log file will be removed.
|
||||||
func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
func NewServerFromFrozen(name string) (s *Server, err error) {
|
||||||
id, err := strconv.Atoi64(name)
|
id, err := strconv.Atoi64(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -457,7 +459,7 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
||||||
if fc.ParentId != nil {
|
if fc.ParentId != nil {
|
||||||
parents[*fc.Id] = *fc.ParentId
|
parents[*fc.Id] = *fc.ParentId
|
||||||
} else {
|
} else {
|
||||||
parents[*fc.Id] = 0, false
|
delete(parents, *fc.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,7 +497,7 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
values, err := walker.Next()
|
values, err := walker.Next()
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -566,10 +568,10 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
||||||
user, ok := s.Users[userId]
|
user, ok := s.Users[userId]
|
||||||
if ok {
|
if ok {
|
||||||
// Clear the server maps. That should do it.
|
// Clear the server maps. That should do it.
|
||||||
s.Users[userId] = nil, false
|
delete(s.Users, userId)
|
||||||
s.UserNameMap[user.Name] = nil, false
|
delete(s.UserNameMap, user.Name)
|
||||||
if len(user.CertHash) > 0 {
|
if len(user.CertHash) > 0 {
|
||||||
s.UserCertMap[user.CertHash] = nil, false
|
delete(s.UserCertMap, user.CertHash)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Skipped UserRemove log entry: No user for given id.")
|
log.Printf("Skipped UserRemove log entry: No user for given id.")
|
||||||
|
|
@ -611,7 +613,7 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
||||||
if fc.ParentId != nil {
|
if fc.ParentId != nil {
|
||||||
parents[*fc.Id] = *fc.ParentId
|
parents[*fc.Id] = *fc.ParentId
|
||||||
} else {
|
} else {
|
||||||
parents[*fc.Id] = 0, false
|
delete(parents, *fc.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *freezer.ChannelRemove:
|
case *freezer.ChannelRemove:
|
||||||
|
|
@ -621,7 +623,7 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.Channels[int(*fc.Id)] = nil
|
s.Channels[int(*fc.Id)] = nil
|
||||||
parents[*fc.Id] = 0, false
|
delete(parents, *fc.Id)
|
||||||
|
|
||||||
case *freezer.BanList:
|
case *freezer.BanList:
|
||||||
fbl := val.(*freezer.BanList)
|
fbl := val.(*freezer.BanList)
|
||||||
|
|
@ -646,11 +648,11 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) {
|
||||||
for chanId, parentId := range parents {
|
for chanId, parentId := range parents {
|
||||||
childChan, exists := s.Channels[int(chanId)]
|
childChan, exists := s.Channels[int(chanId)]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, os.NewError("Non-existant child channel")
|
return nil, errors.New("Non-existant child channel")
|
||||||
}
|
}
|
||||||
parentChan, exists := s.Channels[int(parentId)]
|
parentChan, exists := s.Channels[int(parentId)]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, os.NewError("Non-existant parent channel")
|
return nil, errors.New("Non-existant parent channel")
|
||||||
}
|
}
|
||||||
parentChan.AddChild(childChan)
|
parentChan.AddChild(childChan)
|
||||||
}
|
}
|
||||||
|
|
@ -683,7 +685,7 @@ func (server *Server) UpdateFrozenUser(user *User, state *mumbleproto.UserState)
|
||||||
fu.TextureBlob = proto.String(user.TextureBlob)
|
fu.TextureBlob = proto.String(user.TextureBlob)
|
||||||
}
|
}
|
||||||
if state.CommentHash != nil {
|
if state.CommentHash != nil {
|
||||||
fu.CommentBlob = proto.String(user.CommentBlob)
|
fu.CommentBlob = proto.String(user.CommentBlob)
|
||||||
}
|
}
|
||||||
fu.LastActive = proto.Uint64(uint64(nanos))
|
fu.LastActive = proto.Uint64(uint64(nanos))
|
||||||
err := server.freezelog.Put(fu)
|
err := server.freezelog.Put(fu)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import (
|
||||||
// Generate a 2048-bit RSA keypair and a Grumble auto-generated X509
|
// Generate a 2048-bit RSA keypair and a Grumble auto-generated X509
|
||||||
// certificate. Output PEM-encoded DER representations of the resulting
|
// certificate. Output PEM-encoded DER representations of the resulting
|
||||||
// certificate and private key to certpath and keypath.
|
// certificate and private key to certpath and keypath.
|
||||||
func GenerateSelfSignedCert(certpath, keypath string) (err os.Error) {
|
func GenerateSelfSignedCert(certpath, keypath string) (err error) {
|
||||||
now := time.Seconds()
|
now := time.Seconds()
|
||||||
tmpl := &x509.Certificate{
|
tmpl := &x509.Certificate{
|
||||||
SerialNumber: big.NewInt(0),
|
SerialNumber: big.NewInt(0),
|
||||||
|
|
|
||||||
6
group.go
6
group.go
|
|
@ -6,8 +6,8 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Group struct {
|
type Group struct {
|
||||||
|
|
@ -117,7 +117,7 @@ func (group *Group) Members() map[int]bool {
|
||||||
members[uid] = true
|
members[uid] = true
|
||||||
}
|
}
|
||||||
for uid, _ := range curgroup.Remove {
|
for uid, _ := range curgroup.Remove {
|
||||||
members[uid] = false, false
|
delete(members, uid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ func (channel *Channel) GroupNames() map[string]bool {
|
||||||
for _, group := range iter.Groups {
|
for _, group := range iter.Groups {
|
||||||
// A non-inheritable group in parent. Discard it.
|
// A non-inheritable group in parent. Discard it.
|
||||||
if channel != iter && !group.Inheritable {
|
if channel != iter && !group.Inheritable {
|
||||||
names[group.Name] = false, false
|
delete(names, group.Name)
|
||||||
// An inheritable group. Add it to the list.
|
// An inheritable group. Add it to the list.
|
||||||
} else {
|
} else {
|
||||||
names[group.Name] = true
|
names[group.Name] = true
|
||||||
|
|
|
||||||
14
grumble.go
14
grumble.go
|
|
@ -19,7 +19,7 @@ import (
|
||||||
var servers map[int64]*Server
|
var servers map[int64]*Server
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err os.Error
|
var err error
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if Args.ShowHelp == true {
|
if Args.ShowHelp == true {
|
||||||
|
|
@ -35,13 +35,13 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SetPrefix("[G] ")
|
log.SetPrefix("[G] ")
|
||||||
log.SetFlags(log.LstdFlags|log.Lmicroseconds)
|
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
|
||||||
log.Printf("Grumble")
|
log.Printf("Grumble")
|
||||||
|
|
||||||
log.Printf("Using blob directory: %s", Args.BlobDir)
|
log.Printf("Using blob directory: %s", Args.BlobDir)
|
||||||
err = blobstore.Open(Args.BlobDir, true)
|
err = blobstore.Open(Args.BlobDir, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to initialize blobstore: %v", err.String())
|
log.Fatalf("Unable to initialize blobstore: %v", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if Args.GenerateCert {
|
if Args.GenerateCert {
|
||||||
|
|
@ -67,13 +67,13 @@ func main() {
|
||||||
if SQLiteSupport && len(Args.SQLiteDB) > 0 {
|
if SQLiteSupport && len(Args.SQLiteDB) > 0 {
|
||||||
f, err := os.Open(Args.DataDir)
|
f, err := os.Open(Args.DataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Murmur import failed: %s", err.String())
|
log.Fatalf("Murmur import failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
names, err := f.Readdirnames(-1)
|
names, err := f.Readdirnames(-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Murmur import failed: %s", err.String())
|
log.Fatalf("Murmur import failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Args.CleanUp && len(names) > 0 {
|
if !Args.CleanUp && len(names) > 0 {
|
||||||
|
|
@ -90,7 +90,7 @@ func main() {
|
||||||
|
|
||||||
log.Printf("Importing Murmur data from '%s'", Args.SQLiteDB)
|
log.Printf("Importing Murmur data from '%s'", Args.SQLiteDB)
|
||||||
if err = MurmurImport(Args.SQLiteDB); err != nil {
|
if err = MurmurImport(Args.SQLiteDB); err != nil {
|
||||||
log.Fatalf("Murmur import failed: %s", err.String())
|
log.Fatalf("Murmur import failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Import from Murmur SQLite database succeeded.")
|
log.Printf("Import from Murmur SQLite database succeeded.")
|
||||||
|
|
@ -130,7 +130,7 @@ func main() {
|
||||||
if len(servers) == 0 {
|
if len(servers) == 0 {
|
||||||
s, err := NewServer(1, "0.0.0.0", 64738)
|
s, err := NewServer(1, "0.0.0.0", 64738)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Couldn't start server: %s", err.String())
|
log.Fatalf("Couldn't start server: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
servers[s.Id] = s
|
servers[s.Id] = s
|
||||||
|
|
|
||||||
71
message.go
71
message.go
|
|
@ -45,7 +45,7 @@ func (server *Server) handleCryptSetup(client *Client, msg *Message) {
|
||||||
cs := &mumbleproto.CryptSetup{}
|
cs := &mumbleproto.CryptSetup{}
|
||||||
err := proto.Unmarshal(msg.buf, cs)
|
err := proto.Unmarshal(msg.buf, cs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ func (server *Server) handlePingMessage(client *Client, msg *Message) {
|
||||||
ping := &mumbleproto.Ping{}
|
ping := &mumbleproto.Ping{}
|
||||||
err := proto.Unmarshal(msg.buf, ping)
|
err := proto.Unmarshal(msg.buf, ping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ func (server *Server) handleChannelRemoveMessage(client *Client, msg *Message) {
|
||||||
chanremove := &mumbleproto.ChannelRemove{}
|
chanremove := &mumbleproto.ChannelRemove{}
|
||||||
err := proto.Unmarshal(msg.buf, chanremove)
|
err := proto.Unmarshal(msg.buf, chanremove)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,7 +157,7 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
|
||||||
chanstate := &mumbleproto.ChannelState{}
|
chanstate := &mumbleproto.ChannelState{}
|
||||||
err := proto.Unmarshal(msg.buf, chanstate)
|
err := proto.Unmarshal(msg.buf, chanstate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -262,7 +262,7 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
|
||||||
if len(description) > 0 {
|
if len(description) > 0 {
|
||||||
key, err = blobstore.Put([]byte(description))
|
key, err = blobstore.Put([]byte(description))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -444,7 +444,7 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
|
||||||
} else {
|
} else {
|
||||||
key, err := blobstore.Put([]byte(description))
|
key, err := blobstore.Put([]byte(description))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
}
|
}
|
||||||
channel.DescriptionBlob = key
|
channel.DescriptionBlob = key
|
||||||
}
|
}
|
||||||
|
|
@ -493,7 +493,8 @@ func (server *Server) handleUserRemoveMessage(client *Client, msg *Message) {
|
||||||
userremove := &mumbleproto.UserRemove{}
|
userremove := &mumbleproto.UserRemove{}
|
||||||
err := proto.Unmarshal(msg.buf, userremove)
|
err := proto.Unmarshal(msg.buf, userremove)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the client to be removed.
|
// Get the client to be removed.
|
||||||
|
|
@ -556,7 +557,8 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
||||||
userstate := &mumbleproto.UserState{}
|
userstate := &mumbleproto.UserState{}
|
||||||
err := proto.Unmarshal(msg.buf, userstate)
|
err := proto.Unmarshal(msg.buf, userstate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
actor, ok := server.clients[client.Session]
|
actor, ok := server.clients[client.Session]
|
||||||
|
|
@ -700,7 +702,8 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
||||||
if userstate.Texture != nil && target.user != nil {
|
if userstate.Texture != nil && target.user != nil {
|
||||||
key, err := blobstore.Put(userstate.Texture)
|
key, err := blobstore.Put(userstate.Texture)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.user.TextureBlob != key {
|
if target.user.TextureBlob != key {
|
||||||
|
|
@ -740,7 +743,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
||||||
if userstate.Comment != nil && target.user != nil {
|
if userstate.Comment != nil && target.user != nil {
|
||||||
key, err := blobstore.Put([]byte(*userstate.Comment))
|
key, err := blobstore.Put([]byte(*userstate.Comment))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.user.CommentBlob != key {
|
if target.user.CommentBlob != key {
|
||||||
|
|
@ -888,7 +891,7 @@ func (server *Server) handleBanListMessage(client *Client, msg *Message) {
|
||||||
banlist := &mumbleproto.BanList{}
|
banlist := &mumbleproto.BanList{}
|
||||||
err := proto.Unmarshal(msg.buf, banlist)
|
err := proto.Unmarshal(msg.buf, banlist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -955,7 +958,7 @@ func (server *Server) handleTextMessage(client *Client, msg *Message) {
|
||||||
txtmsg := &mumbleproto.TextMessage{}
|
txtmsg := &mumbleproto.TextMessage{}
|
||||||
err := proto.Unmarshal(msg.buf, txtmsg)
|
err := proto.Unmarshal(msg.buf, txtmsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1011,7 +1014,7 @@ func (server *Server) handleTextMessage(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove ourselves
|
// Remove ourselves
|
||||||
clients[client.Session] = nil, false
|
delete(clients, client.Session)
|
||||||
|
|
||||||
for _, target := range clients {
|
for _, target := range clients {
|
||||||
target.sendProtoMessage(&mumbleproto.TextMessage{
|
target.sendProtoMessage(&mumbleproto.TextMessage{
|
||||||
|
|
@ -1026,7 +1029,8 @@ func (server *Server) handleAclMessage(client *Client, msg *Message) {
|
||||||
acl := &mumbleproto.ACL{}
|
acl := &mumbleproto.ACL{}
|
||||||
err := proto.Unmarshal(msg.buf, acl)
|
err := proto.Unmarshal(msg.buf, acl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up the channel this ACL message operates on.
|
// Look up the channel this ACL message operates on.
|
||||||
|
|
@ -1127,7 +1131,7 @@ func (server *Server) handleAclMessage(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
for uid, _ := range group.Remove {
|
for uid, _ := range group.Remove {
|
||||||
users[uid] = true
|
users[uid] = true
|
||||||
toadd[uid] = false, false
|
delete(toadd, uid)
|
||||||
}
|
}
|
||||||
for uid, _ := range toadd {
|
for uid, _ := range toadd {
|
||||||
mpgroup.Add = append(mpgroup.Add, uint32(uid))
|
mpgroup.Add = append(mpgroup.Add, uint32(uid))
|
||||||
|
|
@ -1144,7 +1148,8 @@ func (server *Server) handleAclMessage(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.sendProtoMessage(reply); err != nil {
|
if err := client.sendProtoMessage(reply); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map the user ids in the user map to usernames of users.
|
// Map the user ids in the user map to usernames of users.
|
||||||
|
|
@ -1243,7 +1248,8 @@ func (server *Server) handleQueryUsers(client *Client, msg *Message) {
|
||||||
query := &mumbleproto.QueryUsers{}
|
query := &mumbleproto.QueryUsers{}
|
||||||
err := proto.Unmarshal(msg.buf, query)
|
err := proto.Unmarshal(msg.buf, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Printf("in handleQueryUsers")
|
server.Printf("in handleQueryUsers")
|
||||||
|
|
@ -1267,7 +1273,7 @@ func (server *Server) handleQueryUsers(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.sendProtoMessage(reply); err != nil {
|
if err := client.sendProtoMessage(reply); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1278,7 +1284,8 @@ func (server *Server) handleUserStatsMessage(client *Client, msg *Message) {
|
||||||
stats := &mumbleproto.UserStats{}
|
stats := &mumbleproto.UserStats{}
|
||||||
err := proto.Unmarshal(msg.buf, stats)
|
err := proto.Unmarshal(msg.buf, stats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if stats.Session == nil {
|
if stats.Session == nil {
|
||||||
|
|
@ -1371,7 +1378,7 @@ func (server *Server) handleUserStatsMessage(client *Client, msg *Message) {
|
||||||
// fixme(mkrautz): we don't do bandwidth tracking yet
|
// fixme(mkrautz): we don't do bandwidth tracking yet
|
||||||
|
|
||||||
if err := client.sendProtoMessage(stats); err != nil {
|
if err := client.sendProtoMessage(stats); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1381,7 +1388,8 @@ func (server *Server) handlePermissionQuery(client *Client, msg *Message) {
|
||||||
query := &mumbleproto.PermissionQuery{}
|
query := &mumbleproto.PermissionQuery{}
|
||||||
err := proto.Unmarshal(msg.buf, query)
|
err := proto.Unmarshal(msg.buf, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if query.ChannelId == nil {
|
if query.ChannelId == nil {
|
||||||
|
|
@ -1397,7 +1405,7 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
|
||||||
blobreq := &mumbleproto.RequestBlob{}
|
blobreq := &mumbleproto.RequestBlob{}
|
||||||
err := proto.Unmarshal(msg.buf, blobreq)
|
err := proto.Unmarshal(msg.buf, blobreq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1413,13 +1421,14 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
|
||||||
if target.user.HasTexture() {
|
if target.user.HasTexture() {
|
||||||
buf, err := blobstore.Get(target.user.TextureBlob)
|
buf, err := blobstore.Get(target.user.TextureBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
userstate.Reset()
|
userstate.Reset()
|
||||||
userstate.Session = proto.Uint32(uint32(target.Session))
|
userstate.Session = proto.Uint32(uint32(target.Session))
|
||||||
userstate.Texture = buf
|
userstate.Texture = buf
|
||||||
if err := client.sendProtoMessage(userstate); err != nil {
|
if err := client.sendProtoMessage(userstate); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1437,13 +1446,14 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
|
||||||
if target.user.HasComment() {
|
if target.user.HasComment() {
|
||||||
buf, err := blobstore.Get(target.user.CommentBlob)
|
buf, err := blobstore.Get(target.user.CommentBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
userstate.Reset()
|
userstate.Reset()
|
||||||
userstate.Session = proto.Uint32(uint32(target.Session))
|
userstate.Session = proto.Uint32(uint32(target.Session))
|
||||||
userstate.Comment = proto.String(string(buf))
|
userstate.Comment = proto.String(string(buf))
|
||||||
if err := client.sendProtoMessage(userstate); err != nil {
|
if err := client.sendProtoMessage(userstate); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1461,12 +1471,13 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
|
||||||
chanstate.Reset()
|
chanstate.Reset()
|
||||||
buf, err := blobstore.Get(channel.DescriptionBlob)
|
buf, err := blobstore.Get(channel.DescriptionBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
chanstate.ChannelId = proto.Uint32(uint32(channel.Id))
|
chanstate.ChannelId = proto.Uint32(uint32(channel.Id))
|
||||||
chanstate.Description = proto.String(string(buf))
|
chanstate.Description = proto.String(string(buf))
|
||||||
if err := client.sendProtoMessage(chanstate); err != nil {
|
if err := client.sendProtoMessage(chanstate); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1480,7 +1491,7 @@ func (server *Server) handleUserList(client *Client, msg *Message) {
|
||||||
userlist := &mumbleproto.UserList{}
|
userlist := &mumbleproto.UserList{}
|
||||||
err := proto.Unmarshal(msg.buf, userlist)
|
err := proto.Unmarshal(msg.buf, userlist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1502,7 +1513,7 @@ func (server *Server) handleUserList(client *Client, msg *Message) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err := client.sendProtoMessage(userlist); err != nil {
|
if err := client.sendProtoMessage(userlist); err != nil {
|
||||||
client.Panic(err.String())
|
client.Panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Rename, registration removal
|
// Rename, registration removal
|
||||||
|
|
|
||||||
39
murmurdb.go
39
murmurdb.go
|
|
@ -10,6 +10,7 @@ package main
|
||||||
// SQLite datbase into a format that Grumble can understand.
|
// SQLite datbase into a format that Grumble can understand.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"grumble/ban"
|
"grumble/ban"
|
||||||
"grumble/blobstore"
|
"grumble/blobstore"
|
||||||
"grumble/sqlite"
|
"grumble/sqlite"
|
||||||
|
|
@ -37,15 +38,15 @@ const (
|
||||||
const SQLiteSupport = true
|
const SQLiteSupport = true
|
||||||
|
|
||||||
// Import the structure of an existing Murmur SQLite database.
|
// Import the structure of an existing Murmur SQLite database.
|
||||||
func MurmurImport(filename string) (err os.Error) {
|
func MurmurImport(filename string) (err error) {
|
||||||
db, err := sqlite.Open(filename)
|
db, err := sqlite.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.String())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, err := db.Prepare("SELECT server_id FROM servers")
|
stmt, err := db.Prepare("SELECT server_id FROM servers")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.String())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverids []int64
|
var serverids []int64
|
||||||
|
|
@ -80,7 +81,7 @@ func MurmurImport(filename string) (err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Server from a Murmur SQLite database
|
// Create a new Server from a Murmur SQLite database
|
||||||
func NewServerFromSQLite(id int64, db *sqlite.Conn) (s *Server, err os.Error) {
|
func NewServerFromSQLite(id int64, db *sqlite.Conn) (s *Server, err error) {
|
||||||
s, err = NewServer(id, "", int(DefaultPort+id-1))
|
s, err = NewServer(id, "", int(DefaultPort+id-1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -125,7 +126,7 @@ func NewServerFromSQLite(id int64, db *sqlite.Conn) (s *Server, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add channel metadata (channel_info table from SQLite) by reading the SQLite database.
|
// Add channel metadata (channel_info table from SQLite) by reading the SQLite database.
|
||||||
func populateChannelInfoFromDatabase(server *Server, c *Channel, db *sqlite.Conn) os.Error {
|
func populateChannelInfoFromDatabase(server *Server, c *Channel, db *sqlite.Conn) error {
|
||||||
stmt, err := db.Prepare("SELECT value FROM channel_info WHERE server_id=? AND channel_id=? AND key=?")
|
stmt, err := db.Prepare("SELECT value FROM channel_info WHERE server_id=? AND channel_id=? AND key=?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -172,7 +173,7 @@ func populateChannelInfoFromDatabase(server *Server, c *Channel, db *sqlite.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate channel with its ACLs by reading the SQLite databse.
|
// Populate channel with its ACLs by reading the SQLite databse.
|
||||||
func populateChannelACLFromDatabase(server *Server, c *Channel, db *sqlite.Conn) os.Error {
|
func populateChannelACLFromDatabase(server *Server, c *Channel, db *sqlite.Conn) error {
|
||||||
stmt, err := db.Prepare("SELECT user_id, group_name, apply_here, apply_sub, grantpriv, revokepriv FROM acl WHERE server_id=? AND channel_id=? ORDER BY priority")
|
stmt, err := db.Prepare("SELECT user_id, group_name, apply_here, apply_sub, grantpriv, revokepriv FROM acl WHERE server_id=? AND channel_id=? ORDER BY priority")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -206,7 +207,7 @@ func populateChannelACLFromDatabase(server *Server, c *Channel, db *sqlite.Conn)
|
||||||
} else if len(Group) > 0 {
|
} else if len(Group) > 0 {
|
||||||
acl.Group = Group
|
acl.Group = Group
|
||||||
} else {
|
} else {
|
||||||
return os.NewError("Invalid ACL: Neither Group or UserId specified")
|
return errors.New("Invalid ACL: Neither Group or UserId specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
acl.Deny = Permission(Deny)
|
acl.Deny = Permission(Deny)
|
||||||
|
|
@ -218,7 +219,7 @@ func populateChannelACLFromDatabase(server *Server, c *Channel, db *sqlite.Conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate channel with groups by reading the SQLite database.
|
// Populate channel with groups by reading the SQLite database.
|
||||||
func populateChannelGroupsFromDatabase(server *Server, c *Channel, db *sqlite.Conn) os.Error {
|
func populateChannelGroupsFromDatabase(server *Server, c *Channel, db *sqlite.Conn) error {
|
||||||
stmt, err := db.Prepare("SELECT group_id, name, inherit, inheritable FROM groups WHERE server_id=? AND channel_id=?")
|
stmt, err := db.Prepare("SELECT group_id, name, inherit, inheritable FROM groups WHERE server_id=? AND channel_id=?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -281,10 +282,10 @@ func populateChannelGroupsFromDatabase(server *Server, c *Channel, db *sqlite.Co
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate the Server with Channels from the database.
|
// Populate the Server with Channels from the database.
|
||||||
func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int) os.Error {
|
func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int) error {
|
||||||
parent, exists := server.Channels[parentId]
|
parent, exists := server.Channels[parentId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("Non-existant parent")
|
return errors.New("Non-existant parent")
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt, err := db.Prepare("SELECT channel_id, name, inheritacl FROM channels WHERE server_id=? AND parent_id=?")
|
stmt, err := db.Prepare("SELECT channel_id, name, inheritacl FROM channels WHERE server_id=? AND parent_id=?")
|
||||||
|
|
@ -350,7 +351,7 @@ func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link a Server's channels together
|
// Link a Server's channels together
|
||||||
func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err os.Error) {
|
func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err error) {
|
||||||
stmt, err := db.Prepare("SELECT channel_id, link_id FROM channel_links WHERE server_id=?")
|
stmt, err := db.Prepare("SELECT channel_id, link_id FROM channel_links WHERE server_id=?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -371,12 +372,12 @@ func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||||
|
|
||||||
channel, exists := server.Channels[ChannelId]
|
channel, exists := server.Channels[ChannelId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("Attempt to perform link operation on non-existant channel.")
|
return errors.New("Attempt to perform link operation on non-existant channel.")
|
||||||
}
|
}
|
||||||
|
|
||||||
other, exists := server.Channels[LinkId]
|
other, exists := server.Channels[LinkId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("Attempt to perform link operation on non-existant channel.")
|
return errors.New("Attempt to perform link operation on non-existant channel.")
|
||||||
}
|
}
|
||||||
|
|
||||||
server.LinkChannels(channel, other)
|
server.LinkChannels(channel, other)
|
||||||
|
|
@ -385,7 +386,7 @@ func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
|
func populateUsers(server *Server, db *sqlite.Conn) (err error) {
|
||||||
// Populate the server with regular user data
|
// Populate the server with regular user data
|
||||||
stmt, err := db.Prepare("SELECT user_id, name, pw, lastchannel, texture, strftime('%s', last_active) FROM users WHERE server_id=?")
|
stmt, err := db.Prepare("SELECT user_id, name, pw, lastchannel, texture, strftime('%s', last_active) FROM users WHERE server_id=?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -413,7 +414,7 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if UserId == 0 {
|
if UserId == 0 {
|
||||||
server.cfg.Set("SuperUserPassword", "sha1$$" + SHA1Password)
|
server.cfg.Set("SuperUserPassword", "sha1$$"+SHA1Password)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := NewUser(uint32(UserId), UserName)
|
user, err := NewUser(uint32(UserId), UserName)
|
||||||
|
|
@ -488,7 +489,7 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate bans
|
// Populate bans
|
||||||
func populateBans(server *Server, db *sqlite.Conn) (err os.Error) {
|
func populateBans(server *Server, db *sqlite.Conn) (err error) {
|
||||||
stmt, err := db.Prepare("SELECT base, mask, name, hash, reason, start, duration FROM bans WHERE server_id=?")
|
stmt, err := db.Prepare("SELECT base, mask, name, hash, reason, start, duration FROM bans WHERE server_id=?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
@ -501,10 +502,10 @@ func populateBans(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||||
|
|
||||||
for stmt.Next() {
|
for stmt.Next() {
|
||||||
var (
|
var (
|
||||||
Ban ban.Ban
|
Ban ban.Ban
|
||||||
IP []byte
|
IP []byte
|
||||||
StartDate string
|
StartDate string
|
||||||
Duration int64
|
Duration int64
|
||||||
)
|
)
|
||||||
|
|
||||||
err = stmt.Scan(&IP, &Ban.Mask, &Ban.Username, &Ban.CertHash, &Ban.Reason, &StartDate, &Duration)
|
err = stmt.Scan(&IP, &Ban.Mask, &Ban.Username, &Ban.CertHash, &Ban.Reason, &StartDate, &Duration)
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "os"
|
import "errors"
|
||||||
|
|
||||||
const SQLiteSupport = false
|
const SQLiteSupport = false
|
||||||
|
|
||||||
func MurmurImport(filename string) (err os.Error) {
|
func MurmurImport(filename string) (err error) {
|
||||||
return os.NewError("no sqlite support built in")
|
return errors.New("no sqlite support built in")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// blobReader is based on the principles of the checksumReader from the archive/zip
|
// blobReader is based on the principles of the checksumReader from the archive/zip
|
||||||
|
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
// ErrHashMismatch is returned if a blobReader has read a file whose computed hash
|
// ErrHashMismatch is returned if a blobReader has read a file whose computed hash
|
||||||
// did not match its key.
|
// did not match its key.
|
||||||
var ErrHashMismatch = os.NewError("hash mismatch")
|
var ErrHashMismatch = errors.New("hash mismatch")
|
||||||
|
|
||||||
// blobReader reads a blob from disk, hashing all incoming data. On EOF, it checks
|
// blobReader reads a blob from disk, hashing all incoming data. On EOF, it checks
|
||||||
// whether the read data matches the key.
|
// whether the read data matches the key.
|
||||||
|
|
@ -28,7 +28,7 @@ type blobReader struct {
|
||||||
hash hash.Hash
|
hash hash.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBlobReader(rc io.ReadCloser, key string) (br *blobReader, err os.Error) {
|
func newBlobReader(rc io.ReadCloser, key string) (br *blobReader, err error) {
|
||||||
sum, err := hex.DecodeString(key)
|
sum, err := hex.DecodeString(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
@ -36,10 +36,10 @@ func newBlobReader(rc io.ReadCloser, key string) (br *blobReader, err os.Error)
|
||||||
return &blobReader{rc, sum, sha1.New()}, nil
|
return &blobReader{rc, sum, sha1.New()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *blobReader) Read(b []byte) (n int, err os.Error) {
|
func (r *blobReader) Read(b []byte) (n int, err error) {
|
||||||
n, err = r.rc.Read(b)
|
n, err = r.rc.Read(b)
|
||||||
r.hash.Write(b[:n])
|
r.hash.Write(b[:n])
|
||||||
if err != os.EOF {
|
if err != io.EOF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !bytes.Equal(r.sum, r.hash.Sum()) {
|
if !bytes.Equal(r.sum, r.hash.Sum()) {
|
||||||
|
|
@ -48,6 +48,6 @@ func (r *blobReader) Read(b []byte) (n int, err os.Error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *blobReader) Close() os.Error {
|
func (r *blobReader) Close() error {
|
||||||
return r.rc.Close()
|
return r.rc.Close()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ package blobstore
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -26,11 +27,11 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrLocked = os.NewError("lockfile acquired by another process")
|
ErrLocked = errors.New("lockfile acquired by another process")
|
||||||
ErrLockAcquirement = os.NewError("unable to acquire lockfile")
|
ErrLockAcquirement = errors.New("unable to acquire lockfile")
|
||||||
ErrBadFile = os.NewError("a bad file exists in the blobstore directory. unable to create container directores.")
|
ErrBadFile = errors.New("a bad file exists in the blobstore directory. unable to create container directores.")
|
||||||
ErrNoSuchKey = os.NewError("no such key")
|
ErrNoSuchKey = errors.New("no such key")
|
||||||
ErrInvalidKey = os.NewError("invalid key")
|
ErrInvalidKey = errors.New("invalid key")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -41,7 +42,7 @@ var (
|
||||||
// Open an existing, or create a new BlobStore at path.
|
// Open an existing, or create a new BlobStore at path.
|
||||||
// Path must point to a directory, and must already exist.
|
// Path must point to a directory, and must already exist.
|
||||||
// See NewBlobStore for more information.
|
// See NewBlobStore for more information.
|
||||||
func Open(path string, makeall bool) (err os.Error) {
|
func Open(path string, makeall bool) (err error) {
|
||||||
defaultMutex.Lock()
|
defaultMutex.Lock()
|
||||||
defer defaultMutex.Unlock()
|
defer defaultMutex.Unlock()
|
||||||
|
|
||||||
|
|
@ -55,7 +56,7 @@ func Open(path string, makeall bool) (err os.Error) {
|
||||||
|
|
||||||
// Close the open default BlobStore. This removes the lockfile allowing
|
// Close the open default BlobStore. This removes the lockfile allowing
|
||||||
// other processes to open the BlobStore.
|
// other processes to open the BlobStore.
|
||||||
func Close() (err os.Error) {
|
func Close() (err error) {
|
||||||
if defaultStore == nil {
|
if defaultStore == nil {
|
||||||
panic("DefaultStore not open")
|
panic("DefaultStore not open")
|
||||||
}
|
}
|
||||||
|
|
@ -71,17 +72,16 @@ func Close() (err os.Error) {
|
||||||
|
|
||||||
// Lookup a blob by its key and return a buffer containing the contents
|
// Lookup a blob by its key and return a buffer containing the contents
|
||||||
// of the blob.
|
// of the blob.
|
||||||
func Get(key string) (buf []byte, err os.Error) {
|
func Get(key string) (buf []byte, err error) {
|
||||||
return defaultStore.Get(key)
|
return defaultStore.Get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store a blob. If the blob was successfully stored, the returned key
|
// Store a blob. If the blob was successfully stored, the returned key
|
||||||
// can be used to retrieve the buf from the BlobStore.
|
// can be used to retrieve the buf from the BlobStore.
|
||||||
func Put(buf []byte) (key string, err os.Error) {
|
func Put(buf []byte) (key string, err error) {
|
||||||
return defaultStore.Put(buf)
|
return defaultStore.Put(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Open an existing, or create a new BlobStore residing at path.
|
// Open an existing, or create a new BlobStore residing at path.
|
||||||
// Path must point to a directory, and must already exist.
|
// Path must point to a directory, and must already exist.
|
||||||
//
|
//
|
||||||
|
|
@ -92,7 +92,7 @@ func Put(buf []byte) (key string, err os.Error) {
|
||||||
// some I/O operations when writing blobs. (Since the BlobStore
|
// some I/O operations when writing blobs. (Since the BlobStore
|
||||||
// knows that all directories will exist, it does not need to check
|
// knows that all directories will exist, it does not need to check
|
||||||
// whether they do, and create them if they do not.).
|
// whether they do, and create them if they do not.).
|
||||||
func NewBlobStore(path string, makeall bool) (bs *BlobStore, err os.Error) {
|
func NewBlobStore(path string, makeall bool) (bs *BlobStore, err error) {
|
||||||
// Does the directory exist?
|
// Does the directory exist?
|
||||||
dir, err := os.Open(path)
|
dir, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -130,7 +130,7 @@ func NewBlobStore(path string, makeall bool) (bs *BlobStore, err os.Error) {
|
||||||
if !fi.IsDirectory() {
|
if !fi.IsDirectory() {
|
||||||
return nil, ErrBadFile
|
return nil, ErrBadFile
|
||||||
}
|
}
|
||||||
} else if e.Error == os.ENOTDIR {
|
} else if e.Err == os.ENOTDIR {
|
||||||
return nil, ErrBadFile
|
return nil, ErrBadFile
|
||||||
}
|
}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|
@ -150,7 +150,7 @@ func NewBlobStore(path string, makeall bool) (bs *BlobStore, err os.Error) {
|
||||||
if !fi.IsDirectory() {
|
if !fi.IsDirectory() {
|
||||||
return nil, ErrBadFile
|
return nil, ErrBadFile
|
||||||
}
|
}
|
||||||
} else if e.Error == os.ENOTDIR {
|
} else if e.Err == os.ENOTDIR {
|
||||||
return nil, ErrBadFile
|
return nil, ErrBadFile
|
||||||
}
|
}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|
@ -170,14 +170,14 @@ func NewBlobStore(path string, makeall bool) (bs *BlobStore, err os.Error) {
|
||||||
|
|
||||||
// Close an open BlobStore. This removes the lockfile allowing
|
// Close an open BlobStore. This removes the lockfile allowing
|
||||||
// other processes to open the BlobStore.
|
// other processes to open the BlobStore.
|
||||||
func (bs *BlobStore) Close() (err os.Error) {
|
func (bs *BlobStore) Close() (err error) {
|
||||||
return os.Remove(bs.lockfn)
|
return os.Remove(bs.lockfn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that a given key is a valid key for the BlobStore.
|
// Checks that a given key is a valid key for the BlobStore.
|
||||||
// If it is, it returns the three components that make up the on-disk path
|
// If it is, it returns the three components that make up the on-disk path
|
||||||
// the given key can be found or should be stored at.
|
// the given key can be found or should be stored at.
|
||||||
func getKeyComponents(key string) (dir1, dir2, fn string, err os.Error) {
|
func getKeyComponents(key string) (dir1, dir2, fn string, err error) {
|
||||||
// SHA1 digests are 40 bytes long when hex-encoded
|
// SHA1 digests are 40 bytes long when hex-encoded
|
||||||
if len(key) != 40 {
|
if len(key) != 40 {
|
||||||
err = ErrInvalidKey
|
err = ErrInvalidKey
|
||||||
|
|
@ -195,7 +195,7 @@ func getKeyComponents(key string) (dir1, dir2, fn string, err os.Error) {
|
||||||
|
|
||||||
// Lookup the path hat a key would have on disk.
|
// Lookup the path hat a key would have on disk.
|
||||||
// Returns an error if the key is not a valid BlobStore key.
|
// Returns an error if the key is not a valid BlobStore key.
|
||||||
func (bs *BlobStore) pathForKey(key string) (fn string, err os.Error) {
|
func (bs *BlobStore) pathForKey(key string) (fn string, err error) {
|
||||||
dir1, dir2, rest, err := getKeyComponents(key)
|
dir1, dir2, rest, err := getKeyComponents(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
@ -207,14 +207,14 @@ func (bs *BlobStore) pathForKey(key string) (fn string, err os.Error) {
|
||||||
|
|
||||||
// Lookup a blob by its key and return a buffer containing the contents
|
// Lookup a blob by its key and return a buffer containing the contents
|
||||||
// of the blob.
|
// of the blob.
|
||||||
func (bs *BlobStore) Get(key string) (buf []byte, err os.Error) {
|
func (bs *BlobStore) Get(key string) (buf []byte, err error) {
|
||||||
fn, err := bs.pathForKey(key)
|
fn, err := bs.pathForKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Open(fn)
|
file, err := os.Open(fn)
|
||||||
if e, ok := err.(*os.PathError); ok && (e.Error == os.ENOENT || e.Error == os.ENOTDIR) {
|
if e, ok := err.(*os.PathError); ok && (e.Err == os.ENOENT || e.Err == os.ENOTDIR) {
|
||||||
err = ErrNoSuchKey
|
err = ErrNoSuchKey
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|
@ -238,7 +238,7 @@ func (bs *BlobStore) Get(key string) (buf []byte, err os.Error) {
|
||||||
|
|
||||||
// Store a blob. If the blob was successfully stored, the returned key
|
// Store a blob. If the blob was successfully stored, the returned key
|
||||||
// can be used to retrieve the buf from the BlobStore.
|
// can be used to retrieve the buf from the BlobStore.
|
||||||
func (bs *BlobStore) Put(buf []byte) (key string, err os.Error) {
|
func (bs *BlobStore) Put(buf []byte) (key string, err error) {
|
||||||
// Calculate the key for the blob. We can't really delay it more than this,
|
// Calculate the key for the blob. We can't really delay it more than this,
|
||||||
// since we need to know the key for the blob to check whether it's already on
|
// since we need to know the key for the blob to check whether it's already on
|
||||||
// disk.
|
// disk.
|
||||||
|
|
@ -263,7 +263,7 @@ func (bs *BlobStore) Put(buf []byte) (key string, err os.Error) {
|
||||||
file.Close()
|
file.Close()
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if e, ok := err.(*os.PathError); ok && (e.Error == os.ENOENT || e.Error == os.ENOTDIR) {
|
if e, ok := err.(*os.PathError); ok && (e.Err == os.ENOENT || e.Err == os.ENOTDIR) {
|
||||||
// No such file exists on disk. Ready to rock!
|
// No such file exists on disk. Ready to rock!
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
|
|
@ -315,10 +315,10 @@ func (bs *BlobStore) Put(buf []byte) (key string, err os.Error) {
|
||||||
// On Unix, it checks for EEXIST. On Windows, it checks for EEXIST
|
// On Unix, it checks for EEXIST. On Windows, it checks for EEXIST
|
||||||
// and Errno code 183 (ERROR_ALREADY_EXISTS)
|
// and Errno code 183 (ERROR_ALREADY_EXISTS)
|
||||||
func isExistError(err *os.PathError) (exists bool) {
|
func isExistError(err *os.PathError) (exists bool) {
|
||||||
if e, ok := err.Error.(os.Errno); ok && e == win32AlreadyExists {
|
if e, ok := err.Err.(os.Errno); ok && e == win32AlreadyExists {
|
||||||
exists = true
|
exists = true
|
||||||
}
|
}
|
||||||
if err.Error == os.EEXIST {
|
if err.Err == os.EEXIST {
|
||||||
exists = true
|
exists = true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ import (
|
||||||
func TestMakeAllCreateAll(t *testing.T) {
|
func TestMakeAllCreateAll(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
bs, err := NewBlobStore(dir, true)
|
bs, err := NewBlobStore(dir, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer bs.Close()
|
defer bs.Close()
|
||||||
|
|
@ -35,7 +35,7 @@ func TestMakeAllCreateAll(t *testing.T) {
|
||||||
dirname := filepath.Join(dir, hex.EncodeToString([]byte{byte(i)}), hex.EncodeToString([]byte{byte(j)}))
|
dirname := filepath.Join(dir, hex.EncodeToString([]byte{byte(i)}), hex.EncodeToString([]byte{byte(j)}))
|
||||||
fi, err := os.Stat(dirname)
|
fi, err := os.Stat(dirname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
if !fi.IsDirectory() {
|
if !fi.IsDirectory() {
|
||||||
t.Errorf("Not a directory")
|
t.Errorf("Not a directory")
|
||||||
|
|
@ -47,65 +47,65 @@ func TestMakeAllCreateAll(t *testing.T) {
|
||||||
func TestAllInvalidFiles(t *testing.T) {
|
func TestAllInvalidFiles(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
err = ioutil.WriteFile(filepath.Join(dir, "00"), []byte{0x0f, 0x00}, 0600)
|
err = ioutil.WriteFile(filepath.Join(dir, "00"), []byte{0x0f, 0x00}, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = NewBlobStore(dir, true)
|
_, err = NewBlobStore(dir, true)
|
||||||
if err == ErrBadFile {
|
if err == ErrBadFile {
|
||||||
// Success
|
// Success
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("NewBlobStore returned without error")
|
t.Error("NewBlobStore returned without error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAllInvalidFilesLevel2(t *testing.T) {
|
func TestAllInvalidFilesLevel2(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
err = os.Mkdir(filepath.Join(dir, "00"), 0700)
|
err = os.Mkdir(filepath.Join(dir, "00"), 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ioutil.WriteFile(filepath.Join(dir, "00", "00"), []byte{0x0f, 0x00}, 0600)
|
err = ioutil.WriteFile(filepath.Join(dir, "00", "00"), []byte{0x0f, 0x00}, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = NewBlobStore(dir, true)
|
_, err = NewBlobStore(dir, true)
|
||||||
if err == ErrBadFile {
|
if err == ErrBadFile {
|
||||||
// Success
|
// Success
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("NewBlobStore returned without error")
|
t.Error("NewBlobStore returned without error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStoreRetrieve(t *testing.T) {
|
func TestStoreRetrieve(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
bs, err := NewBlobStore(dir, false)
|
bs, err := NewBlobStore(dir, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer bs.Close()
|
defer bs.Close()
|
||||||
|
|
@ -114,13 +114,13 @@ func TestStoreRetrieve(t *testing.T) {
|
||||||
|
|
||||||
key, err := bs.Put(data)
|
key, err := bs.Put(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
recv, err := bs.Get(key)
|
recv, err := bs.Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(recv, data) {
|
if !bytes.Equal(recv, data) {
|
||||||
|
|
@ -131,14 +131,14 @@ func TestStoreRetrieve(t *testing.T) {
|
||||||
func TestReadNonExistantKey(t *testing.T) {
|
func TestReadNonExistantKey(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
bs, err := NewBlobStore(dir, false)
|
bs, err := NewBlobStore(dir, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer bs.Close()
|
defer bs.Close()
|
||||||
|
|
@ -148,7 +148,7 @@ func TestReadNonExistantKey(t *testing.T) {
|
||||||
key := hex.EncodeToString(h.Sum())
|
key := hex.EncodeToString(h.Sum())
|
||||||
buf, err := bs.Get(key)
|
buf, err := bs.Get(key)
|
||||||
if err != ErrNoSuchKey {
|
if err != ErrNoSuchKey {
|
||||||
t.Errorf("Expected no such key %v, found it anyway. (buf=%v, err=%v)", key, buf, err)
|
t.Error("Expected no such key %v, found it anyway. (buf=%v, err=%v)", key, buf, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,13 +156,13 @@ func TestReadNonExistantKey(t *testing.T) {
|
||||||
func TestReadInvalidKeyLength(t *testing.T) {
|
func TestReadInvalidKeyLength(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
bs, err := NewBlobStore(dir, false)
|
bs, err := NewBlobStore(dir, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer bs.Close()
|
defer bs.Close()
|
||||||
|
|
@ -174,7 +174,7 @@ func TestReadInvalidKeyLength(t *testing.T) {
|
||||||
|
|
||||||
_, err = bs.Get(key)
|
_, err = bs.Get(key)
|
||||||
if err != ErrInvalidKey {
|
if err != ErrInvalidKey {
|
||||||
t.Errorf("Expected invalid key for %v, got %v", key, err)
|
t.Error("Expected invalid key for %v, got %v", key, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -182,14 +182,14 @@ func TestReadInvalidKeyLength(t *testing.T) {
|
||||||
func TestReadInvalidKeyNonHex(t *testing.T) {
|
func TestReadInvalidKeyNonHex(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
bs, err := NewBlobStore(dir, false)
|
bs, err := NewBlobStore(dir, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer bs.Close()
|
defer bs.Close()
|
||||||
|
|
@ -209,26 +209,26 @@ func TestReadInvalidKeyNonHex(t *testing.T) {
|
||||||
func TestDefaultBlobStore(t *testing.T) {
|
func TestDefaultBlobStore(t *testing.T) {
|
||||||
dir, err := ioutil.TempDir("", "blobstore")
|
dir, err := ioutil.TempDir("", "blobstore")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
err = Open(dir, false)
|
err = Open(dir, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := []byte{0xf, 0x0, 0x0, 0xb, 0xa, 0xf}
|
data := []byte{0xf, 0x0, 0x0, 0xb, 0xa, 0xf}
|
||||||
|
|
||||||
key, err := Put(data)
|
key, err := Put(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchedData, err := Get(key)
|
fetchedData, err := Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(fetchedData, data) {
|
if !bytes.Equal(fetchedData, data) {
|
||||||
|
|
|
||||||
|
|
@ -1,73 +1,73 @@
|
||||||
// Copyright (c) 2011 The Grumble Authors
|
// Copyright (c) 2011 The Grumble Authors
|
||||||
// The use of this source code is goverened by a BSD-style
|
// The use of this source code is goverened by a BSD-style
|
||||||
// license that can be found in the LICENSE-file.
|
// license that can be found in the LICENSE-file.
|
||||||
|
|
||||||
package blobstore
|
package blobstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"os"
|
||||||
"io/ioutil"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Acquire lockfile at path.
|
// Acquire lockfile at path.
|
||||||
func AcquireLockFile(path string) os.Error {
|
func AcquireLockFile(path string) error {
|
||||||
dir, fn := filepath.Split(path)
|
dir, fn := filepath.Split(path)
|
||||||
lockfn := filepath.Join(dir, fn)
|
lockfn := filepath.Join(dir, fn)
|
||||||
|
|
||||||
lockfile, err := os.OpenFile(lockfn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
|
lockfile, err := os.OpenFile(lockfn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
|
||||||
if e, ok := err.(*os.PathError); ok && e.Error == os.EEXIST {
|
if e, ok := err.(*os.PathError); ok && e.Err == os.EEXIST {
|
||||||
content, err := ioutil.ReadFile(lockfn)
|
content, err := ioutil.ReadFile(lockfn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pid, err := strconv.Atoi(string(content))
|
pid, err := strconv.Atoi(string(content))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if syscall.Kill(pid, 0) == 0 {
|
if syscall.Kill(pid, 0) == 0 {
|
||||||
return ErrLocked
|
return ErrLocked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lockfile, err = ioutil.TempFile(dir, "lock")
|
lockfile, err = ioutil.TempFile(dir, "lock")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid()))
|
_, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lockfile.Close()
|
lockfile.Close()
|
||||||
return ErrLockAcquirement
|
return ErrLockAcquirement
|
||||||
}
|
}
|
||||||
|
|
||||||
curfn := lockfile.Name()
|
curfn := lockfile.Name()
|
||||||
|
|
||||||
err = lockfile.Close()
|
err = lockfile.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Rename(curfn, lockfn)
|
err = os.Rename(curfn, lockfn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(curfn)
|
os.Remove(curfn)
|
||||||
return ErrLockAcquirement
|
return ErrLockAcquirement
|
||||||
}
|
}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
_, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid()))
|
_, err = lockfile.WriteString(strconv.Itoa(syscall.Getpid()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
lockfile.Close()
|
lockfile.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release lockfile at path.
|
// Release lockfile at path.
|
||||||
func ReleaseLockFile(path string) os.Error {
|
func ReleaseLockFile(path string) error {
|
||||||
return os.Remove(path)
|
return os.Remove(path)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,26 @@
|
||||||
// Copyright (c) 2011 The Grumble Authors
|
// Copyright (c) 2011 The Grumble Authors
|
||||||
// The use of this source code is goverened by a BSD-style
|
// The use of this source code is goverened by a BSD-style
|
||||||
// license that can be found in the LICENSE-file.
|
// license that can be found in the LICENSE-file.
|
||||||
|
|
||||||
package blobstore
|
package blobstore
|
||||||
|
|
||||||
import (
|
import "syscall"
|
||||||
"os"
|
|
||||||
"syscall"
|
const (
|
||||||
)
|
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
||||||
|
)
|
||||||
const (
|
|
||||||
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
|
||||||
)
|
|
||||||
|
|
||||||
// Acquire a lockfile at path.
|
// Acquire a lockfile at path.
|
||||||
func AcquireLockFile(path string) os.Error {
|
func AcquireLockFile(path string) error {
|
||||||
handle, _ := syscall.CreateFile(syscall.StringToUTF16Ptr(path), syscall.GENERIC_WRITE, 0, nil, syscall.CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0)
|
handle, _ := syscall.CreateFile(syscall.StringToUTF16Ptr(path), syscall.GENERIC_WRITE, 0, nil, syscall.CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0)
|
||||||
if handle < 0 {
|
if handle < 0 {
|
||||||
return ErrLocked
|
return ErrLocked
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the lockfile at path.
|
// Release the lockfile at path.
|
||||||
func ReleaseLockFile(path string) os.Error {
|
func ReleaseLockFile(path string) error {
|
||||||
// No-op because we use FLAG_DELETE_ON_CLOSE.
|
// No-op because we use FLAG_DELETE_ON_CLOSE.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ package cryptstate
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"os"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -20,27 +20,27 @@ type CryptState struct {
|
||||||
DecryptIV [aes.BlockSize]byte
|
DecryptIV [aes.BlockSize]byte
|
||||||
decryptHistory [DecryptHistorySize]byte
|
decryptHistory [DecryptHistorySize]byte
|
||||||
|
|
||||||
LastGoodTime int64
|
LastGoodTime int64
|
||||||
|
|
||||||
Good uint32
|
Good uint32
|
||||||
Late uint32
|
Late uint32
|
||||||
Lost uint32
|
Lost uint32
|
||||||
Resync uint32
|
Resync uint32
|
||||||
RemoteGood uint32
|
RemoteGood uint32
|
||||||
RemoteLate uint32
|
RemoteLate uint32
|
||||||
RemoteLost uint32
|
RemoteLost uint32
|
||||||
RemoteResync uint32
|
RemoteResync uint32
|
||||||
|
|
||||||
cipher *aes.Cipher
|
cipher *aes.Cipher
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() (cs *CryptState, err os.Error) {
|
func New() (cs *CryptState, err error) {
|
||||||
cs = new(CryptState)
|
cs = new(CryptState)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CryptState) GenerateKey() (err os.Error) {
|
func (cs *CryptState) GenerateKey() (err error) {
|
||||||
rand.Read(cs.RawKey[0:])
|
rand.Read(cs.RawKey[0:])
|
||||||
rand.Read(cs.EncryptIV[0:])
|
rand.Read(cs.EncryptIV[0:])
|
||||||
rand.Read(cs.DecryptIV[0:])
|
rand.Read(cs.DecryptIV[0:])
|
||||||
|
|
@ -53,19 +53,19 @@ func (cs *CryptState) GenerateKey() (err os.Error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CryptState) SetKey(key []byte, eiv []byte, div []byte) (err os.Error) {
|
func (cs *CryptState) SetKey(key []byte, eiv []byte, div []byte) (err error) {
|
||||||
if copy(cs.RawKey[0:], key[0:]) != aes.BlockSize {
|
if copy(cs.RawKey[0:], key[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Unable to copy key")
|
err = errors.New("Unable to copy key")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if copy(cs.EncryptIV[0:], eiv[0:]) != aes.BlockSize {
|
if copy(cs.EncryptIV[0:], eiv[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Unable to copy EIV")
|
err = errors.New("Unable to copy EIV")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if copy(cs.DecryptIV[0:], div[0:]) != aes.BlockSize {
|
if copy(cs.DecryptIV[0:], div[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Unable to copy DIV")
|
err = errors.New("Unable to copy DIV")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,15 +77,15 @@ func (cs *CryptState) SetKey(key []byte, eiv []byte, div []byte) (err os.Error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
func (cs *CryptState) Decrypt(dst, src []byte) (err error) {
|
||||||
if len(src) < 4 {
|
if len(src) < 4 {
|
||||||
err = os.NewError("Crypted length too short to decrypt")
|
err = errors.New("Crypted length too short to decrypt")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
plain_len := len(src) - 4
|
plain_len := len(src) - 4
|
||||||
if len(dst) != plain_len {
|
if len(dst) != plain_len {
|
||||||
err = os.NewError("plain_len and src len mismatch")
|
err = errors.New("plain_len and src len mismatch")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
||||||
restore = false
|
restore = false
|
||||||
|
|
||||||
if copy(saveiv[0:], cs.DecryptIV[0:]) != aes.BlockSize {
|
if copy(saveiv[0:], cs.DecryptIV[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Copy failed")
|
err = errors.New("Copy failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = os.NewError("invalid ivbyte")
|
err = errors.New("invalid ivbyte")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Out of order or repeat
|
// Out of order or repeat
|
||||||
|
|
@ -162,13 +162,13 @@ func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = os.NewError("No matching ivbyte")
|
err = errors.New("No matching ivbyte")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cs.decryptHistory[cs.DecryptIV[0]] == cs.DecryptIV[0] {
|
if cs.decryptHistory[cs.DecryptIV[0]] == cs.DecryptIV[0] {
|
||||||
if copy(cs.DecryptIV[0:], saveiv[0:]) != aes.BlockSize {
|
if copy(cs.DecryptIV[0:], saveiv[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Failed to copy aes.BlockSize bytes")
|
err = errors.New("Failed to copy aes.BlockSize bytes")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,10 +179,10 @@ func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
if tag[i] != src[i+1] {
|
if tag[i] != src[i+1] {
|
||||||
if copy(cs.DecryptIV[0:], saveiv[0:]) != aes.BlockSize {
|
if copy(cs.DecryptIV[0:], saveiv[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Error while trying to recover from error")
|
err = errors.New("Error while trying to recover from error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = os.NewError("tag mismatch")
|
err = errors.New("tag mismatch")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +191,7 @@ func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
||||||
|
|
||||||
if restore {
|
if restore {
|
||||||
if copy(cs.DecryptIV[0:], saveiv[0:]) != aes.BlockSize {
|
if copy(cs.DecryptIV[0:], saveiv[0:]) != aes.BlockSize {
|
||||||
err = os.NewError("Error while trying to recover IV")
|
err = errors.New("Error while trying to recover IV")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -262,7 +262,7 @@ func times3(block []byte) {
|
||||||
block[aes.BlockSize-1] ^= ((block[aes.BlockSize-1] << 1) ^ (carry * 135))
|
block[aes.BlockSize-1] ^= ((block[aes.BlockSize-1] << 1) ^ (carry * 135))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CryptState) OCBEncrypt(dst []byte, src []byte, nonce []byte, tag []byte) (err os.Error) {
|
func (cs *CryptState) OCBEncrypt(dst []byte, src []byte, nonce []byte, tag []byte) (err error) {
|
||||||
var delta [aes.BlockSize]byte
|
var delta [aes.BlockSize]byte
|
||||||
var checksum [aes.BlockSize]byte
|
var checksum [aes.BlockSize]byte
|
||||||
var tmp [aes.BlockSize]byte
|
var tmp [aes.BlockSize]byte
|
||||||
|
|
@ -292,17 +292,17 @@ func (cs *CryptState) OCBEncrypt(dst []byte, src []byte, nonce []byte, tag []byt
|
||||||
cs.cipher.Encrypt(pad[0:], tmp[0:])
|
cs.cipher.Encrypt(pad[0:], tmp[0:])
|
||||||
copied := copy(tmp[0:], src[off:])
|
copied := copy(tmp[0:], src[off:])
|
||||||
if copied != remain {
|
if copied != remain {
|
||||||
err = os.NewError("Copy failed")
|
err = errors.New("Copy failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if copy(tmp[copied:], pad[copied:]) != (aes.BlockSize - remain) {
|
if copy(tmp[copied:], pad[copied:]) != (aes.BlockSize - remain) {
|
||||||
err = os.NewError("Copy failed")
|
err = errors.New("Copy failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xor(checksum[0:], checksum[0:], tmp[0:])
|
xor(checksum[0:], checksum[0:], tmp[0:])
|
||||||
xor(tmp[0:], pad[0:], tmp[0:])
|
xor(tmp[0:], pad[0:], tmp[0:])
|
||||||
if copy(dst[off:], tmp[0:]) != remain {
|
if copy(dst[off:], tmp[0:]) != remain {
|
||||||
err = os.NewError("Copy failed")
|
err = errors.New("Copy failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ func (cs *CryptState) OCBEncrypt(dst []byte, src []byte, nonce []byte, tag []byt
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CryptState) OCBDecrypt(plain []byte, encrypted []byte, nonce []byte, tag []byte) (err os.Error) {
|
func (cs *CryptState) OCBDecrypt(plain []byte, encrypted []byte, nonce []byte, tag []byte) (err error) {
|
||||||
var checksum [aes.BlockSize]byte
|
var checksum [aes.BlockSize]byte
|
||||||
var delta [aes.BlockSize]byte
|
var delta [aes.BlockSize]byte
|
||||||
var tmp [aes.BlockSize]byte
|
var tmp [aes.BlockSize]byte
|
||||||
|
|
@ -344,14 +344,14 @@ func (cs *CryptState) OCBDecrypt(plain []byte, encrypted []byte, nonce []byte, t
|
||||||
zeros(tmp[0:])
|
zeros(tmp[0:])
|
||||||
copied := copy(tmp[0:remain], encrypted[off:off+remain])
|
copied := copy(tmp[0:remain], encrypted[off:off+remain])
|
||||||
if copied != remain {
|
if copied != remain {
|
||||||
err = os.NewError("Copy failed")
|
err = errors.New("Copy failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xor(tmp[0:], tmp[0:], pad[0:])
|
xor(tmp[0:], tmp[0:], pad[0:])
|
||||||
xor(checksum[0:], checksum[0:], tmp[0:])
|
xor(checksum[0:], checksum[0:], tmp[0:])
|
||||||
copied = copy(plain[off:off+remain], tmp[0:remain])
|
copied = copy(plain[off:off+remain], tmp[0:remain])
|
||||||
if copied != remain {
|
if copied != remain {
|
||||||
err = os.NewError("Copy failed")
|
err = errors.New("Copy failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,18 @@
|
||||||
|
|
||||||
package freezer
|
package freezer
|
||||||
|
|
||||||
import "os"
|
import "errors"
|
||||||
|
|
||||||
// Writer errors
|
// Writer errors
|
||||||
var (
|
var (
|
||||||
ErrTxGroupFull = os.NewError("transction group is full")
|
ErrTxGroupFull = errors.New("transction group is full")
|
||||||
ErrTxGroupValueTooBig = os.NewError("value too big to put inside the txgroup")
|
ErrTxGroupValueTooBig = errors.New("value too big to put inside the txgroup")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Walker errors
|
// Walker errors
|
||||||
var (
|
var (
|
||||||
ErrUnexpectedEndOfRecord = os.NewError("unexpected end of record")
|
ErrUnexpectedEndOfRecord = errors.New("unexpected end of record")
|
||||||
ErrCRC32Mismatch = os.NewError("CRC32 mismatch")
|
ErrCRC32Mismatch = errors.New("CRC32 mismatch")
|
||||||
ErrRemainingBytesForRecord = os.NewError("remaining bytes in record")
|
ErrRemainingBytesForRecord = errors.New("remaining bytes in record")
|
||||||
ErrRecordTooBig = os.NewError("the record in the file is too big")
|
ErrRecordTooBig = errors.New("the record in the file is too big")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testValues []interface{} = []interface{} {
|
var testValues []interface{} = []interface{}{
|
||||||
&ConfigKeyValuePair{Key: proto.String("Foo")},
|
&ConfigKeyValuePair{Key: proto.String("Foo")},
|
||||||
&BanList{Bans: []*Ban{ &Ban{ Mask: proto.Uint32(32) } } },
|
&BanList{Bans: []*Ban{&Ban{Mask: proto.Uint32(32)}}},
|
||||||
&User{Id: proto.Uint32(0), Name: proto.String("SuperUser")},
|
&User{Id: proto.Uint32(0), Name: proto.String("SuperUser")},
|
||||||
&UserRemove{Id: proto.Uint32(0)},
|
&UserRemove{Id: proto.Uint32(0)},
|
||||||
&Channel{Id: proto.Uint32(0), Name: proto.String("RootChannel")},
|
&Channel{Id: proto.Uint32(0), Name: proto.String("RootChannel")},
|
||||||
|
|
@ -25,7 +25,7 @@ var testValues []interface{} = []interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a byet slice representing an entry in a Tx record
|
// Generate a byet slice representing an entry in a Tx record
|
||||||
func genTxValue(kind uint16, val []byte) (chunk []byte, crc32sum uint32, err os.Error) {
|
func genTxValue(kind uint16, val []byte) (chunk []byte, crc32sum uint32, err error) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
err = binary.Write(buf, binary.LittleEndian, kind)
|
err = binary.Write(buf, binary.LittleEndian, kind)
|
||||||
|
|
@ -53,10 +53,10 @@ func genTxValue(kind uint16, val []byte) (chunk []byte, crc32sum uint32, err os.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the header of a Tx record
|
// Generate the header of a Tx record
|
||||||
func genTestCaseHeader(chunk []byte, numops uint32, crc32sum uint32) (r io.Reader, err os.Error) {
|
func genTestCaseHeader(chunk []byte, numops uint32, crc32sum uint32) (r io.Reader, err error) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
err = binary.Write(buf, binary.LittleEndian, uint32(4 + 4 + len(chunk)))
|
err = binary.Write(buf, binary.LittleEndian, uint32(4+4+len(chunk)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -101,9 +101,9 @@ func TestLogging(t *testing.T) {
|
||||||
defer os.Remove("logging.log")
|
defer os.Remove("logging.log")
|
||||||
|
|
||||||
for _, val := range testValues {
|
for _, val := range testValues {
|
||||||
err = l.Put(val)
|
err = l.Put(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -117,13 +117,13 @@ func TestLogging(t *testing.T) {
|
||||||
i := 0
|
i := 0
|
||||||
for {
|
for {
|
||||||
entries, err := walker.Next()
|
entries, err := walker.Next()
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(entries) != 1 {
|
if len(entries) != 1 {
|
||||||
t.Error("> 1 entry in log tx")
|
t.Error("> 1 entry in log tx")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +157,7 @@ func TestCRC32MismatchLog(t *testing.T) {
|
||||||
t.Errorf("exepcted CRC32 mismatch, got %v", err)
|
t.Errorf("exepcted CRC32 mismatch, got %v", err)
|
||||||
}
|
}
|
||||||
_, err = walker.Next()
|
_, err = walker.Next()
|
||||||
if err != os.EOF {
|
if err != io.EOF {
|
||||||
t.Errorf("expected EOF, got %v", err)
|
t.Errorf("expected EOF, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +187,7 @@ func TestUnknownTypeDecode(t *testing.T) {
|
||||||
t.Errorf("expected empty entries and non-nil err (got %v entries and %v)", len(entries), err)
|
t.Errorf("expected empty entries and non-nil err (got %v entries and %v)", len(entries), err)
|
||||||
}
|
}
|
||||||
_, err = walker.Next()
|
_, err = walker.Next()
|
||||||
if err != os.EOF {
|
if err != io.EOF {
|
||||||
t.Errorf("expected EOF, got %v", err)
|
t.Errorf("expected EOF, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +223,7 @@ func TestTrailingBytesTxRecord(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = walker.Next()
|
_, err = walker.Next()
|
||||||
if err != os.EOF {
|
if err != io.EOF {
|
||||||
t.Errorf("expected EOF, got %v", err)
|
t.Errorf("expected EOF, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +232,7 @@ func TestTrailingBytesTxRecord(t *testing.T) {
|
||||||
// A TxRecord can hold 255 entries, and each of those can be
|
// A TxRecord can hold 255 entries, and each of those can be
|
||||||
// up to 16KB.
|
// up to 16KB.
|
||||||
func TestTooBigTxRecord(t *testing.T) {
|
func TestTooBigTxRecord(t *testing.T) {
|
||||||
bigValue := make([]byte, math.MaxUint16*math.MaxUint8 + 4)
|
bigValue := make([]byte, math.MaxUint16*math.MaxUint8+4)
|
||||||
r, err := genTestCaseHeader(bigValue, 1, 0)
|
r, err := genTestCaseHeader(bigValue, 1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|
@ -242,7 +242,7 @@ func TestTooBigTxRecord(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = walker.Next()
|
_, err = walker.Next()
|
||||||
if err != ErrRecordTooBig {
|
if err != ErrRecordTooBig {
|
||||||
t.Errorf("expected ErrRecordTooBig, got %v", err)
|
t.Errorf("expected ErrRecordTooBig, got %v", err)
|
||||||
|
|
@ -265,7 +265,7 @@ func TestTxGroupCapacityEnforcement(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i <= 255; i++ {
|
for i := 0; i <= 255; i++ {
|
||||||
entry := testValues[i % len(testValues)]
|
entry := testValues[i%len(testValues)]
|
||||||
err = tx.Put(entry)
|
err = tx.Put(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|
@ -277,4 +277,4 @@ func TestTxGroupCapacityEnforcement(t *testing.T) {
|
||||||
if err != ErrTxGroupFull {
|
if err != ErrTxGroupFull {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ import (
|
||||||
|
|
||||||
// Checks whether the error err is an EOF
|
// Checks whether the error err is an EOF
|
||||||
// error.
|
// error.
|
||||||
func isEOF(err os.Error) bool {
|
func isEOF(err error) bool {
|
||||||
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -52,9 +52,9 @@ func newTxReader(r io.Reader) *txReader {
|
||||||
|
|
||||||
// walkReader's Read method. Reads from walkReader's Reader
|
// walkReader's Read method. Reads from walkReader's Reader
|
||||||
// and checksums while reading.
|
// and checksums while reading.
|
||||||
func (txr *txReader) Read(p []byte) (n int, err os.Error) {
|
func (txr *txReader) Read(p []byte) (n int, err error) {
|
||||||
n, err = txr.r.Read(p)
|
n, err = txr.r.Read(p)
|
||||||
if err != nil && err != os.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
txr.consumed += n
|
txr.consumed += n
|
||||||
|
|
@ -80,7 +80,7 @@ func (txr *txReader) Consumed() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Walker that iterates over the entries of the given log file.
|
// Create a new Walker that iterates over the entries of the given log file.
|
||||||
func NewFileWalker(fn string) (walker *Walker, err os.Error) {
|
func NewFileWalker(fn string) (walker *Walker, err error) {
|
||||||
f, err := os.Open(fn)
|
f, err := os.Open(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -93,7 +93,7 @@ func NewFileWalker(fn string) (walker *Walker, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Walker that iterates over the log entries of a given Reader.
|
// Create a new Walker that iterates over the log entries of a given Reader.
|
||||||
func NewReaderWalker(r io.Reader) (walker *Walker, err os.Error) {
|
func NewReaderWalker(r io.Reader) (walker *Walker, err error) {
|
||||||
walker = new(Walker)
|
walker = new(Walker)
|
||||||
walker.r = r
|
walker.r = r
|
||||||
return walker, nil
|
return walker, nil
|
||||||
|
|
@ -108,18 +108,18 @@ func NewReaderWalker(r io.Reader) (walker *Walker, err os.Error) {
|
||||||
//
|
//
|
||||||
// On error, Next returns a nil slice and a non-nil err.
|
// On error, Next returns a nil slice and a non-nil err.
|
||||||
// When the end of the file is reached, Next returns nil, os.EOF.
|
// When the end of the file is reached, Next returns nil, os.EOF.
|
||||||
func (walker *Walker) Next() (entries []interface{}, err os.Error) {
|
func (walker *Walker) Next() (entries []interface{}, err error) {
|
||||||
var (
|
var (
|
||||||
remainBytes uint32
|
remainBytes uint32
|
||||||
remainOps uint32
|
remainOps uint32
|
||||||
crcsum uint32
|
crcsum uint32
|
||||||
kind uint16
|
kind uint16
|
||||||
length uint16
|
length uint16
|
||||||
)
|
)
|
||||||
|
|
||||||
err = binary.Read(walker.r, binary.LittleEndian, &remainBytes)
|
err = binary.Read(walker.r, binary.LittleEndian, &remainBytes)
|
||||||
if isEOF(err) {
|
if isEOF(err) {
|
||||||
return nil, os.EOF
|
return nil, io.EOF
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +128,7 @@ func (walker *Walker) Next() (entries []interface{}, err os.Error) {
|
||||||
return nil, ErrUnexpectedEndOfRecord
|
return nil, ErrUnexpectedEndOfRecord
|
||||||
}
|
}
|
||||||
if remainBytes-8 > math.MaxUint8*math.MaxUint16 {
|
if remainBytes-8 > math.MaxUint8*math.MaxUint16 {
|
||||||
return nil, ErrRecordTooBig
|
return nil, ErrRecordTooBig
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Read(walker.r, binary.LittleEndian, &remainOps)
|
err = binary.Read(walker.r, binary.LittleEndian, &remainOps)
|
||||||
|
|
@ -140,7 +140,7 @@ func (walker *Walker) Next() (entries []interface{}, err os.Error) {
|
||||||
|
|
||||||
err = binary.Read(walker.r, binary.LittleEndian, &crcsum)
|
err = binary.Read(walker.r, binary.LittleEndian, &crcsum)
|
||||||
if isEOF(err) {
|
if isEOF(err) {
|
||||||
return nil, ErrUnexpectedEndOfRecord
|
return nil, ErrUnexpectedEndOfRecord
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -151,14 +151,14 @@ func (walker *Walker) Next() (entries []interface{}, err os.Error) {
|
||||||
for remainOps > 0 {
|
for remainOps > 0 {
|
||||||
err = binary.Read(reader, binary.LittleEndian, &kind)
|
err = binary.Read(reader, binary.LittleEndian, &kind)
|
||||||
if isEOF(err) {
|
if isEOF(err) {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Read(reader, binary.LittleEndian, &length)
|
err = binary.Read(reader, binary.LittleEndian, &length)
|
||||||
if isEOF(err) {
|
if isEOF(err) {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ func (walker *Walker) Next() (entries []interface{}, err os.Error) {
|
||||||
buf := make([]byte, length)
|
buf := make([]byte, length)
|
||||||
_, err = io.ReadFull(reader, buf)
|
_, err = io.ReadFull(reader, buf)
|
||||||
if isEOF(err) {
|
if isEOF(err) {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,21 +37,21 @@ import (
|
||||||
// whole transaction group. In case of a failure, none of the
|
// whole transaction group. In case of a failure, none of the
|
||||||
// entries of a transaction will be applied.
|
// entries of a transaction will be applied.
|
||||||
type Log struct {
|
type Log struct {
|
||||||
wc io.WriteCloser
|
wc io.WriteCloser
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type LogTx represents a transaction in the log.
|
// Type LogTx represents a transaction in the log.
|
||||||
// Transactions can be used to group several changes into an
|
// Transactions can be used to group several changes into an
|
||||||
// atomic entity in the log file.
|
// atomic entity in the log file.
|
||||||
type LogTx struct {
|
type LogTx struct {
|
||||||
log *Log
|
log *Log
|
||||||
crc hash.Hash32
|
crc hash.Hash32
|
||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
numops int
|
numops int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new log file
|
// Create a new log file
|
||||||
func NewLogFile(fn string) (*Log, os.Error) {
|
func NewLogFile(fn string) (*Log, error) {
|
||||||
f, err := os.Create(fn)
|
f, err := os.Create(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -64,7 +64,7 @@ func NewLogFile(fn string) (*Log, os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close a Log
|
// Close a Log
|
||||||
func (log *Log) Close() os.Error {
|
func (log *Log) Close() error {
|
||||||
return log.wc.Close()
|
return log.wc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ func (log *Log) Close() os.Error {
|
||||||
// This method implicitly creates a transaction
|
// This method implicitly creates a transaction
|
||||||
// group for this single Put operation. It is merely
|
// group for this single Put operation. It is merely
|
||||||
// a convenience wrapper.
|
// a convenience wrapper.
|
||||||
func (log *Log) Put(value interface{}) (err os.Error) {
|
func (log *Log) Put(value interface{}) (err error) {
|
||||||
tx := log.BeginTx()
|
tx := log.BeginTx()
|
||||||
err = tx.Put(value)
|
err = tx.Put(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -94,7 +94,7 @@ func (log *Log) BeginTx() *LogTx {
|
||||||
// Append a log entry to the transaction.
|
// Append a log entry to the transaction.
|
||||||
// The transaction's log entries will not be persisted to
|
// The transaction's log entries will not be persisted to
|
||||||
// the log until the Commit has been called on the transaction.
|
// the log until the Commit has been called on the transaction.
|
||||||
func (tx *LogTx) Put(value interface{}) (err os.Error) {
|
func (tx *LogTx) Put(value interface{}) (err error) {
|
||||||
var (
|
var (
|
||||||
buf []byte
|
buf []byte
|
||||||
kind typeKind
|
kind typeKind
|
||||||
|
|
@ -155,17 +155,17 @@ func (tx *LogTx) Put(value interface{}) (err os.Error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.numops += 1;
|
tx.numops += 1
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit all changes of the transaction to the log
|
// Commit all changes of the transaction to the log
|
||||||
// as a single atomic entry.
|
// as a single atomic entry.
|
||||||
func (tx *LogTx) Commit() (err os.Error) {
|
func (tx *LogTx) Commit() (err error) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
err = binary.Write(buf, binary.LittleEndian, uint32(4 + 4 + tx.buf.Len()))
|
err = binary.Write(buf, binary.LittleEndian, uint32(4+4+tx.buf.Len()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -191,4 +191,4 @@ func (tx *LogTx) Commit() (err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ package htmlfilter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
"errors"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"xml"
|
"xml"
|
||||||
)
|
)
|
||||||
|
|
@ -24,12 +25,12 @@ var defaultOptions Options = Options{
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrExceedsTextMessageLength = os.NewError("Exceeds text message length")
|
ErrExceedsTextMessageLength = errors.New("Exceeds text message length")
|
||||||
ErrExceedsImageMessageLength = os.NewError("Exceeds image message length")
|
ErrExceedsImageMessageLength = errors.New("Exceeds image message length")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filter text according to options.
|
// Filter text according to options.
|
||||||
func Filter(text string, options *Options) (filtered string, err os.Error) {
|
func Filter(text string, options *Options) (filtered string, err error) {
|
||||||
// This function filters incoming text from clients according to the three options:
|
// This function filters incoming text from clients according to the three options:
|
||||||
//
|
//
|
||||||
// StripHTML:
|
// StripHTML:
|
||||||
|
|
@ -64,7 +65,7 @@ func Filter(text string, options *Options) (filtered string, err os.Error) {
|
||||||
parser.Entity = xml.HTMLEntity
|
parser.Entity = xml.HTMLEntity
|
||||||
for {
|
for {
|
||||||
tok, err := parser.Token()
|
tok, err := parser.Token()
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -117,7 +118,7 @@ func Filter(text string, options *Options) (filtered string, err os.Error) {
|
||||||
parser.Entity = xml.HTMLEntity
|
parser.Entity = xml.HTMLEntity
|
||||||
for {
|
for {
|
||||||
tok, err := parser.Token()
|
tok, err := parser.Token()
|
||||||
if err == os.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func (cfg *Config) Set(key string, value string) {
|
||||||
func (cfg *Config) Reset(key string) {
|
func (cfg *Config) Reset(key string) {
|
||||||
cfg.mutex.Lock()
|
cfg.mutex.Lock()
|
||||||
defer cfg.mutex.Unlock()
|
defer cfg.mutex.Unlock()
|
||||||
cfg.cfgMap[key] = "", false
|
delete(cfg.cfgMap, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of a specific config key encoded as a string
|
// Get the value of a specific config key encoded as a string
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ func (pool *SessionPool) Reclaim(id uint32) {
|
||||||
if !inUse {
|
if !inUse {
|
||||||
panic("Attempt to reclaim invalid session ID")
|
panic("Attempt to reclaim invalid session ID")
|
||||||
}
|
}
|
||||||
pool.used[id] = false, false
|
delete(pool.used, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.unused = append(pool.unused, id)
|
pool.unused = append(pool.unused, id)
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,18 @@ static int my_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Errno int
|
type Errno int
|
||||||
|
|
||||||
func (e Errno) String() string {
|
func (e Errno) Error() string {
|
||||||
s := errText[e]
|
s := errText[e]
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return fmt.Sprintf("errno %d", int(e))
|
return fmt.Sprintf("errno %d", int(e))
|
||||||
|
|
@ -47,76 +48,76 @@ func (e Errno) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrError os.Error = Errno(1) // /* SQL error or missing database */
|
ErrError error = Errno(1) // /* SQL error or missing database */
|
||||||
ErrInternal os.Error = Errno(2) // /* Internal logic error in SQLite */
|
ErrInternal error = Errno(2) // /* Internal logic error in SQLite */
|
||||||
ErrPerm os.Error = Errno(3) // /* Access permission denied */
|
ErrPerm error = Errno(3) // /* Access permission denied */
|
||||||
ErrAbort os.Error = Errno(4) // /* Callback routine requested an abort */
|
ErrAbort error = Errno(4) // /* Callback routine requested an abort */
|
||||||
ErrBusy os.Error = Errno(5) // /* The database file is locked */
|
ErrBusy error = Errno(5) // /* The database file is locked */
|
||||||
ErrLocked os.Error = Errno(6) // /* A table in the database is locked */
|
ErrLocked error = Errno(6) // /* A table in the database is locked */
|
||||||
ErrNoMem os.Error = Errno(7) // /* A malloc() failed */
|
ErrNoMem error = Errno(7) // /* A malloc() failed */
|
||||||
ErrReadOnly os.Error = Errno(8) // /* Attempt to write a readonly database */
|
ErrReadOnly error = Errno(8) // /* Attempt to write a readonly database */
|
||||||
ErrInterrupt os.Error = Errno(9) // /* Operation terminated by sqlite3_interrupt()*/
|
ErrInterrupt error = Errno(9) // /* Operation terminated by sqlite3_interrupt()*/
|
||||||
ErrIOErr os.Error = Errno(10) // /* Some kind of disk I/O error occurred */
|
ErrIOErr error = Errno(10) // /* Some kind of disk I/O error occurred */
|
||||||
ErrCorrupt os.Error = Errno(11) // /* The database disk image is malformed */
|
ErrCorrupt error = Errno(11) // /* The database disk image is malformed */
|
||||||
ErrFull os.Error = Errno(13) // /* Insertion failed because database is full */
|
ErrFull error = Errno(13) // /* Insertion failed because database is full */
|
||||||
ErrCantOpen os.Error = Errno(14) // /* Unable to open the database file */
|
ErrCantOpen error = Errno(14) // /* Unable to open the database file */
|
||||||
ErrEmpty os.Error = Errno(16) // /* Database is empty */
|
ErrEmpty error = Errno(16) // /* Database is empty */
|
||||||
ErrSchema os.Error = Errno(17) // /* The database schema changed */
|
ErrSchema error = Errno(17) // /* The database schema changed */
|
||||||
ErrTooBig os.Error = Errno(18) // /* String or BLOB exceeds size limit */
|
ErrTooBig error = Errno(18) // /* String or BLOB exceeds size limit */
|
||||||
ErrConstraint os.Error = Errno(19) // /* Abort due to constraint violation */
|
ErrConstraint error = Errno(19) // /* Abort due to constraint violation */
|
||||||
ErrMismatch os.Error = Errno(20) // /* Data type mismatch */
|
ErrMismatch error = Errno(20) // /* Data type mismatch */
|
||||||
ErrMisuse os.Error = Errno(21) // /* Library used incorrectly */
|
ErrMisuse error = Errno(21) // /* Library used incorrectly */
|
||||||
ErrNolfs os.Error = Errno(22) // /* Uses OS features not supported on host */
|
ErrNolfs error = Errno(22) // /* Uses OS features not supported on host */
|
||||||
ErrAuth os.Error = Errno(23) // /* Authorization denied */
|
ErrAuth error = Errno(23) // /* Authorization denied */
|
||||||
ErrFormat os.Error = Errno(24) // /* Auxiliary database format error */
|
ErrFormat error = Errno(24) // /* Auxiliary database format error */
|
||||||
ErrRange os.Error = Errno(25) // /* 2nd parameter to sqlite3_bind out of range */
|
ErrRange error = Errno(25) // /* 2nd parameter to sqlite3_bind out of range */
|
||||||
ErrNotDB os.Error = Errno(26) // /* File opened that is not a database file */
|
ErrNotDB error = Errno(26) // /* File opened that is not a database file */
|
||||||
Row = Errno(100) // /* sqlite3_step() has another row ready */
|
Row = Errno(100) // /* sqlite3_step() has another row ready */
|
||||||
Done = Errno(101) // /* sqlite3_step() has finished executing */
|
Done = Errno(101) // /* sqlite3_step() has finished executing */
|
||||||
)
|
)
|
||||||
|
|
||||||
var errText = map[Errno]string {
|
var errText = map[Errno]string{
|
||||||
1: "SQL error or missing database",
|
1: "SQL error or missing database",
|
||||||
2: "Internal logic error in SQLite",
|
2: "Internal logic error in SQLite",
|
||||||
3: "Access permission denied",
|
3: "Access permission denied",
|
||||||
4: "Callback routine requested an abort",
|
4: "Callback routine requested an abort",
|
||||||
5: "The database file is locked",
|
5: "The database file is locked",
|
||||||
6: "A table in the database is locked",
|
6: "A table in the database is locked",
|
||||||
7: "A malloc() failed",
|
7: "A malloc() failed",
|
||||||
8: "Attempt to write a readonly database",
|
8: "Attempt to write a readonly database",
|
||||||
9: "Operation terminated by sqlite3_interrupt()*/",
|
9: "Operation terminated by sqlite3_interrupt()*/",
|
||||||
10: "Some kind of disk I/O error occurred",
|
10: "Some kind of disk I/O error occurred",
|
||||||
11: "The database disk image is malformed",
|
11: "The database disk image is malformed",
|
||||||
12: "NOT USED. Table or record not found",
|
12: "NOT USED. Table or record not found",
|
||||||
13: "Insertion failed because database is full",
|
13: "Insertion failed because database is full",
|
||||||
14: "Unable to open the database file",
|
14: "Unable to open the database file",
|
||||||
15: "NOT USED. Database lock protocol error",
|
15: "NOT USED. Database lock protocol error",
|
||||||
16: "Database is empty",
|
16: "Database is empty",
|
||||||
17: "The database schema changed",
|
17: "The database schema changed",
|
||||||
18: "String or BLOB exceeds size limit",
|
18: "String or BLOB exceeds size limit",
|
||||||
19: "Abort due to constraint violation",
|
19: "Abort due to constraint violation",
|
||||||
20: "Data type mismatch",
|
20: "Data type mismatch",
|
||||||
21: "Library used incorrectly",
|
21: "Library used incorrectly",
|
||||||
22: "Uses OS features not supported on host",
|
22: "Uses OS features not supported on host",
|
||||||
23: "Authorization denied",
|
23: "Authorization denied",
|
||||||
24: "Auxiliary database format error",
|
24: "Auxiliary database format error",
|
||||||
25: "2nd parameter to sqlite3_bind out of range",
|
25: "2nd parameter to sqlite3_bind out of range",
|
||||||
26: "File opened that is not a database file",
|
26: "File opened that is not a database file",
|
||||||
100: "sqlite3_step() has another row ready",
|
100: "sqlite3_step() has another row ready",
|
||||||
101: "sqlite3_step() has finished executing",
|
101: "sqlite3_step() has finished executing",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) error(rv C.int) os.Error {
|
func (c *Conn) error(rv C.int) error {
|
||||||
if c == nil || c.db == nil {
|
if c == nil || c.db == nil {
|
||||||
return os.NewError("nil sqlite database")
|
return errors.New("nil sqlite database")
|
||||||
}
|
}
|
||||||
if rv == 0 {
|
if rv == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if rv == 21 { // misuse
|
if rv == 21 { // misuse
|
||||||
return Errno(rv)
|
return Errno(rv)
|
||||||
}
|
}
|
||||||
return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db)))
|
return errors.New(Errno(rv).Error() + ": " + C.GoString(C.sqlite3_errmsg(c.db)))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
|
|
@ -124,33 +125,33 @@ type Conn struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Version() string {
|
func Version() string {
|
||||||
p := C.sqlite3_libversion();
|
p := C.sqlite3_libversion()
|
||||||
return C.GoString(p);
|
return C.GoString(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(filename string) (*Conn, os.Error) {
|
func Open(filename string) (*Conn, error) {
|
||||||
if C.sqlite3_threadsafe() == 0 {
|
if C.sqlite3_threadsafe() == 0 {
|
||||||
return nil, os.NewError("sqlite library was not compiled for thread-safe operation")
|
return nil, errors.New("sqlite library was not compiled for thread-safe operation")
|
||||||
}
|
}
|
||||||
|
|
||||||
var db *C.sqlite3
|
var db *C.sqlite3
|
||||||
name := C.CString(filename)
|
name := C.CString(filename)
|
||||||
defer C.free(unsafe.Pointer(name))
|
defer C.free(unsafe.Pointer(name))
|
||||||
rv := C.sqlite3_open_v2(name, &db,
|
rv := C.sqlite3_open_v2(name, &db,
|
||||||
C.SQLITE_OPEN_FULLMUTEX |
|
C.SQLITE_OPEN_FULLMUTEX|
|
||||||
C.SQLITE_OPEN_READWRITE |
|
C.SQLITE_OPEN_READWRITE|
|
||||||
C.SQLITE_OPEN_CREATE,
|
C.SQLITE_OPEN_CREATE,
|
||||||
nil)
|
nil)
|
||||||
if rv != 0 {
|
if rv != 0 {
|
||||||
return nil, Errno(rv)
|
return nil, Errno(rv)
|
||||||
}
|
}
|
||||||
if db == nil {
|
if db == nil {
|
||||||
return nil, os.NewError("sqlite succeeded without returning a database")
|
return nil, errors.New("sqlite succeeded without returning a database")
|
||||||
}
|
}
|
||||||
return &Conn{db}, nil
|
return &Conn{db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, os.Error) {
|
func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, error) {
|
||||||
dname := C.CString(dstTable)
|
dname := C.CString(dstTable)
|
||||||
sname := C.CString(srcTable)
|
sname := C.CString(srcTable)
|
||||||
defer C.free(unsafe.Pointer(dname))
|
defer C.free(unsafe.Pointer(dname))
|
||||||
|
|
@ -164,18 +165,18 @@ func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Backup struct {
|
type Backup struct {
|
||||||
sb *C.sqlite3_backup
|
sb *C.sqlite3_backup
|
||||||
dst, src *Conn
|
dst, src *Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backup) Step(npage int) os.Error {
|
func (b *Backup) Step(npage int) error {
|
||||||
rv := C.sqlite3_backup_step(b.sb, C.int(npage))
|
rv := C.sqlite3_backup_step(b.sb, C.int(npage))
|
||||||
if rv == 0 || Errno(rv) == ErrBusy || Errno(rv) == ErrLocked {
|
if rv == 0 || Errno(rv) == ErrBusy || Errno(rv) == ErrLocked {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return Errno(rv)
|
return Errno(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
type BackupStatus struct {
|
type BackupStatus struct {
|
||||||
Remaining int
|
Remaining int
|
||||||
PageCount int
|
PageCount int
|
||||||
|
|
@ -185,8 +186,8 @@ func (b *Backup) Status() BackupStatus {
|
||||||
return BackupStatus{int(C.sqlite3_backup_remaining(b.sb)), int(C.sqlite3_backup_pagecount(b.sb))}
|
return BackupStatus{int(C.sqlite3_backup_remaining(b.sb)), int(C.sqlite3_backup_pagecount(b.sb))}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) os.Error {
|
func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) error {
|
||||||
var err os.Error
|
var err error
|
||||||
for {
|
for {
|
||||||
err = b.Step(npage)
|
err = b.Step(npage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -197,10 +198,10 @@ func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) os.Error {
|
||||||
}
|
}
|
||||||
time.Sleep(sleepNs)
|
time.Sleep(sleepNs)
|
||||||
}
|
}
|
||||||
return b.dst.error(C.sqlite3_errcode(b.dst.db))
|
return b.dst.error(C.sqlite3_errcode(b.dst.db))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backup) Close() os.Error {
|
func (b *Backup) Close() error {
|
||||||
if b.sb == nil {
|
if b.sb == nil {
|
||||||
return os.EINVAL
|
return os.EINVAL
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +210,7 @@ func (b *Backup) Close() os.Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) BusyTimeout(ms int) os.Error {
|
func (c *Conn) BusyTimeout(ms int) error {
|
||||||
rv := C.sqlite3_busy_timeout(c.db, C.int(ms))
|
rv := C.sqlite3_busy_timeout(c.db, C.int(ms))
|
||||||
if rv == 0 {
|
if rv == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -217,7 +218,7 @@ func (c *Conn) BusyTimeout(ms int) os.Error {
|
||||||
return Errno(rv)
|
return Errno(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
|
func (c *Conn) Exec(cmd string, args ...interface{}) error {
|
||||||
s, err := c.Prepare(cmd)
|
s, err := c.Prepare(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -235,17 +236,17 @@ func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Stmt struct {
|
type Stmt struct {
|
||||||
c *Conn
|
c *Conn
|
||||||
stmt *C.sqlite3_stmt
|
stmt *C.sqlite3_stmt
|
||||||
err os.Error
|
err error
|
||||||
t0 int64
|
t0 int64
|
||||||
sql string
|
sql string
|
||||||
args string
|
args string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Prepare(cmd string) (*Stmt, os.Error) {
|
func (c *Conn) Prepare(cmd string) (*Stmt, error) {
|
||||||
if c == nil || c.db == nil {
|
if c == nil || c.db == nil {
|
||||||
return nil, os.NewError("nil sqlite database")
|
return nil, errors.New("nil sqlite database")
|
||||||
}
|
}
|
||||||
cmdstr := C.CString(cmd)
|
cmdstr := C.CString(cmd)
|
||||||
defer C.free(unsafe.Pointer(cmdstr))
|
defer C.free(unsafe.Pointer(cmdstr))
|
||||||
|
|
@ -258,7 +259,7 @@ func (c *Conn) Prepare(cmd string) (*Stmt, os.Error) {
|
||||||
return &Stmt{c: c, stmt: stmt, sql: cmd, t0: time.Nanoseconds()}, nil
|
return &Stmt{c: c, stmt: stmt, sql: cmd, t0: time.Nanoseconds()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) Exec(args ...interface{}) os.Error {
|
func (s *Stmt) Exec(args ...interface{}) error {
|
||||||
s.args = fmt.Sprintf(" %v", []interface{}(args))
|
s.args = fmt.Sprintf(" %v", []interface{}(args))
|
||||||
rv := C.sqlite3_reset(s.stmt)
|
rv := C.sqlite3_reset(s.stmt)
|
||||||
if rv != 0 {
|
if rv != 0 {
|
||||||
|
|
@ -267,7 +268,7 @@ func (s *Stmt) Exec(args ...interface{}) os.Error {
|
||||||
|
|
||||||
n := int(C.sqlite3_bind_parameter_count(s.stmt))
|
n := int(C.sqlite3_bind_parameter_count(s.stmt))
|
||||||
if n != len(args) {
|
if n != len(args) {
|
||||||
return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Exec: have %d want %d", len(args), n))
|
return errors.New(fmt.Sprintf("incorrect argument count for Stmt.Exec: have %d want %d", len(args), n))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, v := range args {
|
for i, v := range args {
|
||||||
|
|
@ -282,7 +283,7 @@ func (s *Stmt) Exec(args ...interface{}) os.Error {
|
||||||
return s.c.error(rv)
|
return s.c.error(rv)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case bool:
|
case bool:
|
||||||
if v {
|
if v {
|
||||||
str = "1"
|
str = "1"
|
||||||
|
|
@ -293,7 +294,7 @@ func (s *Stmt) Exec(args ...interface{}) os.Error {
|
||||||
default:
|
default:
|
||||||
str = fmt.Sprint(v)
|
str = fmt.Sprint(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
cstr := C.CString(str)
|
cstr := C.CString(str)
|
||||||
rv := C.my_bind_text(s.stmt, C.int(i+1), cstr, C.int(len(str)))
|
rv := C.my_bind_text(s.stmt, C.int(i+1), cstr, C.int(len(str)))
|
||||||
C.free(unsafe.Pointer(cstr))
|
C.free(unsafe.Pointer(cstr))
|
||||||
|
|
@ -304,7 +305,7 @@ func (s *Stmt) Exec(args ...interface{}) os.Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) Error() os.Error {
|
func (s *Stmt) Error() error {
|
||||||
return s.err
|
return s.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,29 +318,29 @@ func (s *Stmt) Next() bool {
|
||||||
if err != Done {
|
if err != Done {
|
||||||
s.err = s.c.error(rv)
|
s.err = s.c.error(rv)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) Reset() os.Error {
|
func (s *Stmt) Reset() error {
|
||||||
C.sqlite3_reset(s.stmt)
|
C.sqlite3_reset(s.stmt)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) Scan(args ...interface{}) os.Error {
|
func (s *Stmt) Scan(args ...interface{}) error {
|
||||||
n := int(C.sqlite3_column_count(s.stmt))
|
n := int(C.sqlite3_column_count(s.stmt))
|
||||||
if n != len(args) {
|
if n != len(args) {
|
||||||
return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Scan: have %d want %d", len(args), n))
|
return errors.New(fmt.Sprintf("incorrect argument count for Stmt.Scan: have %d want %d", len(args), n))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, v := range args {
|
for i, v := range args {
|
||||||
n := C.sqlite3_column_bytes(s.stmt, C.int(i))
|
n := C.sqlite3_column_bytes(s.stmt, C.int(i))
|
||||||
p := C.sqlite3_column_blob(s.stmt, C.int(i))
|
p := C.sqlite3_column_blob(s.stmt, C.int(i))
|
||||||
if p == nil && n > 0 {
|
if p == nil && n > 0 {
|
||||||
return os.NewError("got nil blob")
|
return errors.New("got nil blob")
|
||||||
}
|
}
|
||||||
var data []byte
|
var data []byte
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
data = (*[1<<30]byte)(unsafe.Pointer(p))[0:n]
|
data = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]
|
||||||
}
|
}
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case *[]byte:
|
case *[]byte:
|
||||||
|
|
@ -351,23 +352,23 @@ func (s *Stmt) Scan(args ...interface{}) os.Error {
|
||||||
case *int:
|
case *int:
|
||||||
x, err := strconv.Atoi(string(data))
|
x, err := strconv.Atoi(string(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String())
|
return errors.New("arg " + strconv.Itoa(i) + " as int: " + err.Error())
|
||||||
}
|
}
|
||||||
*v = x
|
*v = x
|
||||||
case *int64:
|
case *int64:
|
||||||
x, err := strconv.Atoi64(string(data))
|
x, err := strconv.Atoi64(string(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return os.NewError("arg " + strconv.Itoa(i) + " as int64: " + err.String())
|
return errors.New("arg " + strconv.Itoa(i) + " as int64: " + err.Error())
|
||||||
}
|
}
|
||||||
*v = x
|
*v = x
|
||||||
case *float64:
|
case *float64:
|
||||||
x, err := strconv.Atof64(string(data))
|
x, err := strconv.Atof64(string(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String())
|
return errors.New("arg " + strconv.Itoa(i) + " as float64: " + err.Error())
|
||||||
}
|
}
|
||||||
*v = x
|
*v = x
|
||||||
default:
|
default:
|
||||||
return os.NewError("unsupported type in Scan: " + reflect.TypeOf(v).String())
|
return errors.New("unsupported type in Scan: " + reflect.TypeOf(v).String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -381,7 +382,7 @@ func (s *Stmt) Nanoseconds() int64 {
|
||||||
return time.Nanoseconds() - s.t0
|
return time.Nanoseconds() - s.t0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stmt) Finalize() os.Error {
|
func (s *Stmt) Finalize() error {
|
||||||
rv := C.sqlite3_finalize(s.stmt)
|
rv := C.sqlite3_finalize(s.stmt)
|
||||||
if rv != 0 {
|
if rv != 0 {
|
||||||
return s.c.error(rv)
|
return s.c.error(rv)
|
||||||
|
|
@ -389,9 +390,9 @@ func (s *Stmt) Finalize() os.Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Close() os.Error {
|
func (c *Conn) Close() error {
|
||||||
if c == nil || c.db == nil {
|
if c == nil || c.db == nil {
|
||||||
return os.NewError("nil sqlite database")
|
return errors.New("nil sqlite database")
|
||||||
}
|
}
|
||||||
rv := C.sqlite3_close(c.db)
|
rv := C.sqlite3_close(c.db)
|
||||||
if rv != 0 {
|
if rv != 0 {
|
||||||
|
|
|
||||||
84
register.go
84
register.go
|
|
@ -13,17 +13,14 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"http"
|
"http"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"url"
|
|
||||||
"xml"
|
"xml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Register struct {
|
type Register struct {
|
||||||
XMLName xml.Name `xml:"server"`
|
XMLName xml.Name `xml:"server"`
|
||||||
//MacHash string `xml:"machash"`
|
//MacHash string `xml:"machash"`
|
||||||
Version string `xml:"version"`
|
Version string `xml:"version"`
|
||||||
Release string `xml:"release"`
|
Release string `xml:"release"`
|
||||||
//OS string `xml:"os"`
|
//OS string `xml:"os"`
|
||||||
//OSVer string `xml:"osver"`
|
//OSVer string `xml:"osver"`
|
||||||
//Qt string `xml:"qt"`
|
//Qt string `xml:"qt"`
|
||||||
|
|
@ -31,15 +28,15 @@ type Register struct {
|
||||||
//CpuId string `xml:"cpuid"`
|
//CpuId string `xml:"cpuid"`
|
||||||
//CpuIdExt string `xml:"cpuidext"`
|
//CpuIdExt string `xml:"cpuidext"`
|
||||||
//CpuSSE2 bool `xml:"cpusse2"`
|
//CpuSSE2 bool `xml:"cpusse2"`
|
||||||
Name string `xml:"name"`
|
Name string `xml:"name"`
|
||||||
Host string `xml:"host"`
|
Host string `xml:"host"`
|
||||||
Password string `xml:"password"`
|
Password string `xml:"password"`
|
||||||
Port int `xml:"port"`
|
Port int `xml:"port"`
|
||||||
Url string `xml:"url"`
|
Url string `xml:"url"`
|
||||||
Digest string `xml:"digest"`
|
Digest string `xml:"digest"`
|
||||||
Users int `xml:"users"`
|
Users int `xml:"users"`
|
||||||
Channels int `xml:"channels"`
|
Channels int `xml:"channels"`
|
||||||
Location string `xml:"location"`
|
Location string `xml:"location"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -47,26 +44,6 @@ const (
|
||||||
registerUrl = "https://mumble.hive.no/register.cgi"
|
registerUrl = "https://mumble.hive.no/register.cgi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a persistent HTTP ClientConn to server at addr with TLS configuration cfg.
|
|
||||||
func newTLSClientAuthConn(addr string, cfg *tls.Config) (c *http.ClientConn, err os.Error) {
|
|
||||||
tcpaddr, err := net.ResolveTCPAddr("tcp", addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tcpconn, err := net.DialTCP("tcp", nil, tcpaddr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsconn := tls.Client(tcpconn, cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return http.NewClientConn(tlsconn, nil), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determines whether a server is public by checking whether the
|
// Determines whether a server is public by checking whether the
|
||||||
// config values required for public registration are set.
|
// config values required for public registration are set.
|
||||||
//
|
//
|
||||||
|
|
@ -135,41 +112,16 @@ func (server *Server) RegisterPublicServer() {
|
||||||
|
|
||||||
// Post registration XML data to server asynchronously in its own goroutine
|
// Post registration XML data to server asynchronously in its own goroutine
|
||||||
go func() {
|
go func() {
|
||||||
// Go's http package does not allow HTTP clients to set their own
|
tr := &http.Transport{
|
||||||
// certificate chain, so we use our own wrapper instead.
|
TLSClientConfig: config,
|
||||||
hc, err := newTLSClientAuthConn(registerAddr, config)
|
DisableCompression: true,
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
r, err := client.Post(registerUrl, "text/xml", ioutil.NopCloser(buf))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Printf("register: unable to create https client: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer hc.Close()
|
|
||||||
|
|
||||||
// The master registration server requires
|
|
||||||
// that a Content-Length be specified in incoming HTTP requests.
|
|
||||||
// Make sure we don't send a chunked request by hand-crafting it.
|
|
||||||
var req http.Request
|
|
||||||
req.Method = "POST"
|
|
||||||
req.ProtoMajor = 1
|
|
||||||
req.ProtoMinor = 1
|
|
||||||
req.Close = true
|
|
||||||
req.Body = ioutil.NopCloser(buf)
|
|
||||||
req.ContentLength = int64(buf.Len())
|
|
||||||
req.Header = http.Header{
|
|
||||||
"Content-Type": {"text/xml"},
|
|
||||||
}
|
|
||||||
|
|
||||||
req.URL, err = url.Parse(registerUrl)
|
|
||||||
if err != nil {
|
|
||||||
server.Printf("register: error parsing url: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := hc.Do(&req)
|
|
||||||
if err != nil && err != http.ErrPersistEOF {
|
|
||||||
server.Printf("register: unable to post registration request: %v", err)
|
server.Printf("register: unable to post registration request: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyBytes, err := ioutil.ReadAll(r.Body)
|
bodyBytes, err := ioutil.ReadAll(r.Body)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
registerMsg := string(bodyBytes)
|
registerMsg := string(bodyBytes)
|
||||||
|
|
|
||||||
65
server.go
65
server.go
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"goprotobuf.googlecode.com/hg/proto"
|
"goprotobuf.googlecode.com/hg/proto"
|
||||||
"grumble/ban"
|
"grumble/ban"
|
||||||
|
|
@ -115,7 +116,7 @@ type clientLogForwarder struct {
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lf clientLogForwarder) Write(incoming []byte) (int, os.Error) {
|
func (lf clientLogForwarder) Write(incoming []byte) (int, error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
buf.WriteString(fmt.Sprintf("<%v:%v(%v)> ", lf.client.Session, lf.client.ShownName(), lf.client.UserId()))
|
buf.WriteString(fmt.Sprintf("<%v:%v(%v)> ", lf.client.Session, lf.client.ShownName(), lf.client.UserId()))
|
||||||
buf.Write(incoming)
|
buf.Write(incoming)
|
||||||
|
|
@ -124,7 +125,7 @@ func (lf clientLogForwarder) Write(incoming []byte) (int, os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new Murmur instance
|
// Allocate a new Murmur instance
|
||||||
func NewServer(id int64, addr string, port int) (s *Server, err os.Error) {
|
func NewServer(id int64, addr string, port int) (s *Server, err error) {
|
||||||
s = new(Server)
|
s = new(Server)
|
||||||
|
|
||||||
s.Id = id
|
s.Id = id
|
||||||
|
|
@ -236,11 +237,11 @@ func (server *Server) CheckSuperUserPassword(password string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the server to initiate a new client connection.
|
// Called by the server to initiate a new client connection.
|
||||||
func (server *Server) NewClient(conn net.Conn) (err os.Error) {
|
func (server *Server) NewClient(conn net.Conn) (err error) {
|
||||||
client := new(Client)
|
client := new(Client)
|
||||||
addr := conn.RemoteAddr()
|
addr := conn.RemoteAddr()
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
err = os.NewError("Unable to extract address for client.")
|
err = errors.New("Unable to extract address for client.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,11 +286,11 @@ func (server *Server) RemoveClient(client *Client, kicked bool) {
|
||||||
}
|
}
|
||||||
server.hclients[host] = newclients
|
server.hclients[host] = newclients
|
||||||
if client.udpaddr != nil {
|
if client.udpaddr != nil {
|
||||||
server.hpclients[client.udpaddr.String()] = nil, false
|
delete(server.hpclients, client.udpaddr.String())
|
||||||
}
|
}
|
||||||
server.hmutex.Unlock()
|
server.hmutex.Unlock()
|
||||||
|
|
||||||
server.clients[client.Session] = nil, false
|
delete(server.clients, client.Session)
|
||||||
server.pool.Reclaim(client.Session)
|
server.pool.Reclaim(client.Session)
|
||||||
|
|
||||||
// Remove client from channel
|
// Remove client from channel
|
||||||
|
|
@ -327,7 +328,7 @@ func (server *Server) RemoveChanel(channel *Channel) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Channels[channel.Id] = nil, false
|
delete(server.Channels, channel.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link two channels
|
// Link two channels
|
||||||
|
|
@ -338,8 +339,8 @@ func (server *Server) LinkChannels(channel *Channel, other *Channel) {
|
||||||
|
|
||||||
// Unlink two channels
|
// Unlink two channels
|
||||||
func (server *Server) UnlinkChannels(channel *Channel, other *Channel) {
|
func (server *Server) UnlinkChannels(channel *Channel, other *Channel) {
|
||||||
channel.Links[other.Id] = nil, false
|
delete(channel.Links, other.Id)
|
||||||
other.Links[channel.Id] = nil, false
|
delete(other.Links, channel.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the synchronous handler goroutine.
|
// This is the synchronous handler goroutine.
|
||||||
|
|
@ -580,7 +581,7 @@ func (server *Server) finishAuthenticate(client *Client) {
|
||||||
} else {
|
} else {
|
||||||
buf, err := blobstore.Get(client.user.TextureBlob)
|
buf, err := blobstore.Get(client.user.TextureBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err.Error())
|
||||||
}
|
}
|
||||||
userstate.Texture = buf
|
userstate.Texture = buf
|
||||||
}
|
}
|
||||||
|
|
@ -593,7 +594,7 @@ func (server *Server) finishAuthenticate(client *Client) {
|
||||||
} else {
|
} else {
|
||||||
buf, err := blobstore.Get(client.user.CommentBlob)
|
buf, err := blobstore.Get(client.user.CommentBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err.Error())
|
||||||
}
|
}
|
||||||
userstate.Comment = proto.String(string(buf))
|
userstate.Comment = proto.String(string(buf))
|
||||||
}
|
}
|
||||||
|
|
@ -729,7 +730,7 @@ func (server *Server) sendUserList(client *Client) {
|
||||||
} else {
|
} else {
|
||||||
buf, err := blobstore.Get(connectedClient.user.TextureBlob)
|
buf, err := blobstore.Get(connectedClient.user.TextureBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err.Error())
|
||||||
}
|
}
|
||||||
userstate.Texture = buf
|
userstate.Texture = buf
|
||||||
}
|
}
|
||||||
|
|
@ -742,7 +743,7 @@ func (server *Server) sendUserList(client *Client) {
|
||||||
} else {
|
} else {
|
||||||
buf, err := blobstore.Get(connectedClient.user.CommentBlob)
|
buf, err := blobstore.Get(connectedClient.user.CommentBlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panicf("Blobstore error: %v", err.String())
|
server.Panicf("Blobstore error: %v", err.Error())
|
||||||
}
|
}
|
||||||
userstate.Comment = proto.String(string(buf))
|
userstate.Comment = proto.String(string(buf))
|
||||||
}
|
}
|
||||||
|
|
@ -802,7 +803,7 @@ func (server *Server) sendClientPermissions(client *Client, channel *Channel) {
|
||||||
|
|
||||||
type ClientPredicate func(client *Client) bool
|
type ClientPredicate func(client *Client) bool
|
||||||
|
|
||||||
func (server *Server) broadcastProtoMessageWithPredicate(msg interface{}, clientcheck ClientPredicate) (err os.Error) {
|
func (server *Server) broadcastProtoMessageWithPredicate(msg interface{}, clientcheck ClientPredicate) error {
|
||||||
for _, client := range server.clients {
|
for _, client := range server.clients {
|
||||||
if !clientcheck(client) {
|
if !clientcheck(client) {
|
||||||
continue
|
continue
|
||||||
|
|
@ -812,14 +813,14 @@ func (server *Server) broadcastProtoMessageWithPredicate(msg interface{}, client
|
||||||
}
|
}
|
||||||
err := client.sendProtoMessage(msg)
|
err := client.sendProtoMessage(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) broadcastProtoMessage(msg interface{}) (err os.Error) {
|
func (server *Server) broadcastProtoMessage(msg interface{}) (err error) {
|
||||||
err = server.broadcastProtoMessageWithPredicate(msg, func(client *Client) bool { return true })
|
err = server.broadcastProtoMessageWithPredicate(msg, func(client *Client) bool { return true })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -863,7 +864,7 @@ func (server *Server) handleIncomingMessage(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetupUDP() (err os.Error) {
|
func (s *Server) SetupUDP() (err error) {
|
||||||
addr := &net.UDPAddr{
|
addr := &net.UDPAddr{
|
||||||
net.ParseIP(s.address),
|
net.ParseIP(s.address),
|
||||||
s.port,
|
s.port,
|
||||||
|
|
@ -1016,7 +1017,7 @@ func (server *Server) userEnterChannel(client *Client, channel *Channel, usersta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register a client on the server.
|
// Register a client on the server.
|
||||||
func (s *Server) RegisterClient(client *Client) (uid uint32, err os.Error) {
|
func (s *Server) RegisterClient(client *Client) (uid uint32, err error) {
|
||||||
// Increment nextUserId only if registration succeeded.
|
// Increment nextUserId only if registration succeeded.
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -1031,7 +1032,7 @@ func (s *Server) RegisterClient(client *Client) (uid uint32, err os.Error) {
|
||||||
|
|
||||||
// Grumble can only register users with certificates.
|
// Grumble can only register users with certificates.
|
||||||
if len(client.CertHash) == 0 {
|
if len(client.CertHash) == 0 {
|
||||||
return 0, os.NewError("no cert hash")
|
return 0, errors.New("no cert hash")
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Email = client.Email
|
user.Email = client.Email
|
||||||
|
|
@ -1046,16 +1047,16 @@ func (s *Server) RegisterClient(client *Client) (uid uint32, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a registered user.
|
// Remove a registered user.
|
||||||
func (s *Server) RemoveRegistration(uid uint32) (err os.Error) {
|
func (s *Server) RemoveRegistration(uid uint32) (err error) {
|
||||||
user, ok := s.Users[uid]
|
user, ok := s.Users[uid]
|
||||||
if !ok {
|
if !ok {
|
||||||
return os.NewError("Unknown user ID")
|
return errors.New("Unknown user ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from user maps
|
// Remove from user maps
|
||||||
s.Users[uid] = nil, false
|
delete(s.Users, uid)
|
||||||
s.UserCertMap[user.CertHash] = nil, false
|
delete(s.UserCertMap, user.CertHash)
|
||||||
s.UserNameMap[user.Name] = nil, false
|
delete(s.UserNameMap, user.Name)
|
||||||
|
|
||||||
// Remove from groups and ACLs.
|
// Remove from groups and ACLs.
|
||||||
s.removeRegisteredUserFromChannel(uid, s.RootChannel())
|
s.removeRegisteredUserFromChannel(uid, s.RootChannel())
|
||||||
|
|
@ -1077,13 +1078,13 @@ func (s *Server) removeRegisteredUserFromChannel(uid uint32, channel *Channel) {
|
||||||
|
|
||||||
for _, grp := range channel.Groups {
|
for _, grp := range channel.Groups {
|
||||||
if _, ok := grp.Add[int(uid)]; ok {
|
if _, ok := grp.Add[int(uid)]; ok {
|
||||||
grp.Add[int(uid)] = false, false
|
delete(grp.Add, int(uid))
|
||||||
}
|
}
|
||||||
if _, ok := grp.Remove[int(uid)]; ok {
|
if _, ok := grp.Remove[int(uid)]; ok {
|
||||||
grp.Remove[int(uid)] = false, false
|
delete(grp.Remove, int(uid))
|
||||||
}
|
}
|
||||||
if _, ok := grp.Temporary[int(uid)]; ok {
|
if _, ok := grp.Temporary[int(uid)]; ok {
|
||||||
grp.Temporary[int(uid)] = false, false
|
delete(grp.Temporary, int(uid))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1101,7 +1102,7 @@ func (server *Server) RemoveChannel(channel *Channel) {
|
||||||
|
|
||||||
// Remove all links
|
// Remove all links
|
||||||
for _, linkedChannel := range channel.Links {
|
for _, linkedChannel := range channel.Links {
|
||||||
linkedChannel.Links[channel.Id] = nil, false
|
delete(linkedChannel.Links, channel.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all subchannels
|
// Remove all subchannels
|
||||||
|
|
@ -1127,8 +1128,8 @@ func (server *Server) RemoveChannel(channel *Channel) {
|
||||||
|
|
||||||
// Remove the channel itself
|
// Remove the channel itself
|
||||||
parent := channel.parent
|
parent := channel.parent
|
||||||
parent.children[channel.Id] = nil, false
|
delete(parent.children, channel.Id)
|
||||||
server.Channels[channel.Id] = nil, false
|
delete(server.Channels, channel.Id)
|
||||||
chanremove := &mumbleproto.ChannelRemove{
|
chanremove := &mumbleproto.ChannelRemove{
|
||||||
ChannelId: proto.Uint32(uint32(channel.Id)),
|
ChannelId: proto.Uint32(uint32(channel.Id)),
|
||||||
}
|
}
|
||||||
|
|
@ -1153,7 +1154,7 @@ func (server *Server) IsBanned(conn net.Conn) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter incoming text according to the server's current rules.
|
// Filter incoming text according to the server's current rules.
|
||||||
func (server *Server) FilterText(text string) (filtered string, err os.Error) {
|
func (server *Server) FilterText(text string) (filtered string, err error) {
|
||||||
options := &htmlfilter.Options{
|
options := &htmlfilter.Options{
|
||||||
StripHTML: !server.cfg.BoolValue("AllowHTML"),
|
StripHTML: !server.cfg.BoolValue("AllowHTML"),
|
||||||
MaxTextMessageLength: server.cfg.IntValue("MaxTextMessageLength"),
|
MaxTextMessageLength: server.cfg.IntValue("MaxTextMessageLength"),
|
||||||
|
|
|
||||||
8
user.go
8
user.go
|
|
@ -6,7 +6,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"os"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file implements Server's handling of Users.
|
// This file implements Server's handling of Users.
|
||||||
|
|
@ -26,12 +26,12 @@ type User struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new User
|
// Create a new User
|
||||||
func NewUser(id uint32, name string) (user *User, err os.Error) {
|
func NewUser(id uint32, name string) (user *User, err error) {
|
||||||
if id < 0 {
|
if id < 0 {
|
||||||
return nil, os.NewError("Invalid user id")
|
return nil, errors.New("Invalid user id")
|
||||||
}
|
}
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return nil, os.NewError("Invalid username")
|
return nil, errors.New("Invalid username")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &User{
|
return &User{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue