A4 (B8 Platform) Discussion Discussion forum for the B8 Audi A4 produced from 2008.5

Troubleshooting MMI 3G

Thread Tools
 
Search this Thread
 
Old 01-31-2024, 02:53 PM
  #61  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

Originally Posted by drgertol
With that, I think my first experiment will be to inject some myLogger messages in MyAudiConnector.processDownloadEvent to start. --g
Keep digging into this.myTransport.getDataElementList() or perhaps result.getXmlResult() to see where it gets to reading the InputStream as a char stream - something seems to fall apart at that point.

Originally Posted by drgertol
@sm87 -- What do you make of this. Using j2sdk1.4_30 on Solaris x64, javac returns "wrong version" for a class file extracted from LSD.JXE:
Yeah I mentioned that here: https://www.audiworld.com/forums/a4-.../#post25874713
I don't know the reason behind it, I did verify the source data for those values in lsd.jxe is what it is (it's not a bug in jxe2jar). Anyway, I think you can safely change that field (bytes 6 and 7) to "48" and the j9 runtime doesn't mind as far as I can tell, either patch jxe2jar or do a post-processing pass to update the .class files.

I'm not entirely convinced that jxe2jar produces runnable/compilable .class files, another strategy is to provide your own stubs for classes/interfaces during compilation but then omit them from the .jar/classpath so in "prod" it will use equivalent types from lsd.jxe.
Old 01-31-2024, 07:44 PM
  #62  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

I think this is failing in LeanSoapTransport.login(). Consider the working example that comes from LSD.JXE (using PPP mode):
Code:
02:41 LC62DBUG:LeanSoapTransport: Performing login with IMSI: 2840332xxxxxxxx VIN: WAUZZZ4G4CNxxxxxx
02:41 LC62DBUG:HttpProxyConfiguration: using custom https-implementation
02:41 LC62DBUG:MonitoredOutputStream: flush() not supported - ignored!
02:41 LC62DBUG:MonitoredOutputStream: flush() not supported - ignored!
02:41 LC62DBUG:HttpsUrlConnection: Connecting to car-001.audi-online.de:443...
02:42 LC62DBUG:HttpsUrlConnection: HTTPS handshaking to car-001.audi-online.de...
...
02:44 LC62DBUG:HttpsUrlConnection: Sending http request (POST)/auth/services/AudiConnectorWS/
...
02:46 LC62DBUG:ListCookieHandler.put: Accepted cookie: JSESSIONID=F5AE69BC87C56979E6CDE7216BA94459.tomcat00
02:46 LC62DBUG:LeanSoapTransport: 569 bytes of uncompressed data
02:46 LC62DBUG:MonitoredInputStream: (SSL) socket closed
02:46 LC62DBUG:LeanSoapTransport: pairing status 3 error code: 0 error desc: OK
and in our case using the (broken) myaudiconnect_nodataconnection.jar, we don't get to the "LeanSoapTransport: 569 bytes of uncompressed data" or the "LeanSoapTransport: pairing status" debug messages.
The login() method:
Code:
  Result login(LoginInfo loginInfo) throws IOException, AudiSOAPClientException
{
    String string;
    this.myLogger.logDebug("LeanSoapTransport: Performing login with IMSI: " + loginInfo.getImsi() + " VIN: " + loginInfo.getVin());
    String string2 = this.myXmlHandler.generateLoginRequest(loginInfo);
    try {
      string = this.sendReceiveInternal(string2, this.myConfig.props.getEPR());
    }
    catch (UnknownHostException unknownHostException) {
      this.myLogger.logWarning("LeanSoapTransport: unknown host during login - trying DNS reset");
      Resolver.res_init(this.myLogger);
      string = this.sendReceiveInternal(string2, this.myConfig.props.getEPR());
    }
    Result result = this.myXmlHandler.parseResult(string);
    if (result != null) {
      this.myLogger.logDebug("LeanSoapTransport: pairing status " + result.getPairingStatus() + " error code: " + result.getErrorCode() + " error desc: " + result.getErrorDesc());
    }
    this.checkForEPRUpdate(result);
    return result;
  }
So, it seems to me that myXmlHandler.parseResult(string) is returning null here. --g
Old 01-31-2024, 10:00 PM
  #63  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

@drgertol, so if you visit those auth endpoints from a browser (and tell it to ignore the self-signed VAG certs):

https://car.audi-online.com/auth/ser...diConnectorWS/ returns a "Content-Encoding: gzip" header while https://car-001.audi-online.de/auth/...diConnectorWS/ does not.

