Пример #1
0
// toProto converts the query to a protocol buffer.
func (q *Query) toProto(appID string) (*pb.Query, os.Error) {
	if q.kind == "" {
		return nil, os.NewError("datastore: empty query kind")
	}
	x := &pb.Query{
		App:  proto.String(appID),
		Kind: proto.String(q.kind),
	}
	if q.ancestor != nil {
		x.Ancestor = keyToProto(appID, q.ancestor)
	}
	if q.keysOnly {
		x.KeysOnly = proto.Bool(true)
		x.RequirePerfectPlan = proto.Bool(true)
	}
	for _, qf := range q.filter {
		if qf.FieldName == "" {
			return nil, os.NewError("datastore: empty query filter field name")
		}
		p, errStr := valueToProto(appID, qf.FieldName, reflect.ValueOf(qf.Value), false)
		if errStr != "" {
			return nil, os.NewError("datastore: bad query filter value type: " + errStr)
		}
		xf := &pb.Query_Filter{
			Op:       operatorToProto[qf.Op],
			Property: []*pb.Property{p},
		}
		if xf.Op == nil {
			return nil, os.NewError("datastore: unknown query filter operator")
		}
		x.Filter = append(x.Filter, xf)
	}
	for _, qo := range q.order {
		if qo.FieldName == "" {
			return nil, os.NewError("datastore: empty query order field name")
		}
		xo := &pb.Query_Order{
			Property:  proto.String(qo.FieldName),
			Direction: sortDirectionToProto[qo.Direction],
		}
		if xo.Direction == nil {
			return nil, os.NewError("datastore: unknown query order direction")
		}
		x.Order = append(x.Order, xo)
	}
	if q.limit != 0 {
		x.Limit = proto.Int(q.limit)
	}
	if q.offset != 0 {
		x.Offset = proto.Int(q.offset)
	}
	return x, nil
}
Пример #2
0
// toProto converts the query to a protocol buffer.
func (q *Query) toProto(dst *pb.Query, appID string, zlp zeroLimitPolicy) error {
	if q.kind == "" {
		return errors.New("datastore: empty query kind")
	}
	dst.Reset()
	dst.App = proto.String(appID)
	dst.Kind = proto.String(q.kind)
	if q.ancestor != nil {
		dst.Ancestor = keyToProto(appID, q.ancestor)
	}
	if q.keysOnly {
		dst.KeysOnly = proto.Bool(true)
		dst.RequirePerfectPlan = proto.Bool(true)
	}
	for _, qf := range q.filter {
		if qf.FieldName == "" {
			return errors.New("datastore: empty query filter field name")
		}
		p, errStr := valueToProto(appID, qf.FieldName, reflect.ValueOf(qf.Value), false)
		if errStr != "" {
			return errors.New("datastore: bad query filter value type: " + errStr)
		}
		xf := &pb.Query_Filter{
			Op:       operatorToProto[qf.Op],
			Property: []*pb.Property{p},
		}
		if xf.Op == nil {
			return errors.New("datastore: unknown query filter operator")
		}
		dst.Filter = append(dst.Filter, xf)
	}
	for _, qo := range q.order {
		if qo.FieldName == "" {
			return errors.New("datastore: empty query order field name")
		}
		xo := &pb.Query_Order{
			Property:  proto.String(qo.FieldName),
			Direction: sortDirectionToProto[qo.Direction],
		}
		if xo.Direction == nil {
			return errors.New("datastore: unknown query order direction")
		}
		dst.Order = append(dst.Order, xo)
	}
	if q.limit != 0 || zlp == zeroLimitMeansZero {
		dst.Limit = proto.Int32(q.limit)
	}
	if q.offset != 0 {
		dst.Offset = proto.Int32(q.offset)
	}
	return nil
}
Пример #3
0
// valueToProto converts a named value to a newly allocated Property.
// The returned error string is empty on success.
func valueToProto(defaultAppID, name string, v reflect.Value, multiple bool) (p *pb.Property, errStr string) {
	var (
		pv          pb.PropertyValue
		unsupported bool
	)
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		pv.Int64Value = proto.Int64(v.Int())
	case reflect.Bool:
		pv.BooleanValue = proto.Bool(v.Bool())
	case reflect.String:
		pv.StringValue = proto.String(v.String())
	case reflect.Float32, reflect.Float64:
		pv.DoubleValue = proto.Float64(v.Float())
	case reflect.Ptr:
		if k, ok := v.Interface().(*Key); ok {
			if k == nil {
				return nil, nilKeyErrStr
			}
			pv.Referencevalue = keyToReferenceValue(defaultAppID, k)
		} else {
			unsupported = true
		}
	case reflect.Slice:
		if b, ok := v.Interface().([]byte); ok {
			pv.StringValue = proto.String(string(b))
		} else {
			// nvToProto should already catch slice values.
			// If we get here, we have a slice of slice values.
			unsupported = true
		}
	default:
		unsupported = true
	}
	if unsupported {
		return nil, "unsupported datastore value type: " + v.Type().String()
	}
	p = &pb.Property{
		Name:     proto.String(name),
		Value:    &pv,
		Multiple: proto.Bool(multiple),
	}
	switch v.Interface().(type) {
	case []byte:
		p.Meaning = pb.NewProperty_Meaning(pb.Property_BLOB)
	case appengine.BlobKey:
		p.Meaning = pb.NewProperty_Meaning(pb.Property_BLOBKEY)
	case Time:
		p.Meaning = pb.NewProperty_Meaning(pb.Property_GD_WHEN)
	}
	return p, ""
}
Пример #4
0
// Helper method for users entering new channels
func (server *Server) userEnterChannel(client *Client, channel *Channel, userstate *mumbleproto.UserState) {
	if client.Channel == channel {
		return
	}

	oldchan := client.Channel
	if oldchan != nil {
		oldchan.RemoveClient(client)
	}
	channel.AddClient(client)

	server.ClearACLCache()
	// fixme(mkrautz): Set LastChannel for user in datastore
	// fixme(mkrautz): Remove channel if temporary

	canspeak := server.HasPermission(client, channel, SpeakPermission)
	if canspeak == client.Suppress {
		client.Suppress = !canspeak
		userstate.Suppress = proto.Bool(client.Suppress)
	}

	server.sendClientPermissions(client, channel)
	if channel.parent != nil {
		server.sendClientPermissions(client, channel.parent)
	}
}
Пример #5
0
// Reads a single arbitrary type and returns the proper StateValue.
func readField(val reflect.Value) *protocol.StateValue {
	msg := &protocol.StateValue{}
	switch f := val.(type) {
	case *reflect.BoolValue:
		msg.Type = protocol.NewStateValue_Type(protocol.StateValue_BOOL)
		msg.BoolVal = proto.Bool(f.Get())
	case *reflect.IntValue:
		msg.Type = protocol.NewStateValue_Type(protocol.StateValue_INT)
		msg.IntVal = proto.Int(int(f.Get()))
	case *reflect.FloatValue:
		msg.Type = protocol.NewStateValue_Type(protocol.StateValue_FLOAT)
		msg.FloatVal = proto.Float32(float32(f.Get()))
	case *reflect.StringValue:
		msg.Type = protocol.NewStateValue_Type(protocol.StateValue_STRING)
		msg.StringVal = proto.String(f.Get())
	case *reflect.SliceValue:
		msg.Type = protocol.NewStateValue_Type(protocol.StateValue_ARRAY)
		msg.ArrayVal = makeStateValueArray(f, f.Len())
	case *reflect.StructValue:
		msg = readStructField(f)
	case *reflect.PtrValue:
		return readField(reflect.Indirect(f)) // Dereference and recurse
	default:
		panic("State value not supported: " + val.Type().String())
	}
	return msg
}
Пример #6
0
func (server *Server) updateCodecVersions() {
	codecusers := map[int32]int{}
	var winner int32
	var count int

	for _, client := range server.clients {
		for _, codec := range client.codecs {
			codecusers[codec] += 1
		}
	}

	for codec, users := range codecusers {
		if users > count {
			count = users
			winner = codec
		}
		if users == count && codec > winner {
			winner = codec
		}
	}

	var current int32
	if server.PreferAlphaCodec {
		current = server.AlphaCodec
	} else {
		current = server.BetaCodec
	}

	if winner == current {
		return
	}

	if winner == CeltCompatBitstream {
		server.PreferAlphaCodec = true
	} else {
		server.PreferAlphaCodec = !server.PreferAlphaCodec
	}

	if server.PreferAlphaCodec {
		server.AlphaCodec = winner
	} else {
		server.BetaCodec = winner
	}

	err := server.broadcastProtoMessage(MessageCodecVersion, &mumbleproto.CodecVersion{
		Alpha:       proto.Int32(server.AlphaCodec),
		Beta:        proto.Int32(server.BetaCodec),
		PreferAlpha: proto.Bool(server.PreferAlphaCodec),
	})
	if err != nil {
		log.Printf("Unable to broadcast.")
		return
	}

	log.Printf("CELT codec switch %#x %#x (PreferAlpha %v)", uint32(server.AlphaCodec), uint32(server.BetaCodec), server.PreferAlphaCodec)
	return
}
// set sets the given items using the given conflict resolution policy.
// The returned slice will have the same length as the input slice.
// If value is not nil, each element should correspond to an item.
func set(c appengine.Context, item []*Item, value [][]byte, policy int32) []os.Error {
	req := &pb.MemcacheSetRequest{
		Item: make([]*pb.MemcacheSetRequest_Item, len(item)),
	}
	for i, t := range item {
		p := &pb.MemcacheSetRequest_Item{
			Key: []byte(t.Key),
		}
		if value == nil {
			p.Value = t.Value
		} else {
			p.Value = value[i]
		}
		if t.Flags != 0 {
			p.Flags = proto.Uint32(t.Flags)
		}
		if t.Expiration != 0 {
			// In the .proto file, MemcacheSetRequest_Item uses a fixed32 (i.e. unsigned)
			// for expiration time, while MemcacheGetRequest_Item uses int32 (i.e. signed).
			// Throughout this .go file, we use int32.
			p.ExpirationTime = proto.Uint32(uint32(t.Expiration))
		}
		if t.casID != 0 {
			p.CasId = proto.Uint64(t.casID)
			p.ForCas = proto.Bool(true)
		}
		p.SetPolicy = pb.NewMemcacheSetRequest_SetPolicy(policy)
		req.Item[i] = p
	}
	res := &pb.MemcacheSetResponse{}
	e := make([]os.Error, len(item))
	if err := c.Call("memcache", "Set", req, res); err != nil {
		for i := range e {
			e[i] = err
		}
		return e
	}
	if len(e) != len(res.SetStatus) {
		for i := range e {
			e[i] = ErrServerError
		}
		return e
	}
	for i := range e {
		switch res.SetStatus[i] {
		case pb.MemcacheSetResponse_STORED:
			e[i] = nil
		case pb.MemcacheSetResponse_NOT_STORED:
			e[i] = ErrNotStored
		case pb.MemcacheSetResponse_EXISTS:
			e[i] = ErrCASConflict
		default:
			e[i] = ErrServerError
		}
	}
	return e
}
Пример #8
0
func makeLoginResult(succeeded bool, reason int32) (msg *protocol.Message) {
	loginResult := &protocol.LoginResult{
		Succeeded: proto.Bool(succeeded),
		Reason:    protocol.NewLoginResult_Reason(reason),
	}

	return &protocol.Message{
		LoginResult: loginResult,
		Type:        protocol.NewMessage_Type(protocol.Message_LOGINRESULT),
	}
}
Пример #9
0
func newTestMessage() *pb.MyMessage {
	msg := &pb.MyMessage{
		Count: proto.Int32(42),
		Name:  proto.String("Dave"),
		Quote: proto.String(`"I didn't want to go."`),
		Pet:   []string{"bunny", "kitty", "horsey"},
		Inner: &pb.InnerMessage{
			Host:      proto.String("footrest.syd"),
			Port:      proto.Int32(7001),
			Connected: proto.Bool(true),
		},
		Others: []*pb.OtherMessage{
			&pb.OtherMessage{
				Key:   proto.Int64(0xdeadbeef),
				Value: []byte{1, 65, 7, 12},
			},
			&pb.OtherMessage{
				Weight: proto.Float32(6.022),
				Inner: &pb.InnerMessage{
					Host: proto.String("lesha.mtv"),
					Port: proto.Int32(8002),
				},
			},
		},
		Bikeshed: pb.NewMyMessage_Color(pb.MyMessage_BLUE),
		Somegroup: &pb.MyMessage_SomeGroup{
			GroupField: proto.Int32(8),
		},
		// One normally wouldn't do this.
		// This is an undeclared tag 13, as a varint (wire type 0) with value 4.
		XXX_unrecognized: []byte{13<<3 | 0, 4},
	}
	ext := &pb.Ext{
		Data: proto.String("Big gobs for big rats"),
	}
	if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil {
		panic(err)
	}

	// Add an unknown extension. We marshal a pb.Ext, and fake the ID.
	b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")})
	if err != nil {
		panic(err)
	}
	b = append(proto.EncodeVarint(104<<3|proto.WireBytes), b...)
	proto.SetRawExtension(msg, 104, b)

	// Extensions can be plain fields, too, so let's test that.
	b = append(proto.EncodeVarint(105<<3|proto.WireVarint), 19)
	proto.SetRawExtension(msg, 105, b)

	return msg
}
Пример #10
0
// chasing a moving target with exec here. currently it's kind of
// clumsy to pull out the return code. with luck the target will
// move again in a way i like.
func runPlugin(cmd, env []string, timeout int64) (result *CheckResult) {
	var output bytes.Buffer
	rc := 0
	log.Printf("running check %s", cmd)

	/* c := exec.Command(cmd[0], cmd...)*/
	c := exec.Command(cmd[0], cmd[1:]...)
	c.Stdout = &output
	starttime := time.Nanoseconds()
	err := c.Start()
	if err != nil {
		log.Fatal("Error running command ", cmd, ": ", err)
	}
	defer c.Process.Release()
	timer := time.AfterFunc(timeout, func() { c.Process.Kill() })
	err = c.Wait()
	timer.Stop()
	endtime := time.Nanoseconds()
	/* log.Print(msg)*/
	if err != nil {
		if msg, ok := err.(*os.Waitmsg); ok {
			rc = msg.ExitStatus()
		} else {
			log.Print("Error running command ", cmd, ": ", err)
		}
	}

	result = &CheckResult{
		StartTimestamp: proto.Int64(starttime),
		EndTimestamp:   proto.Int64(endtime),
		Status:         NewCheckStatus(CheckStatus(rc)),
		CheckPassive:   proto.Bool(*flagPassive),
	}
	switch rc {
	case 0, 1, 2, 3:
		// this is ok!
		log.Printf("%s: returned %s", cmd, CheckStatus_name[int32(rc)])
		result.Status = NewCheckStatus(CheckStatus(rc))
		result.CheckOutput = proto.String(string(bytes.TrimSpace(output.Bytes())))
		break
	default:
		// XXX check for timeout/sig9, presently assumed
		log.Printf("%s: return code %d", cmd, rc)
		result.Status = NewCheckStatus(CheckStatus_UNKNOWN)
		result.CheckOutput = proto.String(fmt.Sprintf("UNKNOWN: Command timed out after %d seconds\n", *flagCmdTimeout) + string(bytes.TrimSpace(output.Bytes())))
	}
	return result
}
Пример #11
0
func runOnce(c appengine.Context, f func(appengine.Context) error, opts *TransactionOptions) error {
	// Begin the transaction.
	t := &transaction{Context: c}
	req := &pb.BeginTransactionRequest{
		App: proto.String(c.FullyQualifiedAppID()),
	}
	if opts != nil && opts.XG {
		req.AllowMultipleEg = proto.Bool(true)
	}
	if err := t.Context.Call("datastore_v3", "BeginTransaction", req, &t.transaction, nil); err != nil {
		return err
	}

	// Call f, rolling back the transaction if f returns a non-nil error, or panics.
	// The panic is not recovered.
	defer func() {
		if t.finished {
			return
		}
		t.finished = true
		// Ignore the error return value, since we are already returning a non-nil
		// error (or we're panicking).
		c.Call("datastore_v3", "Rollback", &t.transaction, &pb.VoidProto{}, nil)
	}()
	if err := f(t); err != nil {
		return err
	}
	t.finished = true

	// Commit the transaction.
	res := &pb.CommitResponse{}
	err := c.Call("datastore_v3", "Commit", &t.transaction, res, nil)
	if ae, ok := err.(*appengine_internal.APIError); ok {
		if appengine.IsDevAppServer() {
			// The Python Dev AppServer raises an ApplicationError with error code 2 (which is
			// Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.".
			if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." {
				return ErrConcurrentTransaction
			}
		}
		if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) {
			return ErrConcurrentTransaction
		}
	}
	return err
}
Пример #12
0
// callNext issues a datastore_v3/Next RPC to advance a cursor, such as that
// returned by a query with more results.
func callNext(c appengine.Context, res *pb.QueryResult, offset, limit int32, zlp zeroLimitPolicy) error {
	if res.Cursor == nil {
		return errors.New("datastore: internal error: server did not return a cursor")
	}
	// TODO: should I eventually call datastore_v3/DeleteCursor on the cursor?
	req := &pb.NextRequest{
		Cursor: res.Cursor,
		Offset: proto.Int32(offset),
	}
	if limit != 0 || zlp == zeroLimitMeansZero {
		req.Count = proto.Int32(limit)
	}
	if res.CompiledCursor != nil {
		req.Compile = proto.Bool(true)
	}
	res.Reset()
	return c.Call("datastore_v3", "Next", req, res, nil)
}
Пример #13
0
func (client *Client) sendChannelTree(channel *Channel) {
	chanstate := &mumbleproto.ChannelState{
		ChannelId: proto.Uint32(uint32(channel.Id)),
		Name:      proto.String(channel.Name),
	}
	if channel.parent != nil {
		chanstate.Parent = proto.Uint32(uint32(channel.parent.Id))
	}

	if channel.HasDescription() {
		if client.Version >= 0x10202 {
			chanstate.DescriptionHash = channel.DescriptionBlobHashBytes()
		} else {
			buf, err := globalBlobstore.Get(channel.DescriptionBlob)
			if err != nil {
				panic("Blobstore error.")
			}
			chanstate.Description = proto.String(string(buf))
		}
	}

	if channel.Temporary {
		chanstate.Temporary = proto.Bool(true)
	}

	chanstate.Position = proto.Int32(int32(channel.Position))

	links := []uint32{}
	for cid, _ := range channel.Links {
		links = append(links, uint32(cid))
	}
	chanstate.Links = links

	err := client.sendProtoMessage(MessageChannelState, chanstate)
	if err != nil {
		client.Panic(err.String())
	}

	for _, subchannel := range channel.children {
		client.sendChannelTree(subchannel)
	}
}
// GetMulti is a batch version of Get. The returned map from keys to items may
// have fewer elements than the input slice, due to memcache cache misses.
// Each key must be at most 250 bytes in length.
func GetMulti(c appengine.Context, key []string) (map[string]*Item, os.Error) {
	keyAsBytes := make([][]byte, len(key))
	for i, k := range key {
		keyAsBytes[i] = []byte(k)
	}
	req := &pb.MemcacheGetRequest{
		Key:    keyAsBytes,
		ForCas: proto.Bool(true),
	}
	res := &pb.MemcacheGetResponse{}
	if err := c.Call("memcache", "Get", req, res); err != nil {
		return nil, err
	}
	m := make(map[string]*Item, len(res.Item))
	for _, p := range res.Item {
		t := protoToItem(p)
		m[t.Key] = t
	}
	return m, nil
}
Пример #15
0
// Close flushes outstanding buffered writes and finalizes the blob. After
// calling Close the key can be retrieved by calling Key.
func (w *Writer) Close() (closeErr error) {
	defer func() {
		// Save the error for Key
		w.closeErr = closeErr
	}()
	if w.closed {
		return errorf("Writer is already closed")
	}
	w.closed = true
	w.flush()
	if w.writeErr != nil {
		return w.writeErr
	}
	req := &files.CloseRequest{
		Filename: proto.String(w.filename),
		Finalize: proto.Bool(true),
	}
	res := &files.CloseResponse{}
	return w.c.Call("file", "Close", req, res, nil)
}
// Close flushes outstanding buffered writes and finalizes the blob. After
// calling Close the key can be retrieved by calling Key.
func (w *Writer) Close() (closeErr os.Error) {
	defer func() {
		// Save the error for Key
		w.closeErr = closeErr
	}()
	if w.closed {
		return errorf("Writer is already closed")
	}
	w.closed = true
	w.flush()
	if w.writeErr != nil {
		return w.writeErr
	}
	req := &files.CloseRequest{
		Filename: proto.String(w.filename),
		Finalize: proto.Bool(true),
	}
	res := &files.CloseResponse{}
	if err := w.c.Call("file", "Close", req, res); err != nil {
		return err
	}
	handle := w.filename[len(blobstoreFileDirectory):]
	if !strings.HasPrefix(handle, creationHandlePrefix) {
		w.blobKey = appengine.BlobKey(handle)
		return nil
	}
	query := datastore.NewQuery("__BlobInfo__").
		Filter("creation_handle =", handle).
		KeysOnly().
		Limit(1)
	key, err := query.Run(w.c).Next(nil)
	if err != nil {
		if err != datastore.Done {
			return errorf("error looking up __BlobInfo__ entity for creation_handle %q: %v", handle, key)
		}
		return errorf("didn't find __BlobInfo__ entity for creation_handle %q", handle)
	}
	w.blobKey = appengine.BlobKey(key.StringID())
	return nil
}
Пример #17
0
// Create begins creating a new blob. The provided mimeType if non-empty
// is stored in the blob's BlobInfo in datastore, else defaults to
// application/octet-stream. The returned Writer should be written to,
// then closed, and then its Key method can be called to retrieve the
// newly-created blob key if there were no errors.
func Create(c appengine.Context, mimeType string) (*Writer, error) {
	if mimeType == "" {
		mimeType = "application/octet-stream"
	}
	req := &files.CreateRequest{
		Filesystem:  proto.String("blobstore"),
		ContentType: files.NewFileContentType_ContentType(files.FileContentType_RAW),
		Parameters: []*files.CreateRequest_Parameter{
			&files.CreateRequest_Parameter{
				Name:  proto.String("content_type"),
				Value: proto.String(mimeType),
			}},
	}
	res := &files.CreateResponse{}
	if err := c.Call("file", "Create", req, res, nil); err != nil {
		return nil, err
	}

	w := &Writer{
		c:        c,
		filename: *res.Filename,
	}
	if !strings.HasPrefix(w.filename, blobstoreFileDirectory) {
		return nil, errorf("unexpected filename from files service")
	}

	oreq := &files.OpenRequest{
		Filename:      res.Filename,
		ContentType:   files.NewFileContentType_ContentType(files.FileContentType_RAW),
		OpenMode:      files.NewOpenRequest_OpenMode(files.OpenRequest_APPEND),
		ExclusiveLock: proto.Bool(true),
	}
	ores := &files.OpenResponse{}
	if err := c.Call("file", "Open", oreq, ores, nil); err != nil {
		return nil, err
	}
	return w, nil
}
Пример #18
0
/*
func SubMsg(data []byte, t int32, encap bool) []byte {
        header := NewSubHeader()
        header.Type = proto.Int32(t)
        header.Encap = proto.Bool(encap)
        hdrdata,_ := proto.Marhal(header)
        hdrlen := uint32(len(hdrdata))
        datalen :=  uint32(len(data))
        buf := make([]byte, 8+hdrlen+datalen)
        binary.Write(this.SBuffer, binary.BigEndian, [2]uint32{hdrlen,datalen})
        copy(buf[8:8+len(hdrdata)],hdrdata)
        copy(buf[8+len(hdrdata):-1], data)
        return buf

}
func UnSubMsg(data []byte) (*SubHeader, []byte) {
    var hdrlen uint32
    var datalen uint32
    hdr,err := data[0:8]
    if err != nil  {
        return nil,err
    }
    fmt.Printf("len(data) = %d\n", len(data))
    err = binary.Read(data[0:4], binary.BigEndian, &hdrlen)
        if err != nil { return nil,nil,err }
    err = binary.Read(data[4:8], binary.BigEndian, &datalen)
        if err != nil { return nil,nil,err }
            fmt.Printf("hdrlen=%d, datalen=%d\n", hdrlen, datalen)
    if !(hdrlen < 96 && datalen < 16000 ) {
        return nil,nil,os.ENOMEM
    }
    hdrdata := make(Buf, hdrlen)
    newdata := make(Buf, datalen)
    tmp,err := this.Read(this.Buffer[0:hdrlen])
    if err != nil {
        //this.Conn.Close()
        return nil,nil,err
    }
    copy(hdrdata,tmp)
    header := NewHeader()
    err = proto.Unmarshal(hdrdata, header)
    if err != nil {
        return nil,nil,err
    }
    tmp,err = this.Read(this.Buffer[0:datalen])
    if err != nil {
        return nil,nil,err
    }
    copy(newdata,tmp)


    return header, newdata,nil
}
*/
func (this *ProtoProxy) SendMsg(data []byte, port int32, t int32, encap bool) {
	h := NewHot(func(shared map[string]interface{}) {
		//self := shared["self"].(*GenericHot)
		header := NewHeader()
		header.Type = proto.Int32(t)
		header.Port = proto.Int32(port)
		header.Encap = proto.Bool(encap)
		hdrdata, err := proto.Marshal(header)
		if err != nil {
			fmt.Printf("%s\n", err)
			return
		}
		hdrlen := uint32(len(hdrdata))
		datalen := uint32(len(data))
		binary.Write(this.SBuffer, binary.BigEndian, [2]uint32{hdrlen, datalen})
		copy(this.SBuffer[8:8+len(hdrdata)], hdrdata)
		copy(this.SBuffer[8+len(hdrdata):8+len(hdrdata)+len(data)], data)
		//fmt.Printf("Writing this: [%d]%s\n", len(this.SBuffer[0:hdrlen+len(data)]), this.SBuffer[0:hdrlen+len(data)])
		this.Conn.Write(this.SBuffer[0 : 8+len(hdrdata)+len(data)])
	})
	this.QueryHot(h)

}
Пример #19
0
func (this *ProtoHandler) Declinebool() {
	msg := NewAcceptBool()
	msg.Accept = proto.Bool(false)
	data, _ := proto.Marshal(msg)
	this.Proxy.SendMsg(data, 0, 0, false)
}
Пример #20
0
// Handle user state changes
func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
	userstate := &mumbleproto.UserState{}
	err := proto.Unmarshal(msg.buf, userstate)
	if err != nil {
		client.Panic(err.String())
	}

	actor, ok := server.clients[client.Session]
	if !ok {
		log.Panic("Client not found in server's client map.")
		return
	}
	target := actor
	if userstate.Session != nil {
		target, ok = server.clients[*userstate.Session]
		if !ok {
			client.Panic("Invalid session in UserState message")
			return
		}
	}

	userstate.Session = proto.Uint32(target.Session)
	userstate.Actor = proto.Uint32(actor.Session)

	// Does it have a channel ID?
	if userstate.ChannelId != nil {
		// Destination channel
		dstChan, ok := server.Channels[int(*userstate.ChannelId)]
		if !ok {
			return
		}

		// If the user and the actor aren't the same, check whether the actor has MovePermission on
		// the user's curent channel.
		if actor != target && !server.HasPermission(actor, target.Channel, MovePermission) {
			client.sendPermissionDenied(actor, target.Channel, MovePermission)
			return
		}

		// Check whether the actor has MovePermission on dstChan.  Check whether user has EnterPermission
		// on dstChan.
		if !server.HasPermission(actor, dstChan, MovePermission) && !server.HasPermission(target, dstChan, EnterPermission) {
			client.sendPermissionDenied(target, dstChan, EnterPermission)
			return
		}

		// fixme(mkrautz): Check whether the channel is full.
	}

	if userstate.Mute != nil || userstate.Deaf != nil || userstate.Suppress != nil || userstate.PrioritySpeaker != nil {
		// Disallow for SuperUser
		if target.IsSuperUser() {
			client.sendPermissionDeniedType("SuperUser")
			return
		}

		// Check whether the actor has 'mutedeafen' permission on user's channel.
		if !server.HasPermission(actor, target.Channel, MuteDeafenPermission) {
			client.sendPermissionDenied(actor, target.Channel, MuteDeafenPermission)
			return
		}

		// Check if this was a suppress operation. Only the server can suppress users.
		if userstate.Suppress != nil {
			client.sendPermissionDenied(actor, target.Channel, MuteDeafenPermission)
			return
		}
	}

	// Comment set/clear
	if userstate.Comment != nil {
		comment := *userstate.Comment

		// Clearing another user's comment.
		if target != actor {
			// Check if actor has 'move' permissions on the root channel. It is needed
			// to clear another user's comment.
			if !server.HasPermission(actor, server.root, MovePermission) {
				client.sendPermissionDenied(actor, server.root, MovePermission)
				return
			}

			// Only allow empty text.
			if len(comment) > 0 {
				client.Panic("Cannot clear another user's comment")
				return
			}
		}

		// todo(mkrautz): Check if the text is allowed.
	}

	// Texture change
	if userstate.Texture != nil {
		// Check the length of the texture
	}

	// Registration
	if userstate.UserId != nil {
		// If user == actor, check for SelfRegisterPermission on root channel.
		// If user != actor, check for RegisterPermission permission on root channel.
		permCheck := Permission(NonePermission)
		uid := *userstate.UserId
		if target == actor {
			permCheck = SelfRegisterPermission
		} else {
			permCheck = RegisterPermission
		}
		if uid >= 0 || !server.HasPermission(actor, server.root, SelfRegisterPermission) {
			client.sendPermissionDenied(actor, server.root, permCheck)
			return
		}

		// We can't register a user with an empty hash.
		if len(target.CertHash) == 0 {
			client.sendPermissionDeniedTypeUser("MissingCertificate", target)
		}
	}

	// Prevent self-targetting state changes to be applied to other users
	// That is, if actor != user, then:
	//   Discard message if it has any of the following things set:
	//      - SelfDeaf
	//      - SelfMute
	//      - Texture
	//      - PluginContext
	//      - PluginIdentity
	//      - Recording
	if actor != target && (userstate.SelfDeaf != nil || userstate.SelfMute != nil ||
		userstate.Texture != nil || userstate.PluginContext != nil || userstate.PluginIdentity != nil ||
		userstate.Recording != nil) {
		client.Panic("Invalid UserState")
		return
	}

	broadcast := false

	if userstate.Texture != nil && target.user != nil {
		key, err := globalBlobstore.Put(userstate.Texture)
		if err != nil {
			log.Panicf("Blobstore error: %v", err.String())
		}

		if target.user.TextureBlob != key {
			target.user.TextureBlob = key
		} else {
			userstate.Texture = nil
		}

		broadcast = true
	}

	if userstate.SelfDeaf != nil {
		target.SelfDeaf = *userstate.SelfDeaf
		if target.SelfDeaf {
			userstate.SelfDeaf = proto.Bool(true)
			target.SelfMute = true
		}
		broadcast = true
	}

	if userstate.SelfMute != nil {
		target.SelfMute = *userstate.SelfMute
		if !target.SelfMute {
			userstate.SelfDeaf = proto.Bool(false)
			target.SelfDeaf = false
		}
	}

	if userstate.PluginContext != nil {
		target.PluginContext = userstate.PluginContext
	}

	if userstate.PluginIdentity != nil {
		target.PluginIdentity = *userstate.PluginIdentity
	}

	if userstate.Comment != nil && target.user != nil {
		key, err := globalBlobstore.Put([]byte(*userstate.Comment))
		if err != nil {
			log.Panicf("Blobstore error: %v", err.String())
		}

		if target.user.CommentBlob != key {
			target.user.CommentBlob = key
		} else {
			userstate.Comment = nil
		}

		broadcast = true
	}

	if userstate.Mute != nil || userstate.Deaf != nil || userstate.Suppress != nil || userstate.PrioritySpeaker != nil {
		if userstate.Deaf != nil {
			target.Deaf = *userstate.Deaf
			if target.Deaf {
				userstate.Mute = proto.Bool(true)
			}
		}
		if userstate.Mute != nil {
			target.Mute = *userstate.Mute
			if !target.Mute {
				userstate.Deaf = proto.Bool(false)
				target.Deaf = false
			}
		}
		if userstate.Suppress != nil {
			target.Suppress = *userstate.Suppress
		}
		if userstate.PrioritySpeaker != nil {
			target.PrioritySpeaker = *userstate.PrioritySpeaker
		}
		broadcast = true
	}

	if userstate.Recording != nil && *userstate.Recording != target.Recording {
		target.Recording = *userstate.Recording

		txtmsg := &mumbleproto.TextMessage{}
		txtmsg.TreeId = append(txtmsg.TreeId, uint32(0))
		if target.Recording {
			txtmsg.Message = proto.String(fmt.Sprintf("User '%s' started recording", target.ShownName()))
		} else {
			txtmsg.Message = proto.String(fmt.Sprintf("User '%s' stopped recording", target.ShownName()))
		}

		server.broadcastProtoMessageWithPredicate(MessageTextMessage, txtmsg, func(client *Client) bool {
			return client.Version < 0x10203
		})

		broadcast = true
	}

	if userstate.UserId != nil {
		// fixme(mkrautz): Registration is currently unhandled.
		log.Printf("handleUserState: (Self)Register not implemented yet!")
		userstate.UserId = nil
	}

	if userstate.ChannelId != nil {
		channel, ok := server.Channels[int(*userstate.ChannelId)]
		if ok {
			server.userEnterChannel(target, channel, userstate)
			broadcast = true
		}
	}

	if broadcast {
		// This variable denotes the length of a zlib-encoded "old-style" texture.
		// Mumble and Murmur used qCompress and qUncompress from Qt to compress
		// textures that were sent over the wire. We can use this to determine
		// whether a texture is a "new style" or an "old style" texture.
		texture := userstate.Texture
		texlen := uint32(0)
		if texture != nil && len(texture) > 4 {
			texlen = uint32(texture[0])<<24 | uint32(texture[1])<<16 | uint32(texture[2])<<8 | uint32(texture[3])
		}
		if texture != nil && len(texture) > 4 && texlen != 600*60*4 {
			// The sent texture is a new-style texture.  Strip it from the message
			// we send to pre-1.2.2 clients.
			userstate.Texture = nil
			err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
				return client.Version < 0x10202
			})
			if err != nil {
				log.Panic("Unable to broadcast UserState")
			}
			// Re-add it to the message, so that 1.2.2+ clients *do* get the new-style texture.
			userstate.Texture = texture
		} else {
			// Old style texture.  We can send the message as-is.
			err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
				return client.Version < 0x10202
			})
			if err != nil {
				log.Panic("Unable to broadcast UserState")
			}
		}

		// If a texture hash is set on user, we transmit that instead of
		// the texture itself. This allows the client to intelligently fetch
		// the blobs that it does not already have in its local storage.
		if userstate.Texture != nil && target.user != nil && target.user.HasTexture() {
			userstate.Texture = nil
			userstate.TextureHash = target.user.TextureBlobHashBytes()
		} else if target.user == nil {
			userstate.Texture = nil
			userstate.TextureHash = nil
		}

		// Ditto for comments.
		if userstate.Comment != nil && target.user.HasComment() {
			userstate.Comment = nil
			userstate.CommentHash = target.user.CommentBlobHashBytes()
		} else if target.user == nil {
			userstate.Comment = nil
			userstate.CommentHash = nil
		}

		err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
			return client.Version >= 0x10203
		})
		if err != nil {
			log.Panic("Unable to broadcast UserState")
		}
	}
}
Пример #21
0
func (server *Server) sendUserList(client *Client) {
	for _, connectedClient := range server.clients {
		if connectedClient.state != StateClientReady {
			continue
		}
		if connectedClient == client {
			continue
		}

		userstate := &mumbleproto.UserState{
			Session:   proto.Uint32(connectedClient.Session),
			Name:      proto.String(connectedClient.ShownName()),
			ChannelId: proto.Uint32(uint32(connectedClient.Channel.Id)),
		}

		if connectedClient.IsRegistered() {
			userstate.UserId = proto.Uint32(uint32(connectedClient.UserId()))

			if connectedClient.user.HasTexture() {
				// Does the client support blobs?
				if client.Version >= 0x10203 {
					userstate.TextureHash = connectedClient.user.TextureBlobHashBytes()
				} else {
					buf, err := globalBlobstore.Get(connectedClient.user.TextureBlob)
					if err != nil {
						log.Panicf("Blobstore error: %v", err.String())
					}
					userstate.Texture = buf
				}
			}

			if connectedClient.user.HasComment() {
				// Does the client support blobs?
				if client.Version >= 0x10203 {
					userstate.CommentHash = connectedClient.user.CommentBlobHashBytes()
				} else {
					buf, err := globalBlobstore.Get(connectedClient.user.CommentBlob)
					if err != nil {
						log.Panicf("Blobstore error: %v", err.String())
					}
					userstate.Comment = proto.String(string(buf))
				}
			}

			if len(connectedClient.user.CertHash) > 0 {
				userstate.Hash = proto.String(connectedClient.user.CertHash)
			}
		}

		if connectedClient.Mute {
			userstate.Mute = proto.Bool(true)
		}
		if connectedClient.Suppress {
			userstate.Suppress = proto.Bool(true)
		}
		if connectedClient.SelfMute {
			userstate.SelfMute = proto.Bool(true)
		}
		if connectedClient.SelfDeaf {
			userstate.SelfDeaf = proto.Bool(true)
		}
		if connectedClient.PrioritySpeaker {
			userstate.PrioritySpeaker = proto.Bool(true)
		}
		if connectedClient.Recording {
			userstate.Recording = proto.Bool(true)
		}
		if connectedClient.PluginContext != nil || len(connectedClient.PluginContext) > 0 {
			userstate.PluginContext = connectedClient.PluginContext
		}
		if len(connectedClient.PluginIdentity) > 0 {
			userstate.PluginIdentity = proto.String(connectedClient.PluginIdentity)
		}

		err := client.sendProtoMessage(MessageUserState, userstate)
		if err != nil {
			// Server panic?
			continue
		}
	}
}
Пример #22
0
// ACL set/query
func (server *Server) handleAclMessage(client *Client, msg *Message) {
	acl := &mumbleproto.ACL{}
	err := proto.Unmarshal(msg.buf, acl)
	if err != nil {
		client.Panic(err.String())
	}

	// Look up the channel this ACL message operates on.
	channel, ok := server.Channels[int(*acl.ChannelId)]
	if !ok {
		return
	}

	// Does the user have permission to update or look at ACLs?
	if !server.HasPermission(client, channel, WritePermission) && !(channel.parent != nil && server.HasPermission(client, channel.parent, WritePermission)) {
		client.sendPermissionDenied(client, channel, WritePermission)
		return
	}

	reply := &mumbleproto.ACL{}
	reply.ChannelId = proto.Uint32(uint32(channel.Id))

	channels := []*Channel{}
	users := map[int]bool{}

	// Query the current ACL state for the channel
	if acl.Query != nil && *acl.Query != false {
		reply.InheritAcls = proto.Bool(channel.InheritACL)
		// Walk the channel tree to get all relevant channels.
		// (Stop if we reach a channel that doesn't have the InheritACL flag set)
		iter := channel
		for iter != nil {
			channels = append([]*Channel{iter}, channels...)
			if iter == channel || iter.InheritACL {
				iter = iter.parent
			} else {
				iter = nil
			}
		}

		// Construct the protobuf ChanACL objects corresponding to the ACLs defined
		// in our channel list.
		reply.Acls = []*mumbleproto.ACL_ChanACL{}
		for _, iter := range channels {
			for _, chanacl := range iter.ACL {
				if iter == channel || chanacl.ApplySubs {
					mpacl := &mumbleproto.ACL_ChanACL{}
					mpacl.Inherited = proto.Bool(iter != channel)
					mpacl.ApplyHere = proto.Bool(chanacl.ApplyHere)
					mpacl.ApplySubs = proto.Bool(chanacl.ApplySubs)
					if chanacl.UserId >= 0 {
						mpacl.UserId = proto.Uint32(uint32(chanacl.UserId))
						users[chanacl.UserId] = true
					} else {
						mpacl.Group = proto.String(chanacl.Group)
					}
					mpacl.Grant = proto.Uint32(uint32(chanacl.Allow))
					mpacl.Deny = proto.Uint32(uint32(chanacl.Deny))
					reply.Acls = append(reply.Acls, mpacl)
				}
			}
		}

		parent := channel.parent
		allnames := channel.GroupNames()

		// Construct the protobuf ChanGroups that we send back to the client.
		// Also constructs a usermap that is a set user ids from the channel's groups.
		reply.Groups = []*mumbleproto.ACL_ChanGroup{}
		for name, _ := range allnames {
			var (
				group  *Group
				pgroup *Group
			)
			group = channel.Groups[name]
			if parent != nil {
				pgroup = parent.Groups[name]
			}

			mpgroup := &mumbleproto.ACL_ChanGroup{}
			mpgroup.Name = proto.String(name)

			mpgroup.Inherit = proto.Bool(true)
			if group != nil {
				mpgroup.Inherit = proto.Bool(group.Inherit)
			}

			mpgroup.Inheritable = proto.Bool(true)
			if group != nil {
				mpgroup.Inheritable = proto.Bool(group.Inheritable)
			}

			mpgroup.Inherited = proto.Bool(pgroup != nil && pgroup.Inheritable)

			// Add the set of user ids that this group affects to the user map.
			// This is used later on in this function to send the client a QueryUsers
			// message that maps user ids to usernames.
			if group != nil {
				toadd := map[int]bool{}
				for uid, _ := range group.Add {
					users[uid] = true
					toadd[uid] = true
				}
				for uid, _ := range group.Remove {
					users[uid] = true
					toadd[uid] = false, false
				}
				for uid, _ := range toadd {
					mpgroup.Add = append(mpgroup.Add, uint32(uid))
				}
			}
			if pgroup != nil {
				for uid, _ := range pgroup.Members() {
					users[uid] = true
					mpgroup.InheritedMembers = append(mpgroup.InheritedMembers, uint32(uid))
				}
			}

			reply.Groups = append(reply.Groups, mpgroup)
		}

		if err := client.sendProtoMessage(MessageACL, reply); err != nil {
			client.Panic(err.String())
		}

		// Map the user ids in the user map to usernames of users.
		// fixme(mkrautz): This requires a persistent datastore, because it retrieves registered users.
		queryusers := &mumbleproto.QueryUsers{}
		for uid, _ := range users {
			queryusers.Ids = append(queryusers.Ids, uint32(uid))
			queryusers.Names = append(queryusers.Names, "Unknown")
		}
		if len(queryusers.Ids) > 0 {
			client.sendProtoMessage(MessageQueryUsers, reply)
		}

		// Set new groups and ACLs
	} else {

		// Get old temporary members
		oldtmp := map[string]map[int]bool{}
		for name, grp := range channel.Groups {
			oldtmp[name] = grp.Temporary
		}

		// Clear current ACLs and groups
		channel.ACL = []*ChannelACL{}
		channel.Groups = map[string]*Group{}

		// Add the received groups to the channel.
		channel.InheritACL = *acl.InheritAcls
		for _, pbgrp := range acl.Groups {
			changroup := NewGroup(channel, *pbgrp.Name)

			changroup.Inherit = *pbgrp.Inherit
			changroup.Inheritable = *pbgrp.Inheritable
			for _, uid := range pbgrp.Add {
				changroup.Add[int(uid)] = true
			}
			for _, uid := range pbgrp.Remove {
				changroup.Remove[int(uid)] = true
			}
			if temp, ok := oldtmp[*pbgrp.Name]; ok {
				changroup.Temporary = temp
			}

			channel.Groups[changroup.Name] = changroup
		}
		// Add the received ACLs to the channel.
		for _, pbacl := range acl.Acls {
			chanacl := NewChannelACL(channel)

			chanacl.ApplyHere = *pbacl.ApplyHere
			chanacl.ApplySubs = *pbacl.ApplySubs
			if pbacl.UserId != nil {
				chanacl.UserId = int(*pbacl.UserId)
			} else {
				chanacl.Group = *pbacl.Group
			}
			chanacl.Deny = Permission(*pbacl.Deny & AllPermissions)
			chanacl.Allow = Permission(*pbacl.Grant & AllPermissions)

			channel.ACL = append(channel.ACL, chanacl)
		}

		// Clear the server's ACL cache
		server.ClearACLCache()

		// Regular user?
		if !server.HasPermission(client, channel, WritePermission) && client.IsRegistered() || client.HasCertificate() {
			chanacl := NewChannelACL(channel)

			chanacl.ApplyHere = true
			chanacl.ApplySubs = false
			if client.IsRegistered() {
				chanacl.UserId = client.UserId()
			} else if client.HasCertificate() {
				chanacl.Group = "$" + client.CertHash
			}
			chanacl.Deny = Permission(NonePermission)
			chanacl.Allow = Permission(WritePermission | TraversePermission)

			channel.ACL = append(channel.ACL, chanacl)

			server.ClearACLCache()
		}

		// fixme(mkrautz): Sync channel to datastore
	}
}
Пример #23
0
	"log"
	"testing"

	"goprotobuf.googlecode.com/hg/proto"

	pb "./testdata/_obj/test_proto"
)

