Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c
32301 views
1
/*
2
* Copyright (c) 2009, 2015, 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
/* use SocketChannelImpl's checkConnect implementation */
76
extern jint Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv* env,
77
jobject this, jobject fdo, jboolean block, jboolean ready);
78
79
/*
80
* Class: sun_nio_ch_sctp_SctpChannelImpl
81
* Method: initIDs
82
* Signature: ()V
83
*/
84
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs
85
(JNIEnv *env, jclass klass) {
86
jclass cls;
87
88
/* MessageInfoImpl */
89
cls = (*env)->FindClass(env, MESSAGE_IMPL_CLASS);
90
CHECK_NULL(cls);
91
smi_class = (*env)->NewGlobalRef(env, cls);
92
CHECK_NULL(smi_class);
93
smi_ctrID = (*env)->GetMethodID(env, cls, "<init>",
94
"(ILjava/net/SocketAddress;IIZZI)V");
95
CHECK_NULL(smi_ctrID);
96
97
/* ResultContainer */
98
cls = (*env)->FindClass(env, RESULT_CONTAINER_CLASS);
99
CHECK_NULL(cls);
100
src_valueID = (*env)->GetFieldID(env, cls, "value", "Ljava/lang/Object;");
101
CHECK_NULL(src_valueID);
102
src_typeID = (*env)->GetFieldID(env, cls, "type", "I");
103
CHECK_NULL(src_typeID);
104
105
/* SendFailed */
106
cls = (*env)->FindClass(env, SEND_FAILED_CLASS);
107
CHECK_NULL(cls);
108
ssf_class = (*env)->NewGlobalRef(env, cls);
109
CHECK_NULL(ssf_class);
110
ssf_ctrID = (*env)->GetMethodID(env, cls, "<init>",
111
"(ILjava/net/SocketAddress;Ljava/nio/ByteBuffer;II)V");
112
CHECK_NULL(ssf_ctrID);
113
114
/* AssociationChange */
115
cls = (*env)->FindClass(env, ASSOC_CHANGE_CLASS);
116
CHECK_NULL(cls);
117
sac_class = (*env)->NewGlobalRef(env, cls);
118
CHECK_NULL(sac_class);
119
sac_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(IIII)V");
120
CHECK_NULL(sac_ctrID);
121
122
/* PeerAddrChange */
123
cls = (*env)->FindClass(env, PEER_CHANGE_CLASS);
124
CHECK_NULL(cls);
125
spc_class = (*env)->NewGlobalRef(env, cls);
126
CHECK_NULL(spc_class);
127
spc_ctrID = (*env)->GetMethodID(env, cls, "<init>",
128
"(ILjava/net/SocketAddress;I)V");
129
CHECK_NULL(spc_ctrID);
130
131
/* Shutdown */
132
cls = (*env)->FindClass(env, SHUTDOWN_CLASS);
133
CHECK_NULL(cls);
134
ss_class = (*env)->NewGlobalRef(env, cls);
135
CHECK_NULL(ss_class);
136
ss_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(I)V");
137
CHECK_NULL(ss_ctrID);
138
}
139
140
void getControlData
141
(struct msghdr* msg, struct controlData* cdata) {
142
struct cmsghdr* cmsg;
143
144
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
145
if (cmsg->cmsg_level == IPPROTO_SCTP && cmsg->cmsg_type == SCTP_SNDRCV) {
146
struct sctp_sndrcvinfo *sri;
147
148
sri = (struct sctp_sndrcvinfo *) CMSG_DATA(cmsg);
149
cdata->assocId = sri->sinfo_assoc_id;
150
cdata->streamNumber = sri->sinfo_stream;
151
cdata->unordered = (sri->sinfo_flags & SCTP_UNORDERED) ? JNI_TRUE :
152
JNI_FALSE;
153
cdata->ppid = ntohl(sri->sinfo_ppid);
154
155
return;
156
}
157
}
158
return;
159
}
160
161
void setControlData
162
(struct msghdr* msg, struct controlData* cdata) {
163
struct cmsghdr* cmsg;
164
struct sctp_sndrcvinfo *sri;
165
166
cmsg = CMSG_FIRSTHDR(msg);
167
cmsg->cmsg_level = IPPROTO_SCTP;
168
cmsg->cmsg_type = SCTP_SNDRCV;
169
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
170
171
/* Initialize the payload */
172
sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg);
173
memset(sri, 0, sizeof (*sri));
174
175
if (cdata->streamNumber > 0) {
176
sri->sinfo_stream = cdata->streamNumber;
177
}
178
if (cdata->assocId > 0) {
179
sri->sinfo_assoc_id = cdata->assocId;
180
}
181
if (cdata->unordered == JNI_TRUE) {
182
sri->sinfo_flags = sri->sinfo_flags | SCTP_UNORDERED;
183
}
184
185
if (cdata->ppid > 0) {
186
sri->sinfo_ppid = htonl(cdata->ppid);
187
}
188
189
/* Sum of the length of all control messages in the buffer. */
190
msg->msg_controllen = cmsg->cmsg_len;
191
}
192
193
// TODO: test: can create send failed without any data? if so need to
194
// update API so that buffer can be null if no data.
195
void handleSendFailed
196
(JNIEnv* env, int fd, jobject resultContainerObj, struct sctp_send_failed *ssf,
197
int read, jboolean isEOR, struct sockaddr* sap) {
198
jobject bufferObj = NULL, resultObj, isaObj;
199
char *addressP;
200
struct sctp_sndrcvinfo *sri;
201
int remaining, dataLength;
202
203
/* the actual undelivered message data is directly after the ssf */
204
int dataOffset = sizeof(struct sctp_send_failed);
205
206
sri = (struct sctp_sndrcvinfo*) &ssf->ssf_info;
207
208
/* the number of bytes remaining to be read in the sctp_send_failed notif*/
209
remaining = ssf->ssf_length - read;
210
211
/* the size of the actual undelivered message */
212
dataLength = ssf->ssf_length - dataOffset;
213
214
/* retrieved address from sockaddr */
215
isaObj = SockAddrToInetSocketAddress(env, sap);
216
CHECK_NULL(isaObj);
217
218
/* data retrieved from sff_data */
219
if (dataLength > 0) {
220
struct iovec iov[1];
221
struct msghdr msg[1];
222
int rv, alreadyRead;
223
char *dataP = (char*) ssf;
224
dataP += dataOffset;
225
226
if ((addressP = malloc(dataLength)) == NULL) {
227
JNU_ThrowOutOfMemoryError(env, "handleSendFailed");
228
return;
229
}
230
231
memset(msg, 0, sizeof (*msg));
232
msg->msg_iov = iov;
233
msg->msg_iovlen = 1;
234
235
bufferObj = (*env)->NewDirectByteBuffer(env, addressP, dataLength);
236
CHECK_NULL(bufferObj);
237
238
alreadyRead = read - dataOffset;
239
if (alreadyRead > 0) {
240
memcpy(addressP, /*ssf->ssf_data*/ dataP, alreadyRead);
241
iov->iov_base = addressP + alreadyRead;
242
iov->iov_len = dataLength - alreadyRead;
243
} else {
244
iov->iov_base = addressP;
245
iov->iov_len = dataLength;
246
}
247
248
if (remaining > 0) {
249
if ((rv = recvmsg(fd, msg, 0)) < 0) {
250
handleSocketError(env, errno);
251
return;
252
}
253
254
if (rv != (dataLength - alreadyRead) || !(msg->msg_flags & MSG_EOR)) {
255
//TODO: assert false: "should not reach here";
256
return;
257
}
258
// TODO: Set and document (in API) buffers position.
259
}
260
}
261
262
/* create SendFailed */
263
resultObj = (*env)->NewObject(env, ssf_class, ssf_ctrID, ssf->ssf_assoc_id,
264
isaObj, bufferObj, ssf->ssf_error, sri->sinfo_stream);
265
CHECK_NULL(resultObj);
266
(*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
267
(*env)->SetIntField(env, resultContainerObj, src_typeID,
268
sun_nio_ch_sctp_ResultContainer_SEND_FAILED);
269
}
270
271
void handleAssocChange
272
(JNIEnv* env, jobject resultContainerObj, struct sctp_assoc_change *sac) {
273
jobject resultObj;
274
int state = 0;
275
276
switch (sac->sac_state) {
277
case SCTP_COMM_UP :
278
state = sun_nio_ch_sctp_AssociationChange_SCTP_COMM_UP;
279
break;
280
case SCTP_COMM_LOST :
281
state = sun_nio_ch_sctp_AssociationChange_SCTP_COMM_LOST;
282
break;
283
case SCTP_RESTART :
284
state = sun_nio_ch_sctp_AssociationChange_SCTP_RESTART;
285
break;
286
case SCTP_SHUTDOWN_COMP :
287
state = sun_nio_ch_sctp_AssociationChange_SCTP_SHUTDOWN;
288
break;
289
case SCTP_CANT_STR_ASSOC :
290
state = sun_nio_ch_sctp_AssociationChange_SCTP_CANT_START;
291
}
292
293
/* create AssociationChange */
294
resultObj = (*env)->NewObject(env, sac_class, sac_ctrID, sac->sac_assoc_id,
295
state, sac->sac_outbound_streams, sac->sac_inbound_streams);
296
CHECK_NULL(resultObj);
297
(*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
298
(*env)->SetIntField(env, resultContainerObj, src_typeID,
299
sun_nio_ch_sctp_ResultContainer_ASSOCIATION_CHANGED);
300
}
301
302
void handleShutdown
303
(JNIEnv* env, jobject resultContainerObj, struct sctp_shutdown_event* sse) {
304
/* create Shutdown */
305
jobject resultObj = (*env)->NewObject(env, ss_class, ss_ctrID, sse->sse_assoc_id);
306
CHECK_NULL(resultObj);
307
(*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
308
(*env)->SetIntField(env, resultContainerObj, src_typeID,
309
sun_nio_ch_sctp_ResultContainer_SHUTDOWN);
310
}
311
312
void handlePeerAddrChange
313
(JNIEnv* env, jobject resultContainerObj, struct sctp_paddr_change* spc) {
314
int event = 0;
315
jobject addressObj, resultObj;
316
unsigned int state = spc->spc_state;
317
318
switch (state) {
319
case SCTP_ADDR_AVAILABLE :
320
event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_AVAILABLE;
321
break;
322
case SCTP_ADDR_UNREACHABLE :
323
event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_UNREACHABLE;
324
break;
325
case SCTP_ADDR_REMOVED :
326
event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_REMOVED;
327
break;
328
case SCTP_ADDR_ADDED :
329
event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_ADDED;
330
break;
331
case SCTP_ADDR_MADE_PRIM :
332
event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_MADE_PRIM;
333
#ifdef __linux__ /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */
334
break;
335
case SCTP_ADDR_CONFIRMED :
336
event = sun_nio_ch_sctp_PeerAddrChange_SCTP_ADDR_CONFIRMED;
337
#endif /* __linux__ */
338
}
339
340
addressObj = SockAddrToInetSocketAddress(env, (struct sockaddr*)&spc->spc_aaddr);
341
CHECK_NULL(addressObj);
342
343
/* create PeerAddressChanged */
344
resultObj = (*env)->NewObject(env, spc_class, spc_ctrID, spc->spc_assoc_id,
345
addressObj, event);
346
CHECK_NULL(resultObj);
347
(*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
348
(*env)->SetIntField(env, resultContainerObj, src_typeID,
349
sun_nio_ch_sctp_ResultContainer_PEER_ADDRESS_CHANGED);
350
}
351
352
void handleUninteresting
353
(union sctp_notification *snp) {
354
//fprintf(stdout,"\nNative: handleUninterestingNotification: Receive notification type [%u]", snp->sn_header.sn_type);
355
}
356
357
/**
358
* Handle notifications from the SCTP stack.
359
* Returns JNI_TRUE if the notification is one that is of interest to the
360
* Java API, otherwise JNI_FALSE.
361
*/
362
jboolean handleNotification
363
(JNIEnv* env, int fd, jobject resultContainerObj, union sctp_notification* snp,
364
int read, jboolean isEOR, struct sockaddr* sap) {
365
switch (snp->sn_header.sn_type) {
366
case SCTP_SEND_FAILED:
367
handleSendFailed(env, fd, resultContainerObj, &snp->sn_send_failed,
368
read, isEOR, sap);
369
return JNI_TRUE;
370
case SCTP_ASSOC_CHANGE:
371
handleAssocChange(env, resultContainerObj, &snp->sn_assoc_change);
372
return JNI_TRUE;
373
case SCTP_SHUTDOWN_EVENT:
374
handleShutdown(env, resultContainerObj, &snp->sn_shutdown_event);
375
return JNI_TRUE;
376
case SCTP_PEER_ADDR_CHANGE:
377
handlePeerAddrChange(env, resultContainerObj, &snp->sn_paddr_change);
378
return JNI_TRUE;
379
default :
380
/* the Java API is not interested in this event, maybe we are? */
381
handleUninteresting(snp);
382
}
383
return JNI_FALSE;
384
}
385
386
void handleMessage
387
(JNIEnv* env, jobject resultContainerObj, struct msghdr* msg,int read,
388
jboolean isEOR, struct sockaddr* sap) {
389
jobject isa, resultObj;
390
struct controlData cdata[1];
391
392
if (read == 0) {
393
/* we reached EOF */
394
read = -1;
395
}
396
397
isa = SockAddrToInetSocketAddress(env, sap);
398
CHECK_NULL(isa);
399
getControlData(msg, cdata);
400
401
/* create MessageInfoImpl */
402
resultObj = (*env)->NewObject(env, smi_class, smi_ctrID, cdata->assocId,
403
isa, read, cdata->streamNumber,
404
isEOR ? JNI_TRUE : JNI_FALSE,
405
cdata->unordered, cdata->ppid);
406
CHECK_NULL(resultObj);
407
(*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
408
(*env)->SetIntField(env, resultContainerObj, src_typeID,
409
sun_nio_ch_sctp_ResultContainer_MESSAGE);
410
}
411
412
/*
413
* Class: sun_nio_ch_sctp_SctpChannelImpl
414
* Method: receive0
415
* Signature: (ILsun/nio/ch/sctp/ResultContainer;JIZ)I
416
*/
417
JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0
418
(JNIEnv *env, jclass klass, jint fd, jobject resultContainerObj,
419
jlong address, jint length, jboolean peek) {
420
SOCKADDR sa;
421
int sa_len = sizeof(sa);
422
ssize_t rv = 0;
423
jlong *addr = jlong_to_ptr(address);
424
struct iovec iov[1];
425
struct msghdr msg[1];
426
char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))];
427
int flags = peek == JNI_TRUE ? MSG_PEEK : 0;
428
429
/* Set up the msghdr structure for receiving */
430
memset(msg, 0, sizeof (*msg));
431
msg->msg_name = &sa;
432
msg->msg_namelen = sa_len;
433
iov->iov_base = addr;
434
iov->iov_len = length;
435
msg->msg_iov = iov;
436
msg->msg_iovlen = 1;
437
msg->msg_control = cbuf;
438
msg->msg_controllen = sizeof(cbuf);
439
msg->msg_flags = 0;
440
441
do {
442
if ((rv = recvmsg(fd, msg, flags)) < 0) {
443
if (errno == EWOULDBLOCK) {
444
return IOS_UNAVAILABLE;
445
} else if (errno == EINTR) {
446
return IOS_INTERRUPTED;
447
448
#ifdef __linux__
449
} else if (errno == ENOTCONN) {
450
/* ENOTCONN when EOF reached */
451
rv = 0;
452
/* there will be no control data */
453
msg->msg_controllen = 0;
454
#endif /* __linux__ */
455
456
} else {
457
handleSocketError(env, errno);
458
return 0;
459
}
460
}
461
462
if (msg->msg_flags & MSG_NOTIFICATION) {
463
char *bufp = (char*)addr;
464
union sctp_notification *snp;
465
jboolean allocated = JNI_FALSE;
466
467
if (!(msg->msg_flags & MSG_EOR) && length < SCTP_NOTIFICATION_SIZE) {
468
char* newBuf;
469
int rvSAVE = rv;
470
471
if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) {
472
JNU_ThrowOutOfMemoryError(env, "Out of native heap space.");
473
return -1;
474
}
475
allocated = JNI_TRUE;
476
477
memcpy(newBuf, addr, rv);
478
iov->iov_base = newBuf + rv;
479
iov->iov_len = SCTP_NOTIFICATION_SIZE - rv;
480
if ((rv = recvmsg(fd, msg, flags)) < 0) {
481
handleSocketError(env, errno);
482
return 0;
483
}
484
bufp = newBuf;
485
rv += rvSAVE;
486
}
487
#ifdef __sparc
488
else if ((intptr_t)addr & 0x3) {
489
/* the given buffer is not 4 byte aligned */
490
char* newBuf;
491
if ((newBuf = malloc(SCTP_NOTIFICATION_SIZE)) == NULL) {
492
JNU_ThrowOutOfMemoryError(env, "Out of native heap space.");
493
return -1;
494
}
495
allocated = JNI_TRUE;
496
497
memcpy(newBuf, addr, rv);
498
bufp = newBuf;
499
}
500
#endif
501
snp = (union sctp_notification *) bufp;
502
if (handleNotification(env, fd, resultContainerObj, snp, rv,
503
(msg->msg_flags & MSG_EOR),
504
(struct sockaddr*)&sa ) == JNI_TRUE) {
505
/* We have received a notification that is of interest to
506
to the Java API. The appropriate notification will be
507
set in the result container. */
508
if (allocated == JNI_TRUE) {
509
free(bufp);
510
}
511
return 0;
512
}
513
514
if (allocated == JNI_TRUE) {
515
free(bufp);
516
}
517
518
// set iov back to addr, and reset msg_controllen
519
iov->iov_base = addr;
520
iov->iov_len = length;
521
msg->msg_control = cbuf;
522
msg->msg_controllen = sizeof(cbuf);
523
}
524
} while (msg->msg_flags & MSG_NOTIFICATION);
525
526
handleMessage(env, resultContainerObj, msg, rv,
527
(msg->msg_flags & MSG_EOR), (struct sockaddr*)&sa);
528
return rv;
529
}
530
531
/*
532
* Class: sun_nio_ch_sctp_SctpChannelImpl
533
* Method: send0
534
* Signature: (IJILjava/net/InetAddress;IIIZI)I
535
*/
536
JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0
537
(JNIEnv *env, jclass klass, jint fd, jlong address, jint length,
538
jobject targetAddress, jint targetPort, jint assocId, jint streamNumber,
539
jboolean unordered, jint ppid) {
540
SOCKADDR sa;
541
int sa_len = sizeof(sa);
542
ssize_t rv = 0;
543
jlong *addr = jlong_to_ptr(address);
544
struct iovec iov[1];
545
struct msghdr msg[1];
546
int cbuf_size = CMSG_SPACE(sizeof (struct sctp_sndrcvinfo));
547
char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))];
548
struct controlData cdata[1];
549
550
/* SctpChannel:
551
* targetAddress may contain the preferred address or NULL to use primary,
552
* assocId will always be -1
553
* SctpMultiChannell:
554
* Setup new association, targetAddress will contain address, assocId = -1
555
* Association already existing, assocId != -1, targetAddress = preferred addr
556
*/
557
if (targetAddress != NULL /*&& assocId <= 0*/) {
558
if (NET_InetAddressToSockaddr(env, targetAddress, targetPort,
559
(struct sockaddr *)&sa,
560
&sa_len, JNI_TRUE) != 0) {
561
return IOS_THROWN;
562
}
563
} else {
564
memset(&sa, '\x0', sa_len);
565
sa_len = 0;
566
}
567
568
/* Set up the msghdr structure for sending */
569
memset(msg, 0, sizeof (*msg));
570
memset(cbuf, 0, cbuf_size);
571
msg->msg_name = &sa;
572
msg->msg_namelen = sa_len;
573
iov->iov_base = addr;
574
iov->iov_len = length;
575
msg->msg_iov = iov;
576
msg->msg_iovlen = 1;
577
msg->msg_control = cbuf;
578
msg->msg_controllen = cbuf_size;
579
msg->msg_flags = 0;
580
581
cdata->streamNumber = streamNumber;
582
cdata->assocId = assocId;
583
cdata->unordered = unordered;
584
cdata->ppid = ppid;
585
setControlData(msg, cdata);
586
587
if ((rv = sendmsg(fd, msg, 0)) < 0) {
588
if (errno == EWOULDBLOCK) {
589
return IOS_UNAVAILABLE;
590
} else if (errno == EINTR) {
591
return IOS_INTERRUPTED;
592
} else if (errno == EPIPE) {
593
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
594
"Socket is shutdown for writing");
595
} else {
596
handleSocketError(env, errno);
597
return 0;
598
}
599
}
600
601
return rv;
602
}
603
604
/*
605
* Class: sun_nio_ch_sctp_SctpChannelImpl
606
* Method: checkConnect
607
* Signature: (Ljava/io/FileDescriptor;ZZ)I
608
*/
609
JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_checkConnect
610
(JNIEnv* env, jobject this, jobject fdo, jboolean block, jboolean ready) {
611
return Java_sun_nio_ch_SocketChannelImpl_checkConnect(env, this,
612
fdo, block, ready);
613
}
614
615