/* * Class: sun_nio_ch_sctp_SctpNet * Method: getPrimAddrOption0 * Signature: (II)Ljava/net/SocketAddress; */ JNIEXPORT jobject JNICALL Java_sun_nio_ch_sctp_SctpNet_getPrimAddrOption0 (JNIEnv *env, jclass klass, jint fd, jint assocId) { struct sctp_setprim prim; unsigned int prim_len = sizeof(prim); struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr; prim.ssp_assoc_id = assocId; if (getsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, &prim_len) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun.nio.ch.SctpNet.getPrimAddrOption0"); return NULL; } return SockAddrToInetSocketAddress(env, sap); }
void handlePeerAddrChange (JNIEnv* env, jobject resultContainerObj, struct sctp_paddr_change* spc) { int event = 0; jobject addressObj, resultObj; unsigned int state = spc->spc_state; switch (state) { case SCTP_ADDR_AVAILABLE : event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_AVAILABLE; break; case SCTP_ADDR_UNREACHABLE : event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_UNREACHABLE; break; case SCTP_ADDR_REMOVED : event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_REMOVED; break; case SCTP_ADDR_ADDED : event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_ADDED; break; case SCTP_ADDR_MADE_PRIM : event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_MADE_PRIM; #ifndef __solaris__ /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */ break; case SCTP_ADDR_CONFIRMED : event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_CONFIRMED; #endif /* __solaris__ */ } addressObj = SockAddrToInetSocketAddress(env, (struct sockaddr*)&spc->spc_aaddr); /* create SctpPeerAddressChanged */ resultObj = (*env)->NewObject(env, spc_class, spc_ctrID, spc->spc_assoc_id, addressObj, event); CHECK_NULL(resultObj); (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); (*env)->SetIntField(env, resultContainerObj, src_typeID, sun_nio_ch_SctpResultContainer_PEER_ADDRESS_CHANGED); }
void handleMessage (JNIEnv* env, jobject resultContainerObj, struct msghdr* msg,int read, jboolean isEOR, struct sockaddr* sap) { jobject isa, resultObj; struct controlData cdata[1]; if (read == 0) { /* we reached EOF */ read = -1; } isa = SockAddrToInetSocketAddress(env, sap); getControlData(msg, cdata); /* create SctpMessageInfoImpl */ resultObj = (*env)->NewObject(env, smi_class, smi_ctrID, cdata->assocId, isa, read, cdata->streamNumber, isEOR ? JNI_TRUE : JNI_FALSE, cdata->unordered, cdata->ppid); CHECK_NULL(resultObj); (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); (*env)->SetIntField(env, resultContainerObj, src_typeID, sun_nio_ch_SctpResultContainer_MESSAGE); }
// TODO: test: can create send failed without any data? if so need to // update API so that buffer can be null if no data. void handleSendFailed (JNIEnv* env, int fd, jobject resultContainerObj, struct sctp_send_failed *ssf, int read, jboolean isEOR, struct sockaddr* sap) { jobject bufferObj = NULL, resultObj, isaObj; char *addressP; struct sctp_sndrcvinfo *sri; int remaining, dataLength; /* the actual undelivered message data is directly after the ssf */ int dataOffset = sizeof(struct sctp_send_failed); sri = (struct sctp_sndrcvinfo*) &ssf->ssf_info; /* the number of bytes remaining to be read in the sctp_send_failed notif*/ remaining = ssf->ssf_length - read; /* the size of the actual undelivered message */ dataLength = ssf->ssf_length - dataOffset; /* retrieved address from sockaddr */ isaObj = SockAddrToInetSocketAddress(env, sap); /* data retrieved from sff_data */ if (dataLength > 0) { struct iovec iov[1]; struct msghdr msg[1]; int rv, alreadyRead; char *dataP = (char*) ssf; dataP += dataOffset; if ((addressP = malloc(dataLength)) == NULL) { JNU_ThrowOutOfMemoryError(env, "handleSendFailed"); return; } memset(msg, 0, sizeof (*msg)); msg->msg_iov = iov; msg->msg_iovlen = 1; bufferObj = (*env)->NewDirectByteBuffer(env, addressP, dataLength); CHECK_NULL(bufferObj); alreadyRead = read - dataOffset; if (alreadyRead > 0) { memcpy(addressP, /*ssf->ssf_data*/ dataP, alreadyRead); iov->iov_base = addressP + alreadyRead; iov->iov_len = dataLength - alreadyRead; } else { iov->iov_base = addressP; iov->iov_len = dataLength; } if (remaining > 0) { if ((rv = recvmsg(fd, msg, 0)) < 0) { handleSocketError(env, errno); return; } if (rv != (dataLength - alreadyRead) || !(msg->msg_flags & MSG_EOR)) { //TODO: assert false: "should not reach here"; return; } // TODO: Set and document (in API) buffers position. } } /* create SctpSendFailed */ resultObj = (*env)->NewObject(env, ssf_class, ssf_ctrID, ssf->ssf_assoc_id, isaObj, bufferObj, ssf->ssf_error, sri->sinfo_stream); CHECK_NULL(resultObj); (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); (*env)->SetIntField(env, resultContainerObj, src_typeID, sun_nio_ch_SctpResultContainer_SEND_FAILED); }