Both return the same 586 byte error response, with 777 bytes transferred from car-001.audi-online.de versus 400 bytes received from car.audi-online.com - so that checks out.

Looking over the code you posted on vwvortex, in the working run sendReceiveInternal() ought to skip over "if (bl) {" block which adds an extra GZIPInputStream layer over InputStream - maybe the impl is buggy and corrupts the data.

Another 'smell' is since there no Content-Type response header it will end up calling "new InputStreamReader(inputStream, null);" and - at least in the version I decompiled - com.ibm.oti.io.CharacterConverter.getConverter(nul l) would throw. A simple thing to try is have getContentEncoding() return "UTF-8" by default instead of null. However since at least one of the runs is successful perhaps there's no issue. (To get all pedantic here HTTP/1.1 says ISO-8859-1 is the default encoding, it shouldn't be deferring to the JVM's default).
Old 02-01-2024, 07:37 AM
  #64  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@sm87 -- Teasing out the expected header content from the two URLs is handy; given your findings, we should expect US clients to require GZIPInputStream (from LSD.JXE), while EU/ROW Going back to LeanSoapTransport, then, it seems I'm interesting seeing what's happening in sendReceiveInternal after storeCookies (since we know this succeeds). Note that we find this source decompiled from the (working) LSD.JXE:
Code:
      InputStream inputStream = uRLConnection.getInputStream();
      String string4 = uRLConnection.getHeaderField("Content-Encoding");
      boolean bl = string4 != null ? string4.compareToIgnoreCase("gzip") == 0 : false;
      String string5 = LeanSoapTransport.getContentEncoding(uRLConnection);
      this.b.storeCookies(this.c, uRLConnection);
      if (bl) {
        int n2;
        object2 = new ByteArrayOutputStream(1024);
        objectArray = new byte[1024];
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        while ((n2 = ((InputStream)bufferedInputStream).read((byte[])objectArray, 0, 1024)) != -1) {
          if (!this.e) {
            ((InputStream)bufferedInputStream).close();
            return "";
          }
          ((ByteArrayOutputStream)object2).write((byte[])objectArray, 0, n2);
          if (((ByteArrayOutputStream)object2).size() <= 256) continue;
          throw new IOException("compressed SOAP data too long! message > 65536 byte");
        }
        ((InputStream)bufferedInputStream).close();
        this.c.logDebug(((Object)new StringBuffer().append("LeanSoapTransport: received ").append(((ByteArrayOutputStream)object2).size()).append(" bytes of gzip compressed data ")).toString());
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(((ByteArrayOutputStream)object2).toByteArray());
        inputStream = new GZIPInputStream(byteArrayInputStream);
      }
It looks like this is my likely initial focus, if I can get LeanSoapTransport.java to compile successfully. --g
Old 02-01-2024, 10:04 AM
  #65  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

Let's see if I can (re)compile LeanSoapTransport.java extracted from myaudiconnect_nodataconnection.jar in preparation for the run-time experiment :
Code:
$ javac14 -classpath .. de/audi/myaudi/impl/leansoap/LeanSoapTransport.java
de/audi/myaudi/impl/leansoap/LeanSoapTransport.java:24: cannot resolve symbol
symbol  : class Closeable
location: package io
import java.io.Closeable;
               ^
