예제 #1
0
  private void TL_RpcError(TL.Object obj) {
    int code = obj.getInt("error_code");
    String msg = obj.getString("error_message");

    Common.logError(String.format("rpc_error: %s (%d)\n", msg, code));

    Message req_msg = TLMessage.get(req_msg_id);
    if (req_msg == null) return;
    Common.logError("message object: " + req_msg.obj.name + ":" + req_msg.obj.type);

    int idx = msg.indexOf("_MIGRATE_");
    if (idx > 0) {
      String type = msg.substring(0, idx);

      String num = msg.substring(idx + 9);
      if ((idx = num.indexOf(":")) > 0) num = num.substring(0, idx);
      int dc_id = Integer.parseInt(num);
      Common.logError("redirect to dc: " + dc_id);

      MTProto m = MTProto.getConnection(dc_id, cb, reuseFlag);
      cb.onRedirect(m);
      if (type.equals("PHONE") || type.equals("NETWORK") || type.equals("USER")) dc_this = dc_id;

      m.sendMessage(req_msg);
    }
  }
예제 #2
0
  private void TL_BadMsgNotification(TL.Object obj) {
    int error_code = obj.getInt("error_code");

    Message msg = TLMessage.get(obj.getLong("bad_msg_id"));
    Common.logError("bad_msg: " + error_code + " " + msg.obj.name + ":" + msg.obj.type);

    if (error_code == 16 || error_code == 17) {
      time_delta = (int) ((cur_message_id >> 32) - Common.getUnixTime());
      last_message_id = 0;
    }

    if (error_code == 32 || error_code == 33) {
      Common.logError("cur seq: " + cur_msg_seq);
      Common.logError("old seq: " + seqno);
      if (!bad_seq) {
        session = GEN_session_id();
        seqno = 0;
        send_ping();
        bad_seq = true;
      }

      // seqno = cur_msg_seq + (cur_msg_seq % 2) + 100;
      //	session = GEN_session_id();
      //	seqno = 0;
    }

    if (obj.id == 0xedab447b) { // bad_server_salt
      server_salt = obj.getLong("new_server_salt");
      dcState.set("server_salt", server_salt);
    }

    retry(obj.getLong("bad_msg_id"));
  }
예제 #3
0
  private void send_client_DH_inner_data(long retry_id) {
    byte[] b_data = new byte[256];
    Common.random.nextBytes(b_data);

    BigInteger b = new BigInteger(1, b_data);
    BigInteger g_b = g.modPow(b, dh_prime);
    Common.logError(
        "g_b length: " + g_b.toByteArray().length + " -> " + Common.toBytes(g_b).length);

    BigInteger akey = g_a.modPow(b, dh_prime);
    Common.logError("auth_key: " + akey.toString());
    setAuthKey(Common.toBytes(akey));

    // gen data (client_DH_inner_data)
    TL.Object data_obj = TL.newObject("client_DH_inner_data", cl_nonce, sv_nonce, retry_id, g_b);
    byte[] data = data_obj.serialize();
    byte[] hash = Common.getSHA1(data);

    byte[] data_with_hash = new byte[(hash.length + data.length + 15) / 16 * 16];
    System.arraycopy(hash, 0, data_with_hash, 0, hash.length);
    System.arraycopy(data, 0, data_with_hash, hash.length, data.length);

    // send set_client_DH_params
    TL.Object req_obj =
        TL.newObject("set_client_DH_params", cl_nonce, sv_nonce, aes.IGE(data_with_hash, true));
    send(req_obj, false, false);
  }
