1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #include <nxt_main.h> 8*0Sigor@sysoev.ru 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru /* sendfile() has been introduced in MacOSX 10.5 (Leopard) */ 11*0Sigor@sysoev.ru 12*0Sigor@sysoev.ru #ifdef NXT_TEST_BUILD_MACOSX_SENDFILE 13*0Sigor@sysoev.ru 14*0Sigor@sysoev.ru ssize_t nxt_macosx_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, 15*0Sigor@sysoev.ru size_t limit); 16*0Sigor@sysoev.ru 17*0Sigor@sysoev.ru static int nxt_sys_sendfile(int fd, int s, off_t offset, off_t *len, 18*0Sigor@sysoev.ru struct sf_hdtr *hdtr, int flags) 19*0Sigor@sysoev.ru { 20*0Sigor@sysoev.ru return -1; 21*0Sigor@sysoev.ru } 22*0Sigor@sysoev.ru 23*0Sigor@sysoev.ru #else 24*0Sigor@sysoev.ru #define nxt_sys_sendfile sendfile 25*0Sigor@sysoev.ru #endif 26*0Sigor@sysoev.ru 27*0Sigor@sysoev.ru 28*0Sigor@sysoev.ru ssize_t 29*0Sigor@sysoev.ru nxt_macosx_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, 30*0Sigor@sysoev.ru size_t limit) 31*0Sigor@sysoev.ru { 32*0Sigor@sysoev.ru size_t hd_size, file_size; 33*0Sigor@sysoev.ru ssize_t n; 34*0Sigor@sysoev.ru nxt_buf_t *fb; 35*0Sigor@sysoev.ru nxt_err_t err; 36*0Sigor@sysoev.ru nxt_off_t sent; 37*0Sigor@sysoev.ru nxt_uint_t nhd, ntr; 38*0Sigor@sysoev.ru struct iovec hd[NXT_IOBUF_MAX], tr[NXT_IOBUF_MAX]; 39*0Sigor@sysoev.ru struct sf_hdtr hdtr, *ht; 40*0Sigor@sysoev.ru nxt_sendbuf_coalesce_t sb; 41*0Sigor@sysoev.ru 42*0Sigor@sysoev.ru sb.buf = b; 43*0Sigor@sysoev.ru sb.iobuf = hd; 44*0Sigor@sysoev.ru sb.nmax = NXT_IOBUF_MAX; 45*0Sigor@sysoev.ru sb.sync = 0; 46*0Sigor@sysoev.ru sb.size = 0; 47*0Sigor@sysoev.ru sb.limit = limit; 48*0Sigor@sysoev.ru 49*0Sigor@sysoev.ru nhd = nxt_sendbuf_mem_coalesce(&sb); 50*0Sigor@sysoev.ru 51*0Sigor@sysoev.ru if (nhd == 0 && sb.sync) { 52*0Sigor@sysoev.ru return 0; 53*0Sigor@sysoev.ru } 54*0Sigor@sysoev.ru 55*0Sigor@sysoev.ru if (sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { 56*0Sigor@sysoev.ru return nxt_event_conn_io_writev(c, hd, nhd); 57*0Sigor@sysoev.ru } 58*0Sigor@sysoev.ru 59*0Sigor@sysoev.ru hd_size = sb.size; 60*0Sigor@sysoev.ru fb = sb.buf; 61*0Sigor@sysoev.ru 62*0Sigor@sysoev.ru file_size = nxt_sendbuf_file_coalesce(&sb); 63*0Sigor@sysoev.ru 64*0Sigor@sysoev.ru if (file_size == 0) { 65*0Sigor@sysoev.ru return nxt_event_conn_io_writev(c, hd, nhd); 66*0Sigor@sysoev.ru } 67*0Sigor@sysoev.ru 68*0Sigor@sysoev.ru sb.iobuf = tr; 69*0Sigor@sysoev.ru 70*0Sigor@sysoev.ru ntr = nxt_sendbuf_mem_coalesce(&sb); 71*0Sigor@sysoev.ru 72*0Sigor@sysoev.ru /* 73*0Sigor@sysoev.ru * Disposal of surplus kernel operations if there are no headers 74*0Sigor@sysoev.ru * and trailers. Besides sendfile() returns EINVAL if a sf_hdtr's 75*0Sigor@sysoev.ru * count is 0, but corresponding pointer is not NULL. 76*0Sigor@sysoev.ru */ 77*0Sigor@sysoev.ru 78*0Sigor@sysoev.ru nxt_memzero(&hdtr, sizeof(struct sf_hdtr)); 79*0Sigor@sysoev.ru ht = NULL; 80*0Sigor@sysoev.ru 81*0Sigor@sysoev.ru if (nhd != 0) { 82*0Sigor@sysoev.ru ht = &hdtr; 83*0Sigor@sysoev.ru hdtr.headers = hd; 84*0Sigor@sysoev.ru hdtr.hdr_cnt = nhd; 85*0Sigor@sysoev.ru } 86*0Sigor@sysoev.ru 87*0Sigor@sysoev.ru if (ntr != 0) { 88*0Sigor@sysoev.ru ht = &hdtr; 89*0Sigor@sysoev.ru hdtr.trailers = tr; 90*0Sigor@sysoev.ru hdtr.trl_cnt = ntr; 91*0Sigor@sysoev.ru } 92*0Sigor@sysoev.ru 93*0Sigor@sysoev.ru /* 94*0Sigor@sysoev.ru * MacOSX has the same bug as old FreeBSD (http://bugs.freebsd.org/33771). 95*0Sigor@sysoev.ru * However this bug has never been fixed and instead of this it has been 96*0Sigor@sysoev.ru * documented as a feature in MacOSX 10.7 (Lion) sendfile(2): 97*0Sigor@sysoev.ru * 98*0Sigor@sysoev.ru * When a header or trailer is specified, the value of len argument 99*0Sigor@sysoev.ru * indicates the maximum number of bytes in the header and/or file 100*0Sigor@sysoev.ru * to be sent. It does not control the trailer; if a trailer exists, 101*0Sigor@sysoev.ru * all of it will be sent. 102*0Sigor@sysoev.ru */ 103*0Sigor@sysoev.ru sent = hd_size + file_size; 104*0Sigor@sysoev.ru 105*0Sigor@sysoev.ru nxt_log_debug(c->socket.log, 106*0Sigor@sysoev.ru "sendfile(%FD, %d, @%O, %O) hd:%ui tr:%ui hs:%uz", 107*0Sigor@sysoev.ru fb->file->fd, c->socket.fd, fb->file_pos, sent, 108*0Sigor@sysoev.ru nhd, ntr, hd_size); 109*0Sigor@sysoev.ru 110*0Sigor@sysoev.ru n = nxt_sys_sendfile(fb->file->fd, c->socket.fd, 111*0Sigor@sysoev.ru fb->file_pos, &sent, ht, 0); 112*0Sigor@sysoev.ru 113*0Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 114*0Sigor@sysoev.ru 115*0Sigor@sysoev.ru nxt_log_debug(c->socket.log, "sendfile(): %d sent:%O", n, sent); 116*0Sigor@sysoev.ru 117*0Sigor@sysoev.ru if (n == -1) { 118*0Sigor@sysoev.ru switch (err) { 119*0Sigor@sysoev.ru 120*0Sigor@sysoev.ru case NXT_EAGAIN: 121*0Sigor@sysoev.ru c->socket.write_ready = 0; 122*0Sigor@sysoev.ru break; 123*0Sigor@sysoev.ru 124*0Sigor@sysoev.ru case NXT_EINTR: 125*0Sigor@sysoev.ru break; 126*0Sigor@sysoev.ru 127*0Sigor@sysoev.ru default: 128*0Sigor@sysoev.ru c->socket.error = err; 129*0Sigor@sysoev.ru nxt_log_error(nxt_socket_error_level(err, c->socket.log_error), 130*0Sigor@sysoev.ru c->socket.log, "sendfile(%FD, %d, %O, %O) failed " 131*0Sigor@sysoev.ru "%E \"%FN\" hd:%ui tr:%ui", fb->file->fd, 132*0Sigor@sysoev.ru c->socket.fd, fb->file_pos, sent, err, 133*0Sigor@sysoev.ru fb->file->name, nhd, ntr); 134*0Sigor@sysoev.ru 135*0Sigor@sysoev.ru return NXT_ERROR; 136*0Sigor@sysoev.ru } 137*0Sigor@sysoev.ru 138*0Sigor@sysoev.ru nxt_log_debug(c->socket.log, "sendfile() %E", err); 139*0Sigor@sysoev.ru 140*0Sigor@sysoev.ru return sent; 141*0Sigor@sysoev.ru } 142*0Sigor@sysoev.ru 143*0Sigor@sysoev.ru if (sent == 0) { 144*0Sigor@sysoev.ru nxt_log_error(NXT_LOG_ERR, c->socket.log, 145*0Sigor@sysoev.ru "file \"%FN\" was truncated while sendfile()", 146*0Sigor@sysoev.ru fb->file->name); 147*0Sigor@sysoev.ru 148*0Sigor@sysoev.ru return NXT_ERROR; 149*0Sigor@sysoev.ru } 150*0Sigor@sysoev.ru 151*0Sigor@sysoev.ru if (sent < (nxt_off_t) sb.size) { 152*0Sigor@sysoev.ru c->socket.write_ready = 0; 153*0Sigor@sysoev.ru } 154*0Sigor@sysoev.ru 155*0Sigor@sysoev.ru return sent; 156*0Sigor@sysoev.ru } 157*0Sigor@sysoev.ru 158*0Sigor@sysoev.ru 159*0Sigor@sysoev.ru #if 0 160*0Sigor@sysoev.ru 161*0Sigor@sysoev.ru typedef struct { 162*0Sigor@sysoev.ru nxt_socket_t socket; 163*0Sigor@sysoev.ru nxt_err_t error; 164*0Sigor@sysoev.ru 165*0Sigor@sysoev.ru uint8_t write_ready; /* 1 bit */ 166*0Sigor@sysoev.ru uint8_t log_error; 167*0Sigor@sysoev.ru } nxt_sendbuf_t; 168*0Sigor@sysoev.ru 169*0Sigor@sysoev.ru 170*0Sigor@sysoev.ru ssize_t nxt_macosx_sendfile(nxt_thread_t *thr, nxt_sendbuf_t *sb, nxt_buf_t *b, 171*0Sigor@sysoev.ru size_t limit); 172*0Sigor@sysoev.ru ssize_t nxt_writev(nxt_thread_t *thr, nxt_sendbuf_t *sb, nxt_iobuf_t *iob, 173*0Sigor@sysoev.ru nxt_uint_t niob); 174*0Sigor@sysoev.ru ssize_t nxt_send(nxt_thread_t *thr, nxt_sendbuf_t *sb, void *buf, size_t size); 175*0Sigor@sysoev.ru 176*0Sigor@sysoev.ru 177*0Sigor@sysoev.ru ssize_t 178*0Sigor@sysoev.ru nxt_macosx_sendfile(nxt_thread_t *thr, nxt_sendbuf_t *sb, nxt_buf_t *b, 179*0Sigor@sysoev.ru size_t limit) 180*0Sigor@sysoev.ru { 181*0Sigor@sysoev.ru size_t hd_size, file_size; 182*0Sigor@sysoev.ru ssize_t n; 183*0Sigor@sysoev.ru nxt_buf_t *buf; 184*0Sigor@sysoev.ru nxt_err_t err; 185*0Sigor@sysoev.ru nxt_off_t sent; 186*0Sigor@sysoev.ru nxt_uint_t nhd, ntr; 187*0Sigor@sysoev.ru struct iovec hd[NXT_IOBUF_MAX], tr[NXT_IOBUF_MAX]; 188*0Sigor@sysoev.ru struct sf_hdtr hdtr, *ht; 189*0Sigor@sysoev.ru nxt_sendbuf_coalesce_t sbc; 190*0Sigor@sysoev.ru 191*0Sigor@sysoev.ru sbc.buf = b; 192*0Sigor@sysoev.ru sbc.iobuf = hd; 193*0Sigor@sysoev.ru sbc.nmax = NXT_IOBUF_MAX; 194*0Sigor@sysoev.ru sbc.sync = 0; 195*0Sigor@sysoev.ru sbc.size = 0; 196*0Sigor@sysoev.ru sbc.limit = limit; 197*0Sigor@sysoev.ru 198*0Sigor@sysoev.ru nhd = nxt_sendbuf_mem_coalesce(&sbc); 199*0Sigor@sysoev.ru 200*0Sigor@sysoev.ru if (nhd == 0 && sbc.sync) { 201*0Sigor@sysoev.ru return 0; 202*0Sigor@sysoev.ru } 203*0Sigor@sysoev.ru 204*0Sigor@sysoev.ru if (sbc.buf == NULL || !nxt_buf_is_file(sbc.buf)) { 205*0Sigor@sysoev.ru return nxt_writev(thr, sb, hd, nhd); 206*0Sigor@sysoev.ru } 207*0Sigor@sysoev.ru 208*0Sigor@sysoev.ru hd_size = sbc.size; 209*0Sigor@sysoev.ru buf = sbc.buf; 210*0Sigor@sysoev.ru 211*0Sigor@sysoev.ru file_size = nxt_sendbuf_file_coalesce(&sbc); 212*0Sigor@sysoev.ru 213*0Sigor@sysoev.ru if (file_size == 0) { 214*0Sigor@sysoev.ru return nxt_writev(thr, sb, hd, nhd); 215*0Sigor@sysoev.ru } 216*0Sigor@sysoev.ru 217*0Sigor@sysoev.ru sbc.iobuf = tr; 218*0Sigor@sysoev.ru 219*0Sigor@sysoev.ru ntr = nxt_sendbuf_mem_coalesce(&sbc); 220*0Sigor@sysoev.ru 221*0Sigor@sysoev.ru /* 222*0Sigor@sysoev.ru * Disposal of surplus kernel operations if there are no headers 223*0Sigor@sysoev.ru * and trailers. Besides sendfile() returns EINVAL if a sf_hdtr's 224*0Sigor@sysoev.ru * count is 0, but corresponding pointer is not NULL. 225*0Sigor@sysoev.ru */ 226*0Sigor@sysoev.ru 227*0Sigor@sysoev.ru nxt_memzero(&hdtr, sizeof(struct sf_hdtr)); 228*0Sigor@sysoev.ru ht = NULL; 229*0Sigor@sysoev.ru 230*0Sigor@sysoev.ru if (nhd != 0) { 231*0Sigor@sysoev.ru ht = &hdtr; 232*0Sigor@sysoev.ru hdtr.headers = hd; 233*0Sigor@sysoev.ru hdtr.hdr_cnt = nhd; 234*0Sigor@sysoev.ru } 235*0Sigor@sysoev.ru 236*0Sigor@sysoev.ru if (ntr != 0) { 237*0Sigor@sysoev.ru ht = &hdtr; 238*0Sigor@sysoev.ru hdtr.trailers = tr; 239*0Sigor@sysoev.ru hdtr.trl_cnt = ntr; 240*0Sigor@sysoev.ru } 241*0Sigor@sysoev.ru 242*0Sigor@sysoev.ru /* 243*0Sigor@sysoev.ru * MacOSX has the same bug as old FreeBSD (http://bugs.freebsd.org/33771). 244*0Sigor@sysoev.ru * However this bug has never been fixed and instead of this it has been 245*0Sigor@sysoev.ru * documented as a feature in MacOSX 10.7 (Lion) sendfile(2): 246*0Sigor@sysoev.ru * 247*0Sigor@sysoev.ru * When a header or trailer is specified, the value of len argument 248*0Sigor@sysoev.ru * indicates the maximum number of bytes in the header and/or file 249*0Sigor@sysoev.ru * to be sent. It does not control the trailer; if a trailer exists, 250*0Sigor@sysoev.ru * all of it will be sent. 251*0Sigor@sysoev.ru */ 252*0Sigor@sysoev.ru sent = hd_size + file_size; 253*0Sigor@sysoev.ru 254*0Sigor@sysoev.ru nxt_log_debug(thr->log, "sendfile(%FD, %d, @%O, %O) hd:%ui tr:%ui hs:%uz", 255*0Sigor@sysoev.ru buf->file->fd, sb->socket, buf->file_pos, sent, 256*0Sigor@sysoev.ru nhd, ntr, hd_size); 257*0Sigor@sysoev.ru 258*0Sigor@sysoev.ru n = nxt_sys_sendfile(buf->file->fd, sb->socket, 259*0Sigor@sysoev.ru buf->file_pos, &sent, ht, 0); 260*0Sigor@sysoev.ru 261*0Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 262*0Sigor@sysoev.ru 263*0Sigor@sysoev.ru nxt_log_debug(thr->log, "sendfile(): %d sent:%O", n, sent); 264*0Sigor@sysoev.ru 265*0Sigor@sysoev.ru if (n == -1) { 266*0Sigor@sysoev.ru switch (err) { 267*0Sigor@sysoev.ru 268*0Sigor@sysoev.ru case NXT_EAGAIN: 269*0Sigor@sysoev.ru sb->write_ready = 0; 270*0Sigor@sysoev.ru break; 271*0Sigor@sysoev.ru 272*0Sigor@sysoev.ru case NXT_EINTR: 273*0Sigor@sysoev.ru break; 274*0Sigor@sysoev.ru 275*0Sigor@sysoev.ru default: 276*0Sigor@sysoev.ru sb->error = err; 277*0Sigor@sysoev.ru nxt_log_error(nxt_socket_error_level(err, sb->log_error), thr->log, 278*0Sigor@sysoev.ru "sendfile(%FD, %d, %O, %O) failed %E \"%FN\" " 279*0Sigor@sysoev.ru "hd:%ui tr:%ui", buf->file->fd, sb->socket, 280*0Sigor@sysoev.ru buf->file_pos, sent, err, buf->file->name, nhd, ntr); 281*0Sigor@sysoev.ru 282*0Sigor@sysoev.ru return NXT_ERROR; 283*0Sigor@sysoev.ru } 284*0Sigor@sysoev.ru 285*0Sigor@sysoev.ru nxt_log_debug(thr->log, "sendfile() %E", err); 286*0Sigor@sysoev.ru 287*0Sigor@sysoev.ru return sent; 288*0Sigor@sysoev.ru } 289*0Sigor@sysoev.ru 290*0Sigor@sysoev.ru if (sent == 0) { 291*0Sigor@sysoev.ru nxt_log_error(NXT_LOG_ERR, thr->log, 292*0Sigor@sysoev.ru "file \"%FN\" was truncated while sendfile()", 293*0Sigor@sysoev.ru buf->file->name); 294*0Sigor@sysoev.ru 295*0Sigor@sysoev.ru return NXT_ERROR; 296*0Sigor@sysoev.ru } 297*0Sigor@sysoev.ru 298*0Sigor@sysoev.ru if (sent < (nxt_off_t) sbc.size) { 299*0Sigor@sysoev.ru sb->write_ready = 0; 300*0Sigor@sysoev.ru } 301*0Sigor@sysoev.ru 302*0Sigor@sysoev.ru return sent; 303*0Sigor@sysoev.ru } 304*0Sigor@sysoev.ru 305*0Sigor@sysoev.ru 306*0Sigor@sysoev.ru ssize_t 307*0Sigor@sysoev.ru nxt_writev(nxt_thread_t *thr, nxt_sendbuf_t *sb, nxt_iobuf_t *iob, 308*0Sigor@sysoev.ru nxt_uint_t niob) 309*0Sigor@sysoev.ru { 310*0Sigor@sysoev.ru ssize_t n; 311*0Sigor@sysoev.ru nxt_err_t err; 312*0Sigor@sysoev.ru 313*0Sigor@sysoev.ru if (niob == 1) { 314*0Sigor@sysoev.ru /* Disposal of surplus kernel iovec copy-in operation. */ 315*0Sigor@sysoev.ru return nxt_send(thr, sb, iob->iov_base, iob->iov_len); 316*0Sigor@sysoev.ru } 317*0Sigor@sysoev.ru 318*0Sigor@sysoev.ru for ( ;; ) { 319*0Sigor@sysoev.ru n = writev(sb->socket, iob, niob); 320*0Sigor@sysoev.ru 321*0Sigor@sysoev.ru err = (n == -1) ? nxt_socket_errno : 0; 322*0Sigor@sysoev.ru 323*0Sigor@sysoev.ru nxt_log_debug(thr->log, "writev(%d, %ui): %d", sb->socket, niob, n); 324*0Sigor@sysoev.ru 325*0Sigor@sysoev.ru if (n > 0) { 326*0Sigor@sysoev.ru return n; 327*0Sigor@sysoev.ru } 328*0Sigor@sysoev.ru 329*0Sigor@sysoev.ru /* n == -1 */ 330*0Sigor@sysoev.ru 331*0Sigor@sysoev.ru switch (err) { 332*0Sigor@sysoev.ru 333*0Sigor@sysoev.ru case NXT_EAGAIN: 334*0Sigor@sysoev.ru nxt_log_debug(thr->log, "writev() %E", err); 335*0Sigor@sysoev.ru sb->write_ready = 0; 336*0Sigor@sysoev.ru return NXT_AGAIN; 337*0Sigor@sysoev.ru 338*0Sigor@sysoev.ru case NXT_EINTR: 339*0Sigor@sysoev.ru nxt_log_debug(thr->log, "writev() %E", err); 340*0Sigor@sysoev.ru continue; 341*0Sigor@sysoev.ru 342*0Sigor@sysoev.ru default: 343*0Sigor@sysoev.ru sb->error = err; 344*0Sigor@sysoev.ru nxt_log_error(nxt_socket_error_level(err, sb->log_error), thr->log, 345*0Sigor@sysoev.ru "writev(%d, %ui) failed %E", sb->socket, niob, err); 346*0Sigor@sysoev.ru return NXT_ERROR; 347*0Sigor@sysoev.ru } 348*0Sigor@sysoev.ru } 349*0Sigor@sysoev.ru } 350*0Sigor@sysoev.ru 351*0Sigor@sysoev.ru 352*0Sigor@sysoev.ru ssize_t 353*0Sigor@sysoev.ru nxt_send(nxt_thread_t *thr, nxt_sendbuf_t *sb, void *buf, size_t size) 354*0Sigor@sysoev.ru { 355*0Sigor@sysoev.ru ssize_t n; 356*0Sigor@sysoev.ru nxt_err_t err; 357*0Sigor@sysoev.ru 358*0Sigor@sysoev.ru for ( ;; ) { 359*0Sigor@sysoev.ru n = send(sb->socket, buf, size, 0); 360*0Sigor@sysoev.ru 361*0Sigor@sysoev.ru err = (n == -1) ? nxt_socket_errno : 0; 362*0Sigor@sysoev.ru 363*0Sigor@sysoev.ru nxt_log_debug(thr->log, "send(%d, %p, %uz): %z", 364*0Sigor@sysoev.ru sb->socket, buf, size, n); 365*0Sigor@sysoev.ru 366*0Sigor@sysoev.ru if (n > 0) { 367*0Sigor@sysoev.ru return n; 368*0Sigor@sysoev.ru } 369*0Sigor@sysoev.ru 370*0Sigor@sysoev.ru /* n == -1 */ 371*0Sigor@sysoev.ru 372*0Sigor@sysoev.ru switch (err) { 373*0Sigor@sysoev.ru 374*0Sigor@sysoev.ru case NXT_EAGAIN: 375*0Sigor@sysoev.ru nxt_log_debug(thr->log, "send() %E", err); 376*0Sigor@sysoev.ru sb->write_ready = 0; 377*0Sigor@sysoev.ru return NXT_AGAIN; 378*0Sigor@sysoev.ru 379*0Sigor@sysoev.ru case NXT_EINTR: 380*0Sigor@sysoev.ru nxt_log_debug(thr->log, "send() %E", err); 381*0Sigor@sysoev.ru continue; 382*0Sigor@sysoev.ru 383*0Sigor@sysoev.ru default: 384*0Sigor@sysoev.ru sb->error = err; 385*0Sigor@sysoev.ru nxt_log_error(nxt_socket_error_level(err, sb->log_error), thr->log, 386*0Sigor@sysoev.ru "send(%d, %p, %uz) failed %E", 387*0Sigor@sysoev.ru sb->socket, buf, size, err); 388*0Sigor@sysoev.ru return NXT_ERROR; 389*0Sigor@sysoev.ru } 390*0Sigor@sysoev.ru } 391*0Sigor@sysoev.ru } 392*0Sigor@sysoev.ru 393*0Sigor@sysoev.ru #endif 394