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 }