Annotation of embedaddon/istgt/src/istgt_sock.c, revision 1.1.1.3

1.1       misho       1: /*
1.1.1.2   misho       2:  * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
1.1       misho       3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  *
                     14:  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     17:  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
                     18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     24:  * SUCH DAMAGE.
                     25:  *
                     26:  */
                     27: 
                     28: #ifdef HAVE_CONFIG_H
                     29: #include "config.h"
                     30: #endif
                     31: 
                     32: #include <errno.h>
                     33: #include <stdio.h>
                     34: #include <string.h>
                     35: #include <unistd.h>
                     36: #include <poll.h>
                     37: #include <sys/types.h>
                     38: #include <sys/socket.h>
                     39: #include <netdb.h>
                     40: #include <netinet/in.h>
                     41: #include <netinet/tcp.h>
                     42: 
                     43: #include "istgt.h"
1.1.1.3 ! misho      44: #include "istgt_log.h"
1.1       misho      45: #include "istgt_sock.h"
                     46: #include "istgt_misc.h"
                     47: 
                     48: //#define USE_POLLWAIT
                     49: #undef USE_POLLWAIT
                     50: #define TIMEOUT_RW 60
                     51: #define POLLWAIT 1000
                     52: #define PORTNUMLEN 32
                     53: 
                     54: #ifndef AI_NUMERICSERV
                     55: #define AI_NUMERICSERV 0
                     56: #endif
                     57: 
1.1.1.2   misho      58: #if !defined(__GNUC__)
                     59: #undef __attribute__
                     60: #define __attribute__(x)
                     61: #endif
                     62: 