var cloneTestMessage = &pb.MyMessage{
	Count: proto.Int32(42),
	Name:  proto.String("Dave"),
	Pet:   []string{"bunny", "kitty", "horsey"},
	Inner: &pb.InnerMessage{
		Host:      proto.String("niles"),
		Port:      proto.Int32(9099),
		Connected: proto.Bool(true),
	},
	Others: []*pb.OtherMessage{
		&pb.OtherMessage{
			Value: []byte("some bytes"),
		},
	},
	RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
}

func init() {
	ext := &pb.Ext{
		Data: proto.String("extension"),
	}
	if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
		log.Fatalf("SetExtension: %v", err)
Пример #24
0
// RoundTrip issues a single HTTP request and returns its response. Per the
// http.RoundTripper interface, RoundTrip only returns an error if there
// was a problem with the request being malformed
// (ErrInvalidFetchRequest) or the URL Fetch proxy fails (ErrFetch).
// Note that HTTP response codes such as 5xx, 403, 404, etc are not
// errors as far as the transport is concerned and will be returned
// with err set to nil.
func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err os.Error) {
	methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method]
	if !ok {
		return nil, &ErrInvalidFetchRequest{"Unsupported method: " + req.Method, nil}
	}

	method := pb.URLFetchRequest_RequestMethod(methNum)

	freq := &pb.URLFetchRequest{
		Method:                        &method,
		Url:                           proto.String(req.URL.String()),
		FollowRedirects:               proto.Bool(false), // http.Client's responsibility
		MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate),
	}

	if t.DeadlineSeconds != 0 {
		freq.Deadline = proto.Float64(t.DeadlineSeconds)
	}

	for k, vals := range req.Header {
		for _, val := range vals {
			freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{
				Key:   proto.String(k),
				Value: proto.String(val),
			})
		}
	}
	if methodAcceptsRequestBody[req.Method] {
		freq.Payload, err = ioutil.ReadAll(req.Body)
		if err != nil {
			return nil, &ErrInvalidFetchRequest{"Failed to read body", err}
		}
	}

	fres := &pb.URLFetchResponse{}
	if err := t.Context.Call("urlfetch", "Fetch", freq, fres); err != nil {
		return nil, &ErrFetch{err.String()}
	}

	res = &http.Response{}
	res.StatusCode = int(*fres.StatusCode)
	res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode))
	res.Header = http.Header(make(map[string][]string))
	res.RequestMethod = req.Method

	// Faked:
	res.ProtoMajor = 1
	res.ProtoMinor = 1
	res.Proto = "HTTP/1.1"
	res.Close = true

	for _, h := range fres.Header {
		hkey := http.CanonicalHeaderKey(*h.Key)
		hval := *h.Value
		if hkey == "Content-Length" {
			// Will get filled in below for all but HEAD requests.
			if req.Method == "HEAD" {
				res.ContentLength, _ = strconv.Atoi64(hval)
			}
			continue
		}
		res.Header.Add(hkey, hval)
	}

	if req.Method != "HEAD" {
		res.ContentLength = int64(len(fres.Content))
	}

	truncated := proto.GetBool(fres.ContentWasTruncated)
	res.Body = &bodyReader{content: fres.Content, truncated: truncated}
	return
}
Пример #25
0
// The last part of authentication runs in the server's synchronous handler.
func (server *Server) finishAuthenticate(client *Client) {
	// If the client succeeded in proving to the server that it should be granted
	// the credentials of a registered user, do some sanity checking to make sure
	// that user isn't already connected.
	//
	// If the user is already connected, try to check whether this new client is
	// connecting from the same IP address. If that's the case, disconnect the
	// previous client and let the new guy in.
	if client.user != nil {
		found := false
		for _, connectedClient := range server.clients {
			if connectedClient.UserId() == client.UserId() {
				found = true
				break
			}
		}
		// The user is already present on the server.
		if found {
			// todo(mkrautz): Do the address checking.
			client.RejectAuth("UsernameInUse", "A client is already connected using those credentials.")
			return
		}

		// No, that user isn't already connected. Move along.
	}

	// Add the client to the connected list
	client.Session = server.GenSessionId()
	server.clients[client.Session] = client

	// First, check whether we need to tell the other connected
	// clients to switch to a codec so the new guy can actually speak.
	server.updateCodecVersions()

	client.sendChannelList()

	// Add the client to the host slice for its host address.
	host := client.tcpaddr.IP.String()
	server.hmutex.Lock()
	server.hclients[host] = append(server.hclients[host], client)
	server.hmutex.Unlock()

	userstate := &mumbleproto.UserState{
		Session:   proto.Uint32(client.Session),
		Name:      proto.String(client.ShownName()),
		ChannelId: proto.Uint32(0),
	}
	if client.IsRegistered() {
		userstate.UserId = proto.Uint32(uint32(client.UserId()))

		if client.user.HasTexture() {
			// Does the client support blobs?
			if client.Version >= 0x10203 {
				userstate.TextureHash = client.user.TextureBlobHashBytes()
			} else {
				buf, err := globalBlobstore.Get(client.user.TextureBlob)
				if err != nil {
					log.Panicf("Blobstore error: %v", err.String())
				}
				userstate.Texture = buf
			}
		}

		if client.user.HasComment() {
			// Does the client support blobs?
			if client.Version >= 0x10203 {
				userstate.CommentHash = client.user.CommentBlobHashBytes()
			} else {
				buf, err := globalBlobstore.Get(client.user.CommentBlob)
				if err != nil {
					log.Panicf("Blobstore error: %v", err.String())
				}
				userstate.Comment = proto.String(string(buf))
			}
		}
	}

	server.userEnterChannel(client, server.root, userstate)
	if err := server.broadcastProtoMessage(MessageUserState, userstate); err != nil {
		// Server panic?
	}

	server.sendUserList(client)

	sync := &mumbleproto.ServerSync{}
	sync.Session = proto.Uint32(client.Session)
	sync.MaxBandwidth = proto.Uint32(server.MaxBandwidth)
	if client.IsSuperUser() {
		sync.Permissions = proto.Uint64(uint64(AllPermissions))
	} else {
		server.HasPermission(client, server.root, EnterPermission)
		perm := server.aclcache.GetPermission(client, server.root)
		if !perm.IsCached() {
			client.Panic("Corrupt ACL cache")
			return
		}
		perm.ClearCacheBit()
		sync.Permissions = proto.Uint64(uint64(perm))
	}
	if err := client.sendProtoMessage(MessageServerSync, sync); err != nil {
		client.Panic(err.String())
		return
	}

	err := client.sendProtoMessage(MessageServerConfig, &mumbleproto.ServerConfig{
		AllowHtml:          proto.Bool(true),
		MessageLength:      proto.Uint32(1000),
		ImageMessageLength: proto.Uint32(1000),
	})
	if err != nil {
		client.Panic(err.String())
		return
	}

	client.state = StateClientReady
	client.clientReady <- true
}