/* * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* Initialize the payload */
sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg);
memset(sri, 0, sizeof (*sri));
if (cdata->streamNumber > 0) {
sri->sinfo_stream = cdata->streamNumber;
} if (cdata->assocId > 0) {
sri->sinfo_assoc_id = cdata->assocId;
} if (cdata->unordered == JNI_TRUE) {
sri->sinfo_flags = sri->sinfo_flags | SCTP_UNORDERED;
}
if (cdata->ppid > 0) {
sri->sinfo_ppid = htonl(cdata->ppid);
}
/* Sum of the length of all control messages in the buffer. */
msg->msg_controllen = cmsg->cmsg_len;
}
// 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;
void handleAssocChange
(JNIEnv* env, jobject resultContainerObj, struct sctp_assoc_change *sac) {
jobject resultObj; int state = 0;
switch (sac->sac_state) { case SCTP_COMM_UP :
state = sun_nio_ch_sctp_AssociationChange_SCTP_COMM_UP; break; case SCTP_COMM_LOST :
state = sun_nio_ch_sctp_AssociationChange_SCTP_COMM_LOST; break; case SCTP_RESTART :
state = sun_nio_ch_sctp_AssociationChange_SCTP_RESTART; break; case SCTP_SHUTDOWN_COMP :
state = sun_nio_ch_sctp_AssociationChange_SCTP_SHUTDOWN; break; case SCTP_CANT_STR_ASSOC :
state = sun_nio_ch_sctp_AssociationChange_SCTP_CANT_START;
}
/** * Handle notifications from the SCTP stack. * Returns JNI_TRUE if the notification is one that is of interest to the * Java API, otherwise JNI_FALSE.
*/
jboolean handleNotification
(JNIEnv* env, int fd, jobject resultContainerObj, union sctp_notification* snp, int read, jboolean isEOR, struct sockaddr* sap) { switch (snp->sn_header.sn_type) { case SCTP_SEND_FAILED:
handleSendFailed(env, fd, resultContainerObj, &snp->sn_send_failed,
read, isEOR, sap); return JNI_TRUE; case SCTP_ASSOC_CHANGE:
handleAssocChange(env, resultContainerObj, &snp->sn_assoc_change); return JNI_TRUE; case SCTP_SHUTDOWN_EVENT:
handleShutdown(env, resultContainerObj, &snp->sn_shutdown_event); return JNI_TRUE; case SCTP_PEER_ADDR_CHANGE:
handlePeerAddrChange(env, resultContainerObj, &snp->sn_paddr_change); return JNI_TRUE; default : /* the Java API is not interested in this event, maybe we are? */
handleUninteresting(snp);
} return JNI_FALSE;
}
/* Set up the msghdr structure for receiving */
memset(msg, 0, sizeof (*msg));
msg->msg_name = &sa;
msg->msg_namelen = sizeof(sa);
iov->iov_base = addr;
iov->iov_len = length;
msg->msg_iov = iov;
msg->msg_iovlen = 1;
msg->msg_control = cbuf;
msg->msg_controllen = sizeof(cbuf);
msg->msg_flags = 0;
do { if ((rv = recvmsg(fd, msg, flags)) < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return IOS_UNAVAILABLE;
} elseif (errno == EINTR) { return IOS_INTERRUPTED;
#ifdef __linux__
} elseif (errno == ENOTCONN) { /* ENOTCONN when EOF reached */
rv = 0; /* there will be no control data */
msg->msg_controllen = 0; #endif/* __linux__ */
if (msg->msg_flags & MSG_NOTIFICATION) { char *bufp = (char*)addr; union sctp_notification *snp;
jboolean allocated = JNI_FALSE;
if (!(msg->msg_flags & MSG_EOR) && length < SCTP_NOTIFICATION_SIZE) { char* newBuf; int rvSAVE = rv;
if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) {
JNU_ThrowOutOfMemoryError(env, "Out of native heap space."); return -1;
}
allocated = JNI_TRUE;
memcpy(newBuf, addr, rv);
iov->iov_base = newBuf + rv;
iov->iov_len = SCTP_NOTIFICATION_SIZE - rv; if ((rv = recvmsg(fd, msg, flags)) < 0) {
handleSocketError(env, errno);
free(newBuf); return 0;
}
bufp = newBuf;
rv += rvSAVE;
}
snp = (union sctp_notification *) bufp; if (handleNotification(env, fd, resultContainerObj, snp, rv,
(msg->msg_flags & MSG_EOR),
&sa.sa) == JNI_TRUE) { /* We have received a notification that is of interest to the Java API. The appropriate notification will be
set in the result container. */ if (allocated == JNI_TRUE) {
free(bufp);
} return 0;
}
if (allocated == JNI_TRUE) {
free(bufp);
}
// set iov back to addr, and reset msg_controllen
iov->iov_base = addr;
iov->iov_len = length;
msg->msg_control = cbuf;
msg->msg_controllen = sizeof(cbuf);
}
} while (msg->msg_flags & MSG_NOTIFICATION);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.