1.1       misho      63: int
                     64: istgt_getaddr(int sock, char *saddr, int slen, char *caddr, int clen)
                     65: {
                     66:        struct sockaddr_storage sa;
                     67:        socklen_t salen;
                     68:        int rc;
                     69: 
                     70:        memset(&sa, 0, sizeof sa);
                     71:        salen = sizeof sa;
                     72:        rc = getsockname(sock, (struct sockaddr *) &sa, &salen);
                     73:        if (rc != 0) {
1.1.1.3 ! misho      74:                ISTGT_ERRLOG("getsockname() failed (errno=%d)\n", errno);
1.1       misho      75:                return -1;
                     76:        }
                     77:        rc = getnameinfo((struct sockaddr *) &sa, salen,
1.1.1.2   misho      78:            saddr, slen, NULL, 0, NI_NUMERICHOST);
1.1       misho      79:        if (rc != 0) {
1.1.1.3 ! misho      80:                ISTGT_ERRLOG("getnameinfo() failed (errno=%d)\n", errno);
1.1       misho      81:                return -1;
                     82:        }
                     83: 
                     84:        memset(&sa, 0, sizeof sa);
                     85:        salen = sizeof sa;
                     86:        rc = getpeername(sock, (struct sockaddr *) &sa, &salen);
                     87:        if (rc != 0) {
1.1.1.3 ! misho      88:                ISTGT_ERRLOG("getpeername() failed (errno=%d)\n", errno);
1.1       misho      89:                return -1;
                     90:        }
                     91:        rc = getnameinfo((struct sockaddr *) &sa, salen,
1.1.1.2   misho      92:            caddr, clen, NULL, 0, NI_NUMERICHOST);
1.1       misho      93:        if (rc != 0) {
1.1.1.3 ! misho      94:                ISTGT_ERRLOG("getnameinfo() failed (errno=%d)\n", errno);
1.1       misho      95:                return -1;
                     96:        }
                     97: 
                     98:        return 0;
                     99: }
                    100: 
                    101: int
                    102: istgt_listen(const char *ip, int port)
                    103: {
                    104:        char buf[MAX_TMPBUF];
                    105:        char portnum[PORTNUMLEN];
                    106:        char *p;
                    107:        struct addrinfo hints, *res, *res0;
                    108:        int sock;
                    109:        int val = 1;
                    110:        int rc;
                    111: 
                    112:        if (ip == NULL)
                    113:                return -1;
                    114:        if (ip[0] == '[') {
                    115:                strlcpy(buf, ip + 1, sizeof buf);
                    116:                p = strchr(buf, ']');
                    117:                if (p != NULL)
                    118:                        *p = '\0';
                    119:                ip = (const char *) &buf[0];
                    120:                if (strcasecmp(ip, "*") == 0) {
                    121:                        strlcpy(buf, "::", sizeof buf);
                    122:                        ip = (const char *) &buf[0];
                    123:                }
                    124:        } else {
                    125:                if (strcasecmp(ip, "*") == 0) {
                    126:                        strlcpy(buf, "0.0.0.0", sizeof buf);
                    127:                        ip = (const char *) &buf[0];
                    128:                }
                    129:        }
                    130:        snprintf(portnum, sizeof portnum, "%d", port);
                    131:        memset(&hints, 0, sizeof hints);
                    132:        hints.ai_family = PF_UNSPEC;
                    133:        hints.ai_socktype = SOCK_STREAM;
                    134:        hints.ai_flags = AI_NUMERICSERV;
                    135:        hints.ai_flags |= AI_PASSIVE;
                    136:        hints.ai_flags |= AI_NUMERICHOST;
                    137:        rc = getaddrinfo(ip, portnum, &hints, &res0);
                    138:        if (rc != 0) {
1.1.1.3 ! misho     139:                ISTGT_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno);
1.1       misho     140:                return -1;
                    141:        }
                    142: 
                    143:        /* try listen */
                    144:        sock = -1;
                    145:        for (res = res0; res != NULL; res = res->ai_next) {
                    146:        retry:
                    147:                sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                    148:                if (sock < 0) {
                    149:                        /* error */
                    150:                        continue;
                    151:                }
                    152:                rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
                    153:                if (rc != 0) {
                    154:                        /* error */
                    155:                        continue;
                    156:                }
                    157:                rc = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val);
                    158:                if (rc != 0) {
                    159:                        /* error */
                    160:                        continue;
                    161:                }
                    162:                rc = bind(sock, res->ai_addr, res->ai_addrlen);
                    163:                if (rc == -1 && errno == EINTR) {
                    164:                        /* interrupted? */
                    165:                        close(sock);
                    166:                        sock = -1;
                    167:                        goto retry;
                    168:                }
                    169:                if (rc != 0) {
                    170:                        /* try next family */
                    171:                        close(sock);
                    172:                        sock = -1;
                    173:                        continue;
                    174:                }
                    175:                /* bind OK */
                    176:                rc = listen(sock, 2);
                    177:                if (rc != 0) {
                    178:                        close(sock);
                    179:                        sock = -1;
                    180:                        break;
                    181:                }
                    182:                break;
                    183:        }
                    184:        freeaddrinfo(res0);
                    185: 
                    186:        if (sock < 0) {
                    187:                return -1;
                    188:        }
                    189:        return sock;
                    190: }
                    191: 
                    192: int
                    193: istgt_connect(const char *host, int port)
                    194: {
                    195:        char buf[MAX_TMPBUF];
                    196:        char portnum[PORTNUMLEN];
                    197:        char *p;
                    198:        struct addrinfo hints, *res, *res0;
                    199:        int sock;
                    200:        int val = 1;
                    201:        int rc;
                    202: 
                    203:        if (host == NULL)
                    204:                return -1;
                    205:        if (host[0] == '[') {
                    206:                strlcpy(buf, host + 1, sizeof buf);
                    207:                p = strchr(buf, ']');
                    208:                if (p != NULL)
                    209:                        *p = '\0';
                    210:                host = (const char *) &buf[0];
                    211:                if (strcasecmp(host, "*") == 0) {
                    212:                        strlcpy(buf, "::", sizeof buf);
                    213:                        host = (const char *) &buf[0];
                    214:                }
                    215:        } else {
                    216:                if (strcasecmp(host, "*") == 0) {
                    217:                        strlcpy(buf, "0.0.0.0", sizeof buf);
                    218:                        host = (const char *) &buf[0];
                    219:                }
                    220:        }
                    221:        snprintf(portnum, sizeof portnum, "%d", port);
                    222:        memset(&hints, 0, sizeof hints);
                    223:        hints.ai_family = PF_UNSPEC;
                    224:        hints.ai_socktype = SOCK_STREAM;
                    225:        hints.ai_flags = AI_NUMERICSERV;
                    226:        rc = getaddrinfo(host, portnum, &hints, &res0);
                    227:        if (rc != 0) {
1.1.1.3 ! misho     228:                ISTGT_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno);
1.1       misho     229:                return -1;
                    230:        }
                    231: 
                    232:        /* try connect */
                    233:        sock = -1;
                    234:        for (res = res0; res != NULL; res = res->ai_next) {
                    235:        retry:
                    236:                sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                    237:                if (sock < 0) {
                    238:                        /* error */
                    239:                        continue;
                    240:                }
                    241:                rc = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val);
                    242:                if (rc != 0) {
                    243:                        /* error */
                    244:                        continue;
                    245:                }
                    246:                rc = connect(sock, res->ai_addr, res->ai_addrlen);
                    247:                if (rc == -1 && errno == EINTR) {
                    248:                        /* interrupted? */
                    249:                        close(sock);
                    250:                        sock = -1;
                    251:                        goto retry;
                    252:                }
                    253:                if (rc != 0) {
                    254:                        /* try next family */
                    255:                        close(sock);
                    256:                        sock = -1;
                    257:                        continue;
                    258:                }
                    259:                /* connect OK */
                    260:                break;
                    261:        }
                    262:        freeaddrinfo(res0);
                    263: 
                    264:        if (sock < 0) {
                    265:                return -1;
                    266:        }
                    267:        return sock;
                    268: }
                    269: 
                    270: int
                    271: istgt_set_recvtimeout(int s, int msec)
                    272: {
                    273:        struct timeval tv;
                    274:        int rc;
                    275: 
                    276:        memset(&tv, 0, sizeof tv);
                    277:        tv.tv_sec = msec / 1000;
                    278:        tv.tv_usec = (msec % 1000) * 1000;
                    279:        rc = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
                    280:        if (rc != 0)
                    281:                return -1;
                    282:        return 0;
                    283: }
                    284: 
                    285: int
                    286: istgt_set_sendtimeout(int s, int msec)
                    287: {
                    288:        struct timeval tv;
                    289:        int rc;
                    290: 
                    291:        memset(&tv, 0, sizeof tv);
                    292:        tv.tv_sec = msec / 1000;
                    293:        tv.tv_usec = (msec % 1000) * 1000;
                    294:        rc = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
                    295:        if (rc != 0)
                    296:                return -1;
                    297:        return 0;
                    298: }
                    299: 
