Exemplo n.º 1
0
func (ch *controlChan) onOpenChannelMsg(msg *packet.OpenChannel) error {
	log := ch.conn.endpoint.log
	chanType := msg.GetChannelType()
	rawChanID := msg.GetChannelIdentifier()
	if rawChanID <= 0 || rawChanID >= math.MaxUint16 {
		return fmt.Errorf("attempted to open invalid channel ID: %v", rawChanID)
	}
	chanID := (uint16)(rawChanID) // So f*****g stupid.
	if ch.conn.isServer && (chanID&1 == 0) {
		return fmt.Errorf("client attempted to open even channel ID: %v", chanID)
	}
	if !ch.conn.isServer && (chanID&1 == 1) {
		return fmt.Errorf("server attempted to open odd channel ID: %v", chanID)
	}
	if ch.conn.chanMap[chanID] != nil {
		return fmt.Errorf("attempted to open duplicate channel ID: %v", chanID)
	}

	log.Printf("chan open attempt: %v (%d)", chanType, chanID)

	var newCh ricochetChan
	var err error
	switch chanType {
	case authHiddenServiceChannelType:
		if !ch.conn.isServer {
			return fmt.Errorf("attempted to open auth channel to client")
		}
		if ch.isAuthenticated {
			return fmt.Errorf("attempted to open auth channel when authed")
		}
		if ch.authChan != invalidChanID {
			return fmt.Errorf("attempted to open auth channel when one exists")
		}
		if newCh, err = newServerAuthHSChan(ch.conn, msg); err != nil {
			return err
		}
		ch.authChan = (int)(chanID)
	case contactReqChannelType:
		if !ch.conn.isServer {
			return fmt.Errorf("attempted to open contact req channel to client")
		}
		if !ch.isAuthenticated {
			return fmt.Errorf("attempted to open contact req channel pre-auth")
		}
		if ch.contactReqChan != invalidChanID {
			return fmt.Errorf("attempted to open contact req channel when one exists")
		}
		if newCh, err = newServerContactReqChan(ch.conn, msg); err != nil {
			return err
		}
		ch.contactReqChan = (int)(chanID)
	case chatChannelType:
		if !ch.isAuthenticated {
			return fmt.Errorf("attempted to open chat channel pre-auth")
		}
		if ch.incomingChatChan != invalidChanID {
			return fmt.Errorf("attempted to open chat channel when one exists")
		}
		if newCh, err = newServerChatChan(ch.conn, msg); err != nil {
			return err
		}
		ch.incomingChatChan = (int)(chanID)
	default:
		return fmt.Errorf("attempted to open unknown channel type")
	}

	// Send the response and add the channel to the global channel map.
	//
	// Note: The code will opt to tear down the connection instead of sending
	// any sort of failure response.  Rather rude, but that's arguably correct
	// behavior for most responses anyway.
	if newCh != nil && err == nil {
		if err = newCh.onOpenChannel(); err != nil {
			return err
		}

		ch.conn.Lock()
		defer ch.conn.Unlock()
		ch.conn.chanMap[chanID] = newCh
	}
	return err
}