javacommons/gcfprotocols/http/javasrc.s60/com/nokia/mj/impl/http/HttpConnectionNative.java
changeset 80 d6dafc5d983f
parent 49 35baca0e7a2e
child 87 1627c337e51e
equal deleted inserted replaced
78:71ad690e91f5 80:d6dafc5d983f
    76     protected final static int SETUP = 1;
    76     protected final static int SETUP = 1;
    77     protected final static int CONNECTED = 2;
    77     protected final static int CONNECTED = 2;
    78     protected final static int REQUEST_HEADERS_SENT = 3;
    78     protected final static int REQUEST_HEADERS_SENT = 3;
    79     protected final static int REQUEST_SENT = 4;
    79     protected final static int REQUEST_SENT = 4;
    80     protected final static int REPLY_RECEIVED = 5;
    80     protected final static int REPLY_RECEIVED = 5;
       
    81     protected final static int PARTIAL_REQUEST_SENT = 6;
    81 
    82 
    82     // Character constants
    83     // Character constants
    83     protected final static char HASH = '#';
    84     protected final static char HASH = '#';
    84     protected final static int QUESTION_MARK = 63;
    85     protected final static int QUESTION_MARK = 63;
    85     protected final static int CR = 13;
    86     protected final static int CR = 13;
   129     protected AccessPoint iApn = null;
   130     protected AccessPoint iApn = null;
   130     private static boolean iIsSessionDeleted = false;
   131     private static boolean iIsSessionDeleted = false;
   131     private boolean iTrustedSuite = true;
   132     private boolean iTrustedSuite = true;
   132     private int iRespTimeOut = -1;
   133     private int iRespTimeOut = -1;
   133     private int iRetries = 0;
   134     private int iRetries = 0;
       
   135     private int iRequestBodyLen = -1;
       
   136     private int iTotalPostDataLen = 0;
       
   137     private boolean iEndOfRequest = false;
       
   138     private boolean iChunkedTransfer = false;
       
   139 
       
   140     protected final BlockingOperation iPostDataBlock;
   134 
   141 
   135     static
   142     static
   136     {
   143     {
   137         try
   144         try
   138         {
   145         {
   192 
   199 
   193         // Blocking operations to allow async native transactions
   200         // Blocking operations to allow async native transactions
   194         iTransactionBlock = new BlockingOperation();
   201         iTransactionBlock = new BlockingOperation();
   195         iNativeDataReadyForRead = new BlockingOperation();
   202         iNativeDataReadyForRead = new BlockingOperation();
   196         iNativeDataReadyForRead.setResult(BlockingOperation.BLOCKED);
   203         iNativeDataReadyForRead.setResult(BlockingOperation.BLOCKED);
       
   204         iPostDataBlock = new BlockingOperation();
   197         iFinalizer = registerForFinalization();
   205         iFinalizer = registerForFinalization();
   198         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- HttpConnectionNative new ");
   206         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- HttpConnectionNative new ");
   199 
   207 
   200         ApplicationInfo appInfo = ApplicationInfo.getInstance();
   208         ApplicationInfo appInfo = ApplicationInfo.getInstance();
   201         String runtime = appInfo.getRuntimeType();
   209         String runtime = appInfo.getRuntimeType();
   811                 iRequestProperties.put(aKey, val);
   819                 iRequestProperties.put(aKey, val);
   812             }
   820             }
   813             else
   821             else
   814             {
   822             {
   815                 iRequestProperties.put(aKey, aValue);
   823                 iRequestProperties.put(aKey, aValue);
       
   824             }
       
   825             if (aKey.equals(TRANSFER_ENCODING))
       
   826             {
       
   827                 String tmp = aValue.toLowerCase();
       
   828                 if (tmp.equals("chunked"))
       
   829                 {
       
   830                     iChunkedTransfer = true;
       
   831                     iRequestBodyLen = -1;    // as per RFC, precedence should be give to "transfer-encoding" when "content-length" is also set.
       
   832                 }
       
   833             }
       
   834             if (aKey.equals(CONTENT_LENGTH))
       
   835             {
       
   836                 iRequestBodyLen = Integer.parseInt(aValue);
       
   837 
   816             }
   838             }
   817         }
   839         }
   818         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- setRequestProperty(String, String)" );
   840         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- setRequestProperty(String, String)" );
   819         return;
   841         return;
   820     }
   842     }
   862         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
   884         Logger.LOG(Logger.ESOCKET, Logger.EInfo,
   863                    "-------- inputStreamClosed()");
   885                    "-------- inputStreamClosed()");
   864     }
   886     }
   865 
   887 
   866 
   888 
   867     protected synchronized void outputStreamFlushed() throws IOException
   889     private void waitForPostDataCompletion()
   868     {
   890     {
   869         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ outputStreamFlushed()" );
   891         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+waitForPostDataCompletion");
       
   892         iPostDataBlock.waitForCompletion();
       
   893         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "-waitForPostDataCompletion");
       
   894 
       
   895     }
       
   896 
       
   897     private synchronized void sendPartialRequest() throws IOException
       
   898     {
       
   899         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "HTTP sendPartialRequest() ");
   870         switch (iState)
   900         switch (iState)
   871         {
   901         {
   872         case SETUP:
   902         case SETUP:
   873         case CONNECTED:
   903         case CONNECTED:
   874         case REQUEST_HEADERS_SENT:
   904 
   875             ensureResponse();
   905             synchronized (iPostDataBlock.getLock())
       
   906             {
       
   907                 synchronized (iPostDataBlock)
       
   908                 {
       
   909                     sendRequest(true);
       
   910                     iPostedDataStream.reset();
       
   911                     waitForPostDataCompletion();
       
   912                 }
       
   913             }
   876             break;
   914             break;
   877 
   915 
   878         default:
   916         case PARTIAL_REQUEST_SENT :
   879             // No-op
   917 
   880             ;
   918             byte[] postData = iPostedDataStream.toByteArray();
       
   919             iPostedDataStream.reset();
       
   920             int len = -1;
       
   921             if (postData != null)
       
   922             {
       
   923                 len = postData.length;
       
   924                 iTotalPostDataLen = iTotalPostDataLen + len;
       
   925             }
       
   926             // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "HTTP content-len = "+iRequestBodyLen + " totalflushed = "+ iTotalPostDataLen +" os len = "+ postData.length);
       
   927             if (iTotalPostDataLen == iRequestBodyLen)
       
   928             {
       
   929                 iEndOfRequest = true;
       
   930             }
       
   931 
       
   932             synchronized (iPostDataBlock.getLock())
       
   933             {
       
   934                 synchronized (iPostDataBlock)
       
   935                 {
       
   936                     int err = _postData(iNativeTransactionHande, postData, len, iEndOfRequest);
       
   937 
       
   938                     if (err != 0)
       
   939                     {
       
   940                         throwIOException("Unable to write data .Symbian os error code: "
       
   941                                          + err);
       
   942                     }
       
   943                     if (iEndOfRequest == false)
       
   944                     {
       
   945                         // wait until http stack consumes the data
       
   946                         waitForPostDataCompletion();
       
   947                     }
       
   948                     else
       
   949                     {
       
   950                         // request complete, wait until the first chunk of response header arrives
       
   951                         synchronized (iTransactionBlock.getLock())
       
   952                         {
       
   953                             synchronized (iTransactionBlock)
       
   954                             {
       
   955                                 waitForTransaction();
       
   956                             }
       
   957                         }
       
   958 
       
   959                     }  // end else
       
   960                 } // end syn
       
   961 
       
   962             } // end syn getlock
       
   963 
       
   964             break;
       
   965         }
       
   966 
       
   967     }
       
   968 
       
   969     protected synchronized void outputStreamFlushed() throws IOException
       
   970     {
       
   971         int postDataLength = iPostedDataStream.size();
       
   972 
       
   973 
       
   974         if ((iRequestBodyLen > postDataLength) || (iChunkedTransfer == true))
       
   975         {
       
   976             // chunked http request will be sent in two cases
       
   977             // 1) application sets "Content-Lenght" request header and writes to output stream multiple times using flush
       
   978             //     like a sequence of os.write(); os.flush() operations
       
   979             // 2) application sets "Transfer-Encoding" request header and writes to ouput stream multiple times using flush
       
   980             sendPartialRequest();
       
   981 
       
   982         }
       
   983         else
       
   984         {
       
   985             switch (iState)
       
   986             {
       
   987             case SETUP:
       
   988             case CONNECTED:
       
   989             case REQUEST_HEADERS_SENT:
       
   990                 ensureResponse();
       
   991                 break;
       
   992 
       
   993             default:
       
   994                 // No-op
       
   995                 ;
       
   996             }
   881         }
   997         }
   882         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- outputStreamFlushed()" );
   998         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- outputStreamFlushed()" );
   883     }
   999     }
   884 
  1000 
   885     protected synchronized void outputStreamClosed() throws IOException
  1001     protected synchronized void outputStreamClosed() throws IOException
   936         }
  1052         }
   937         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- ensureOpen()" );
  1053         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- ensureOpen()" );
   938         return;
  1054         return;
   939     }
  1055     }
   940 
  1056 
       
  1057     private void waitForResponse() throws IOException
       
  1058     {
       
  1059         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "HTTP flush case, waitForResponse: total len =  "+iRequestBodyLen + " totalflushed = "+ iTotalPostDataLen );
       
  1060         if (iEndOfRequest == false)
       
  1061         {
       
  1062             // chunked http request was sent, but end of request not sent
       
  1063             // only in case of "transfer-encoding" request header, control will come here
       
  1064             iEndOfRequest = true;
       
  1065             byte[] postData = iPostedDataStream.toByteArray();
       
  1066             iPostedDataStream.reset();
       
  1067             int len = -1;
       
  1068             if (postData != null)
       
  1069             {
       
  1070                 len = postData.length;
       
  1071                 // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "More data left in os, len = "+len);
       
  1072                 iTotalPostDataLen = iTotalPostDataLen + len;
       
  1073             }
       
  1074             int err = _postData(iNativeTransactionHande, postData, len , iEndOfRequest);
       
  1075             if (err != 0)
       
  1076             {
       
  1077                 throwIOException("Unable to write data .Symbian os error code: "
       
  1078                                  + err);
       
  1079             }
       
  1080             synchronized (iTransactionBlock.getLock())
       
  1081             {
       
  1082                 synchronized (iTransactionBlock)
       
  1083                 {
       
  1084                     waitForTransaction();
       
  1085                 }
       
  1086             }
       
  1087         }
       
  1088         getResponse();
       
  1089         iState = REPLY_RECEIVED;
       
  1090 
       
  1091     }
       
  1092 
   941     protected void ensureResponse() throws IOException
  1093     protected void ensureResponse() throws IOException
   942     {
  1094     {
   943         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ ensureResponse()" );
  1095         // Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ ensureResponse()" );
   944         ensureConnected();
  1096         ensureConnected();
   945         switch (iState)
  1097         switch (iState)
   946         {
  1098         {
       
  1099         case PARTIAL_REQUEST_SENT:
       
  1100             waitForResponse();
       
  1101             break;
       
  1102 
   947         case CONNECTED:
  1103         case CONNECTED:
   948 
  1104 
   949             sendRequest();
  1105             sendRequest(false);      // sendRequest() will block until the first chunk of http response arrives from the server.
   950             // Fall Through
  1106             // Fall Through
   951         case REQUEST_HEADERS_SENT:
  1107         case REQUEST_HEADERS_SENT:
   952         case REQUEST_SENT:
  1108         case REQUEST_SENT:
   953             getResponse();
  1109             getResponse();
   954             iState = REPLY_RECEIVED;
  1110             iState = REPLY_RECEIVED;
  1071             sepIndex = -1;
  1227             sepIndex = -1;
  1072         }
  1228         }
  1073         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- readHeaders(InputStream)" );
  1229         //Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- readHeaders(InputStream)" );
  1074     }
  1230     }
  1075 
  1231 
  1076     protected synchronized void sendRequest() throws IOException
  1232     protected synchronized void sendRequest(boolean aPartialDataFlag) throws IOException
  1077     {
  1233     {
  1078         ensureConnected();
  1234         ensureConnected();
       
  1235         Logger.PLOG(Logger.ESOCKET, "HTTP sendRequest() , Flag : "  + aPartialDataFlag);
  1079         final int count = iRequestProperties.size();
  1236         final int count = iRequestProperties.size();
  1080         int headerCount = count;
  1237         int headerCount = count;
  1081 
  1238 
  1082         final Enumeration keyEnum = iRequestProperties.keys();
  1239         final Enumeration keyEnum = iRequestProperties.keys();
  1083         String[] headers = null;
  1240         String[] headers = null;
  1105         // Data to be sent native
  1262         // Data to be sent native
  1106         if (iPostedDataStream != null)
  1263         if (iPostedDataStream != null)
  1107         {
  1264         {
  1108             postData = iPostedDataStream.toByteArray();
  1265             postData = iPostedDataStream.toByteArray();
  1109             postDataLength = postData.length;
  1266             postDataLength = postData.length;
       
  1267 
  1110         }
  1268         }
  1111 
  1269 
  1112         synchronized (iTransactionBlock.getLock())
  1270         synchronized (iTransactionBlock.getLock())
  1113         {
  1271         {
  1114             // Submit the headers and the data at the same time
  1272             // Submit the headers and the data at the same time
  1117             synchronized (iTransactionBlock)
  1275             synchronized (iTransactionBlock)
  1118             {
  1276             {
  1119                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1277                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1120                            "before _submitTransaction ");
  1278                            "before _submitTransaction ");
  1121                 final int err = _submitTransaction(iNativeTransactionHande,
  1279                 final int err = _submitTransaction(iNativeTransactionHande,
  1122                                                    headers, postData, postDataLength,iRespTimeOut);
  1280                                                    headers, postData, postDataLength,iRespTimeOut, aPartialDataFlag);
  1123 
  1281 
  1124                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1282                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1125                            "-_submitTransaction +err " + err);
  1283                            "-_submitTransaction +err " + err);
  1126 
  1284 
  1127                 // Clear tempory byte array and headers array
  1285                 // Clear tempory byte array and headers array
  1128                 postData = null;
  1286                 postData = null;
  1129                 headers = null;
  1287                 headers = null;
  1130                 if (err != 0)
  1288                 if (err != 0)
  1131                     throwIOException("Unable to connect to server.Symbian os error code: "
  1289                     throwIOException("Unable to connect to server.Symbian os error code: "
  1132                                      + err);
  1290                                      + err);
  1133                 iState = REQUEST_SENT;
  1291                 if (aPartialDataFlag == true)
  1134                 waitForTransaction();
  1292                 {
       
  1293                     iState = PARTIAL_REQUEST_SENT;
       
  1294                     iTotalPostDataLen = iTotalPostDataLen + postDataLength;
       
  1295                 }
       
  1296                 else
       
  1297                 {
       
  1298                     // block and wait for response headers only when it a complete request
       
  1299                     iState = REQUEST_SENT;
       
  1300                     waitForTransaction();
       
  1301                 }
  1135                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1302                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1136                            "- sendRequest _submitTransaction");
  1303                            "- sendRequest _submitTransaction");
  1137             }
  1304             }
  1138         }
  1305         }
  1139         if ((iTransactionBlock.getResult() == -18) &&(iRetries < 2))
  1306         if (aPartialDataFlag == false)
  1140         {
  1307         {
  1141             iRetries++;
  1308             if ((iTransactionBlock.getResult() == -18) &&(iRetries < 2))
  1142             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1309             {
  1143                        "- sendRequest KErrNotReady erroi, calling recursive sendRequest()");
  1310                 iRetries++;
  1144             sendRequest();
  1311                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1145             Logger.LOG(Logger.ESOCKET, Logger.EInfo,
  1312                            "- sendRequest KErrNotReady erroi, calling recursive sendRequest()");
  1146                        "- sendRequest KErrNotReady erroi, calling recursive sendRequest() returned");
  1313                 sendRequest(false);
       
  1314                 Logger.LOG(Logger.ESOCKET, Logger.EInfo,
       
  1315                            "- sendRequest KErrNotReady erroi, calling recursive sendRequest() returned");
       
  1316             }
  1147         }
  1317         }
  1148     }
  1318     }
  1149 
  1319 
  1150     protected void throwIOException(String aMessage) throws IOException
  1320     protected void throwIOException(String aMessage) throws IOException
  1151     {
  1321     {
  1289                    + aStatus);
  1459                    + aStatus);
  1290         iNativeDataReadyForRead.notifyCompleted(aStatus);
  1460         iNativeDataReadyForRead.notifyCompleted(aStatus);
  1291         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- dataReadyForReadCallBack");
  1461         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "- dataReadyForReadCallBack");
  1292     }
  1462     }
  1293 
  1463 
       
  1464     protected void postDataConsumedCallback()
       
  1465     {
       
  1466         Logger.LOG(Logger.ESOCKET, Logger.EInfo, "+ postDataconsumedCallback  ");
       
  1467         iPostDataBlock.notifyCompleted(0);
       
  1468 
       
  1469     }
       
  1470 
  1294     /*
  1471     /*
  1295      * Native Calls
  1472      * Native Calls
  1296      */
  1473      */
  1297     private native int _createHttpSession(int a, int aType, int aApn,
  1474     private native int _createHttpSession(int a, int aType, int aApn,
  1298                                           int[] retval);
  1475                                           int[] retval);
  1299     private native int _createNativeTransaction(int aNativeHttpSessionHandle,
  1476     private native int _createNativeTransaction(int aNativeHttpSessionHandle,
  1300             String aUri, String aRequestMethod);
  1477             String aUri, String aRequestMethod);
  1301     private native int _submitTransaction(int aNativeTransactionHande,
  1478     private native int _submitTransaction(int aNativeTransactionHande,
  1302                                           String[] aHeaders, byte[] aPostData, int aPostLength,
  1479                                           String[] aHeaders, byte[] aPostData, int aPostLength,
  1303                                           int aRespTimeOut);
  1480                                           int aRespTimeOut, boolean aPartialData);
  1304     private native String[] _getResponse(int aNativeTransactionHande);
  1481     private native String[] _getResponse(int aNativeTransactionHande);
  1305     private native int _getBytes(int aNativeTransactionHande, byte[] aBuffer,
  1482     private native int _getBytes(int aNativeTransactionHande, byte[] aBuffer,
  1306                                  int aLength);
  1483                                  int aLength);
  1307     private native void _closeTransaction(int aNativeTransactionHande);
  1484     private native void _closeTransaction(int aNativeTransactionHande);
  1308     private native int _available(int aNativeTransactionHande);
  1485     private native int _available(int aNativeTransactionHande);
  1309     private native String _getUserAgentHeaderValue(boolean aMidpRuntime);
  1486     private native String _getUserAgentHeaderValue(boolean aMidpRuntime);
       
  1487     private native int _postData(int aNativeTransactionHandle, byte[] aPostData, int aLength, boolean iEndOfRequest);
  1310 
  1488 
  1311     /*
  1489     /*
  1312      *
  1490      *
  1313      * class PlainDataInputStream
  1491      * class PlainDataInputStream
  1314      *
  1492      *