1.1.1.3 ! misho     300: int
        !           301: istgt_set_recvlowat(int s, int nbytes)
        !           302: {
        !           303:        int val;
        !           304:        int rc;
        !           305: 
        !           306:        val = nbytes;
        !           307:        rc = setsockopt(s, SOL_SOCKET, SO_RCVLOWAT, &val, sizeof val);
        !           308:        if (rc != 0)
        !           309:                return -1;
        !           310:        return 0;
        !           311: }
        !           312: 
1.1       misho     313: #ifdef USE_POLLWAIT
                    314: static int
                    315: can_read_socket(int s, int msec)
                    316: {
                    317:        struct pollfd fds[1];
                    318:        int rc;
                    319: 
                    320:        fds[0].fd = s;
                    321:        fds[0].events = POLLIN;
                    322:  retry:
                    323:        do {
                    324:                rc = poll(fds, 1, msec);
                    325:        } while (rc == -1 && errno == EINTR);
                    326:        if (rc == -1 && errno == EAGAIN) {
                    327:                goto retry;
                    328:        }
                    329:        if (rc < 0) {
                    330:                /* error */
                    331:                return -1;
                    332:        }
                    333:        if (fds[0].revents & POLLIN) {
                    334:                /* read OK */
                    335:                return 1;
                    336:        }
                    337:        return 0;
                    338: }
                    339: 
                    340: static int
                    341: can_write_socket(int s, int msec)
                    342: {
                    343:        struct pollfd fds[1];
                    344:        int rc;
                    345: 
                    346:        fds[0].fd = s;
                    347:        fds[0].events = POLLOUT;
                    348:  retry:
                    349:        do {
                    350:                rc = poll(fds, 1, msec);
                    351:        } while (rc == -1 && errno == EINTR);
                    352:        if (rc == -1 && errno == EAGAIN) {
                    353:                goto retry;
                    354:        }
                    355:        if (rc < 0) {
                    356:                /* error */
                    357:                return -1;
                    358:        }
                    359:        if (fds[0].revents & POLLOUT) {
                    360:                /* write OK */
                    361:                return 1;
                    362:        }
                    363:        return 0;
                    364: }
                    365: #endif /* USE_POLLWAIT */
                    366: 
