1 /* 2 * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdlib.h> 27 #include <string.h> 28 #include "Sctp.h" 29 30 #include "jni.h" 31 #include "nio_util.h" 32 #include "nio.h" 33 #include "net_util.h" 34 #include "net_util_md.h" 35 #include "sun_nio_ch_sctp_SctpNet.h" 36 #include "sun_nio_ch_sctp_SctpChannelImpl.h" 37 #include "sun_nio_ch_sctp_AssociationChange.h" 38 #include "sun_nio_ch_sctp_ResultContainer.h" 39 #include "sun_nio_ch_sctp_PeerAddrChange.h" 40 41 static int SCTP_NOTIFICATION_SIZE = sizeof(union sctp_notification); 42 43 #define MESSAGE_IMPL_CLASS "sun/nio/ch/sctp/MessageInfoImpl" 44 #define RESULT_CONTAINER_CLASS "sun/nio/ch/sctp/ResultContainer" 45 #define SEND_FAILED_CLASS "sun/nio/ch/sctp/SendFailed" 46 #define ASSOC_CHANGE_CLASS "sun/nio/ch/sctp/AssociationChange" 47 #define PEER_CHANGE_CLASS "sun/nio/ch/sctp/PeerAddrChange" 48 #define SHUTDOWN_CLASS "sun/nio/ch/sctp/Shutdown" 49 50 struct controlData { 51 int assocId; 52 unsigned short streamNumber; 53 jboolean unordered; 54 unsigned int ppid; 55 }; 56 57 static jclass smi_class; /* sun.nio.ch.sctp.MessageInfoImpl */ 58 static jmethodID smi_ctrID; /* sun.nio.ch.sctp.MessageInfoImpl.<init> */ 59 static jfieldID src_valueID; /* sun.nio.ch.sctp.ResultContainer.value */ 60 static jfieldID src_typeID; /* sun.nio.ch.sctp.ResultContainer.type */ 61 static jclass ssf_class; /* sun.nio.ch.sctp.SendFailed */ 62 static jmethodID ssf_ctrID; /* sun.nio.ch.sctp.SendFailed.<init> */ 63 static jclass sac_class; /* sun.nio.ch.sctp.AssociationChange */ 64 static jmethodID sac_ctrID; /* sun.nio.ch.sctp.AssociationChange.<init> */ 65 static jclass spc_class; /* sun.nio.ch.sctp.PeerAddressChanged */ 66 static jmethodID spc_ctrID; /* sun.nio.ch.sctp.PeerAddressChanged.<init> */ 67 static jclass ss_class; /* sun.nio.ch.sctp.Shutdown */ 68 static jmethodID ss_ctrID; /* sun.nio.ch.sctp.Shutdown.<init> */ 69 70 /* defined in SctpNet.c */ 71 jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr); 72 73 jint handleSocketError(JNIEnv *env, jint errorValue); 74 75 /* 76 * Class: sun_nio_ch_sctp_SctpChannelImpl 77 * Method: initIDs 78 * Signature: ()V 79 */ 80 JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs 81 (JNIEnv *env, jclass klass) { 82 jclass cls; 83 84 /* MessageInfoImpl */ 85 cls = (*env)->FindClass(env, MESSAGE_IMPL_CLASS); 86 CHECK_NULL(cls); 87 smi_class = (*env)->NewGlobalRef(env, cls); 88 CHECK_NULL(smi_class); 89 smi_ctrID = (*env)->GetMethodID(env, cls, "<init>", 90 "(ILjava/net/SocketAddress;IIZZI)V"); 91 CHECK_NULL(smi_ctrID); 92 93 /* ResultContainer */ 94 cls = (*env)->FindClass(env, RESULT_CONTAINER_CLASS); 95 CHECK_NULL(cls); 96 src_valueID = (*env)->GetFieldID(env, cls, "value", "Ljava/lang/Object;"); 97 CHECK_NULL(src_valueID); 98 src_typeID = (*env)->GetFieldID(env, cls, "type", "I"); 99 CHECK_NULL(src_typeID); 100 101 /* SendFailed */ 102 cls = (*env)->FindClass(env, SEND_FAILED_CLASS); 103 CHECK_NULL(cls); 104 ssf_class = (*env)->NewGlobalRef(env, cls); 105 CHECK_NULL(ssf_class); 106 ssf_ctrID = (*env)->GetMethodID(env, cls, "<init>", 107 "(ILjava/net/SocketAddress;Ljava/nio/ByteBuffer;II)V"); 108 CHECK_NULL(ssf_ctrID); 109 110 /* AssociationChange */ 111 cls = (*env)->FindClass(env, ASSOC_CHANGE_CLASS); 112 CHECK_NULL(cls); 113 sac_class = (*env)->NewGlobalRef(env, cls); 114 CHECK_NULL(sac_class); 115 sac_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(IIII)V"); 116 CHECK_NULL(sac_ctrID); 117 118 /* PeerAddrChange */ 119 cls = (*env)->FindClass(env, PEER_CHANGE_CLASS); 120 CHECK_NULL(cls); 121 spc_class = (*env)->NewGlobalRef(env, cls); 122 CHECK_NULL(spc_class); 123 spc_ctrID = (*env)->GetMethodID(env, cls, "<init>", 124 "(ILjava/net/SocketAddress;I)V"); 125 CHECK_NULL(spc_ctrID); 126 127 /* Shutdown */ 128 cls = (*env)->FindClass(env, SHUTDOWN_CLASS); 129 CHECK_NULL(cls); 130 ss_class = (*env)->NewGlobalRef(env, cls); 131 CHECK_NULL(ss_class); 132 ss_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(I)V"); 133 CHECK_NULL(ss_ctrID); 134 } 135 136 void getControlData 137 (struct msghdr* msg, struct controlData* cdata) { 138 struct cmsghdr* cmsg; 139 140 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { 141 if (cmsg->cmsg_level == IPPROTO_SCTP && cmsg->cmsg_type == SCTP_SNDRCV) { 142 struct sctp_sndrcvinfo *sri; 143 144 sri = (struct sctp_sndrcvinfo *) CMSG_DATA(cmsg); 145 cdata->assocId = sri->sinfo_assoc_id; 146 cdata->streamNumber = sri->sinfo_stream; 147 cdata->unordered = (sri->sinfo_flags & SCTP_UNORDERED) ? JNI_TRUE : 148 JNI_FALSE; 149 cdata->ppid = ntohl(sri->sinfo_ppid); 150 151 return; 152 } 153 } 154 return; 155 } 156 157 void setControlData 158 (struct msghdr* msg, struct controlData* cdata) { 159 struct cmsghdr* cmsg; 160 struct sctp_sndrcvinfo *sri; 161 162 cmsg = CMSG_FIRSTHDR(msg); 163 cmsg->cmsg_level = IPPROTO_SCTP; 164 cmsg->cmsg_type = SCTP_SNDRCV; 165 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 166 167 /* Initialize the payload */ 168 sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg); 169 memset(sri, 0, sizeof (*sri)); 170 171 if (cdata->streamNumber > 0) { 172 sri->sinfo_stream = cdata->streamNumber; 173 } 174 if (cdata->assocId > 0) { 175 sri->sinfo_assoc_id = cdata->assocId; 176 } 177 if (cdata->unordered == JNI_TRUE) { 178 sri->sinfo_flags = sri->sinfo_flags | SCTP_UNORDERED; 179 } 180 181 if (cdata->ppid > 0) { 182 sri->sinfo_ppid = htonl(cdata->ppid); 183 } 184 185 /* Sum of the length of all control messages in the buffer. */ 186 msg->msg_controllen = cmsg->cmsg_len; 187 } 188 189 // TODO: test: can create send failed without any data? if so need to 190 // update API so that buffer can be null if no data. 191 void handleSendFailed 192 (JNIEnv* env, int fd, jobject resultContainerObj, struct sctp_send_failed *ssf, 193 int read, jboolean isEOR, struct sockaddr* sap) { 194 jobject bufferObj = NULL, resultObj, isaObj; 195 char *addressP; 196 struct sctp_sndrcvinfo *sri; 197 int remaining, dataLength; 198 199 /* the actual undelivered message data is directly after the ssf */ 200 int dataOffset = sizeof(struct sctp_send_failed); 201 202 sri = (struct sctp_sndrcvinfo*) &ssf->ssf_info; 203 204 /* the number of bytes remaining to be read in the sctp_send_failed notif*/ 205 remaining = ssf->ssf_length - read; 206 207 /* the size of the actual undelivered message */ 208 dataLength = ssf->ssf_length - dataOffset; 209 210 /* retrieved address from sockaddr */ 211 isaObj = SockAddrToInetSocketAddress(env, sap); 212 CHECK_NULL(isaObj); 213 214 /* data retrieved from sff_data */ 215 if (dataLength > 0) { 216 struct iovec iov[1]; 217 struct msghdr msg[1]; 218 int rv, alreadyRead; 219 char *dataP = (char*) ssf; 220 dataP += dataOffset; 221 222 if ((addressP = malloc(dataLength)) == NULL) { 223 JNU_ThrowOutOfMemoryError(env, "handleSendFailed"); 224 return; 225 } 226 227 memset(msg, 0, sizeof (*msg)); 228 msg->msg_iov = iov; 229 msg->msg_iovlen = 1; 230 231 bufferObj = (*env)->NewDirectByteBuffer(env, addressP, dataLength); 232 CHECK_NULL(bufferObj); 233 234 alreadyRead = read - dataOffset; 235 if (alreadyRead > 0) { 236 memcpy(addressP, /*ssf->ssf_data*/ dataP, alreadyRead); 237 iov->iov_base = addressP + alreadyRead; 238 iov->iov_len = dataLength - alreadyRead; 239 } else { 240 iov->iov_base = addressP; 241 iov->iov_len = dataLength; 242 } 243 244 if (remaining > 0) { 245 if ((rv = recvmsg(fd, msg, 0)) < 0) { 246 handleSocketError(env, errno); 247 return; 248 } 249 250 if (rv != (dataLength - alreadyRead) || !(msg->msg_flags & MSG_EOR)) { 251 //TODO: assert false: "should not reach here"; 252 return; 253 } 254 // TODO: Set and document (in API) buffers position. 255 } 256 } 257 258 /* create SendFailed */ 259 resultObj = (*env)->NewObject(env, ssf_class, ssf_ctrID, ssf->ssf_assoc_id, 260 isaObj, bufferObj, ssf->ssf_error, sri->sinfo_stream); 261 CHECK_NULL(resultObj); 262 (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); 263 (*env)->SetIntField(env, resultContainerObj, src_typeID, 264 sun_nio_ch_sctp_ResultContainer_SEND_FAILED); 265 } 266 267 void handleAssocChange 268 (JNIEnv* env, jobject resultContainerObj, struct sctp_assoc_change *sac) { 269 jobject resultObj; 270 int state = 0; 271 272 switch (sac->sac_state) { 273 case SCTP_COMM_UP : 274 state = sun_nio_ch_sctp_AssociationChange_SCTP_COMM_UP; 275 break; 276 case SCTP_COMM_LOST : 277 state = sun_nio_ch_sctp_AssociationChange_SCTP_COMM_LOST; 278 break; 279 case SCTP_RESTART : 280 state = sun_nio_ch_sctp_AssociationChange_SCTP_RESTART; 281 break; 282 case SCTP_SHUTDOWN_COMP : 283 state = sun_nio_ch_sctp_AssociationChange_SCTP_SHUTDOWN; 284 break; 285 case SCTP_CANT_STR_ASSOC : 286 state = sun_nio_ch_sctp_AssociationChange_SCTP_CANT_START; 287 } 288 289 /* create AssociationChange */ 290 resultObj = (*env)->NewObject(env, sac_class, sac_ctrID, sac->sac_assoc_id, 291 state, sac->sac_outbound_streams, sac->sac_inbound_streams); 292 CHECK_NULL(resultObj); 293 (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); 294 (*env)->SetIntField(env, resultContainerObj, src_typeID, 295 sun_nio_ch_sctp_ResultContainer_ASSOCIATION_CHANGED); 296 } 297 298 void handleShutdown 299 (JNIEnv* env, jobject resultContainerObj, struct sctp_shutdown_event* sse) { 300 /* create Shutdown */ 301 jobject resultObj = (*env)->NewObject(env, ss_class, ss_ctrID, sse->sse_assoc_id); 302 CHECK_NULL(resultObj); 303 (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); 304 (*env)->SetIntField(env, resultContainerObj, src_typeID, 305 sun_nio_ch_sctp_ResultContainer_SHUTDOWN); 306 } 307 308 void handlePeerAddrChange 309 (JNIEnv* env, jobject resultContainerObj, struct sctp_paddr_change* spc) { 310 int event = 0; 311 jobject addressObj, resultObj; 312 unsigned int state = spc->spc_state; 313 314 switch (state) { 315 case SCTP_ADDR_AVAILABLE : 316 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_AVAILABLE; 317 break; 318 case SCTP_ADDR_UNREACHABLE : 319 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_UNREACHABLE; 320 break; 321 case SCTP_ADDR_REMOVED : 322 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_REMOVED; 323 break; 324 case SCTP_ADDR_ADDED : 325 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_ADDED; 326 break; 327 case SCTP_ADDR_MADE_PRIM : 328 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_MADE_PRIM; 329 #ifdef __linux__ /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */ 330 break; 331 case SCTP_ADDR_CONFIRMED : 332 event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_CONFIRMED; 333 #endif /* __linux__ */ 334 } 335 336 addressObj = SockAddrToInetSocketAddress(env, (struct sockaddr*)&spc->spc_aaddr); 337 CHECK_NULL(addressObj); 338 339 /* create PeerAddressChanged */ 340 resultObj = (*env)->NewObject(env, spc_class, spc_ctrID, spc->spc_assoc_id, 341 addressObj, event); 342 CHECK_NULL(resultObj); 343 (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); 344 (*env)->SetIntField(env, resultContainerObj, src_typeID, 345 sun_nio_ch_sctp_ResultContainer_PEER_ADDRESS_CHANGED); 346 } 347 348 void handleUninteresting 349 (union sctp_notification *snp) { 350 //fprintf(stdout,"\nNative: handleUninterestingNotification: Receive notification type [%u]", snp->sn_header.sn_type); 351 } 352 353 /** 354 * Handle notifications from the SCTP stack. 355 * Returns JNI_TRUE if the notification is one that is of interest to the 356 * Java API, otherwise JNI_FALSE. 357 */ 358 jboolean handleNotification 359 (JNIEnv* env, int fd, jobject resultContainerObj, union sctp_notification* snp, 360 int read, jboolean isEOR, struct sockaddr* sap) { 361 switch (snp->sn_header.sn_type) { 362 case SCTP_SEND_FAILED: 363 handleSendFailed(env, fd, resultContainerObj, &snp->sn_send_failed, 364 read, isEOR, sap); 365 return JNI_TRUE; 366 case SCTP_ASSOC_CHANGE: 367 handleAssocChange(env, resultContainerObj, &snp->sn_assoc_change); 368 return JNI_TRUE; 369 case SCTP_SHUTDOWN_EVENT: 370 handleShutdown(env, resultContainerObj, &snp->sn_shutdown_event); 371 return JNI_TRUE; 372 case SCTP_PEER_ADDR_CHANGE: 373 handlePeerAddrChange(env, resultContainerObj, &snp->sn_paddr_change); 374 return JNI_TRUE; 375 default : 376 /* the Java API is not interested in this event, maybe we are? */ 377 handleUninteresting(snp); 378 } 379 return JNI_FALSE; 380 } 381 382 void handleMessage 383 (JNIEnv* env, jobject resultContainerObj, struct msghdr* msg,int read, 384 jboolean isEOR, struct sockaddr* sap) { 385 jobject isa, resultObj; 386 struct controlData cdata[1]; 387 388 if (read == 0) { 389 /* we reached EOF */ 390 read = -1; 391 } 392 393 isa = SockAddrToInetSocketAddress(env, sap); 394 CHECK_NULL(isa); 395 getControlData(msg, cdata); 396 397 /* create MessageInfoImpl */ 398 resultObj = (*env)->NewObject(env, smi_class, smi_ctrID, cdata->assocId, 399 isa, read, cdata->streamNumber, 400 isEOR ? JNI_TRUE : JNI_FALSE, 401 cdata->unordered, cdata->ppid); 402 CHECK_NULL(resultObj); 403 (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj); 404 (*env)->SetIntField(env, resultContainerObj, src_typeID, 405 sun_nio_ch_sctp_ResultContainer_MESSAGE); 406 } 407 408 /* 409 * Class: sun_nio_ch_sctp_SctpChannelImpl 410 * Method: receive0 411 * Signature: (ILsun/nio/ch/sctp/ResultContainer;JIZ)I 412 */ 413 JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0 414 (JNIEnv *env, jclass klass, jint fd, jobject resultContainerObj, 415 jlong address, jint length, jboolean peek) { 416 SOCKETADDRESS sa; 417 ssize_t rv = 0; 418 jlong *addr = jlong_to_ptr(address); 419 struct iovec iov[1]; 420 struct msghdr msg[1]; 421 char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))]; 422 int flags = peek == JNI_TRUE ? MSG_PEEK : 0; 423 424 /* Set up the msghdr structure for receiving */ 425 memset(msg, 0, sizeof (*msg)); 426 msg->msg_name = &sa; 427 msg->msg_namelen = sizeof(sa); 428 iov->iov_base = addr; 429 iov->iov_len = length; 430 msg->msg_iov = iov; 431 msg->msg_iovlen = 1; 432 msg->msg_control = cbuf; 433 msg->msg_controllen = sizeof(cbuf); 434 msg->msg_flags = 0; 435 436 do { 437 if ((rv = recvmsg(fd, msg, flags)) < 0) { 438 if (errno == EAGAIN || errno == EWOULDBLOCK) { 439 return IOS_UNAVAILABLE; 440 } else if (errno == EINTR) { 441 return IOS_INTERRUPTED; 442 443 #ifdef __linux__ 444 } else if (errno == ENOTCONN) { 445 /* ENOTCONN when EOF reached */ 446 rv = 0; 447 /* there will be no control data */ 448 msg->msg_controllen = 0; 449 #endif /* __linux__ */ 450 451 } else { 452 handleSocketError(env, errno); 453 return 0; 454 } 455 } 456 457 if (msg->msg_flags & MSG_NOTIFICATION) { 458 char *bufp = (char*)addr; 459 union sctp_notification *snp; 460 jboolean allocated = JNI_FALSE; 461 462 if (!(msg->msg_flags & MSG_EOR) && length < SCTP_NOTIFICATION_SIZE) { 463 char* newBuf; 464 int rvSAVE = rv; 465 466 if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) { 467 JNU_ThrowOutOfMemoryError(env, "Out of native heap space."); 468 return -1; 469 } 470 allocated = JNI_TRUE; 471 472 memcpy(newBuf, addr, rv); 473 iov->iov_base = newBuf + rv; 474 iov->iov_len = SCTP_NOTIFICATION_SIZE - rv; 475 if ((rv = recvmsg(fd, msg, flags)) < 0) { 476 handleSocketError(env, errno); 477 return 0; 478 } 479 bufp = newBuf; 480 rv += rvSAVE; 481 } 482 #ifdef __sparc 483 else if ((intptr_t)addr & 0x3) { 484 /* the given buffer is not 4 byte aligned */ 485 char* newBuf; 486 if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) { 487 JNU_ThrowOutOfMemoryError(env, "Out of native heap space."); 488 return -1; 489 } 490 allocated = JNI_TRUE; 491 492 memcpy(newBuf, addr, rv); 493 bufp = newBuf; 494 } 495 #endif 496 snp = (union sctp_notification *) bufp; 497 if (handleNotification(env, fd, resultContainerObj, snp, rv, 498 (msg->msg_flags & MSG_EOR), 499 &sa.sa) == JNI_TRUE) { 500 /* We have received a notification that is of interest 501 to the Java API. The appropriate notification will be 502 set in the result container. */ 503 if (allocated == JNI_TRUE) { 504 free(bufp); 505 } 506 return 0; 507 } 508 509 if (allocated == JNI_TRUE) { 510 free(bufp); 511 } 512 513 // set iov back to addr, and reset msg_controllen 514 iov->iov_base = addr; 515 iov->iov_len = length; 516 msg->msg_control = cbuf; 517 msg->msg_controllen = sizeof(cbuf); 518 } 519 } while (msg->msg_flags & MSG_NOTIFICATION); 520 521 handleMessage(env, resultContainerObj, msg, rv, 522 (msg->msg_flags & MSG_EOR), &sa.sa); 523 return rv; 524 } 525 526 /* 527 * Class: sun_nio_ch_sctp_SctpChannelImpl 528 * Method: send0 529 * Signature: (IJILjava/net/InetAddress;IIIZI)I 530 */ 531 JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 532 (JNIEnv *env, jclass klass, jint fd, jlong address, jint length, 533 jobject targetAddress, jint targetPort, jint assocId, jint streamNumber, 534 jboolean unordered, jint ppid) { 535 SOCKETADDRESS sa; 536 int sa_len = 0; 537 ssize_t rv = 0; 538 jlong *addr = jlong_to_ptr(address); 539 struct iovec iov[1]; 540 struct msghdr msg[1]; 541 int cbuf_size = CMSG_SPACE(sizeof (struct sctp_sndrcvinfo)); 542 char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))]; 543 struct controlData cdata[1]; 544 545 /* SctpChannel: 546 * targetAddress may contain the preferred address or NULL to use primary, 547 * assocId will always be -1 548 * SctpMultiChannell: 549 * Setup new association, targetAddress will contain address, assocId = -1 550 * Association already existing, assocId != -1, targetAddress = preferred addr 551 */ 552 if (targetAddress != NULL /*&& assocId <= 0*/) { 553 if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, &sa, 554 &sa_len, JNI_TRUE) != 0) { 555 return IOS_THROWN; 556 } 557 } else { 558 memset(&sa, '\x0', sizeof(sa)); 559 } 560 561 /* Set up the msghdr structure for sending */ 562 memset(msg, 0, sizeof (*msg)); 563 memset(cbuf, 0, cbuf_size); 564 msg->msg_name = &sa; 565 msg->msg_namelen = sa_len; 566 iov->iov_base = addr; 567 iov->iov_len = length; 568 msg->msg_iov = iov; 569 msg->msg_iovlen = 1; 570 msg->msg_control = cbuf; 571 msg->msg_controllen = cbuf_size; 572 msg->msg_flags = 0; 573 574 cdata->streamNumber = streamNumber; 575 cdata->assocId = assocId; 576 cdata->unordered = unordered; 577 cdata->ppid = ppid; 578 setControlData(msg, cdata); 579 580 if ((rv = sendmsg(fd, msg, 0)) < 0) { 581 if (errno == EAGAIN || errno == EWOULDBLOCK) { 582 return IOS_UNAVAILABLE; 583 } else if (errno == EINTR) { 584 return IOS_INTERRUPTED; 585 } else if (errno == EPIPE) { 586 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", 587 "Socket is shutdown for writing"); 588 } else { 589 handleSocketError(env, errno); 590 return 0; 591 } 592 } 593 594 return rv; 595 } 596