com_barchart_udt_SocketUDT.cpp

00001 
00038 /*
00039  * NOTE: provides ONLY ipv4 implementation (not ipv6)
00040  *
00041  */
00042 
00043 // ### keep outside [extern "C"]
00044 #include "com_barchart_udt_SocketUDT.h"
00045 #include "JNICCCFactory.h"
00046 #include "JNICCC.h"
00047 
00048 #include "udt.h"
00049 
00050 #include "JNIHelpers.h"
00051 
00052 //
00053 // stack trace support
00054 //
00055 #if defined(LINUX) && !defined(ANDROID)
00056 
00057 #include <signal.h>
00058 #include <stdlib.h>
00059 #include <execinfo.h>
00060 
00061 void X_PrintStackTrace() {
00062 
00063         const size_t max_depth = 100;
00064 
00065         size_t stack_depth;
00066         void *stack_addrs[max_depth];
00067         char **stack_strings;
00068 
00069         stack_depth = backtrace(stack_addrs, max_depth);
00070         stack_strings = backtrace_symbols(stack_addrs, stack_depth);
00071 
00072         printf("stack trace \n");
00073 
00074         for (size_t index = 1; index < stack_depth; index++) {
00075                 printf("   %s\n", stack_strings[index]);
00076         }
00077 
00078         free(stack_strings);
00079 
00080 }
00081 #else
00082 
00083 void X_PrintStackTrace() {
00084         // TODO
00085 }
00086 
00087 #endif
00088 
00089 // do not use cout; else will introduce GLIBCXX_3.4.9 dependency with 'g++ -O2'
00090 //#include <iostream>
00091 
00092 using namespace std;
00093 
00094 // do not use to avoid ambiguity
00095 //using namespace UDT;
00096 
00097 // for JNI method signature compatibility
00098 extern "C" { /* specify the C calling convention */
00099 
00100 // ### keep inside extern "C"
00101 
00102 // ########################################################
00103 
00104 // ### UDT references
00105 
00106 // UDT classes
00107 static jclass udt_clsSocketUDT; // com.barchart.udt.SocketUDT
00108 static jclass udt_clsTypeUDT; // com.barchart.udt.TypeUDT
00109 static jclass udt_clsFactoryUDT; // com.barchart.udt.FactoryUDT
00110 static jclass udt_clsMonitorUDT; // com.barchart.udt.MonitorUDT
00111 static jclass udt_clsExceptionUDT; // com.barchart.udt.ExceptionUDT
00112 static jclass udt_clsLingerUDT; // com.barchart.udt.ExceptionUDT
00113 static jclass udt_clsCCC; // com.barchart.udt.CCC
00114 
00115 // UDT fields: com.barchart.udt.SocketUDT
00116 static jfieldID udts_TypeID;
00117 static jfieldID udts_RemoteSocketAddressID;
00118 static jfieldID udts_LocalSocketAddressID;
00119 static jfieldID udts_MonitorID;
00120 static jfieldID udts_SocketID;
00121 
00122 // UDT fields: com.barchart.udt.TypeUDT
00123 static jfieldID udtt_TypeCodeID;
00124 
00125 // UDT methods
00126 static jmethodID udt_clsSocketUDT_initID1; // new SocketUDT(int type, int id)
00127 static jmethodID udt_clsExceptionUDT_initID0; // new ExceptionUDT(int code, String message)
00128 static jmethodID udt_clsLingerUDT_initID; // new LingerUDT(int value)
00129 
00130 // UDT fields: com.barchart.udt.MonitorUDT
00131 //
00132 // global measurements
00133 static jfieldID udtm_msTimeStamp; // time since the UDT entity is started, in milliseconds
00134 static jfieldID udtm_pktSentTotal; // total number of sent data packets, including retransmissions
00135 static jfieldID udtm_pktRecvTotal; // total number of received packets
00136 static jfieldID udtm_pktSndLossTotal; // total number of lost packets (sender side)
00137 static jfieldID udtm_pktRcvLossTotal; // total number of lost packets (receiver side)
00138 static jfieldID udtm_pktRetransTotal; // total number of retransmitted packets
00139 static jfieldID udtm_pktSentACKTotal; // total number of sent ACK packets
00140 static jfieldID udtm_pktRecvACKTotal; // total number of received ACK packets
00141 static jfieldID udtm_pktSentNAKTotal; // total number of sent NAK packets
00142 static jfieldID udtm_pktRecvNAKTotal; // total number of received NAK packets
00143 static jfieldID udtm_usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive)
00144 //
00145 // local measurements
00146 static jfieldID udtm_pktSent; // number of sent data packets, including retransmissions
00147 static jfieldID udtm_pktRecv; // number of received packets
00148 static jfieldID udtm_pktSndLoss; // number of lost packets (sender side)
00149 static jfieldID udtm_pktRcvLoss; // number of lost packets (receiverer side)
00150 static jfieldID udtm_pktRetrans; // number of retransmitted packets
00151 static jfieldID udtm_pktSentACK; // number of sent ACK packets
00152 static jfieldID udtm_pktRecvACK; // number of received ACK packets
00153 static jfieldID udtm_pktSentNAK; // number of sent NAK packets
00154 static jfieldID udtm_pktRecvNAK; // number of received NAK packets
00155 static jfieldID udtm_mbpsSendRate; // sending rate in Mb/s
00156 static jfieldID udtm_mbpsRecvRate; // receiving rate in Mb/s
00157 static jfieldID udtm_usSndDuration; // busy sending time (i.e., idle time exclusive)
00158 //
00159 // instant measurements
00160 static jfieldID udtm_usPktSndPeriod; // packet sending period, in microseconds
00161 static jfieldID udtm_pktFlowWindow; // flow window size, in number of packets
00162 static jfieldID udtm_pktCongestionWindow; // congestion window size, in number of packets
00163 static jfieldID udtm_pktFlightSize; // number of packets on flight
00164 static jfieldID udtm_msRTT; // RTT, in milliseconds
00165 static jfieldID udtm_mbpsBandwidth; // estimated bandwidth, in Mb/s
00166 static jfieldID udtm_byteAvailSndBuf; // available UDT sender buffer size
00167 static jfieldID udtm_byteAvailRcvBuf; // available UDT receiver buffer size
00168 
00169 // ########################################################
00170 
00171 // not used
00172 void XXX_ThrowSocketExceptionMessage( //
00173                 JNIEnv * const env, //
00174                 const char* message //
00175                 ) {
00176         CHK_NUL_RET_RET(env, "env");
00177         CHK_NUL_RET_RET(message, "message");
00178         CHK_NUL_RET_RET(jdk_clsSocketException, "jdk_clsSocketException");
00179         env->ThrowNew(jdk_clsSocketException, message);
00180 }
00181 
00182 // ########################################################
00183 
00184 // custom class for struct linger conversion
00185 jobject UDT_NewLingerUDT( //
00186                 JNIEnv * const env, //
00187                 linger * const lingerValue //
00188                 ) {
00189         CHK_NUL_RET_NUL(env, "env");
00190         CHK_NUL_RET_NUL(lingerValue, "lingerValue");
00191         int value;
00192         if (lingerValue->l_onoff == 0) {
00193                 value = 0;
00194         } else {
00195                 value = lingerValue->l_linger;
00196         }
00197         jobject objLinger = env->NewObject(udt_clsLingerUDT,
00198                         udt_clsLingerUDT_initID, (jint) value);
00199         CHK_NUL_RET_NUL(objLinger, "objLinger");
00200         return objLinger;
00201 }
00202 
00203 // java wrapper exception error codes; keep in sync with ErrorUDT.java
00204 #define UDT_WRAPPER_UNKNOWN -1 // WRAPPER_UNKNOWN(-1, "unknown error code"), //
00205 #define UDT_WRAPPER_UNIMPLEMENTED -2 // WRAPPER_UNIMPLEMENTED(-2, "this feature is not yet implemented"), //
00206 #define UDT_WRAPPER_MESSAGE -3 // WRAPPER_MESSAGE(-3, "wrapper generated error"), //
00207 #define UDT_USER_DEFINED_MESSAGE -4 // USER_DEFINED_MESSAGE(-4, "user defined message"), //
00208 //
00209 
00210 // NOTE: socket id stored in java object SocketUDT
00211 jint UDT_GetSocketID( //
00212                 JNIEnv * const env, //
00213                 const jobject self //
00214                 ) {
00215         return env->GetIntField(self, udts_SocketID);
00216 }
00217 // NOTE: socket id stored in java object SocketUDT
00218 void UDT_SetSocketID( //
00219                 JNIEnv * const env, //
00220                 const jobject self, //
00221                 const jint socketID //
00222                 ) {
00223         env->SetIntField(self, udts_SocketID, socketID);
00224 }
00225 
00226 jthrowable UDT_NewExceptionUDT( //
00227                 JNIEnv * const env, //
00228                 const jint socketID, //
00229                 const jint errorCode, //
00230                 const char* message //
00231                 ) {
00232         CHK_NUL_RET_NUL(env, "env");
00233         const jstring messageString = env->NewStringUTF(message);
00234         CHK_NUL_RET_NUL(messageString, "messageString");
00235         const jobject exception = env->NewObject(udt_clsExceptionUDT,
00236                         udt_clsExceptionUDT_initID0, socketID, errorCode, messageString);
00237         return static_cast<jthrowable>(exception);
00238 }
00239 
00240 void UDT_ThrowExceptionUDT_Message( //
00241                 JNIEnv * const env, //
00242                 const jint socketID, //
00243                 const char *comment //
00244                 ) {
00245         CHK_NUL_RET_RET(env, "env");
00246         CHK_NUL_RET_RET(comment, "comment");
00247         const jint code = UDT_WRAPPER_MESSAGE;
00248         const jthrowable exception = UDT_NewExceptionUDT(env, socketID, code,
00249                         comment);
00250         CHK_NUL_RET_RET(exception, "exception");
00251         env->Throw(exception);
00252 }
00253 
00254 // socketID == 0 means not applicable / not known id
00255 void UDT_ThrowExceptionUDT_ErrorInfo( //
00256                 JNIEnv * const env, //
00257                 const jint socketID, //
00258                 const char* comment, //
00259                 UDT::ERRORINFO * const errorInfo //
00260                 ) {
00261         CHK_NUL_RET_RET(env, "env");
00262         CHK_NUL_RET_RET(comment, "comment");
00263         CHK_NUL_RET_RET(errorInfo, "errorInfo");
00264         const jint code = errorInfo->getErrorCode();
00265         const jthrowable exception = //
00266                         UDT_NewExceptionUDT(env, socketID, code, comment);
00267         CHK_NUL_RET_RET(exception, "exception");
00268         env->Throw(exception);
00269 }
00270 
00271 void UDT_InitFieldMonitor( //
00272                 JNIEnv * const env //
00273                 ) {
00274 
00275         const jclass cls = udt_clsMonitorUDT;
00276 
00277         // global measurements
00278         udtm_msTimeStamp = env->GetFieldID(cls, "msTimeStamp", "J"); // time since the UDT entity is started, in milliseconds
00279         udtm_pktSentTotal = env->GetFieldID(cls, "pktSentTotal", "J"); // total number of sent data packets, including retransmissions
00280         udtm_pktRecvTotal = env->GetFieldID(cls, "pktRecvTotal", "J"); // total number of received packets
00281         udtm_pktSndLossTotal = env->GetFieldID(cls, "pktSndLossTotal", "I"); // total number of lost packets (sender side)
00282         udtm_pktRcvLossTotal = env->GetFieldID(cls, "pktRcvLossTotal", "I"); // total number of lost packets (receiver side)
00283         udtm_pktRetransTotal = env->GetFieldID(cls, "pktRetransTotal", "I"); // total number of retransmitted packets
00284         udtm_pktSentACKTotal = env->GetFieldID(cls, "pktSentACKTotal", "I"); // total number of sent ACK packets
00285         udtm_pktRecvACKTotal = env->GetFieldID(cls, "pktRecvACKTotal", "I"); // total number of received ACK packets
00286         udtm_pktSentNAKTotal = env->GetFieldID(cls, "pktSentNAKTotal", "I"); // total number of sent NAK packets
00287         udtm_pktRecvNAKTotal = env->GetFieldID(cls, "pktRecvNAKTotal", "I"); // total number of received NAK packets
00288         udtm_usSndDurationTotal = env->GetFieldID(cls, "usSndDurationTotal", "J"); // total time duration when UDT is sending data (idle time exclusive)
00289 
00290         // local measurements
00291         udtm_pktSent = env->GetFieldID(cls, "pktSent", "J"); // number of sent data packets, including retransmissions
00292         udtm_pktRecv = env->GetFieldID(cls, "pktRecv", "J"); // number of received packets
00293         udtm_pktSndLoss = env->GetFieldID(cls, "pktSndLoss", "I"); // number of lost packets (sender side)
00294         udtm_pktRcvLoss = env->GetFieldID(cls, "pktRcvLoss", "I"); // number of lost packets (receiverer side)
00295         udtm_pktRetrans = env->GetFieldID(cls, "pktRetrans", "I"); // number of retransmitted packets
00296         udtm_pktSentACK = env->GetFieldID(cls, "pktSentACK", "I"); // number of sent ACK packets
00297         udtm_pktRecvACK = env->GetFieldID(cls, "pktRecvACK", "I"); // number of received ACK packets
00298         udtm_pktSentNAK = env->GetFieldID(cls, "pktSentNAK", "I"); // number of sent NAK packets
00299         udtm_pktRecvNAK = env->GetFieldID(cls, "pktRecvNAK", "I"); // number of received NAK packets
00300         udtm_mbpsSendRate = env->GetFieldID(cls, "mbpsSendRate", "D"); // sending rate in Mb/s
00301         udtm_mbpsRecvRate = env->GetFieldID(cls, "mbpsRecvRate", "D"); // receiving rate in Mb/s
00302         udtm_usSndDuration = env->GetFieldID(cls, "usSndDuration", "J"); // busy sending time (i.e., idle time exclusive)
00303 
00304         // instant measurements
00305         udtm_usPktSndPeriod = env->GetFieldID(cls, "usPktSndPeriod", "D"); // packet sending period, in microseconds
00306         udtm_pktFlowWindow = env->GetFieldID(cls, "pktFlowWindow", "I"); // flow window size, in number of packets
00307         udtm_pktCongestionWindow = env->GetFieldID(cls, "pktCongestionWindow", "I"); // congestion window size, in number of packets
00308         udtm_pktFlightSize = env->GetFieldID(cls, "pktFlightSize", "I"); // number of packets on flight
00309         udtm_msRTT = env->GetFieldID(cls, "msRTT", "D"); // RTT, in milliseconds
00310         udtm_mbpsBandwidth = env->GetFieldID(cls, "mbpsBandwidth", "D"); // estimated bandwidth, in Mb/s
00311         udtm_byteAvailSndBuf = env->GetFieldID(cls, "byteAvailSndBuf", "I"); // available UDT sender buffer size
00312         udtm_byteAvailRcvBuf = env->GetFieldID(cls, "byteAvailRcvBuf", "I"); // available UDT receiver buffer size
00313 
00314 }
00315 
00316 void UDT_InitClassRefAll(JNIEnv * const env) {
00317 
00318         // JDK
00319 
00320         X_InitClassReference(env, &jdk_clsBoolean, "java/lang/Boolean");
00321         X_InitClassReference(env, &jdk_clsInteger, "java/lang/Integer");
00322         X_InitClassReference(env, &jdk_clsLong, "java/lang/Long");
00323 
00324         X_InitClassReference(env, &jdk_clsInet4Address, "java/net/Inet4Address");
00325         X_InitClassReference(env, &jdk_clsInet6Address, "java/net/Inet6Address");
00326         X_InitClassReference(env, &jdk_clsInetSocketAddress,
00327                         "java/net/InetSocketAddress");
00328 
00329         X_InitClassReference(env, &jdk_clsSocketException,
00330                         "java/net/SocketException");
00331 
00332         X_InitClassReference(env, &jdk_clsSet, "java/util/Set");
00333         X_InitClassReference(env, &jdk_clsIterator, "java/util/Iterator");
00334 
00335         // UDT
00336 
00337         X_InitClassReference(env, &udt_clsSocketUDT, //
00338                         "com/barchart/udt/SocketUDT");
00339         X_InitClassReference(env, &udt_clsTypeUDT, //
00340                         "com/barchart/udt/TypeUDT");
00341         X_InitClassReference(env, &udt_clsFactoryUDT, //
00342                         "com/barchart/udt/FactoryUDT");
00343         X_InitClassReference(env, &udt_clsMonitorUDT, //
00344                         "com/barchart/udt/MonitorUDT");
00345         X_InitClassReference(env, &udt_clsExceptionUDT, //
00346                         "com/barchart/udt/ExceptionUDT");
00347         X_InitClassReference(env, &udt_clsLingerUDT, //
00348                         "com/barchart/udt/LingerUDT");
00349         X_InitClassReference(env, &udt_clsCCC, //
00350                         "com/barchart/udt/CCC");
00351         X_InitClassReference(env, &udt_clsFactoryInterfaceUDT,
00352                         "com/barchart/udt/FactoryInterfaceUDT");
00353 
00354 }
00355 
00356 void UDT_FreeClassRefAll(JNIEnv * const env) {
00357 
00358         // JDK
00359 
00360         X_FreeClassReference(env, &jdk_clsBoolean);
00361         X_FreeClassReference(env, &jdk_clsInteger);
00362         X_FreeClassReference(env, &jdk_clsLong);
00363 
00364         X_FreeClassReference(env, &jdk_clsInet4Address);
00365         X_FreeClassReference(env, &jdk_clsInet6Address);
00366         X_FreeClassReference(env, &jdk_clsInetSocketAddress);
00367 
00368         X_FreeClassReference(env, &jdk_clsSocketException);
00369 
00370         X_FreeClassReference(env, &jdk_clsSet);
00371         X_FreeClassReference(env, &jdk_clsIterator);
00372 
00373         // UDT
00374 
00375         X_FreeClassReference(env, &udt_clsSocketUDT);
00376         X_FreeClassReference(env, &udt_clsTypeUDT);
00377         X_FreeClassReference(env, &udt_clsFactoryUDT);
00378         X_FreeClassReference(env, &udt_clsMonitorUDT);
00379         X_FreeClassReference(env, &udt_clsExceptionUDT);
00380         X_FreeClassReference(env, &udt_clsLingerUDT);
00381         X_FreeClassReference(env, &udt_clsCCC);
00382         X_FreeClassReference(env, &udt_clsFactoryInterfaceUDT);
00383 }
00384 
00385 void UDT_InitFieldRefAll(JNIEnv * const env) {
00386 
00387         // JDK
00388 
00389         // FIXME private field access
00390         ia_AddressID = env->GetFieldID(jdk_clsInet4Address, "address", "I");
00391 
00392         // UDT SocketUDT
00393 
00394         udts_SocketID = env->GetFieldID(udt_clsSocketUDT, //
00395                         "socketID", "I");
00396         udts_RemoteSocketAddressID = env->GetFieldID(udt_clsSocketUDT, //
00397                         "remoteSocketAddress", "Ljava/net/InetSocketAddress;");
00398         udts_LocalSocketAddressID = env->GetFieldID(udt_clsSocketUDT, //
00399                         "localSocketAddress", "Ljava/net/InetSocketAddress;");
00400         udts_TypeID = env->GetFieldID(udt_clsSocketUDT, //
00401                         "type", "Lcom/barchart/udt/TypeUDT;");
00402         udts_MonitorID = env->GetFieldID(udt_clsSocketUDT, //
00403                         "monitor", "Lcom/barchart/udt/MonitorUDT;");
00404 
00405         // UDT TypeUDT
00406 
00407         udtt_TypeCodeID = env->GetFieldID(udt_clsTypeUDT, "code", "I");
00408 
00409         // UDT MonitorUDT
00410 
00411         UDT_InitFieldMonitor(env);
00412 
00413         // UDT CCC
00414 
00415         udt_clsCCC_fld_nativeHandleID = env->GetFieldID(udt_clsCCC, //
00416                         "nativeHandle", "J");
00417 
00418 }
00419 
00420 void X_InitMethodRef( //
00421                 JNIEnv * const env, //
00422                 jmethodID *methodID, //
00423                 const jclass klaz, //
00424                 const char* name, //
00425                 const char* signature //
00426                 ) {
00427 
00428         *methodID = env->GetMethodID(klaz, name, signature);
00429 
00430         CHK_NUL_RET_RET(*methodID, name);
00431 
00432 }
00433 
00434 void UDT_InitMethodRefAll( //
00435                 JNIEnv * const env //
00436                 ) {
00437 
00438         // JDK
00439 
00440         jdk_clsBoolean_initID = env->GetMethodID(jdk_clsBoolean, //
00441                         "<init>", "(Z)V");
00442         CHK_NUL_RET_RET(jdk_clsBoolean_initID, "jdk_clsBoolean_initID");
00443 
00444         jdk_clsInteger_initID = env->GetMethodID(jdk_clsInteger, //
00445                         "<init>", "(I)V");
00446         CHK_NUL_RET_RET(jdk_clsInteger_initID, "jdk_clsInteger_initID");
00447 
00448         jdk_clsLong_initID = env->GetMethodID(jdk_clsLong, //
00449                         "<init>", "(J)V");
00450         CHK_NUL_RET_RET(jdk_clsLong_initID, "jdk_clsLong_initID");
00451 
00452         jdk_clsInet4Address_initID = env->GetMethodID(jdk_clsInet4Address, "<init>",
00453                         "()V");
00454         CHK_NUL_RET_RET(jdk_clsInet4Address_initID, "jdk_clsInet4Address_initID");
00455 
00456         jdk_clsInetSocketAddress_initID = env->GetMethodID(jdk_clsInetSocketAddress, //
00457                         "<init>", "(Ljava/net/InetAddress;I)V");
00458         CHK_NUL_RET_RET(jdk_clsInetSocketAddress_initID,
00459                         "jdk_clsInetSocketAddress_initID");
00460 
00461         jdk_clsInetSocketAddress_getAddressID = env->GetMethodID(jdk_clsInetSocketAddress, //
00462                         "getAddress", "()Ljava/net/InetAddress;");
00463         CHK_NUL_RET_RET(jdk_clsInetSocketAddress_getAddressID,
00464                         "jdk_clsInetSocketAddress_getAddressID");
00465 
00466         jdk_clsInetSocketAddress_getPortID = env->GetMethodID(jdk_clsInetSocketAddress, //
00467                         "getPort", "()I");
00468         CHK_NUL_RET_RET(jdk_clsInetSocketAddress_getPortID,
00469                         "jdk_clsInetSocketAddress_getPortID");
00470 
00471 
00472         // java.util.Set
00473         jdk_clsSet_iteratorID = env->GetMethodID(jdk_clsSet, //
00474                         "iterator", "()Ljava/util/Iterator;");
00475         CHK_NUL_RET_RET(jdk_clsSet_iteratorID, "jdk_clsSet_iteratorID");
00476         jdk_clsSet_addID = env->GetMethodID(jdk_clsSet, //
00477                         "add", "(Ljava/lang/Object;)Z");
00478         CHK_NUL_RET_RET(jdk_clsSet_addID, "jdk_clsSet_addID");
00479         jdk_clsSet_containsID = env->GetMethodID(jdk_clsSet, //
00480                         "contains", "(Ljava/lang/Object;)Z");
00481         CHK_NUL_RET_RET(jdk_clsSet_containsID, "jdk_clsSet_containsID");
00482 
00483         // java.util.Iterator
00484         jdk_clsIterator_hasNextID = env->GetMethodID(jdk_clsIterator, //
00485                         "hasNext", "()Z");
00486         CHK_NUL_RET_RET(jdk_clsIterator_hasNextID, "jdk_clsIterator_hasNextID");
00487         jdk_clsIterator_nextID = env->GetMethodID(jdk_clsIterator, //
00488                         "next", "()Ljava/lang/Object;");
00489         CHK_NUL_RET_RET(jdk_clsIterator_nextID, "jdk_clsIterator_nextID");
00490 
00491         // UDT
00492 
00493         udt_clsSocketUDT_initID1 = env->GetMethodID(udt_clsSocketUDT, //
00494                         "<init>", "(Lcom/barchart/udt/TypeUDT;I)V");
00495         CHK_NUL_RET_RET(udt_clsSocketUDT_initID1, "udt_clsSocketUDT_initID1");
00496 
00497         udt_clsExceptionUDT_initID0 = env->GetMethodID(udt_clsExceptionUDT, //
00498                         "<init>", "(IILjava/lang/String;)V");
00499         CHK_NUL_RET_RET(udt_clsExceptionUDT_initID0, "udt_clsExceptionUDT_initID0");
00500 
00501         udt_clsLingerUDT_initID = env->GetMethodID(udt_clsLingerUDT, //
00502                         "<init>", "(I)V");
00503         CHK_NUL_RET_RET(udt_clsLingerUDT_initID, "udt_clsLingerUDT_initID");
00504 
00505 }
00506 
00507 // ########################################################
00508 
00509 /* signature is a monotonously increasing integer; set in java class SocketUDT */
00510 
00511 // validate consistency of java code and native library
00512 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_getSignatureJNI0( //
00513                 JNIEnv * const env, //
00514                 const jclass clsSocketUDT //
00515                 ) {
00516 
00517         UNUSED(env);
00518         UNUSED(clsSocketUDT);
00519 
00520         return com_barchart_udt_SocketUDT_SIGNATURE_JNI;
00521 
00522 }
00523 
00524 // called on java class load
00525 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_initClass0( //
00526                 JNIEnv* const env, //
00527                 const jclass clsSocketUDT //
00528                 ) {
00529 
00530         UNUSED(env);
00531         UNUSED(clsSocketUDT);
00532 
00533         UDT_InitClassRefAll(env);
00534 
00535         UDT_InitFieldRefAll(env);
00536 
00537         UDT_InitMethodRefAll(env);
00538 
00539         const int rv = UDT::startup();
00540 
00541         if (rv == UDT::ERROR) {
00542                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00543                 UDT_ThrowExceptionUDT_ErrorInfo( //
00544                                 env, 0, "initClass0:startup", &errorInfo);
00545                 return;
00546         }
00547 
00548 }
00549 
00550 // called on java class unload
00551 void JNICALL Java_com_barchart_udt_SocketUDT_stopClass0( //
00552                 JNIEnv* const env, //
00553                 const jclass clsSocketUDT //
00554                 ) {
00555 
00556         UNUSED(env);
00557         UNUSED(clsSocketUDT);
00558 
00559         //Release global JNI references
00560         UDT_FreeClassRefAll(env);
00561 
00562         const int rv = UDT::cleanup();
00563 
00564         if (rv == UDT::ERROR) {
00565                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00566                 UDT_ThrowExceptionUDT_ErrorInfo( //
00567                                 env, 0, "stopClass0:cleanup", &errorInfo);
00568                 return;
00569         }
00570 
00571 }
00572 
00573 // used by default constructor
00574 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_initInstance0( //
00575                 JNIEnv * const env, //
00576                 const jobject self, //
00577                 const jint typeCode //
00578                 ) {
00579 
00580         int socketAddressFamily = AF_INET;
00581         int socketType = typeCode;
00582 
00583         const jint socketID = UDT::socket(socketAddressFamily, socketType, 0);
00584 
00585         UDT_SetSocketID(env, self, socketID);
00586 
00587         if (socketID == UDT::INVALID_SOCK) {
00588                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00589                 UDT_ThrowExceptionUDT_ErrorInfo( //
00590                                 env, socketID, "initInstance0:INVALID_SOCK", &errorInfo);
00591                 return JNI_ERR;
00592         }
00593 
00594         return socketID;
00595 
00596 }
00597 
00598 // used by accept constructor
00599 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_initInstance1( //
00600                 JNIEnv * const env, //
00601                 const jobject self, //
00602                 const jint socketID //
00603                 ) {
00604 
00605         UNUSED(self);
00606 
00607         if (socketID == UDT::INVALID_SOCK) {
00608                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00609                 UDT_ThrowExceptionUDT_ErrorInfo( //
00610                                 env, socketID, "initInstance1:INVALID_SOCK", &errorInfo);
00611                 return JNI_ERR;
00612         }
00613 
00614         return socketID;
00615 
00616 }
00617 
00618 JNIEXPORT jobject JNICALL Java_com_barchart_udt_SocketUDT_accept0( //
00619                 JNIEnv * const env, //
00620                 const jobject self //
00621                 ) {
00622 
00623         sockaddr remoteSockAddr;
00624         int remoteSockAddrSize = sizeof(remoteSockAddr);
00625 
00626         const jint socketID = UDT_GetSocketID(env, self);
00627 
00628         const jint socketACC = UDT::accept(socketID, &remoteSockAddr,
00629                         &remoteSockAddrSize);
00630 
00631         if (socketACC == UDT::INVALID_SOCK) {
00632 
00633                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00634 
00635                 const jint errorCode = errorInfo.getErrorCode();
00636 
00637                 if (errorCode == UDT::ERRORINFO::EASYNCRCV) {
00638                         // not a java exception: non-blocking mode return, when not connections in the queue
00639                 } else {
00640                         // really exception
00641                         UDT_ThrowExceptionUDT_ErrorInfo( //
00642                                         env, socketID, "accept0:accept", &errorInfo);
00643                 }
00644 
00645                 return NULL;
00646 
00647         }
00648 
00649         jobject objTypeUDT = env->GetObjectField(self, udts_TypeID);
00650 
00651         CHK_NUL_RET_NUL(objTypeUDT, "objTypeUDT");
00652 
00653         jobject objSocketUDT = env->NewObject(udt_clsSocketUDT,
00654                         udt_clsSocketUDT_initID1, objTypeUDT, socketACC);
00655 
00656         CHK_NUL_RET_NUL(objSocketUDT, "objSocketUDT");
00657 
00658         return objSocketUDT;
00659 
00660 }
00661 
00662 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_bind0( //
00663                 JNIEnv * const env, //
00664                 const jobject self, //
00665                 const jobject objLocalSocketAddress //
00666                 ) {
00667 
00668         const jint socketID = UDT_GetSocketID(env, self);
00669 
00670         int rv;
00671 
00672         sockaddr localSockAddr;
00673 
00674         rv = X_InitSockAddr(&localSockAddr);
00675 
00676         if (rv == JNI_ERR) {
00677                 UDT_ThrowExceptionUDT_Message(env, socketID, "can not X_InitSockAddr");
00678                 return;
00679         }
00680 
00681         rv = X_ConvertInetSocketAddressToSockaddr(env, objLocalSocketAddress,
00682                         &localSockAddr);
00683 
00684         if (rv == JNI_ERR) {
00685                 UDT_ThrowExceptionUDT_Message(env, socketID,
00686                                 "can not X_ConvertInetSocketAddressToSockaddr");
00687                 return;
00688         }
00689 
00690         rv = UDT::bind(socketID, &localSockAddr, sizeof(localSockAddr));
00691 
00692         if (rv == UDT::ERROR) {
00693                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00694                 UDT_ThrowExceptionUDT_ErrorInfo( //
00695                                 env, socketID, "bind0:bind", &errorInfo);
00696                 return;
00697         }
00698 
00699 }
00700 
00701 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_close0( //
00702                 JNIEnv * const env, //
00703                 const jobject self //
00704                 ) {
00705 
00706         const jint socketID = UDT_GetSocketID(env, self);
00707 
00708         const int rv = UDT::close(socketID);
00709 
00710         if (rv == UDT::ERROR) {
00711                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00712                 UDT_ThrowExceptionUDT_ErrorInfo( //
00713                                 env, socketID, "close0:close", &errorInfo);
00714                 return;
00715         }
00716 
00717 }
00718 
00719 //
00720 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_connect0( //
00721                 JNIEnv * const env, //
00722                 const jobject self, //
00723                 const jobject objRemoteSocketAddress //
00724                 ) {
00725 
00726         const jint socketID = UDT_GetSocketID(env, self);
00727 
00728         if (objRemoteSocketAddress == NULL) {
00729                 UDT_ThrowExceptionUDT_Message(env, socketID,
00730                                 "objRemoteSocketAddress == NULL");
00731                 return;
00732         }
00733 
00734         int rv;
00735 
00736         sockaddr remoteSockAddr;
00737 
00738         rv = X_InitSockAddr(&remoteSockAddr);
00739 
00740         if (rv == JNI_ERR) {
00741                 UDT_ThrowExceptionUDT_Message(env, socketID, "can not X_InitSockAddr");
00742                 return;
00743         }
00744 
00745         rv = X_ConvertInetSocketAddressToSockaddr(env, //
00746                         objRemoteSocketAddress, &remoteSockAddr);
00747 
00748         if (rv == JNI_ERR) {
00749                 UDT_ThrowExceptionUDT_Message(env, socketID,
00750                                 "can not X_ConvertInetSocketAddressToSockaddr");
00751                 return;
00752         }
00753 
00754         rv = UDT::connect(socketID, &remoteSockAddr, sizeof(remoteSockAddr));
00755 
00756         if (rv == UDT::ERROR) {
00757                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00758                 UDT_ThrowExceptionUDT_ErrorInfo( //
00759                                 env, socketID, "connect0:connect", &errorInfo);
00760                 return;
00761         }
00762 
00763 }
00764 
00765 JNIEXPORT jboolean JNICALL Java_com_barchart_udt_SocketUDT_hasLoadedRemoteSocketAddress( //
00766                 JNIEnv * const env, //
00767                 const jobject self //
00768                 ) {
00769 
00770         const jint socketID = UDT_GetSocketID(env, self);
00771 
00772         sockaddr remoteSockAddr;
00773         int remoteSockAddrSize = sizeof(remoteSockAddr);
00774 
00775         // "peer" is remote
00776         const int rv = UDT::getpeername( //
00777                         socketID, &remoteSockAddr, &remoteSockAddrSize);
00778 
00779         if (rv == UDT::ERROR) {
00780                 // no exceptions
00781                 return JNI_FALSE;
00782         }
00783 
00784         jobject objRemoteSocketAddress = env->GetObjectField(self,
00785                         udts_RemoteSocketAddressID);
00786 
00787         if (objRemoteSocketAddress == NULL
00788                         || !X_IsSockaddrEqualsInetSocketAddress(env, &remoteSockAddr,
00789                                         objRemoteSocketAddress)) {
00790 
00791                 objRemoteSocketAddress = X_NewInetSocketAddress(env, &remoteSockAddr);
00792 
00793                 env->SetObjectField(self, udts_RemoteSocketAddressID,
00794                                 objRemoteSocketAddress);
00795 
00796         }
00797 
00798         return JNI_TRUE;
00799 
00800 }
00801 
00802 JNIEXPORT jboolean JNICALL Java_com_barchart_udt_SocketUDT_hasLoadedLocalSocketAddress( //
00803                 JNIEnv * const env, //
00804                 const jobject self //
00805                 ) {
00806 
00807         const jint socketID = UDT_GetSocketID(env, self);
00808 
00809         sockaddr localSockAddr;
00810         int localSockAddrSize = sizeof(localSockAddr);
00811 
00812         // "sock" is local
00813         const int rv = UDT::getsockname( //
00814                         socketID, &localSockAddr, &localSockAddrSize);
00815 
00816         if (rv == UDT::ERROR) {
00817                 // no exceptions
00818                 return JNI_FALSE;
00819         }
00820 
00821         jobject objLocalSocketAddress = env->GetObjectField(self,
00822                         udts_LocalSocketAddressID);
00823 
00824         if (objLocalSocketAddress == NULL
00825                         || !X_IsSockaddrEqualsInetSocketAddress(env, &localSockAddr,
00826                                         objLocalSocketAddress)) {
00827 
00828                 objLocalSocketAddress = X_NewInetSocketAddress(env, &localSockAddr);
00829 
00830                 env->SetObjectField(self, udts_LocalSocketAddressID,
00831                                 objLocalSocketAddress);
00832 
00833         }
00834 
00835         return JNI_TRUE;
00836 
00837 }
00838 
00839 // struct that fits all UDT options types
00840 union UDT_OptVal {
00841         void* factory;
00842         linger lingerValue;
00843         int64_t longValue;
00844         int intValue;
00845         bool boolValue;
00846 };
00847 
00848 JNIEXPORT jobject JNICALL Java_com_barchart_udt_SocketUDT_getOption0( //
00849                 JNIEnv * const env, //
00850                 const jobject self, //
00851                 const jint enumCode, //
00852                 const jclass klaz //
00853                 ) {
00854 
00855         UDT::SOCKOPT optionName = (UDT::SOCKOPT) enumCode;
00856         UDT_OptVal optionValue;
00857         int optionValueSize = sizeof(optionValue);
00858 
00859         const jint socketID = UDT_GetSocketID(env, self);
00860 
00861         const int rv = UDT::getsockopt( //
00862                         socketID, 0, optionName, (void*) &optionValue, &optionValueSize);
00863 
00864         if (rv == UDT::ERROR) {
00865                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00866                 UDT_ThrowExceptionUDT_ErrorInfo( //
00867                                 env, socketID, "getOption0:getsockopt", &errorInfo);
00868                 return NULL;
00869         }
00870 
00871         if (env->IsSameObject(klaz, jdk_clsBoolean)) {
00872 
00873                 return X_NewBoolean(env, optionValue.boolValue);
00874 
00875         } else if (env->IsSameObject(klaz, jdk_clsInteger)) {
00876 
00877                 return X_NewInteger(env, optionValue.intValue);
00878 
00879         } else if (env->IsSameObject(klaz, udt_clsLingerUDT)) {
00880 
00881                 return UDT_NewLingerUDT(env, &(optionValue.lingerValue));
00882 
00883         } else if (env->IsSameObject(klaz, jdk_clsLong)) {
00884 
00885                 return X_NewLong(env, optionValue.longValue);
00886 
00887         } else if (env->IsSameObject(klaz, udt_clsFactoryUDT)) {
00888 
00889                 CCC* pCCC = reinterpret_cast<CCC*>(optionValue.factory);
00890 
00891                 //check to see if they type is as JNICCC class
00892                 JNICCC* pJNICCC = dynamic_cast<JNICCC*>(pCCC);
00893 
00894                 if (pJNICCC != NULL) {
00895                         //it is, so return the corresponding Java CCC (or derivative) class
00896                         return pJNICCC->getJavaCCC();
00897                 } else {
00898                         //it's a plain CCC class or standard C++ congestion
00899                         //control class so return NULL instead
00900                         return NULL;
00901                 }
00902 
00903         } else {
00904 
00905                 UDT_ThrowExceptionUDT_Message(env, socketID,
00906                                 "unsupported option class in OptionUDT");
00907 
00908                 return NULL;
00909         }
00910 
00911 }
00912 
00913 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_setOption0( //
00914                 JNIEnv * const env, //
00915                 const jobject self, //
00916                 const jint enumCode, //
00917                 const jclass klaz, //
00918                 const jobject objValue //
00919                 ) {
00920 
00921         const jint socketID = UDT_GetSocketID(env, self);
00922 
00923         UDT::SOCKOPT optionName = (UDT::SOCKOPT) enumCode;
00924         UDT_OptVal optionValue;
00925         int optionValueSize = sizeof(optionValue);
00926 
00927         if (env->IsSameObject(klaz, jdk_clsBoolean)) {
00928 
00929                 jmethodID methodID = //
00930                                 env->GetMethodID(jdk_clsBoolean, "booleanValue", "()Z");
00931                 jboolean value = env->CallBooleanMethod(objValue, methodID);
00932 
00933                 optionValue.boolValue = BOOL(value);
00934                 optionValueSize = sizeof(bool);
00935 
00936         } else if (env->IsSameObject(klaz, jdk_clsInteger)) {
00937 
00938                 jmethodID methodID = //
00939                                 env->GetMethodID(jdk_clsInteger, "intValue", "()I");
00940                 jint value = env->CallIntMethod(objValue, methodID);
00941 
00942                 optionValue.intValue = value;
00943                 optionValueSize = sizeof(int);
00944 
00945         } else if (env->IsSameObject(klaz, udt_clsLingerUDT)) {
00946 
00947                 jmethodID methodID = //
00948                                 env->GetMethodID(udt_clsLingerUDT, "intValue", "()I");
00949                 int value = env->CallIntMethod(objValue, methodID);
00950 
00951                 if (value <= 0) {
00952                         optionValue.lingerValue.l_onoff = 0;
00953                         optionValue.lingerValue.l_linger = 0;
00954                 } else {
00955                         optionValue.lingerValue.l_onoff = 1;
00956                         optionValue.lingerValue.l_linger = value; // msvc C4244
00957                 }
00958 
00959                 optionValueSize = sizeof(linger);
00960 
00961         } else if (env->IsSameObject(klaz, jdk_clsLong)) {
00962 
00963                 jmethodID methodID = //
00964                                 env->GetMethodID(jdk_clsLong, "longValue", "()J");
00965                 jlong value = env->CallLongMethod(objValue, methodID);
00966 
00967                 optionValue.longValue = value;
00968                 optionValueSize = sizeof(int64_t);
00969 
00970         } else if (env->IsSameObject(klaz, udt_clsFactoryUDT)) {
00971 
00972                 optionValue.factory = new JNICCCFactory(env, objValue);
00973                 optionValueSize = sizeof(void*);
00974 
00975         } else {
00976 
00977                 UDT_ThrowExceptionUDT_Message(env, socketID,
00978                                 "unsupported option class in OptionUDT");
00979 
00980                 return;
00981         }
00982 
00983         const int rv = UDT::setsockopt(socketID, 0, optionName,
00984                         (void*) (optionName == UDT_CC ? optionValue.factory : &optionValue),
00985                         optionValueSize);
00986 
00987         if (optionName == UDT_CC && optionValue.factory != NULL) {
00988                 delete reinterpret_cast<JNICCCFactory*>(optionValue.factory);
00989         }
00990 
00991         if (rv == UDT::ERROR) {
00992                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
00993                 UDT_ThrowExceptionUDT_ErrorInfo( //
00994                                 env, socketID, "setOption0:setsockopt", &errorInfo);
00995                 return;
00996         }
00997 
00998 }
00999 
01000 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_listen0( //
01001                 JNIEnv * const env, //
01002                 const jobject self, //
01003                 const jint queueSize //
01004                 ) {
01005 
01006         const jint socketID = UDT_GetSocketID(env, self);
01007 
01008         const int rv = UDT::listen(socketID, queueSize);
01009 
01010         if (rv == UDT::ERROR) {
01011                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01012                 UDT_ThrowExceptionUDT_ErrorInfo( //
01013                                 env, socketID, "listen0:listen", &errorInfo);
01014                 return;
01015         }
01016 
01017 }
01018 
01019 // #########################################################################
01020 
01021 bool X_IsValidRange( //
01022                 JNIEnv * const env, //
01023                 const jint socketID, //
01024                 const jlong position, //
01025                 const jlong limit, //
01026                 const jlong capacity //
01027                 ) {
01028         if (!X_IsInRange(0, position, capacity)) {
01029                 UDT_ThrowExceptionUDT_Message( //
01030                                 env, socketID, "position is out of range");
01031                 return false;
01032         }
01033         if (!X_IsInRange(0, limit, capacity)) {
01034                 UDT_ThrowExceptionUDT_Message( //
01035                                 env, socketID, "limit is out of range");
01036                 return false;
01037         }
01038         if (position > limit) {
01039                 UDT_ThrowExceptionUDT_Message( //
01040                                 env, socketID, "position > limit");
01041                 return false;
01042         }
01043         return true;
01044 }
01045 
01046 // #######################################################################
01047 
01048 /*
01049  * receiveX call is shared for both receive() and receivemsg()
01050  */
01051 
01052 // return values, if exception is NOT thrown
01053 // -1 : nothing received (non-blocking only)
01054 // =0 : timeout expired (blocking only)
01055 // >0 : normal receive
01056 jint UDT_ReturnReceiveError( //
01057                 JNIEnv * const env, //
01058                 const jint socketID //
01059                 ) {
01060         UDT::ERRORINFO errorInfo = UDT::getlasterror();
01061         const int errorCode = errorInfo.getErrorCode();
01062         if (errorCode == UDT::ERRORINFO::EASYNCRCV) {
01063                 // not a java exception: non-blocking mode return when nothing is received
01064         } else {
01065                 // really exception
01066                 UDT_ThrowExceptionUDT_ErrorInfo( //
01067                                 env, socketID, "recv/recvmsg", &errorInfo);
01068         }
01069         return JNI_ERR;
01070 }
01071 
01072 // receive into complete array
01073 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_receive0( //
01074                 JNIEnv * const env, //
01075                 const jclass clsSocketUDT, //
01076                 const jint socketID, //
01077                 const jint socketType, //
01078                 const jbyteArray arrayObj //
01079                 ) {
01080 
01081         UNUSED(clsSocketUDT);
01082 
01083         jboolean isCopy; // whether JVM returns a reference or a copy
01084 
01085         jbyte * const data = env->GetByteArrayElements(arrayObj, &isCopy); // note: must release
01086 
01087         const jsize size = env->GetArrayLength(arrayObj);
01088 
01089         int rv;
01090 
01091         switch (socketType) {
01092         case SOCK_STREAM:
01093                 rv = UDT::recv(socketID, (char*) data, (int) size, 0);
01094                 break;
01095         case SOCK_DGRAM:
01096                 rv = UDT::recvmsg(socketID, (char*) data, (int) size);
01097                 break;
01098         default:
01099                 env->ReleaseByteArrayElements(arrayObj, data, JNI_ABORT); // do not copy back
01100                 UDT_ThrowExceptionUDT_Message(env, socketID,
01101                                 "recv/recvmsg : unexpected socketType");
01102                 return JNI_ERR;
01103         }
01104 
01105         if (rv > 0) { // normal
01106                 env->ReleaseByteArrayElements(arrayObj, data, JNI_UPDATE); //
01107                 return rv;
01108         } else if (rv < 0) { // UDT::ERROR
01109                 env->ReleaseByteArrayElements(arrayObj, data, JNI_ABORT); //
01110                 return UDT_ReturnReceiveError(env, socketID);
01111         } else { // ==0; UDT_TIMEOUT
01112                 env->ReleaseByteArrayElements(arrayObj, data, JNI_ABORT); //
01113                 return UDT_TIMEOUT;
01114         }
01115 
01116 }
01117 
01118 // receive into a portion of an array
01119 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_receive1( //
01120                 JNIEnv * const env, //
01121                 const jclass clsSocketUDT, //
01122                 const jint socketID, //
01123                 const jint socketType, //
01124                 const jbyteArray arrayObj, //
01125                 const jint position, //
01126                 const jint limit //
01127                 ) {
01128 
01129         UNUSED(clsSocketUDT);
01130 
01131         const jsize capacity = env->GetArrayLength(arrayObj);
01132 
01133         if (!X_IsValidRange(env, socketID, position, limit, capacity)) {
01134                 return JNI_ERR;
01135         }
01136 
01137         const jsize size = limit - position;
01138 
01139         jbyte * const data = (jbyte *) malloc(sizeof(jbyte) * size);
01140 
01141         if (data == NULL) {
01142                 UDT_ThrowExceptionUDT_Message(env, socketID,
01143                                 "recv/recvmsg : can not allocate data array");
01144                 return JNI_ERR;
01145         }
01146 
01147         int rv;
01148 
01149         switch (socketType) {
01150         case SOCK_STREAM:
01151                 rv = UDT::recv(socketID, (char*) data, (int) size, 0);
01152                 break;
01153         case SOCK_DGRAM:
01154                 rv = UDT::recvmsg(socketID, (char*) data, (int) size);
01155                 break;
01156         default:
01157                 free(data);
01158                 UDT_ThrowExceptionUDT_Message(env, socketID,
01159                                 "recv/recvmsg : unexpected socketType");
01160                 return JNI_ERR;
01161         }
01162 
01163         if (rv > 0) { // normal
01164                 env->SetByteArrayRegion(arrayObj, position, rv, data);
01165                 free(data);
01166                 return rv;
01167         } else if (rv < 0) { // UDT::ERROR
01168                 free(data);
01169                 return UDT_ReturnReceiveError(env, socketID);
01170         } else { // ==0; UDT_TIMEOUT
01171                 free(data);
01172                 return UDT_TIMEOUT;
01173         }
01174 
01175 }
01176 
01177 // receive into direct byte buffer
01178 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_receive2( //
01179                 JNIEnv * const env, //
01180                 const jclass clsSocketUDT, //
01181                 const jint socketID, //
01182                 const jint socketType, //
01183                 const jobject bufferObj, //
01184                 const jint position, //
01185                 const jint limit //
01186                 ) {
01187 
01188         UNUSED(clsSocketUDT);
01189 
01190         const jlong capacity = env->GetDirectBufferCapacity(bufferObj);
01191 
01192         if (!X_IsValidRange(env, socketID, position, limit, capacity)) {
01193                 return JNI_ERR;
01194         }
01195 
01196         const jbyte * bufferAddress = //
01197                         static_cast<jbyte*>(env->GetDirectBufferAddress(bufferObj));
01198 
01199         const jbyte * data = bufferAddress + position;
01200         const jsize size = static_cast<jsize>(limit - position);
01201 
01202         // memory boundary test
01203         // assert(data[0] | 1);
01204         // assert(data[size - 1] | 1);
01205 
01206         int rv;
01207 
01208         switch (socketType) {
01209         case SOCK_STREAM:
01210                 rv = UDT::recv(socketID, (char*) data, (int) size, 0);
01211                 break;
01212         case SOCK_DGRAM:
01213                 rv = UDT::recvmsg(socketID, (char*) data, (int) size);
01214                 break;
01215         default:
01216                 UDT_ThrowExceptionUDT_Message(env, socketID,
01217                                 "recv/recvmsg : unexpected socketType");
01218                 return JNI_ERR;
01219         }
01220 
01221         if (rv > 0) { // normal
01222                 return rv;
01223         } else if (rv < 0) { //  UDT::ERROR
01224                 return UDT_ReturnReceiveError(env, socketID);
01225         } else { // ==0; UDT_TIMEOUT
01226                 return UDT_TIMEOUT;
01227         }
01228 
01229 }
01230 
01231 JNIEXPORT jlong JNICALL Java_com_barchart_udt_SocketUDT_receiveFile0(
01232                 JNIEnv * const env, //
01233                 const jclass clsSocketUDT, //
01234                 const jint socketID, //
01235                 const jstring path, //
01236                 const jlong offset, //
01237                 const jlong length, //
01238                 const jint block //
01239                 ) {
01240 
01241         UNUSED(clsSocketUDT);
01242 
01243         const char * filePath = env->GetStringUTFChars(path, NULL);
01244         int64_t fileOffset = static_cast<int64_t>(offset);
01245         int64_t fileLength = static_cast<int64_t>(length);
01246         int fileBlock = static_cast<int>(block);
01247 
01248         const int64_t rv = UDT::recvfile2( //
01249                         socketID, filePath, &fileOffset, fileLength, fileBlock);
01250 
01251         if (rv == UDT::ERROR) {
01252                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01253                 UDT_ThrowExceptionUDT_ErrorInfo( //
01254                                 env, socketID, "receiveFile0:recvfile2", &errorInfo);
01255                 return JNI_ERR;
01256         }
01257 
01258         return static_cast<jlong>(rv);
01259 
01260 }
01261 
01262 // return values, if exception is NOT thrown
01263 // -1 : no buffer space (non-blocking only )
01264 // =0 : timeout expired (blocking only)
01265 // >0 : normal send, byte count
01266 jint UDT_ReturnSendError( //
01267                 JNIEnv * const env, //
01268                 const jint socketID //
01269                 ) {
01270         UDT::ERRORINFO errorInfo = UDT::getlasterror();
01271         const int errorCode = errorInfo.getErrorCode();
01272         if (errorCode == UDT::ERRORINFO::EASYNCSND) {
01273                 // not a java exception: non-blocking mode return when no space in UDT buffer
01274         } else {
01275                 // really exception
01276                 UDT_ThrowExceptionUDT_ErrorInfo( //
01277                                 env, socketID, "send/sendmsg", &errorInfo);
01278         }
01279         return JNI_ERR;
01280 }
01281 
01282 // send from complete array
01283 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_send0( //
01284                 JNIEnv * const env, //
01285                 const jclass clsSocketUDT, //
01286                 const jint socketID, //
01287                 const jint socketType, //
01288                 const jint timeToLive, //
01289                 const jboolean isOrdered, //
01290                 const jbyteArray arrayObj //
01291                 ) {
01292 
01293         UNUSED(clsSocketUDT);
01294 
01295         jboolean isCopy; // whether JVM returned reference or copy
01296 
01297         jbyte * const data = env->GetByteArrayElements(arrayObj, &isCopy); // note: must release
01298 
01299         const jsize size = env->GetArrayLength(arrayObj);
01300 
01301         int rv;
01302 
01303         switch (socketType) {
01304         case SOCK_STREAM:
01305                 rv = UDT::send(socketID, (char*) data, (int) size, 0);
01306                 break;
01307         case SOCK_DGRAM:
01308                 rv = UDT::sendmsg(socketID, (char*) data, (int) size, (int) timeToLive,
01309                                 BOOL(isOrdered));
01310                 break;
01311         default:
01312                 env->ReleaseByteArrayElements(arrayObj, data, JNI_ABORT); // do not copy back
01313                 UDT_ThrowExceptionUDT_Message(env, socketID,
01314                                 "send/sendmsg : unexpected socketType");
01315                 return JNI_ERR;
01316         }
01317 
01318         env->ReleaseByteArrayElements(arrayObj, data, JNI_ABORT); // do not copy back
01319 
01320         if (rv > 0) { // normal
01321                 return rv;
01322         } else if (rv < 0) { // UDT::ERROR
01323                 return UDT_ReturnSendError(env, socketID);
01324         } else { // ==0; UDT_TIMEOUT
01325                 return UDT_TIMEOUT;
01326         }
01327 
01328 }
01329 
01330 // send from a portion of array
01331 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_send1( //
01332                 JNIEnv * const env, //
01333                 const jclass clsSocketUDT, //
01334                 const jint socketID, //
01335                 const jint socketType, //
01336                 const jint timeToLive, //
01337                 const jboolean isOrdered, //
01338                 const jbyteArray arrayObj, //
01339                 const jint position, //
01340                 const jint limit //
01341                 ) {
01342 
01343         UNUSED(clsSocketUDT);
01344 
01345         const jsize capacity = env->GetArrayLength(arrayObj);
01346 
01347         if (!X_IsValidRange(env, socketID, position, limit, capacity)) {
01348                 return JNI_ERR;
01349         }
01350 
01351         const jsize size = limit - position;
01352 
01353         jbyte * const data = (jbyte *) malloc(sizeof(jbyte) * size);
01354 
01355         if (data == NULL) {
01356                 UDT_ThrowExceptionUDT_Message(env, socketID,
01357                                 "send/sendmsg : can not allocate data array");
01358                 return JNI_ERR;
01359         }
01360 
01361         env->GetByteArrayRegion(arrayObj, position, size, data);
01362 
01363         int rv;
01364 
01365         switch (socketType) {
01366         case SOCK_STREAM:
01367                 rv = UDT::send(socketID, (char*) data, (int) size, 0);
01368                 break;
01369         case SOCK_DGRAM:
01370                 rv = UDT::sendmsg(socketID, (char*) data, (int) size, (int) timeToLive,
01371                                 BOOL(isOrdered));
01372                 break;
01373         default:
01374                 free(data);
01375                 UDT_ThrowExceptionUDT_Message(env, socketID,
01376                                 "send/sendmsg : unexpected socketType");
01377                 return JNI_ERR;
01378         }
01379 
01380         free(data);
01381 
01382         if (rv > 0) { // normal
01383                 return rv;
01384         } else if (rv < 0) { // UDT::ERROR
01385                 return UDT_ReturnSendError(env, socketID);
01386         } else { // ==0; UDT_TIMEOUT
01387                 return UDT_TIMEOUT;
01388         }
01389 
01390 }
01391 
01392 // send direct byte buffer
01393 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_send2( //
01394                 JNIEnv * const env, //
01395                 const jclass clsSocketUDT, //
01396                 const jint socketID, //
01397                 const jint socketType, //
01398                 const jint timeToLive, //
01399                 const jboolean isOrdered, //
01400                 const jobject bufferObj, //
01401                 const jint position, //
01402                 const jint limit //
01403                 ) {
01404 
01405         UNUSED(clsSocketUDT);
01406 
01407         const jbyte* address = //
01408                         static_cast<jbyte*>(env->GetDirectBufferAddress(bufferObj));
01409         const jlong capacity = env->GetDirectBufferCapacity(bufferObj);
01410 
01411         if (!X_IsValidRange(env, socketID, position, limit, capacity)) {
01412                 return JNI_ERR;
01413         }
01414 
01415         const jbyte* data = address + position;
01416         const jsize size = static_cast<jsize>(limit - position);
01417 
01418         // memory boundary test
01419         // assert(data[0] | 1);
01420         // assert(data[size - 1] | 1);
01421 
01422         int rv;
01423 
01424         switch (socketType) {
01425         case SOCK_STREAM:
01426                 rv = UDT::send(socketID, (char*) data, (int) size, 0);
01427                 break;
01428         case SOCK_DGRAM:
01429                 rv = UDT::sendmsg(socketID, (char*) data, (int) size, (int) timeToLive,
01430                                 BOOL(isOrdered));
01431                 break;
01432         default:
01433                 UDT_ThrowExceptionUDT_Message(env, socketID,
01434                                 "send/sendmsg : unexpected socketType");
01435                 return JNI_ERR;
01436         }
01437 
01438         if (rv > 0) { // normal
01439                 return rv;
01440         } else if (rv < 0) { // UDT::ERROR
01441                 return UDT_ReturnSendError(env, socketID);
01442         } else { // ==0; UDT_TIMEOUT
01443                 return UDT_TIMEOUT;
01444         }
01445 
01446 }
01447 
01448 JNIEXPORT jlong JNICALL Java_com_barchart_udt_SocketUDT_sendFile0( //
01449                 JNIEnv * const env, //
01450                 const jclass clsSocketUDT, //
01451                 const jint socketID, //
01452                 const jstring path, //
01453                 const jlong offset, //
01454                 const jlong length, //
01455                 const jint block //
01456                 ) {
01457 
01458         UNUSED(clsSocketUDT);
01459 
01460         const char * filePath = env->GetStringUTFChars(path, NULL);
01461         int64_t fileOffset = static_cast<int64_t>(offset);
01462         int64_t fileLength = static_cast<int64_t>(length);
01463         int fileBlock = static_cast<int>(block);
01464 
01465         const int64_t rv = UDT::sendfile2( //
01466                         socketID, filePath, &fileOffset, fileLength, fileBlock);
01467 
01468         if (rv == UDT::ERROR) {
01469                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01470                 UDT_ThrowExceptionUDT_ErrorInfo( //
01471                                 env, socketID, "sendFile0:sendfile2", &errorInfo);
01472                 return JNI_ERR;
01473         }
01474 
01475         return static_cast<jlong>(rv);
01476 
01477 }
01478 
01479 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_getErrorCode0( //
01480                 JNIEnv * const env, //
01481                 const jobject self //
01482                 ) {
01483 
01484         UNUSED(env);
01485         UNUSED(self);
01486 
01487         const jint errorCode = UDT::getlasterror().getErrorCode();
01488 
01489         return errorCode;
01490 
01491 }
01492 
01493 JNIEXPORT jstring JNICALL Java_com_barchart_udt_SocketUDT_getErrorMessage0( //
01494                 JNIEnv * const env, //
01495                 const jobject self //
01496                 ) {
01497 
01498         UNUSED(self);
01499 
01500         const char* errorMessage = UDT::getlasterror().getErrorMessage();
01501 
01502         return (errorMessage == NULL) ?
01503                         env->NewStringUTF("<NONE>") : env->NewStringUTF(errorMessage);
01504 
01505 }
01506 
01507 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_clearError0( //
01508                 JNIEnv * const env, const jobject self //
01509                 ) {
01510 
01511         UNUSED(env);
01512         UNUSED(self);
01513 
01514         UDT::getlasterror().clear();
01515 
01516 }
01517 
01518 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_updateMonitor0( //
01519                 JNIEnv * const env, //
01520                 const jobject self, //
01521                 const jboolean makeClear //
01522                 ) {
01523 
01524         UDT::TRACEINFO monitor;
01525 
01526         const jint socketID = UDT_GetSocketID(env, self);
01527 
01528         const int rv = UDT::perfmon(socketID, &monitor, BOOL(makeClear));
01529 
01530         if (rv == UDT::ERROR) {
01531                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01532                 UDT_ThrowExceptionUDT_ErrorInfo( //
01533                                 env, socketID, "updateMonitor0:perfmon", &errorInfo);
01534                 return;
01535         }
01536 
01537         const jobject objMonitor = env->GetObjectField(self, udts_MonitorID);
01538 
01539         CHK_NUL_RET_RET(objMonitor, "objMonitor");
01540 
01541         // global measurements
01542         env->SetLongField(objMonitor, udtm_msTimeStamp, monitor.msTimeStamp); // time since the UDT entity is started, in milliseconds
01543         env->SetLongField(objMonitor, udtm_pktSentTotal, monitor.pktSentTotal); // total number of sent data packets, including retransmissions
01544         env->SetLongField(objMonitor, udtm_pktRecvTotal, monitor.pktRecvTotal); // total number of received packets
01545         env->SetIntField(objMonitor, udtm_pktSndLossTotal, monitor.pktSndLossTotal); // total number of lost packets (sender side)
01546         env->SetIntField(objMonitor, udtm_pktRcvLossTotal, monitor.pktRcvLossTotal); // total number of lost packets (receiver side)
01547         env->SetIntField(objMonitor, udtm_pktRetransTotal, monitor.pktRetransTotal); // total number of retransmitted packets
01548         env->SetIntField(objMonitor, udtm_pktSentACKTotal, monitor.pktSentACKTotal); // total number of sent ACK packets
01549         env->SetIntField(objMonitor, udtm_pktRecvACKTotal, monitor.pktRecvACKTotal); // total number of received ACK packets
01550         env->SetIntField(objMonitor, udtm_pktSentNAKTotal, monitor.pktSentNAKTotal); // total number of sent NAK packets
01551         env->SetIntField(objMonitor, udtm_pktRecvNAKTotal, monitor.pktRecvNAKTotal); // total number of received NAK packets
01552         env->SetLongField(objMonitor, udtm_usSndDurationTotal,
01553                         monitor.usSndDurationTotal); // total time duration when UDT is sending data (idle time exclusive)
01554 
01555         // local measurements
01556         env->SetLongField(objMonitor, udtm_pktSent, monitor.pktSent); // number of sent data packets, including retransmissions
01557         env->SetLongField(objMonitor, udtm_pktRecv, monitor.pktRecv); // number of received packets
01558         env->SetIntField(objMonitor, udtm_pktSndLoss, monitor.pktSndLoss); // number of lost packets (sender side)
01559         env->SetIntField(objMonitor, udtm_pktRcvLoss, monitor.pktRcvLoss); // number of lost packets (receiverer side)
01560         env->SetIntField(objMonitor, udtm_pktRetrans, monitor.pktRetrans); // number of retransmitted packets
01561         env->SetIntField(objMonitor, udtm_pktSentACK, monitor.pktSentACK); // number of sent ACK packets
01562         env->SetIntField(objMonitor, udtm_pktRecvACK, monitor.pktRecvACK); // number of received ACK packets
01563         env->SetIntField(objMonitor, udtm_pktSentNAK, monitor.pktSentNAK); // number of sent NAK packets
01564         env->SetIntField(objMonitor, udtm_pktRecvNAK, monitor.pktRecvNAK); // number of received NAK packets
01565         env->SetDoubleField(objMonitor, udtm_mbpsSendRate, monitor.mbpsSendRate); // sending rate in Mb/s
01566         env->SetDoubleField(objMonitor, udtm_mbpsRecvRate, monitor.mbpsRecvRate); // receiving rate in Mb/s
01567         env->SetLongField(objMonitor, udtm_usSndDuration, monitor.usSndDuration); // busy sending time (i.e., idle time exclusive)
01568 
01569         // instant measurements
01570         env->SetDoubleField(objMonitor, udtm_usPktSndPeriod,
01571                         monitor.usPktSndPeriod); // packet sending period, in microseconds
01572         env->SetIntField(objMonitor, udtm_pktFlowWindow, monitor.pktFlowWindow); // flow window size, in number of packets
01573         env->SetIntField(objMonitor, udtm_pktCongestionWindow,
01574                         monitor.pktCongestionWindow); // congestion window size, in number of packets
01575         env->SetIntField(objMonitor, udtm_pktFlightSize, monitor.pktFlightSize); // number of packets on flight
01576         env->SetDoubleField(objMonitor, udtm_msRTT, monitor.msRTT); // RTT, in milliseconds
01577         env->SetDoubleField(objMonitor, udtm_mbpsBandwidth, monitor.mbpsBandwidth); // estimated bandwidth, in Mb/s
01578         env->SetIntField(objMonitor, udtm_byteAvailSndBuf, monitor.byteAvailSndBuf); // available UDT sender buffer size
01579         env->SetIntField(objMonitor, udtm_byteAvailRcvBuf, monitor.byteAvailRcvBuf); // available UDT receiver buffer size
01580 
01581 }
01582 
01583 // #########################################################################
01584 
01585 void UDT_CopyArrayToSet(jint* array, set<UDTSOCKET>* udSet, const jsize size) {
01586         for (jint index = 0; index < size; index++) {
01587                 const jint socketID = array[index];
01588                 udSet->insert(socketID);
01589         }
01590 }
01591 
01592 void UDT_CopySetToArray(set<UDTSOCKET>* udSet, jint* array, const jsize size) {
01593         set<UDTSOCKET>::iterator iterator = udSet->begin();
01594         for (jint index = 0; index < size; index++) {
01595                 const jint socketID = *iterator;
01596                 array[index] = socketID;
01597                 ++iterator;
01598         }
01599 }
01600 
01601 #define UDT_READ_INDEX          com_barchart_udt_SocketUDT_UDT_READ_INDEX
01602 #define UDT_WRITE_INDEX         com_barchart_udt_SocketUDT_UDT_WRITE_INDEX
01603 #define UDT_EXCEPT_INDEX        com_barchart_udt_SocketUDT_UDT_EXCEPT_INDEX
01604 #define UDT_SIZE_COUNT          com_barchart_udt_SocketUDT_UDT_SIZE_COUNT
01605 #define UDT_SELECT_LIMIT        com_barchart_udt_SocketUDT_DEFAULT_MAX_SELECTOR_SIZE
01606 
01607 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_getStatus0( //
01608                 JNIEnv * const env, //
01609                 const jobject self //
01610                 ) {
01611 
01612         const jint socketID = UDT_GetSocketID(env, self);
01613 
01614         const UDTSTATUS status = UDT::getsockstate(socketID);
01615 
01616         return static_cast<jint>(status);
01617 
01618 }
01619 
01620 //
01621 
01622 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_epollCreate0( //
01623                 JNIEnv * const env, //
01624                 const jclass clsSocketUDT //
01625                 ) {
01626 
01627         UNUSED(env);
01628         UNUSED(clsSocketUDT);
01629 
01630         const int rv = UDT::epoll_create();
01631 
01632         if (rv == UDT::ERROR) {
01633                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01634                 UDT_ThrowExceptionUDT_ErrorInfo( //
01635                                 env, 0, "epollCreate0:epoll_create", &errorInfo);
01636                 return JNI_ERR;
01637         }
01638 
01639         return static_cast<jint>(rv);
01640 
01641 }
01642 
01643 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollRelease0( //
01644                 JNIEnv * const env, //
01645                 const jclass clsSocketUDT, //
01646                 const jint pollID) {
01647 
01648         UNUSED(env);
01649         UNUSED(clsSocketUDT);
01650 
01651         const int rv = UDT::epoll_release(pollID);
01652 
01653         if (rv == UDT::ERROR) {
01654                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01655                 UDT_ThrowExceptionUDT_ErrorInfo( //
01656                                 env, 0, "epollRelease0:epoll_release", &errorInfo);
01657                 return;
01658         }
01659 
01660 }
01661 
01662 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollAdd0( //
01663                 JNIEnv * const env, //
01664                 const jclass clsSocketUDT, //
01665                 const jint pollID, //
01666                 const jint socketID, //
01667                 const jint pollOpt //
01668                 ) {
01669 
01670         UNUSED(env);
01671         UNUSED(clsSocketUDT);
01672 
01673         const int events = static_cast<int>(pollOpt);
01674 
01675         const int rv = UDT::epoll_add_usock(pollID, socketID, &events);
01676 
01677         if (rv == UDT::ERROR) {
01678                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01679                 UDT_ThrowExceptionUDT_ErrorInfo( //
01680                                 env, socketID, "epollAdd0:epoll_add_usock", &errorInfo);
01681                 return;
01682         }
01683 
01684 }
01685 
01686 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollRemove0( //
01687                 JNIEnv * const env, //
01688                 const jclass clsSocketUDT, //
01689                 const jint pollID, //
01690                 const jint socketID //
01691                 ) {
01692 
01693         UNUSED(env);
01694         UNUSED(clsSocketUDT);
01695 
01696         const int rv = UDT::epoll_remove_usock(pollID, socketID);
01697 
01698         if (rv == UDT::ERROR) {
01699                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01700                 UDT_ThrowExceptionUDT_ErrorInfo( //
01701                                 env, socketID, "epollRemove0:epoll_remove_usock", &errorInfo);
01702                 return;
01703         }
01704 
01705 }
01706 
01707 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_epollUpdate0( //
01708                 JNIEnv * const env, //
01709                 const jclass clsSocketUDT, //
01710                 const jint pollID, //
01711                 const jint socketID, //
01712                 const jint pollOpt //
01713                 ) {
01714 
01715         UNUSED(clsSocketUDT);
01716 
01717         const int events = static_cast<int>(pollOpt);
01718 
01719         const int rv = UDT::epoll_update_usock(pollID, socketID, &events);
01720 
01721         if (rv == UDT::ERROR) {
01722                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01723                 UDT_ThrowExceptionUDT_ErrorInfo( //
01724                                 env, socketID, "epollUpdate0:epoll_update_usock", &errorInfo);
01725                 return;
01726         }
01727 
01728 }
01729 
01730 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_epollVerify0( //
01731                 JNIEnv * const env, //
01732                 const jclass clsSocketUDT, //
01733                 const jint pollID, //
01734                 const jint socketID) {
01735 
01736         UNUSED(clsSocketUDT);
01737 
01738         int events = 0;
01739 
01740         const int rv = UDT::epoll_verify_usock(pollID, socketID, &events);
01741 
01742         if (rv == UDT::ERROR) {
01743                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01744                 UDT_ThrowExceptionUDT_ErrorInfo( //
01745                                 env, socketID, "epollVerify0:epoll_update_usock", &errorInfo);
01746                 return JNI_ERR;
01747         }
01748 
01749         return static_cast<jint>(events);
01750 
01751 }
01752 
01753 JNIEXPORT jint JNICALL Java_com_barchart_udt_SocketUDT_epollWait0( //
01754                 JNIEnv * const env, //
01755                 const jclass clsSocketUDT, //
01756                 const jint pollID, //
01757                 const jobject objReadBuffer, //
01758                 const jobject objWriteBuffer, //
01759                 const jobject objSizeBuffer, //
01760                 const jlong millisTimeout //
01761                 ) {
01762 
01763         UNUSED(clsSocketUDT);
01764 
01765         // readiness sets
01766         set<UDTSOCKET> readSet;
01767         set<UDTSOCKET> writeSet;
01768 
01769         // readiness report
01770         const int rv = UDT::epoll_wait( //
01771                         pollID, &readSet, &writeSet, millisTimeout, NULL, NULL);
01772 
01773         // readiness reports size array
01774         jint* const sizeArray = //
01775                         static_cast<jint*>(env->GetDirectBufferAddress(objSizeBuffer));
01776 
01777         // process timeout & errors
01778         if (rv <= 0) { // UDT::ERROR is '-1'
01779                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01780                 if (errorInfo.getErrorCode() == UDT::ERRORINFO::ETIMEOUT) {
01781                         // not a java exception:
01782                         sizeArray[UDT_READ_INDEX] = 0;
01783                         sizeArray[UDT_WRITE_INDEX] = 0;
01784                         sizeArray[UDT_EXCEPT_INDEX] = 0;
01785                         return UDT_TIMEOUT;
01786                 } else {
01787                         // really exception
01788                         UDT_ThrowExceptionUDT_ErrorInfo( //
01789                                         env, 0, "epollWait0:epoll_wait", &errorInfo);
01790                         return JNI_ERR;
01791                 }
01792         }
01793 
01794         // return read interest
01795         const jsize readSize = readSet.size();
01796         sizeArray[UDT_READ_INDEX] = readSize;
01797         if (readSize > 0) {
01798                 if (readSize > env->GetDirectBufferCapacity(objReadBuffer)) {
01799                         UDT_ThrowExceptionUDT_Message(env, 0,
01800                                         "readSize > objReadBuffer capacity");
01801                         return JNI_ERR;
01802                 }
01803                 jint* const readArray = //
01804                                 static_cast<jint*>(env->GetDirectBufferAddress(objReadBuffer));
01805                 UDT_CopySetToArray(&readSet, readArray, readSize);
01806         }
01807 
01808         // return write interest
01809         const jsize writeSize = writeSet.size();
01810         sizeArray[UDT_WRITE_INDEX] = writeSize;
01811         if (writeSize > 0) {
01812                 if (writeSize > env->GetDirectBufferCapacity(objWriteBuffer)) {
01813                         UDT_ThrowExceptionUDT_Message(env, 0,
01814                                         "writeSize > objWriteBuffer capacity");
01815                         return JNI_ERR;
01816                 }
01817                 jint* const writeArray = //
01818                                 static_cast<jint*>(env->GetDirectBufferAddress(objWriteBuffer));
01819                 UDT_CopySetToArray(&writeSet, writeArray, writeSize);
01820         }
01821 
01822         return rv;
01823 
01824 }
01825 
01826 // #########################################
01827 // #
01828 // # start - used for development only
01829 // #
01830 
01831 // test cost of JNI call
01832 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testEmptyCall0( //
01833                 JNIEnv * const env, //
01834                 const jclass clsSocketUDT //
01835                 ) {
01836 
01837         UNUSED(env);
01838         UNUSED(clsSocketUDT);
01839 
01840 }
01841 
01842 // test cost of JNI-to-Java array iteration
01843 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testIterateArray0( //
01844                 JNIEnv * const env, //
01845                 const jclass clsSocketUDT, //
01846                 const jobjectArray objArray //
01847                 ) {
01848 
01849         UNUSED(clsSocketUDT);
01850 
01851         const jsize size = env->GetArrayLength(objArray);
01852         for (jint index = 0; index < size; index++) {
01853                 jobject objAny = env->GetObjectArrayElement(objArray, index);
01854                 UNUSED(objAny);
01855                 objAny = NULL;
01856         }
01857 
01858 }
01859 
01860 // test cost of JNI-to-Java set iteration
01861 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testIterateSet0( //
01862                 JNIEnv * const env, //
01863                 const jclass clsSocketUDT, //
01864                 const jobject objSet //
01865                 ) {
01866 
01867         UNUSED(clsSocketUDT);
01868 
01869         jobject iterator = env->CallObjectMethod(objSet, jdk_clsSet_iteratorID);
01870 
01871         jint count = 0;
01872 
01873         while (JNI_TRUE
01874                         == env->CallBooleanMethod(iterator, jdk_clsIterator_hasNextID)) {
01875                 jobject objAny = env->CallObjectMethod( //
01876                                 iterator, jdk_clsIterator_nextID);
01877                 UNUSED(objAny);
01878                 objAny = NULL;
01879                 count++;
01880         }
01881 
01882 }
01883 
01884 // test cost of JNI-to-Java make array
01885 JNIEXPORT jintArray JNICALL JNICALL Java_com_barchart_udt_SocketUDT_testMakeArray0( //
01886                 JNIEnv * const env, //
01887                 const jclass clsSocketUDT, //
01888                 const jint size //
01889                 ) {
01890 
01891         UNUSED(clsSocketUDT);
01892 
01893         jintArray array = env->NewIntArray(size);
01894 
01895         return array;
01896 
01897 }
01898 
01899 // test cost of array copy
01900 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testGetSetArray0( //
01901                 JNIEnv * const env, //
01902                 const jclass clsSocketUDT, //
01903                 const jintArray objArray, //
01904                 const jboolean isReturn //
01905                 ) {
01906 
01907         UNUSED(clsSocketUDT);
01908 
01909         jboolean isCopy;
01910 
01911         jint* data = env->GetIntArrayElements(objArray, &isCopy);
01912 
01913 //      jsize size = env->GetArrayLength(objArray);
01914 
01915         if (isReturn == JNI_TRUE) {
01916                 env->ReleaseIntArrayElements(objArray, data, JNI_UPDATE);
01917         } else {
01918                 env->ReleaseIntArrayElements(objArray, data, JNI_ABORT);
01919         }
01920 
01921 }
01922 
01923 // test error on close of a closed socket
01924 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testInvalidClose0( //
01925                 JNIEnv * const env, //
01926                 const jclass clsSocketUDT, //
01927                 const jint socketID //
01928                 ) {
01929 
01930         UNUSED(clsSocketUDT);
01931 
01932         const int rv = UDT::close(socketID);
01933 
01934         if (rv == UDT::ERROR) {
01935                 UDT::ERRORINFO errorInfo = UDT::getlasterror();
01936                 UDT_ThrowExceptionUDT_ErrorInfo( //
01937                                 env, socketID, "testInvalidClose0:close", &errorInfo);
01938                 return;
01939         }
01940 
01941 }
01942 
01943 // test crash jvm to debug crash log parser
01944 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testCrashJVM0( //
01945                 JNIEnv * const env, //
01946                 const jclass clsSocketUDT //
01947                 ) {
01948 
01949         printf("native: test crash jvm \n");
01950 
01951         UNUSED(env);
01952         UNUSED(clsSocketUDT);
01953 
01954         jint *array = NULL;
01955 
01956         array[0] = 1;
01957 
01958 }
01959 
01960 // test correctness of direct BYTE buffer access
01961 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testDirectByteBufferAccess0( //
01962                 JNIEnv * const env, //
01963                 const jclass clsSocketUDT, //
01964                 const jobject bufferObj //
01965                 ) {
01966 
01967         UNUSED(clsSocketUDT);
01968 
01969         jbyte* byteBuffer = //
01970                         static_cast<jbyte*>(env->GetDirectBufferAddress(bufferObj));
01971 
01972         jlong capacity = env->GetDirectBufferCapacity(bufferObj);
01973 
01974         printf("native: byteBuffer capacity=%d \n", (int) capacity);
01975 
01976         byteBuffer[0] = 'A';
01977         byteBuffer[1] = 'B';
01978         byteBuffer[2] = 'C';
01979         byteBuffer[3] = 'D';
01980         byteBuffer[4] = 'E';
01981         byteBuffer[5] = 'F';
01982         byteBuffer[6] = 'G';
01983         byteBuffer[7] = 'H';
01984 
01985 }
01986 
01987 // test correctness of direct INT buffer access
01988 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testDirectIntBufferAccess0( //
01989                 JNIEnv * const env, //
01990                 const jclass clsSocketUDT, //
01991                 const jobject bufferObj //
01992                 ) {
01993 
01994         UNUSED(clsSocketUDT);
01995 
01996         jint* intBuffer = static_cast<jint*>(env->GetDirectBufferAddress(bufferObj));
01997 
01998         jlong capacity = env->GetDirectBufferCapacity(bufferObj);
01999 
02000         printf("native: intBuffer capacity=%d \n", (int) capacity);
02001 
02002         intBuffer[0] = 'A';
02003         intBuffer[1] = 'B';
02004         intBuffer[2] = 'C';
02005         intBuffer[3] = 'D';
02006         intBuffer[4] = 'E';
02007         intBuffer[5] = 'F';
02008         intBuffer[6] = 'G';
02009         intBuffer[7] = 'H';
02010 
02011 }
02012 
02013 // test cost of jni array fill
02014 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testFillArray0( //
02015                 JNIEnv * const env, //
02016                 const jclass clsSocketUDT, //
02017                 const jbyteArray arrayObj) {
02018 
02019         UNUSED(clsSocketUDT);
02020 
02021         jboolean isCopy;
02022         jbyte* array = env->GetByteArrayElements(arrayObj, &isCopy);
02023         jsize size = env->GetArrayLength(arrayObj);
02024 
02025         for (int k = 0; k < size; k++) {
02026                 array[k] = (char) k;
02027         }
02028 
02029         env->ReleaseByteArrayElements(arrayObj, array, JNI_UPDATE);
02030 
02031 }
02032 
02033 // test cost of jni direct buffer fill
02034 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testFillBuffer0( //
02035                 JNIEnv * const env, //
02036                 const jclass clsSocketUDT, //
02037                 const jobject bufferObj //
02038                 ) {
02039 
02040         UNUSED(clsSocketUDT);
02041 
02042         jbyte* buffer = static_cast<jbyte*>(env->GetDirectBufferAddress(bufferObj));
02043 
02044         jlong capacity = env->GetDirectBufferCapacity(bufferObj);
02045 
02046         for (int k = 0; k < capacity; k++) {
02047                 buffer[k] = (char) k;
02048         }
02049 
02050 }
02051 
02052 // test cost of direct INT buffer load
02053 JNIEXPORT void JNICALL Java_com_barchart_udt_SocketUDT_testDirectIntBufferLoad0( //
02054                 JNIEnv * const env, //
02055                 const jclass clsSocketUDT, //
02056                 const jobject bufferObj //
02057                 ) {
02058 
02059         UNUSED(clsSocketUDT);
02060 
02061         const jint* byteBuffer = //
02062                         static_cast<jint*>(env->GetDirectBufferAddress(bufferObj));
02063 
02064         UNUSED(byteBuffer);
02065 
02066         const jlong capacity = env->GetDirectBufferCapacity(bufferObj);
02067 
02068         UNUSED(capacity);
02069 
02070 }
02071 
02072 // #
02073 // # finish - used for development only
02074 // #
02075 // #########################################
02076 
02077 }// [extern "C"]

Generated on 9 Feb 2013 for barchart-udt-core-2.2.2 by  doxygen 1.6.1