blob: 21ba86712e16ea2faffa6df2fe31b9a5afc6df8d [file] [log] [blame]
Simon Xu6f224942013-12-06 11:51:16 +08001/* SCTP kernel Implementation
uid5281789de9aa2003-10-23 18:42:24 +00002 * (C) Copyright IBM Corp. 2003
3 * Copyright (c) 2003 Intel Corp.
4 *
Simon Xu6f224942013-12-06 11:51:16 +08005 * The SCTP implementation is free software;
uid5281789de9aa2003-10-23 18:42:24 +00006 * you can redistribute it and/or modify it under the terms of
7 * the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
Simon Xu6f224942013-12-06 11:51:16 +080011 * The SCTP implementation is distributed in the hope that it
uid5281789de9aa2003-10-23 18:42:24 +000012 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13 * ************************
14 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU CC; see the file COPYING. If not, write to
19 * the Free Software Foundation, 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 *
22 * Please send any bug reports or fixes you make to the
23 * email address(es):
24 * lksctp developers <lksctp-developers@lists.sourceforge.net>
25 *
26 * Or submit a bug report through the following website:
27 * http://www.sf.net/projects/lksctp
28 *
29 * Any bugs reported to us we will try to fix... any fixes shared will
30 * be incorporated into the next SCTP release.
31 *
32 * Written or modified by:
33 * To compile the v6 version, set the symbol TEST_V6 to 1.
34 *
35 * Written or modified by:
36 * Ardelle Fan <ardelle.fan@intel.com>
37 * Sridhar Samudrala <sri@us.ibm.com>
38 */
39
40/* This is a basic functional test for the SCTP new library APIs
41 * sctp_sendmsg() and sctp_recvmsg(). test_timetolive.c is rewritten using
Simon Xu6f224942013-12-06 11:51:16 +080042 * these new APIs.
uid5281789de9aa2003-10-23 18:42:24 +000043 */
44
45#include <stdio.h>
46#include <unistd.h>
47#include <stdlib.h>
48#include <string.h>
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <sys/uio.h>
52#include <netinet/in.h>
Simon Xu6f224942013-12-06 11:51:16 +080053#include <sys/errno.h>
uid5281789de9aa2003-10-23 18:42:24 +000054#include <errno.h>
55#include <netinet/sctp.h>
56#include <sctputil.h>
57
58char *TCID = __FILE__;
mridge64a341f2006-01-03 19:16:46 +000059int TST_TOTAL = 10;
uid5281789de9aa2003-10-23 18:42:24 +000060int TST_CNT = 0;
61
mridge64a341f2006-01-03 19:16:46 +000062/* RCVBUF value, and indirectly RWND*2 */
63#define SMALL_RCVBUF 3000
uid5281789de9aa2003-10-23 18:42:24 +000064#define SMALL_MAXSEG 100
mridge64a341f2006-01-03 19:16:46 +000065/* This is extra data length to ensure rwnd closes */
66#define RWND_SLOP 100
67static char *fillmsg = NULL;
uid5281789de9aa2003-10-23 18:42:24 +000068static char *ttlmsg = "This should time out!\n";
69static char *nottlmsg = "This should NOT time out!\n";
Simon Xu6f224942013-12-06 11:51:16 +080070static char ttlfrag[SMALL_MAXSEG*3] = {0};
uid5281789de9aa2003-10-23 18:42:24 +000071static char *message = "Hello world\n";
72
73int main(int argc, char *argv[])
74{
75 int sk1, sk2;
76 sockaddr_storage_t loop1;
77 sockaddr_storage_t loop2;
78 sockaddr_storage_t msgname;
79 int error;
Simon Xu6f224942013-12-06 11:51:16 +080080 int pf_class;
uid5281789de9aa2003-10-23 18:42:24 +000081 uint32_t ppid;
82 uint32_t stream;
83 struct sctp_event_subscribe subscribe;
84 char *big_buffer;
mridge64a341f2006-01-03 19:16:46 +000085 int offset, msg_flags;
Simon Xu6f224942013-12-06 11:51:16 +080086 socklen_t msgname_len;
uid5281789de9aa2003-10-23 18:42:24 +000087 size_t buflen;
88 struct sctp_send_failed *ssf;
89 struct sctp_sndrcvinfo sinfo;
mridge64a341f2006-01-03 19:16:46 +000090 struct sctp_sndrcvinfo snd_sinfo;
Simon Xu6f224942013-12-06 11:51:16 +080091 sctp_assoc_t associd1;
92 socklen_t len, oldlen;
mridge64a341f2006-01-03 19:16:46 +000093 struct sctp_status gstatus;
uid5281789de9aa2003-10-23 18:42:24 +000094
95 /* Rather than fflush() throughout the code, set stdout to
96 * be unbuffered.
97 */
98 setvbuf(stdout, NULL, _IONBF, 0);
99
100 /* Set some basic values which depend on the address family. */
101#if TEST_V6
102 pf_class = PF_INET6;
uid5281789de9aa2003-10-23 18:42:24 +0000103
104 loop1.v6.sin6_family = AF_INET6;
105 loop1.v6.sin6_addr = in6addr_loopback;
106 loop1.v6.sin6_port = htons(SCTP_TESTPORT_1);
107
108 loop2.v6.sin6_family = AF_INET6;
109 loop2.v6.sin6_addr = in6addr_loopback;
110 loop2.v6.sin6_port = htons(SCTP_TESTPORT_2);
111#else
112 pf_class = PF_INET;
uid5281789de9aa2003-10-23 18:42:24 +0000113
114 loop1.v4.sin_family = AF_INET;
115 loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
116 loop1.v4.sin_port = htons(SCTP_TESTPORT_1);
117
118 loop2.v4.sin_family = AF_INET;
119 loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
120 loop2.v4.sin_port = htons(SCTP_TESTPORT_2);
121#endif /* TEST_V6 */
122
123 /* Create the two endpoints which will talk to each other. */
124 sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP);
Simon Xu6f224942013-12-06 11:51:16 +0800125 sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP);
uid5281789de9aa2003-10-23 18:42:24 +0000126
127 /* Set the MAXSEG to something smallish. */
128 {
129 int val = SMALL_MAXSEG;
130 test_setsockopt(sk1, SCTP_MAXSEG, &val, sizeof(val));
131 }
132
133 memset(&subscribe, 0, sizeof(subscribe));
134 subscribe.sctp_data_io_event = 1;
135 subscribe.sctp_association_event = 1;
136 subscribe.sctp_send_failure_event = 1;
137 test_setsockopt(sk1, SCTP_EVENTS, &subscribe, sizeof(subscribe));
138 test_setsockopt(sk2, SCTP_EVENTS, &subscribe, sizeof(subscribe));
139
Simon Xu6f224942013-12-06 11:51:16 +0800140 /* Bind these sockets to the test ports. */
141 test_bind(sk1, &loop1.sa, sizeof(loop1));
142 test_bind(sk2, &loop2.sa, sizeof(loop2));
uid5281789de9aa2003-10-23 18:42:24 +0000143
mridge64a341f2006-01-03 19:16:46 +0000144 /*
145 * Set the RWND small so we can fill it up easily.
146 * then reset RCVBUF to avoid frame droppage
147 */
148 len = sizeof(int);
149 error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &oldlen, &len);
Simon Xu6f224942013-12-06 11:51:16 +0800150
mridge64a341f2006-01-03 19:16:46 +0000151 if (error)
Simon Xu6f224942013-12-06 11:51:16 +0800152 tst_brkm(TBROK, tst_exit, "can't get rcvbuf size: %s",
mridge64a341f2006-01-03 19:16:46 +0000153 strerror(errno));
uid5281789de9aa2003-10-23 18:42:24 +0000154
Simon Xu6f224942013-12-06 11:51:16 +0800155 len = SMALL_RCVBUF; /* Really becomes 2xlen when set. */
mridge64a341f2006-01-03 19:16:46 +0000156
157 error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
158 if (error)
Simon Xu6f224942013-12-06 11:51:16 +0800159 tst_brkm(TBROK, tst_exit, "setsockopt(SO_RCVBUF): %s",
mridge64a341f2006-01-03 19:16:46 +0000160 strerror(errno));
uid5281789de9aa2003-10-23 18:42:24 +0000161
Simon Xu6f224942013-12-06 11:51:16 +0800162 /* Mark sk2 as being able to accept new associations. */
uid5281789de9aa2003-10-23 18:42:24 +0000163 test_listen(sk2, 1);
164
165 /* Send the first message. This will create the association. */
166 ppid = rand();
167 stream = 1;
168 test_sctp_sendmsg(sk1, message, strlen(message) + 1,
169 (struct sockaddr *)&loop2, sizeof(loop2),
170 ppid, 0, stream, 0, 0);
171
172 tst_resm(TPASS, "sctp_sendmsg");
173
174 /* Get the communication up message on sk2. */
175 buflen = REALLY_BIG;
176 big_buffer = test_malloc(buflen);
177 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800178 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000179 error = test_sctp_recvmsg(sk2, big_buffer, buflen,
uid5281789de9aa2003-10-23 18:42:24 +0000180 (struct sockaddr *)&msgname, &msgname_len,
Garrett Cooper2c282152010-12-16 00:55:50 -0800181 &sinfo, &msg_flags);
Simon Xu6f224942013-12-06 11:51:16 +0800182#if 0
mridge64a341f2006-01-03 19:16:46 +0000183 associd2 = ((struct sctp_assoc_change *)big_buffer)->sac_assoc_id;
Simon Xu6f224942013-12-06 11:51:16 +0800184#endif
uid5281789de9aa2003-10-23 18:42:24 +0000185 test_check_buf_notification(big_buffer, error, msg_flags,
186 sizeof(struct sctp_assoc_change),
187 SCTP_ASSOC_CHANGE, SCTP_COMM_UP);
188
Simon Xu6f224942013-12-06 11:51:16 +0800189
mridge64a341f2006-01-03 19:16:46 +0000190 /* restore the rcvbuffer size for the receiving socket */
Simon Xu6f224942013-12-06 11:51:16 +0800191 error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &oldlen,
192 sizeof(oldlen));
mridge64a341f2006-01-03 19:16:46 +0000193
194 if (error)
Simon Xu6f224942013-12-06 11:51:16 +0800195 tst_brkm(TBROK, tst_exit, "setsockopt(SO_RCVBUF): %s",
mridge64a341f2006-01-03 19:16:46 +0000196 strerror(errno));
197
uid5281789de9aa2003-10-23 18:42:24 +0000198 /* Get the communication up message on sk1. */
199 buflen = REALLY_BIG;
200 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800201 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000202 error = test_sctp_recvmsg(sk1, big_buffer, buflen,
uid5281789de9aa2003-10-23 18:42:24 +0000203 (struct sockaddr *)&msgname, &msgname_len,
Simon Xu6f224942013-12-06 11:51:16 +0800204 &sinfo, &msg_flags);
mridge64a341f2006-01-03 19:16:46 +0000205 associd1 = ((struct sctp_assoc_change *)big_buffer)->sac_assoc_id;
uid5281789de9aa2003-10-23 18:42:24 +0000206 test_check_buf_notification(big_buffer, error, msg_flags,
207 sizeof(struct sctp_assoc_change),
208 SCTP_ASSOC_CHANGE, SCTP_COMM_UP);
209
210 tst_resm(TPASS, "sctp_recvmsg SCTP_COMM_UP notification");
211
212 /* Get the first message which was sent. */
213 buflen = REALLY_BIG;
214 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800215 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000216 error = test_sctp_recvmsg(sk2, big_buffer, buflen,
uid5281789de9aa2003-10-23 18:42:24 +0000217 (struct sockaddr *)&msgname, &msgname_len,
Simon Xu6f224942013-12-06 11:51:16 +0800218 &sinfo, &msg_flags);
mridge64a341f2006-01-03 19:16:46 +0000219 test_check_buf_data(big_buffer, error, msg_flags, &sinfo,
Simon Xu6f224942013-12-06 11:51:16 +0800220 strlen(message) + 1, MSG_EOR, stream, ppid);
uid5281789de9aa2003-10-23 18:42:24 +0000221
222 tst_resm(TPASS, "sctp_recvmsg data");
223
mridge64a341f2006-01-03 19:16:46 +0000224 /* Figure out how big to make our fillmsg */
225 len = sizeof(struct sctp_status);
Simon Xu6f224942013-12-06 11:51:16 +0800226 memset(&gstatus,0,sizeof(struct sctp_status));
mridge64a341f2006-01-03 19:16:46 +0000227 gstatus.sstat_assoc_id = associd1;
228 error = getsockopt(sk1, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len);
229
230 if (error)
Simon Xu6f224942013-12-06 11:51:16 +0800231 tst_brkm(TBROK, tst_exit, "can't get rwnd size: %s",
232 strerror(errno));
mridge64a341f2006-01-03 19:16:46 +0000233 tst_resm(TINFO, "creating a fillmsg of size %d",
Simon Xu6f224942013-12-06 11:51:16 +0800234 gstatus.sstat_rwnd+RWND_SLOP);
235 fillmsg = malloc(gstatus.sstat_rwnd+RWND_SLOP);
mridge64a341f2006-01-03 19:16:46 +0000236
uid5281789de9aa2003-10-23 18:42:24 +0000237 /* Send a fillmsg */
Simon Xu6f224942013-12-06 11:51:16 +0800238 memset(fillmsg, 'X', gstatus.sstat_rwnd+RWND_SLOP);
239 fillmsg[gstatus.sstat_rwnd+RWND_SLOP-1] = '\0';
uid5281789de9aa2003-10-23 18:42:24 +0000240 ppid++;
241 stream++;
Simon Xu6f224942013-12-06 11:51:16 +0800242 test_sctp_sendmsg(sk1, fillmsg, gstatus.sstat_rwnd+RWND_SLOP,
uid5281789de9aa2003-10-23 18:42:24 +0000243 (struct sockaddr *)&loop2, sizeof(loop2),
244 ppid, 0, stream, 0, 0);
245
246 /* Now send a message that will timeout. */
247 test_sctp_sendmsg(sk1, ttlmsg, strlen(ttlmsg) + 1,
248 (struct sockaddr *)&loop2, sizeof(loop2),
249 ppid, 0, stream, 2000, 0);
250
251 tst_resm(TPASS, "sctp_sendmsg with ttl");
252
253 /* Next send a message that won't time out. */
254 test_sctp_sendmsg(sk1, nottlmsg, strlen(nottlmsg) + 1,
255 (struct sockaddr *)&loop2, sizeof(loop2),
256 ppid, 0, stream, 0, 0);
257
258 tst_resm(TPASS, "sctp_sendmsg with zero ttl");
259
260 /* And finally a fragmented message that will time out. */
261 memset(ttlfrag, '0', sizeof(ttlfrag));
Simon Xu6f224942013-12-06 11:51:16 +0800262 ttlfrag[sizeof(ttlfrag)-1] = '\0';
uid5281789de9aa2003-10-23 18:42:24 +0000263 test_sctp_sendmsg(sk1, ttlfrag, sizeof(ttlfrag),
264 (struct sockaddr *)&loop2, sizeof(loop2),
265 ppid, 0, stream, 2000, 0);
266
267 tst_resm(TPASS, "sctp_sendmsg fragmented msg with ttl");
268
269 /* Sleep waiting for the message to time out. */
270 tst_resm(TINFO, "** SLEEPING for 3 seconds **");
271 sleep(3);
272
273 /* Get the fillmsg. */
274 do {
275 buflen = REALLY_BIG;
276 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800277 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000278 test_sctp_recvmsg(sk2, big_buffer, buflen,
Simon Xu6f224942013-12-06 11:51:16 +0800279 (struct sockaddr *)&msgname, &msgname_len,
280 &sinfo, &msg_flags);
uid5281789de9aa2003-10-23 18:42:24 +0000281 } while (!(msg_flags & MSG_EOR));
282
283 /* Get the message that did NOT time out. */
284 buflen = REALLY_BIG;
285 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800286 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000287 error = test_sctp_recvmsg(sk2, big_buffer, buflen,
Simon Xu6f224942013-12-06 11:51:16 +0800288 (struct sockaddr *)&msgname, &msgname_len,
289 &sinfo, &msg_flags);
mridge64a341f2006-01-03 19:16:46 +0000290 test_check_buf_data(big_buffer, error, msg_flags, &sinfo,
Simon Xu6f224942013-12-06 11:51:16 +0800291 strlen(nottlmsg) + 1, MSG_EOR, stream, ppid);
uid5281789de9aa2003-10-23 18:42:24 +0000292 if (0 != strncmp(big_buffer, nottlmsg, strlen(nottlmsg)))
Simon Xu6f224942013-12-06 11:51:16 +0800293 tst_brkm(TBROK, tst_exit, "sctp_recvmsg: Wrong Message !!!");
uid5281789de9aa2003-10-23 18:42:24 +0000294
295 tst_resm(TPASS, "sctp_recvmsg msg with zero ttl");
296
297 /* Get the SEND_FAILED notification for the message that DID
298 * time out.
299 */
300 buflen = REALLY_BIG;
301 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800302 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000303 error = test_sctp_recvmsg(sk1, big_buffer, buflen,
Simon Xu6f224942013-12-06 11:51:16 +0800304 (struct sockaddr *)&msgname, &msgname_len,
305 &sinfo, &msg_flags);
uid5281789de9aa2003-10-23 18:42:24 +0000306 test_check_buf_notification(big_buffer, error, msg_flags,
307 sizeof(struct sctp_send_failed) +
Simon Xu6f224942013-12-06 11:51:16 +0800308 strlen(ttlmsg) + 1,
309 SCTP_SEND_FAILED, 0);
uid5281789de9aa2003-10-23 18:42:24 +0000310 ssf = (struct sctp_send_failed *)big_buffer;
mridge64a341f2006-01-03 19:16:46 +0000311 if (0 != strncmp(ttlmsg, (char *)ssf->ssf_data, strlen(ttlmsg) + 1))
Simon Xu6f224942013-12-06 11:51:16 +0800312 tst_brkm(TBROK, tst_exit, "SEND_FAILED data mismatch");
uid5281789de9aa2003-10-23 18:42:24 +0000313
314 tst_resm(TPASS, "sctp_recvmsg SEND_FAILED for message with ttl");
315
316 offset = 0;
317
Simon Xu6f224942013-12-06 11:51:16 +0800318 /* Get the SEND_FAILED notifications for the fragmented message that
uid5281789de9aa2003-10-23 18:42:24 +0000319 * timed out.
320 */
321 do {
322 buflen = REALLY_BIG;
323 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800324 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000325 error = test_sctp_recvmsg(sk1, big_buffer, buflen,
Simon Xu6f224942013-12-06 11:51:16 +0800326 (struct sockaddr *)&msgname, &msgname_len,
327 &sinfo, &msg_flags);
uid5281789de9aa2003-10-23 18:42:24 +0000328 test_check_buf_notification(big_buffer, error, msg_flags,
329 sizeof(struct sctp_send_failed) +
Simon Xu6f224942013-12-06 11:51:16 +0800330 SMALL_MAXSEG,
331 SCTP_SEND_FAILED, 0);
uid5281789de9aa2003-10-23 18:42:24 +0000332 ssf = (struct sctp_send_failed *)big_buffer;
mridge64a341f2006-01-03 19:16:46 +0000333 if (0 != strncmp(&ttlfrag[offset], (char *)ssf->ssf_data,
334 SMALL_MAXSEG))
Simon Xu6f224942013-12-06 11:51:16 +0800335 tst_brkm(TBROK, tst_exit, "SEND_FAILED data mismatch");
uid5281789de9aa2003-10-23 18:42:24 +0000336 offset += SMALL_MAXSEG;
Simon Xu6f224942013-12-06 11:51:16 +0800337 } while (!(ssf->ssf_info.sinfo_flags & 0x01)); /* LAST FRAG */
uid5281789de9aa2003-10-23 18:42:24 +0000338
339 tst_resm(TPASS, "sctp_recvmsg SEND_FAILED for fragmented message with "
340 "ttl");
341
mridge64a341f2006-01-03 19:16:46 +0000342 snd_sinfo.sinfo_ppid = rand();
Simon Xu6f224942013-12-06 11:51:16 +0800343 snd_sinfo.sinfo_flags = 0;
344 snd_sinfo.sinfo_stream = 2;
345 snd_sinfo.sinfo_timetolive = 0;
346 snd_sinfo.sinfo_assoc_id = associd1;
mridge64a341f2006-01-03 19:16:46 +0000347 test_sctp_send(sk1, message, strlen(message) + 1, &snd_sinfo,
348 MSG_NOSIGNAL);
349
350 buflen = REALLY_BIG;
351 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800352 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000353 error = test_sctp_recvmsg(sk2, big_buffer, buflen,
354 (struct sockaddr *)&msgname, &msgname_len,
Simon Xu6f224942013-12-06 11:51:16 +0800355 &sinfo, &msg_flags);
mridge64a341f2006-01-03 19:16:46 +0000356 test_check_buf_data(big_buffer, error, msg_flags, &sinfo,
Simon Xu6f224942013-12-06 11:51:16 +0800357 strlen(message) + 1, MSG_EOR, snd_sinfo.sinfo_stream,
358 snd_sinfo.sinfo_ppid);
mridge64a341f2006-01-03 19:16:46 +0000359
360 tst_resm(TPASS, "sctp_send");
361
uid5281789de9aa2003-10-23 18:42:24 +0000362 /* Shut down the link. */
363 close(sk1);
364
365 /* Get the shutdown complete notification. */
366 buflen = REALLY_BIG;
367 msgname_len = sizeof(msgname);
Simon Xu6f224942013-12-06 11:51:16 +0800368 msg_flags = 0;
mridge64a341f2006-01-03 19:16:46 +0000369 error = test_sctp_recvmsg(sk2, big_buffer, buflen,
Simon Xu6f224942013-12-06 11:51:16 +0800370 (struct sockaddr *)&msgname, &msgname_len,
371 &sinfo, &msg_flags);
uid5281789de9aa2003-10-23 18:42:24 +0000372 test_check_buf_notification(big_buffer, error, msg_flags,
373 sizeof(struct sctp_assoc_change),
374 SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP);
375
376 close(sk2);
377
378 /* Indicate successful completion. */
Simon Xu6f224942013-12-06 11:51:16 +0800379 return 0;
Chris Dearmanec6edca2012-10-17 19:54:01 -0700380}