1.1.1.2   misho     367: #ifdef USE_POLLWAIT
                    368: #define UNUSED_POLLWAIT(x) x
                    369: #else
                    370: #define UNUSED_POLLWAIT(x) x __attribute__((__unused__))
                    371: #endif
                    372: 
1.1       misho     373: ssize_t
1.1.1.2   misho     374: istgt_read_socket(int s, void *buf, size_t nbytes, int UNUSED_POLLWAIT(timeout))
1.1       misho     375: {
                    376:        ssize_t n;
                    377: #ifdef USE_POLLWAIT
                    378:        int msec = POLLWAIT;
                    379:        int rc;
                    380: #endif /* USE_POLLWAIT */
                    381: 
                    382:        if (nbytes == 0)
                    383:                return 0;
                    384: 
                    385: #ifdef USE_POLLWAIT
                    386:        msec = timeout * 1000;
                    387:        rc = can_read_socket(s, msec);
                    388:        if (rc < 0) {
                    389:                return -1;
                    390:        }
                    391:        if (rc == 0) {
                    392:                /* TIMEOUT */
                    393:                return -2;
                    394:        }
                    395:  retry:
                    396:        do {
                    397:                n = read(s, buf, nbytes);
                    398:        } while (n == -1 && errno == EINTR);
                    399:        if (n == -1 && errno == EAGAIN) {
                    400:                goto retry;
                    401:        }
                    402:        if (n < 0) {
                    403:                return -1;
                    404:        }
                    405: #else
                    406:        do {
                    407:                n = recv(s, buf, nbytes, 0);
                    408:        } while (n == -1 && errno == EINTR);
                    409:        if (n == -1 && errno == EAGAIN) {
                    410:                /* TIMEOUT */
                    411:                return -2;
                    412:        }
                    413:        if (n == -1) {
                    414:                return -1;
                    415:        }
                    416: #endif /* USE_POLLWAIT */
                    417:        return n;
                    418: }
                    419: 
                    420: ssize_t