de/audi/myaudi/impl/leansoap/LeanSoapTransport.java:132: cannot resolve symbol
symbol  : method getPairingStatus ()
location: class java.lang.Object
      if (3 == object.getPairingStatus()) {
                     ^
...
de/audi/myaudi/impl/leansoap/LeanSoapTransport.java:271: inconvertible types
found   : java.lang.Object[]
required: char[]
        ((StringBuffer)object).append((char[])objectArray, 0, n);
                                              ^
20 errors
Nope. Hmmm, I'm not finding file Closeable.class in dir java/io extracted from LSD.JXE. Grrr. OK, full disclosure: I haven't poked at compiling any Java code since grad school 25 years ago for my dissertation research. Ugh. --g
Old 02-01-2024, 08:54 PM
  #66  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

Originally Posted by drgertol
I haven't poked at compiling any Java code since grad school 25 years ago for my dissertation research. Ugh. --g
So you're picking up java again right where you left off then?

java.io.Closeable is not supposed to make an appearance until Java 1.5 (maybe that .jar was created some time later with a newer SDK than lsd.jxe). If it's not in lsd.jxe then presumably nothing in that codebase would be calling through the interface, removing "implements Closeable" should be safe. But since it's a super simple interface (https://docs.oracle.com/javase/6/doc...Closeable.html), could also just define it yourself for compilation:
Code:
package java.io;
public abstract interface Closeable { void close(); }
object.getPairingStatus() error is from reusing a single Object variable for various purposes - works perfectly well in java bytecode and likely the work of the optimizer, but the original Java was different than what the decompiler spat out. Change it to something like:
Code:
      Result result = this.a(loginInfo);
      if (result != null && 3 == result.getPairingStatus()) { ...
Similar for "(char[])objectArray" just declare a new char[] variable instead of recycling and casting the Object[] variable.
Old 02-02-2024, 06:41 AM
  #67  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@sm87 -- Thanks for the (off-topic) Java lesson(s) here. The jar file extracts without issue with file date stamps of 16 Sep 2009. Inspection of the class major version shows that they are all "45" -- JDK 1.1 ? Referring back to your post #35, we see this reported by your HelloWorld class:
Code:
J9 - VM for the Java(TM) platform, Version 2.3
java.vm.version=2.3
java.runtime.version=2.3
java.specification.name=J2ME Foundation Specification
java.class.version=47.0
java.vm.info=IBM J9 2.3 QNX sh4-32  (JIT enabled)
Might we conclude that this is a J2ME 1.3 run-time environment ?
And I (sort of) get what's happening with the generic "Object object" construction; changing this to, say, "Result rx", gets past the unresolved symbol error, now to work through resulting type issues:
Code:
$ javac14 -classpath .. de/audi/myaudi/impl/leansoap/LeanSoapTransport.java
de/audi/myaudi/impl/leansoap/LeanSoapTransport.java:140: incompatible types
found   : java.lang.String
required: de.audi.connector.types.Result
    rx = this.determineEPRbyElementType(dataElementTypeEnum);
                                       ^
de/audi/myaudi/impl/leansoap/LeanSoapTransport.java:142: inconvertible types
found   : de.audi.connector.types.Result
required: java.lang.String
    String string2 = this.sendReceiveInternal(string, (String)rx);
                                                              ^
...
So, some progress, at least. --g
Old 02-02-2024, 03:16 PM
  #68  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

After making some educated guesses about the context of the generic Object types in LeanSoapTransport, for example, before:
Code:
  Result getData(LoginInfo loginInfo, DataElementTypeEnum dataElementTypeEnum) throws IOException, AudiSOAPClientException {
    Object object;
    if (!this.isLoggedIn) {
      object = this.login(loginInfo);
      if (3 == object.getPairingStatus()) {
        this.isLoggedIn = true;
      } else {
        this.isLoggedIn = false;
        throw new NoPairingException(object.getErrorCode(), "getData failed", object.getPairingStatus());
      }
    }
    object = this.determineEPRbyElementType(dataElementTypeEnum);
    String string = this.myXmlHandler.generateGetDataRequest(loginInfo, dataElementTypeEnum.getId());
    String string2 = this.sendReceiveInternal(string, (String)object);
    Result result = this.myXmlHandler.parseResult(string2);
    return result;
  }
and after:
Code:
  Result getData(LoginInfo loginInfo, DataElementTypeEnum dataElementTypeEnum) throws IOException, AudiSOAPClientException {
//  Object object;
    Result ra;
    if (!this.isLoggedIn) {
      ra = this.login(loginInfo);
      if (3 == ra.getPairingStatus()) {
        this.isLoggedIn = true;
      } else {
        this.isLoggedIn = false;
        throw new NoPairingException(ra.getErrorCode(), "getData failed", ra.getPairingStatus());
      }
    }
    String a = this.determineEPRbyElementType(dataElementTypeEnum);
    String string = this.myXmlHandler.generateGetDataRequest(loginInfo, dataElementTypeEnum.getId());  
    String string2 = this.sendReceiveInternal(string, a);
    Result result = this.myXmlHandler.parseResult(string2);
    return result; 
  }
and removing the Closeable type, for example:
Code:
//      closeable = new ByteArrayOutputStream(1024);
        ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
LeanSoapTransport.java compiles without complaint, so we'll see how this behaves when I drop it back in the myaudiconnect_nodataconnection.jar and give it a spin in the car this weekend.

BTW, I couldn't find the trick to making Closeable work here; with your suggestion, I got this:
Code:
de/audi/myaudi/impl/leansoap/LeanSoapTransport.java:279: incompatible types
found   : java.io.InputStreamReader
required: java.io.Closeable
    closeable = new InputStreamReader(inputStream, string5);
                ^
So I reworked this as:
Code:
    InputStreamReader isr = new InputStreamReader(inputStream, string5);
    BufferedReader bufferedReader = new BufferedReader(isr);
--g
Old 02-03-2024, 03:42 PM
  #69  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@sm87 -- Thanks again for your post #63, above. After running some experiments in our cold garage today, I can report that myAudi on-line contacts work properly in fair/DLINK mode.

Your hint about gzip content-encoding was an important observation. With a few logDebug statements in LeanSoapTransport.sendReceiveInternal, I saw this in the syslog:
Code:
02:50 LC62DBUG:HttpsUrlConnection: Connecting to car.audi-online.com:443...
02:50 LC62DBUG:HttpsUrlConnection: HTTPS handshaking to car.audi-online.com...
02:52 LC62DBUG:HttpsUrlConnection: Sending http request (POST)/auth/services/AudiConnectorWS/
02:54 LC62DBUG:ListCookieHandler.put: Accepted cookie: JSESSIONID=4CC20CC9D68F82DEB27BCA2B984EA160.tomcat00
02:54 LC62DBUG:LST.srd: string4: null
02:54 LC62DBUG:LST.srd: string5: UTF-8
02:54 LC62DBUG:LST.srd: after if(bl)
02:54 LC62EROR:LeanSoapTransport.sendReceiveInternal: Caught ioException - transmission incomplete
02:54 LC62EROR:MyAudiConnector.processDownloadEvent: Exception during download of information null 
java.io.CharConversionException
        at java.io.InputStreamReader.conve...
02:54 LC62WARN:MyAudiConnector: async exception occured (error code: 2002, msg: Connection to myAudi server failed. (null), rtype:0)
As noted earlier, the code never enters "if(bl)" block in sendReceiveInternal because string4 is null. And if we expect "Content-Encoding: gzip" from the US server, we should also expect to enter the "if(bl)" block. The java.io.CharConversionException inside java.io.InputStreamReader suggested a problem with the data being read from the server. Without spending any time trying to tease out why string4 is null, I just set "bl = true" to get at gzip decompression, and on the next test run, voila:
Code:
02:57 LC62DBUG:HttpsUrlConnection: Connecting to car.audi-online.com:443...
02:57 LC62DBUG:HttpsUrlConnection: HTTPS handshaking to car.audi-online.com...
02:59 LC62DBUG:HttpsUrlConnection: Sending http request (POST)/auth/services/AudiConnectorWS/
03:00 LC62DBUG:ListCookieHandler.put: Accepted cookie: JSESSIONID=E380CC8886B79EA9AB02CA444720113B.tomcat00
03:00 LC62DBUG:LST.srd: string4: null
03:00 LC62DBUG:LST.srd: string5: UTF-8
03:00 LC62DBUG:LST.srd: in if-bl !
03:00 LC62DBUG:MonitoredInputStream: (SSL) socket closed
03:00 LC62DBUG:LeanSoapTransport: received 256 bytes of gzip compressed data
03:00 LC62DBUG: LST.srd: after if(bl)
03:00 LC62DBUG: LST.srd: in while(bufferedReader) !
03:00 LC62DBUG: LST.srd: sb: <?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> soapenv:Body><ns5...
03:00 LC62DBUG:LeanSoapTransport: 569 bytes of uncompressed data
03:00 LC62DBUG:LeanSoapTransport: pairing status 3 error code: 0 error desc: OK
I'm a bit curious why this is broken in the .jar while the code in the .jxe behaves correctly. Maybe this will be a rainy weekend project, but for now, I'll clean up the LeanSoapTransport code and move on. Thanks for the pointers along the way. --g
Old 02-05-2024, 08:57 PM
  #70  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

@drgertol glad to hear you got it working. Seems like another reminder that rolling your own HTTP stack implementation is a bad idea, IBM.
I wonder how long they plan to keep that service going, the SSL certs including the root expired ages ago. Should be pretty simple to reverse engineer the service if it comes down to it.

As to the original topic, the eeprom from my original MMI unit is dead so I think the only option left is to find someone with ODIS to deactivate CP. I plugged in the old unit back into the car and tried to read the eeprom with OBDEleven but app kept hanging (reads bits from the new one OK though). I desoldered the eeprom chip and tried in a programmer but couldn't get it to show any signs of life (possible I cooked it in the process..) anyway those 0.65mm pitch contacts are impossible to work with as far my skills go.


Quick Reply: Troubleshooting MMI 3G



All times are GMT -8. The time now is 10:15 AM.