예제 #4
0
  public void onReceive(ByteBuffer b) {
    if (b.remaining() == 4) {
      Common.logError("invalid packet:");
      byte[] data = new byte[b.remaining()];
      b.get(data);
      Common.print_dump(data);
      //	retry( TLMessage.keyAt(  TLMessage.size() - 1) );
      return;
    }

    try {
      if (b.getLong() == 0) { // auth_key_id
        b.getLong(); // message_id
        b.getInt(); // message length
        process(TL.deserialize(b));
      } else {
        byte[] msg_key = new byte[16];
        b.get(msg_key);
        byte[] data = new byte[b.remaining()];
        b.get(data);

        synchronized (aes) {
          aes.prepare(false, msg_key, auth_key);
          data = aes.IGE(data, false);
        }

        ByteBuffer btmp = ByteBuffer.wrap(data);
        btmp.order(ByteOrder.LITTLE_ENDIAN);
        server_salt = btmp.getLong();
        btmp.getLong(); // session_id
        cur_message_id = btmp.getLong(); // message_id
        cur_msg_seq = btmp.getInt(); // seq_no
        // if (cur_msg_seq > seqno)
        //	seqno = cur_msg_seq + cur_msg_seq % 2;
        int bsize = btmp.getInt();
        if (bsize < 0 || bsize > 1024 * 1024) {
          Common.print_dump(btmp.array());
          Common.logError(new String(btmp.array()));
          Common.logError("FFFUUUUUUUUUUU!!!");
        }

        b = BufferAlloc(bsize);
        btmp.get(b.array());
        b.getInt();
        ack_message(cur_msg_seq, cur_message_id);
        b.position(0);

        process(TL.deserialize(b));
        send_accept();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
예제 #5
0
 public void retry(long message_id) {
   Common.logError("retry");
   Message msg = TLMessage.get(message_id);
   if (msg == null) return;
   TLMessage.delete(message_id);
   sendMessage(msg);
 }
예제 #6
0
  public void onAuthorized() {
    dcState.set("auth_key", auth_key);
    dcState.set("server_salt", server_salt);

    long upd_delta = (long) Common.getUnixTime() - (long) dc_date;
    if (Main.mtp == this && upd_delta > 5 * 60) api_help_getConfig();

    if (!bind && this != Main.mtp) {
      final MTProto m = this;
      Common.logError("exportAuthorization");
      Main.mtp.api(
          new TL.OnResultRPC() {
            @Override
            public void onResultRPC(TL.Object result, Object param, boolean error) {
              if (!error) return;
              if (result.id != 0xdf969c2d) return; // auth.ExportedAuthorization
              Common.logError("importAuthorization");
              m.api(
                  null,
                  null,
                  "auth.importAuthorization",
                  result.getInt("id"),
                  result.getBytes("bytes"));
            }
          },
          null,
          "auth.exportAuthorization",
          dcState.getInt("id"));
      return;
    }

    if (bind) cb.onBind();
    send_queue();
  }
예제 #7
0
 public static MTProto getConnection(int dc_id, MTProtoListener callback, int reuseFlag) {
   MTProto m = getActiveMTP(dc_id, reuseFlag);
   if (m != null) {
     Common.logError("reuse");
     return m;
   }
   m = new MTProto(dc_id, callback, reuseFlag);
   mtp.add(m);
   return m;
 }
예제 #8
0
  // MTProto
  public MTProto(int dc_id, MTProtoListener callback, int reuseFlag) {
    this.reuseFlag = reuseFlag;
    cb = callback;
    for (int i = 0; i < dcStates.size(); i++)
      if (dcStates.get(i).getInt("id") == dc_id) {
        dcState = dcStates.get(i);
        // Common.hexStringToByteArray("23D03699CE2AB29BA2273084D95DA126EC3A1D55BE4C317615CE66609D5562BDC0EFDE5AE1F9185001C35781F622B31DF5294685559340DE7D5CC8D7F6F86AE049107D8E498EB2AC3D6FA735DF90648EEC34A6B7BE3A5075A455F5696DB39280BF68C1637E1580E1EBA3F0C12EF2C03B8E9B5ECCFD3E4885BF636863388E3EC9E9EF60C722FF9B45CD93FA5E8D0D277B45A6A9370860582A159187F2F352D418D195D8E9310B5559E170F51CB2056F6CB6DB586E9349192A1B7EAA50887C115A14F996F5A855E90E47635A81EA3048615F4FD91347D73335E5503179857D0D29132483271B28E6591172C3D94686BD96E91FDB7AD9591A526218B3DDFC7A2A09")
        setAuthKey(dcState.getBytes("auth_key"));
        bind = dcState.getBool("bind");
        seqno = dcState.getInt("seqno");
        session = dcState.getLong("session");
        server_salt = dcState.getLong("server_salt");
        Common.logError("session: " + session + " seqno: " + seqno);

        connected = false;
        Thread netThread = new Thread(transport = new TransportTCP(this, true));
        netThread.setPriority(Thread.MIN_PRIORITY);
        netThread.start();

        return;
      }
    Common.logError("dc not found: " + dc_id);
  }
예제 #9
0
파일: User.java 프로젝트: randhika/arcanum
 public void setTyping(int chat_id, boolean isTyping) {
   Common.logError(getTitle() + " is typing " + isTyping);
   if (typing != isTyping) {
     typing = isTyping;
     if (typing) {
       typing_time = Common.getUnixTime() + 6;
       typing_chat_id = chat_id;
     }
     ;
     Dialog dialog =
         chat_id != -1 ? Dialog.getDialog(-1, chat_id, true) : Dialog.getDialog(id, -1, true);
     Main.main.updateDialogItem(dialog);
     Main.main.updateUser(this);
   }
 }
예제 #10
0
  public void invoke(String name, TL.Object obj) {
    Method m;
    try {
      m = MTProto.class.getDeclaredMethod("TL_" + name.replace(".", "_"), TL.Object.class);
      m.setAccessible(true);
    } catch (Exception e) {
      Common.logWarning("not handled: Main::" + name);
      return;
    }

    try {
      Common.logInfo("invoke: Main::" + name);
      m.invoke(this, obj);
    } catch (Exception e) {
      Common.logError("invoke error in Main");
      e.printStackTrace();
    }
  }
예제 #11
0
  private void process(TL.Object obj) {
    //		if (obj instanceof TL.Vector)
    //			return;
    Method m;
    try {
      m = MTProto.class.getDeclaredMethod("TL_" + obj.type.replace(".", "_"), TL.Object.class);
      m.setAccessible(true);
    } catch (Exception e) {
      Common.logWarning("not handled: " + obj.type + " (" + obj.name + ")");
      return;
    }

    try {
      Common.logInfo("invoke: " + obj.type + " (" + obj.name + ")");
      m.invoke(this, obj);
    } catch (Exception e) {
      Common.logError("process error");
      e.printStackTrace();
    }
  }
예제 #12
0
  public void TL_messages_Dialogs(TL.Object obj) {
    User.addUsers(obj.getVector("users"));
    Chat.addChats(obj.getVector("chats"));

    // dialogs
    TL.Vector dialogs = obj.getVector("dialogs");
    for (int i = 0; i < dialogs.count; i++) {
      TL.Object dobj = dialogs.getObject(i);
      Dialog d = Dialog.getDialog(-1, dobj.getObject("peer"), true);
      d.updating = true;
    }

    // messages
    TL.Vector messages = obj.getVector("messages");
    for (int i = 0; i < messages.count; i++)
      cb.onMessage(messages.getObject(i), Dialog.MSG_HISTORY);

    for (int i = 0; i < dialogs.count; i++) {
      TL.Object dobj = dialogs.getObject(i);
      Dialog d = Dialog.getDialog(-1, dobj.getObject("peer"), true);
      if (dobj.getInt("top_message") == -7) // config_dialogs magic
      d.noHistory = true;
      d.unread_count = dobj.getInt("unread_count");
      d.updating = false;
      Main.main.updateDialog(d);
    }

    Common.logError("dialogs: " + Dialog.dialogs.size());

    // slice
    if (obj.name.equals("messages.dialogsSlice") && dialogs.count > 0) {
      int limit = obj.getInt("count") - Dialog.dialogs.size();
      if (limit > 0) api_messages_getDialogs(Dialog.dialogs.size(), 0, limit);
    }

    if (Main.main != null) Main.main.resetDialogs();
  }
예제 #13
0
  private void TL_ResPQ(TL.Object obj) {
    sv_nonce = obj.getBytes("server_nonce");
    BigInteger pq = new BigInteger(1, obj.getBytes("pq"));
    TL.Vector v_fp = obj.getVector("server_public_key_fingerprints");
    fp = v_fp.getLong(0);
    Common.logError("pq: " + pq.toString());

    // prime factorization for pq
    BigInteger q = Common.rho(pq);
    BigInteger p = pq.divide(q);
    if (p.compareTo(q) > 0) {
      BigInteger t = p;
      p = q;
      q = t;
    }
    SecureRandom rnd = new SecureRandom();
    new_nonce = new byte[32];
    rnd.nextBytes(new_nonce);

    // generate encrypted_data
    TL.Object data_obj = TL.newObject("p_q_inner_data", pq, p, q, cl_nonce, sv_nonce, new_nonce);

    byte[] data = data_obj.serialize();
    byte[] hash = Common.getSHA1(data);

    byte[] data_with_hash = new byte[255];
    System.arraycopy(hash, 0, data_with_hash, 0, hash.length);
    System.arraycopy(data, 0, data_with_hash, hash.length, data.length);
    GEN_random_bytes(data_with_hash, data.length + hash.length, 255);

    byte[] encrypted_data = Common.RSA(RSA_MODULUS, RSA_EXPONENT, data_with_hash);

    // req_DH_params
    TL.Object req_obj = TL.newObject("req_DH_params", cl_nonce, sv_nonce, p, q, fp, encrypted_data);
    send(req_obj, false, false);
  }
예제 #14
0
  public synchronized boolean sendMessage(Message msg) {
    if (msg == null) return false;

    if (!connected || (msg.encrypted && (auth_key == null || auth_key.length == 0)) || bad_seq) {
      Common.logError("add to queue " + connected + " " + msg.encrypted);
      TLMessageQueue.add(msg);
      return false;
    }
    ByteBuffer b = null;

    Common.logInfo("message send: " + msg.obj.name + ":" + msg.obj.type);
    byte[] msg_data = msg.obj.serialize();

    /*
    if (msg_data.length > 255) {
    	Common.logError("compress...");
    	byte[] data = Common.gzipDeflate(msg_data); // TODO: compress message data
    	if (data.length < msg_data.length && data.length > 32)
    		msg_data = TL.newObject("gzip_packed", data).serialize();
    }
    */

    if (msg.encrypted) {
      long message_id = GEN_message_id();
      TLMessage.put(message_id, msg);

      int size_real = 32 + msg_data.length;
      int size_padding = (size_real + 15) / 16 * 16;

      ByteBuffer p = BufferAlloc(size_padding);
      p.putLong(server_salt);
      p.putLong(session);
      p.putLong(message_id);

      if (msg.accept) seqno++;
      p.putInt(seqno);
      if (msg.accept) seqno++;

      p.putInt(msg_data.length);
      p.put(msg_data);
      byte[] data = p.array();
      GEN_random_bytes(data, p.position(), data.length);

      // encrypt data
      byte[] msg_key = Common.ASUB(Common.getSHA1(Common.ASUB(data, 0, size_real)), 4, 16);

      synchronized (aes) {
        aes.prepare(true, msg_key, auth_key);
        data = aes.IGE(data, true);
      }

      // write encrypted packet
      b = BufferAlloc(24 + data.length);
      b.putLong(auth_key_id);
      b.put(msg_key);
      b.put(data);
    } else {
      b = BufferAlloc(20 + msg_data.length);
      b.putLong(0);
      b.putLong(GEN_message_id());
      b.putInt(msg_data.length);
      b.put(msg_data);
    }

    try {
      synchronized (transport) {
        transport.send(b.array());
        return true;
      }
    } catch (Exception e) {
      return false;
    }
  }
예제 #15
0
 public void api_messages_getDialogs(int offset, int max_id, int limit) {
   Common.logError("get dialogs: " + offset + " " + max_id + " " + limit);
   api(null, null, "messages.getDialogs", offset, max_id, limit);
 }
예제 #16
0
 public void api_messages_getHistory(
     TL.Object peer, int offset, int max_id, int limit, TL.OnResultRPC result) {
   Common.logError("get history " + offset + " " + max_id + " " + limit);
   api(result, limit, "messages.getHistory", peer, offset, max_id, limit);
 }
예제 #17
0
파일: User.java 프로젝트: randhika/arcanum
  public void getPhoto(ImageView img) {
    final TL.Object location = getPhotoLocation();
    img.setTag(location);

    if (location == null) {
      img.setImageResource(getDefPhoto());
      return;
    }

    String path = FileQuery.exists(location);
    if (path != null) {
      Bitmap bmp = BitmapCache.get(path);
      if (bmp != null) {
        img.setImageBitmap(bmp);
        return;
      }
    }

    final WeakReference<ImageView> ref = new WeakReference<ImageView>(img);

    try {
      new FileQuery(
          location,
          null,
          new FileQuery.OnResultListener() {
            @Override
            public void onResult(TL.Object result) {
              ImageView img = ref.get();
              if (img == null || img.getTag() != location) return;

              final Bitmap bmp =
                  result != null
                      ? BitmapCache.loadBitmap(
                          result.getString("fileName"),
                          Main.SIZE_THUMB_USER,
                          Main.SIZE_THUMB_USER,
                          true,
                          false,
                          true)
                      : BitmapFactory.decodeResource(Main.main.getResources(), getDefPhoto());

              try {
                img.post(
                    new Runnable() {
                      @Override
                      public void run() {
                        ImageView img = ref.get();
                        if (img == null || img.getTag() != location) return;
                        img.setImageBitmap(bmp);
                      }
                    });
              } catch (Exception e) {
                Common.logError("error loading bitmap");
                e.printStackTrace();
              }
            }

            @Override
            public void onProgress(float progress) {}
          });
    } catch (Exception e) {
      Common.logError("error query file");
      e.printStackTrace();
    }
  }
예제 #18
0
 public void auth() {
   Common.logError("auth");
   TL.Object req_pq = TL.newObject("req_pq", cl_nonce = GEN_random_bytes(16));
   send(req_pq, false, false);
 }