1.1.1.2   misho     421: istgt_write_socket(int s, const void *buf, size_t nbytes, int UNUSED_POLLWAIT(timeout))
1.1       misho     422: {
                    423:        ssize_t n;
                    424: #ifdef USE_POLLWAIT
                    425:        int msec = POLLWAIT;
                    426:        int rc;
                    427: #endif /* USE_POLLWAIT */
                    428: 
                    429:        if (nbytes == 0)
                    430:                return 0;
                    431: 
                    432: #ifdef USE_POLLWAIT
                    433:        msec = timeout * 1000;
                    434:        rc = can_write_socket(s, msec);
                    435:        if (rc < 0) {
                    436:                return -1;
                    437:        }
                    438:        if (rc == 0) {
                    439:                /* TIMEOUT */
                    440:                return -2;
                    441:        }
                    442:  retry:
                    443:        do {
                    444:                n = write(s, buf, nbytes);
                    445:        } while (n == -1 && errno == EINTR);
                    446:        if (n == -1 && errno == EAGAIN) {
                    447:                goto retry;
                    448:        }
                    449:        if (n < 0) {
                    450:                return -1;
                    451:        }
                    452: #else
                    453:        do {
                    454:                n = send(s, buf, nbytes, 0);
                    455:        } while (n == -1 && (errno == EINTR || errno == EAGAIN));
                    456:        if (n == -1) {
                    457:                return -1;
                    458:        }
                    459: #endif /* USE_POLLWAIT */
                    460:        return n;
                    461: }
                    462: 
                    463: ssize_t
                    464: istgt_readline_socket(int sock, char *buf, size_t size, char *tmp, size_t tmpsize, int *tmpidx, int *tmpcnt, int timeout)
                    465: {
                    466:        unsigned char *up, *utp;
                    467:        ssize_t maxsize;
                    468:        ssize_t total;
                    469:        ssize_t n;
                    470:        int got_cr;
                    471:        int idx, cnt;
                    472:        int ch;
                    473: 
                    474:        if (size < 2) {
                    475:                return -1;
                    476:        }
                    477: 
                    478:        up = (unsigned char *) buf;
                    479:        utp = (unsigned char *) tmp;
                    480:        maxsize = size - 2; /* LF + NUL */
                    481:        total = 0;
                    482:        idx = *tmpidx;
                    483:        cnt = *tmpcnt;
                    484:        got_cr = 0;
                    485: 
                    486:        /* receive with LF */
                    487:        while (total < maxsize) {
                    488:                /* fill temporary buffer */
                    489:                if (idx == cnt) {
                    490:                        *tmpidx = idx;
                    491:                        up[total] = '\0';
                    492:                        n = istgt_read_socket(sock, tmp, tmpsize, timeout);
                    493:                        if (n < 0) {
                    494:                                if (total != 0) {
                    495:                                        up[total] = '\0';
                    496:                                        return total;
                    497:                                }
                    498:                                return -1;
                    499:                        }
                    500:                        if (n == 0) {
                    501:                                /* EOF */
                    502:                                up[total] = '\0';
                    503:                                return total;
                    504:                        }
                    505:                        /* got n bytes */
                    506:                        cnt = *tmpcnt = n;
                    507:                        idx = 0;
                    508:                }
                    509: 
                    510:                /* copy from temporary until LF */
                    511:                ch = utp[idx++];
                    512:                if (got_cr && ch != '\n') {
                    513:                        /* CR only */
                    514:                        /* back to temporary */
                    515:                        idx--;
                    516:                        /* remove CR */
                    517:                        total--;
                    518:                        break;
                    519:                } else if (ch == '\n') {
                    520:                        if (got_cr) {
                    521:                                /* CRLF */
                    522:                                /* remove CR */
                    523:                                total--;
                    524:                        } else {
                    525:                                /* LF only */
                    526:                        }
                    527:                        break;
                    528:                } else if (ch == '\r') {
                    529:                        got_cr = 1;
                    530:                }
                    531:                up[total++] = ch;
                    532:        }
                    533:        *tmpidx = idx;
                    534:        /* always append LF + NUL */
                    535:        up[total++] = '\n';
                    536:        up[total] = '\0';
                    537:        return total;
                    538: }
                    539: 
                    540: static ssize_t
                    541: istgt_allwrite_socket(int s, const void *buf, size_t nbytes, int timeout)
                    542: {
                    543:        const uint8_t *cp;
                    544:        size_t total;
                    545:        ssize_t n;
                    546: 
                    547:        total = 0;
                    548:        cp = (const uint8_t *) buf;
                    549:        do {
                    550:                n = istgt_write_socket(s, cp + total, (nbytes - total), timeout);
                    551:                if (n < 0) {
                    552:                        return n;
                    553:                }
                    554:                total += n;
                    555:        } while (total < nbytes);
                    556:        return total;
                    557: }
                    558: 
                    559: ssize_t
                    560: istgt_writeline_socket(int sock, const char *buf, int timeout)
                    561: {
                    562:        const unsigned char *up;
                    563:        ssize_t total;
                    564:        ssize_t n;
                    565:        int idx;
                    566:        int ch;
                    567: 
                    568:        up = (const unsigned char *) buf;
                    569:        total = 0;
                    570:        idx = 0;
                    571: 
                    572:        if (up[0] == '\0') {
                    573:                /* empty string */
                    574:                n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
                    575:                if (n < 0) {
                    576:                        return -1;
                    577:                }
                    578:                if (n != 2) {
                    579:                        return -1;
                    580:                }
                    581:                total = n;
                    582:                return total;
                    583:        }
                    584: 
                    585:        /* send with CRLF */
                    586:        while ((ch = up[idx]) != '\0') {
                    587:                if (ch == '\r') {
                    588:                        if (up[idx + 1] == '\n') {
                    589:                                /* CRLF */
                    590:                                n = istgt_allwrite_socket(sock, up, idx + 2, timeout);
                    591:                                if (n < 0) {
                    592:                                        return -1;
                    593:                                }
                    594:                                if (n != idx + 2) {
                    595:                                        return -1;
                    596:                                }
                    597:                                idx += 2;
                    598:                        } else {
                    599:                                /* CR Only */
                    600:                                n = istgt_allwrite_socket(sock, up, idx, timeout);
                    601:                                if (n < 0) {
                    602:                                        return -1;
                    603:                                }
                    604:                                if (n != idx) {
                    605:                                        return -1;
                    606:                                }
                    607:                                idx += 1;
                    608:                                n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
                    609:                                if (n < 0) {
                    610:                                        return -1;
                    611:                                }
                    612:                                if (n != 2) {
                    613:                                        return -1;
                    614:                                }
                    615:                        }
                    616:                } else if (ch == '\n') {
                    617:                        /* LF Only */
                    618:                        n = istgt_allwrite_socket(sock, up, idx, timeout);
                    619:                        if (n < 0) {
                    620:                                return -1;
                    621:                        }
                    622:                        if (n != idx) {
                    623:                                return -1;
                    624:                        }
                    625:                        idx += 1;
                    626:                        n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
                    627:                        if (n < 0) {
                    628:                                return -1;
                    629:                        }
                    630:                        if (n != 2) {
                    631:                                return -1;
                    632:                        }
                    633:                } else {
                    634:                        idx++;
                    635:                        continue;
                    636:                }
                    637:                up += idx;
                    638:                total += idx;
                    639:                idx = 0;
                    640:        }
                    641: 
                    642:        if (idx != 0) {
                    643:                /* no CRLF string */
                    644:                n = istgt_allwrite_socket(sock, up, idx, timeout);
                    645:                if (n < 0) {
                    646:                        return -1;
                    647:                }
                    648:                if (n != idx) {
                    649:                        return -1;
                    650:                }
                    651:                n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
                    652:                if (n < 0) {
                    653:                        return -1;
                    654:                }
                    655:                if (n != 2) {
                    656:                        return -1;
                    657:                }
                    658:                up += idx;
                    659:                total += idx + 2;
                    660:                idx = 0;
                    661:        }
                    662: 
                    663:        return total;
                    664: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>