Changeset 2050

Show
Ignore:
Timestamp:
05/26/07 16:03:07
Author:
pvanhoof
Message:

Experimental connection recovery

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r2048 r2050  
     12007-05-26  Philip Van Hoof  <pvanhoof@gnome.org> 
     2 
     3        * Experimental connection recovery for IMAP 
     4        * Letting IDLE support cope with connection failures 
     5 
    162007-05-25  Philip Van Hoof  <pvanhoof@gnome.org> 
    27 
  • trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.c

    r1943 r2050  
    501501                fdmax = fd + 1; 
    502502                tv.tv_sec = 0; 
     503                tv.tv_usec = 0; 
     504                nread = -1; 
     505 
     506                res = select(fdmax, &rdset, 0, 0, &tv); 
     507                if (res == -1) 
     508                        ; 
     509                else if (res == 0) 
     510                        errno = ETIMEDOUT; 
     511                else { 
     512                        do { 
     513                                nread = read (fd, buf, n); 
     514                        } while (0 && (nread == -1 && errno == EINTR)); 
     515                } 
     516        } while (0 && (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))); 
     517 
     518        errnosav = errno; 
     519        fcntl (fd, F_SETFL, flags); 
     520        errno = errnosav; 
     521 
     522        return nread; 
     523} 
     524 
     525 
     526 
     527ssize_t 
     528camel_read_idle (int fd, char *buf, size_t n) 
     529{ 
     530        ssize_t nread; 
     531 
     532        int errnosav, flags, fdmax; 
     533        fd_set rdset; 
     534         
     535        flags = fcntl (fd, F_GETFL); 
     536        fcntl (fd, F_SETFL, flags | O_NONBLOCK); 
     537         
     538        do { 
     539                struct timeval tv; 
     540                int res; 
     541 
     542                FD_ZERO (&rdset); 
     543                FD_SET (fd, &rdset); 
     544                fdmax = fd + 1; 
     545                tv.tv_sec = 5; 
    503546                tv.tv_usec = 0; 
    504547                nread = -1; 
     
    685728} 
    686729 
     730 
     731ssize_t 
     732camel_read_socket_idle (int fd, char *buf, size_t n) 
     733{ 
     734#ifndef G_OS_WIN32 
     735        return camel_read_idle (fd, buf, n); 
     736#else 
     737        ssize_t nread; 
     738        int cancel_fd; 
     739         
     740        if (camel_operation_cancel_check (NULL)) { 
     741                errno = EINTR; 
     742                return -1; 
     743        } 
     744        cancel_fd = camel_operation_cancel_fd (NULL); 
     745 
     746        if (cancel_fd == -1) { 
     747                do { 
     748                        nread = recv (fd, buf, n, 0); 
     749                } while ((nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)); 
     750        } else { 
     751                int fdmax; 
     752                fd_set rdset; 
     753                u_long yes = 1; 
     754 
     755                ioctlsocket (fd, FIONBIO, &yes); 
     756                fdmax = MAX (fd, cancel_fd) + 1; 
     757                do { 
     758                        struct timeval tv; 
     759                        int res; 
     760 
     761                        FD_ZERO (&rdset); 
     762                        FD_SET (fd, &rdset); 
     763                        FD_SET (cancel_fd, &rdset); 
     764                        tv.tv_sec = 1; 
     765                        tv.tv_usec = 0; 
     766                        nread = -1; 
     767 
     768                        res = select(fdmax, &rdset, 0, 0, &tv); 
     769                        if (res == -1) 
     770                                ; 
     771                        else if (res == 0) 
     772                                errno = ETIMEDOUT; 
     773                        else if (FD_ISSET (cancel_fd, &rdset)) { 
     774                                errno = EINTR; 
     775                                goto failed; 
     776                        } else {                                 
     777                                nread = recv (fd, buf, n, 0); 
     778                        } 
     779                } while ((nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK)); 
     780        failed: 
     781                ; 
     782        } 
     783         
     784        return nread; 
     785#endif 
     786} 
    687787ssize_t 
    688788camel_read_socket_nb (int fd, char *buf, size_t n) 
     
    741841#endif 
    742842} 
     843 
     844 
    743845 
    744846/** 
  • trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.h

    r1943 r2050  
    7474ssize_t camel_write (int fd, const char *buf, size_t n); 
    7575 
    76 ssize_t camel_read_socket (int fd, char *buf, size_t n); 
     76ssize_t camel_read_socket_idle (int fd, char *buf, size_t n); 
    7777ssize_t camel_write_socket (int fd, const char *buf, size_t n); 
    7878 
     79ssize_t camel_read_socket (int fd, char *buf, size_t n); 
    7980ssize_t camel_read_socket_nb (int fd, char *buf, size_t n); 
    8081 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.c

    r1943 r2050  
    430430 
    431431 
     432 
    432433int 
    433 camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max) 
     434camel_stream_buffer_gets_idle (CamelStreamBuffer *sbf, char *buf, unsigned int max) 
    434435{ 
    435436        register char *outptr, *inptr, *inend, c, *outend; 
     
    454455                        break; 
    455456 
     457                bytes_read = camel_stream_read_idle (sbf->stream, (char*)sbf->buf, sbf->size); 
     458                if (bytes_read == -1) { 
     459                        if (buf == outptr) 
     460                                return -1; 
     461                        else 
     462                                bytes_read = 0; 
     463                } 
     464                sbf->ptr = sbf->buf; 
     465                sbf->end = sbf->buf + bytes_read; 
     466                inptr = (char*)sbf->ptr; 
     467                inend = (char*)sbf->end; 
     468        } while (bytes_read>0); 
     469 
     470        sbf->ptr = (unsigned char*)inptr; 
     471        *outptr = 0; 
     472 
     473        return (int)(outptr - buf); 
     474} 
     475 
     476int 
     477camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max) 
     478{ 
     479        register char *outptr, *inptr, *inend, c, *outend; 
     480        int bytes_read; 
     481 
     482        outptr = buf; 
     483        inptr = (char*)sbf->ptr; 
     484        inend = (char*)sbf->end; 
     485        outend = buf+max-1;     /* room for NUL */ 
     486 
     487        do { 
     488                while (inptr<inend && outptr<outend) { 
     489                        c = *inptr++; 
     490                        *outptr++ = c; 
     491                        if (c == '\n') { 
     492                                *outptr = 0; 
     493                                sbf->ptr = (unsigned char*) inptr; 
     494                                return outptr-buf; 
     495                        } 
     496                } 
     497                if (outptr == outend) 
     498                        break; 
     499 
    456500                bytes_read = camel_tcp_stream_read_nb ((CamelTcpStream *)sbf->stream, (char*)sbf->buf, sbf->size); 
    457501                if (bytes_read == -1) { 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.h

    r1943 r2050  
    9696char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf); 
    9797int camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max); 
     98int camel_stream_buffer_gets_idle (CamelStreamBuffer *sbf, char *buf, unsigned int max); 
     99 
    98100 
    99101G_END_DECLS 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream.c

    r1014 r2050  
    9797         
    9898        return (CS_CLASS (stream)->read) (stream, buffer, n); 
     99} 
     100 
     101ssize_t 
     102camel_stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
     103{ 
     104        g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); 
     105        g_return_val_if_fail (n == 0 || buffer, -1); 
     106 
     107        /* Default impl */ 
     108        if (!CS_CLASS (stream)->read_idle) 
     109                return (CS_CLASS (stream)->read) (stream, buffer, n); 
     110 
     111        return (CS_CLASS (stream)->read_idle) (stream, buffer, n); 
    99112} 
    100113 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream.h

    r1943 r2050  
    5757        int       (*reset)      (CamelStream *stream); 
    5858 
     59        ssize_t   (*read_idle)  (CamelStream *stream, char *buffer, size_t n); 
     60 
    5961} CamelStreamClass; 
    6062 
     
    6365 
    6466/* public methods */ 
     67ssize_t    camel_stream_read_idle  (CamelStream *stream, char *buffer, size_t n); 
     68 
    6569ssize_t    camel_stream_read       (CamelStream *stream, char *buffer, size_t n); 
    6670ssize_t    camel_stream_write      (CamelStream *stream, const char *buffer, size_t n); 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c

    r1943 r2050  
    6666static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); 
    6767static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); 
     68static ssize_t stream_read_idle (CamelStream *stream, char *buffer, size_t n); 
    6869 
    6970static void signal_swallow( int num ) 
     
    8586 
    8687        /* virtual method overload */ 
     88        camel_stream_class->read_idle = stream_read_idle; 
    8789        camel_stream_class->read = stream_read; 
    8890        camel_stream_class->write = stream_write; 
    8991        camel_stream_class->flush = stream_flush; 
    9092        camel_stream_class->close = stream_close; 
    91          
     93 
    9294        camel_tcp_stream_class->read_nb = stream_read_nb; 
    9395        camel_tcp_stream_class->connect = stream_connect; 
     
    263265} 
    264266 
     267 
     268static ssize_t  
     269stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
     270{ 
     271        CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); 
     272         
     273        return camel_read_socket_idle (raw->sockfd, buffer, n); 
     274} 
     275 
    265276static ssize_t 
    266277stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n) 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-ssl.c

    r1943 r2050  
    8888static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); 
    8989static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); 
     90static ssize_t stream_read_idle (CamelStream *stream, char *buffer, size_t n); 
    9091 
    9192struct _CamelTcpStreamSSLPrivate { 
     
    110111         
    111112        /* virtual method overload */ 
     113        camel_stream_class->read_idle = stream_read_idle; 
     114 
    112115        camel_stream_class->read = stream_read; 
    113116        camel_stream_class->write = stream_write; 
     
    475478        return nread; 
    476479} 
     480 
     481 
     482 
     483static ssize_t  
     484stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
     485{ 
     486        CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); 
     487        PRFileDesc *cancel_fd; 
     488        ssize_t nread; 
     489         
     490        if (camel_operation_cancel_check (NULL)) { 
     491                errno = EINTR; 
     492                return -1; 
     493        } 
     494         
     495        cancel_fd = camel_operation_cancel_prfd (NULL); 
     496        if (cancel_fd == NULL) { 
     497                do { 
     498                        nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 
     499                        if (nread == -1) 
     500                                set_errno (PR_GetError ()); 
     501                } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || 
     502                                         PR_GetError () == PR_IO_PENDING_ERROR || 
     503                                         PR_GetError () == PR_WOULD_BLOCK_ERROR)); 
     504        } else { 
     505                PRSocketOptionData sockopts; 
     506                PRPollDesc pollfds[2]; 
     507                gboolean nonblock; 
     508                int error; 
     509                 
     510                /* get O_NONBLOCK options */ 
     511                sockopts.option = PR_SockOpt_Nonblocking; 
     512                PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
     513                sockopts.option = PR_SockOpt_Nonblocking; 
     514                nonblock = sockopts.value.non_blocking; 
     515                sockopts.value.non_blocking = TRUE; 
     516                PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
     517 
     518                pollfds[0].fd = tcp_stream_ssl->priv->sockfd; 
     519                pollfds[0].in_flags = PR_POLL_READ; 
     520                pollfds[1].fd = cancel_fd; 
     521                pollfds[1].in_flags = PR_POLL_READ; 
     522                 
     523                do { 
     524                        PRInt32 res; 
     525 
     526                        pollfds[0].out_flags = 0; 
     527                        pollfds[1].out_flags = 0; 
     528                        nread = -1; 
     529 
     530                        res = PR_Poll(pollfds, 2, 5); 
     531 
     532                        if (res == -1) 
     533                                set_errno(PR_GetError()); 
     534                        else if (res == 0) { 
     535#ifdef ETIMEDOUT 
     536                                errno = ETIMEDOUT; 
     537#else 
     538                                errno = EIO; 
     539#endif 
     540                        } else if (pollfds[1].out_flags == PR_POLL_READ) { 
     541                                errno = EINTR; 
     542                                goto failed; 
     543                        } else { 
     544                                do { 
     545                                        nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 
     546                                        if (nread == -1) 
     547                                                set_errno (PR_GetError ()); 
     548                                } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 
     549                        } 
     550                } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || 
     551                                         PR_GetError () == PR_IO_PENDING_ERROR || 
     552                                         PR_GetError () == PR_WOULD_BLOCK_ERROR)); 
     553                 
     554                /* restore O_NONBLOCK options */ 
     555        failed: 
     556                error = errno; 
     557                sockopts.option = PR_SockOpt_Nonblocking; 
     558                sockopts.value.non_blocking = nonblock; 
     559                PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
     560                errno = error; 
     561        } 
     562         
     563        return nread; 
     564} 
     565 
    477566 
    478567static ssize_t 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream.c

    r1548 r2050  
    9191} 
    9292 
     93 
     94 
    9395static int 
    9496tcp_connect (CamelTcpStream *stream, struct addrinfo *host) 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream.h

    r1943 r2050  
    108108        struct sockaddr * (*get_remote_address) (CamelTcpStream *stream, socklen_t *len); 
    109109        ssize_t (*read_nb)   (CamelTcpStream *stream, char *buffer, size_t n); 
    110          
    111110} CamelTcpStreamClass; 
    112111 
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c

    r2041 r2050  
    6161                                         const char *fmt, ...); 
    6262 
    63  
     63static char * imap_read_untagged_idle (CamelImapStore *store, char *line, CamelException *ex); 
    6464 
    6565 
     
    444444        char *respbuf; 
    445445 
    446         if (camel_imap_store_readline (store, &respbuf, ex) < 0) 
     446        if (camel_imap_store_readline_idle (store, &respbuf, ex) < 0) 
    447447                return CAMEL_IMAP_RESPONSE_ERROR; 
    448448 
     
    464464                /* Read the rest of the response. */ 
    465465                type = CAMEL_IMAP_RESPONSE_UNTAGGED; 
    466                 respbuf = imap_read_untagged (store, respbuf, ex); 
     466                respbuf = imap_read_untagged_idle (store, respbuf, ex); 
    467467                if (!respbuf) 
    468468                        type = CAMEL_IMAP_RESPONSE_ERROR; 
     
    708708} 
    709709 
     710 
     711 
     712static char * 
     713imap_read_untagged_idle (CamelImapStore *store, char *line, CamelException *ex) 
     714{ 
     715        int fulllen, ldigits, nread, n, i, sexp = 0; 
     716        unsigned int length; 
     717        GPtrArray *data; 
     718        GString *str; 
     719        char *end, *p, *s, *d; 
     720         
     721        p = strrchr (line, '{'); 
     722        if (!p) 
     723                return line; 
     724         
     725        data = g_ptr_array_new (); 
     726        fulllen = 0; 
     727         
     728        while (1) { 
     729                str = g_string_new (line); 
     730                g_free (line); 
     731                fulllen += str->len; 
     732                g_ptr_array_add (data, str); 
     733                 
     734                if (!(p = strrchr (str->str, '{')) || p[1] == '-') 
     735                        break; 
     736                 
     737                /* HACK ALERT: We scan the non-literal part of the string, looking for possible s expression braces. 
     738                   This assumes we're getting s-expressions, which we should be. 
     739                   This is so if we get a blank line after a literal, in an s-expression, we can keep going, since 
     740                   we do no other parsing at this level. 
     741                   TODO: handle quoted strings? */ 
     742                for (s=str->str; s<p; s++) { 
     743                        if (*s == '(') 
     744                                sexp++; 
     745                        else if (*s == ')') 
     746                                sexp--; 
     747                } 
     748                 
     749                length = strtoul (p + 1, &end, 10); 
     750                if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2) 
     751                        break; 
     752                ldigits = end - (p + 1); 
     753                 
     754                /* Read the literal */ 
     755                str = g_string_sized_new (length + 2); 
     756                str->str[0] = '\n'; 
     757                nread = 0; 
     758                 
     759                do { 
     760                        if ((n = camel_stream_read_idle (store->istream, str->str + nread + 1, length - nread)) == -1) { 
     761                                if (errno == EINTR) 
     762                                        camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, 
     763                                                             _("Operation cancelled")); 
     764                                else 
     765                                        camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 
     766                                                             g_strerror (errno)); 
     767                                camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 
     768                                g_string_free (str, TRUE); 
     769                                goto lose; 
     770                        } 
     771                         
     772                        nread += n; 
     773                } while (n > 0 && nread < length); 
     774                 
     775                if (nread < length) { 
     776                        camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 
     777                                             _("Server response ended too soon.")); 
     778                        camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 
     779                        g_string_free (str, TRUE); 
     780                        goto lose; 
     781                } 
     782                str->str[length + 1] = '\0'; 
     783 
     784                if (camel_debug("imap")) { 
     785                        printf("Literal: -->"); 
     786                        fwrite(str->str+1, 1, length, stdout); 
     787                        printf("<--\n"); 
     788                } 
     789                 
     790                /* Fix up the literal, turning CRLFs into LF. Also, if 
     791                 * we find any embedded NULs, strip them. This is 
     792                 * dubious, but: 
     793                 *   - The IMAP grammar says you can't have NULs here 
     794                 *     anyway, so this will not affect our behavior 
     795                 *     against any completely correct server. 
     796                 *   - WU-imapd 12.264 (at least) will cheerily pass 
     797                 *     NULs along if they are embedded in the message 
     798                 */ 
     799                 
     800                s = d = str->str + 1; 
     801                end = str->str + 1 + length; 
     802                while (s < end) { 
     803                        while (s < end && *s == '\0') { 
     804                                s++; 
     805                                length--; 
     806                        } 
     807                        if (*s == '\r' && *(s + 1) == '\n') { 
     808                                s++; 
     809                                length--; 
     810                        } 
     811                        *d++ = *s++; 
     812                } 
     813                *d = '\0'; 
     814                str->len = length + 1; 
     815                 
     816                /* p points to the "{" in the line that starts the 
     817                 * literal. The length of the CR-less response must be 
     818                 * less than or equal to the length of the response 
     819                 * with CRs, therefore overwriting the old value with 
     820                 * the new value cannot cause an overrun. However, we 
     821                 * don't want it to be shorter either, because then the 
     822                 * GString's length would be off... 
     823                 */ 
     824                sprintf (p, "{%0*u}", ldigits, length); 
     825                 
     826                fulllen += str->len; 
     827                g_ptr_array_add (data, str); 
     828 
     829                /* Read the next line. */ 
     830                do { 
     831                        if (camel_imap_store_readline_idle (store, &line, ex) < 0) 
     832                                goto lose; 
     833 
     834                        /* MAJOR HACK ALERT, gropuwise sometimes sends an extra blank line after literals, check that here 
     835                           But only do it if we're inside an sexpression */ 
     836                        if (line[0] == 0 && sexp > 0) 
     837                                g_warning("Server sent empty line after a literal, assuming in error"); 
     838                } while (line[0] == 0 && sexp > 0); 
     839        } 
     840         
     841        /* Now reassemble the data. */ 
     842        p = line = g_malloc (fulllen + 1); 
     843        for (i = 0; i < data->len; i++) { 
     844                str = data->pdata[i]; 
     845                memcpy (p, str->str, str->len); 
     846                p += str->len; 
     847                g_string_free (str, TRUE); 
     848        } 
     849        *p = '\0'; 
     850        g_ptr_array_free (data, TRUE); 
     851        return line; 
     852         
     853 lose: 
     854        for (i = 0; i < data->len; i++) 
     855                g_string_free (data->pdata[i], TRUE); 
     856        g_ptr_array_free (data, TRUE); 
     857        return NULL; 
     858} 
    710859 
    711860/** 
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c

    r2041 r2050  
    33993399 
    34003400        g_mutex_lock (store->stream_lock); 
    3401         store->idle_prefix = g_strdup_printf ("%c%.5u",  
    3402                 store->tag_prefix, store->command++); 
    3403         camel_stream_printf (store->ostream, "%s IDLE\r\n", 
    3404                 store->idle_prefix); 
     3401        if (store->ostream && store->istream && CAMEL_IS_STREAM (store->ostream)) 
     3402        { 
     3403                store->idle_prefix = g_strdup_printf ("%c%.5u",  
     3404                        store->tag_prefix, store->command++); 
     3405                camel_stream_printf (store->ostream, "%s IDLE\r\n", 
     3406                        store->idle_prefix); 
     3407        } else { 
     3408                idle_debug ("idle_real_start connection lost\n"); 
     3409                goto errh; 
     3410        } 
    34053411 
    34063412        /* The IDLE command is sent from the client to the server when the 
     
    34353441                g_free (resp); 
    34363442 
     3443errh: 
    34373444        g_mutex_unlock (store->stream_lock); 
    34383445 
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c

    r2049 r2050  
    37433743 
    37443744 
     3745 
     3746/* FIXME: please god, when will the hurting stop? Thus function is so 
     3747   fucking broken it's not even funny. */ 
    37453748ssize_t 
    3746 camel_imap_store_readline_nl (CamelImapStore *store, char **dest, CamelException *ex) 
     3749camel_imap_store_readline_idle (CamelImapStore *store, char **dest, CamelException *ex) 
    37473750{ 
    37483751        CamelStreamBuffer *stream; 
     
    37643767                return -1; 
    37653768 
     3769        g_mutex_lock (store->stream_lock); 
    37663770        camel_imap_store_restore_stream_buffer (store); 
    3767  
    3768         if (!store->istream) 
    3769                 return -1; 
    3770  
    37713771        stream = CAMEL_STREAM_BUFFER (store->istream); 
    37723772 
    37733773        ba = g_byte_array_new (); 
    3774         while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) { 
     3774        while ((nread = camel_stream_buffer_gets_idle (stream, linebuf, sizeof (linebuf))) > 0) { 
    37753775                g_byte_array_append (ba, (const guchar*) linebuf, nread); 
    37763776                if (linebuf[nread - 1] == '\n') 
    37773777                        break; 
    37783778        } 
     3779        g_mutex_unlock (store->stream_lock); 
    37793780 
    37803781        if (nread <= 0) { 
     
    38173818 
    38183819ssize_t 
     3820camel_imap_store_readline_nl (CamelImapStore *store, char **dest, CamelException *ex) 
     3821{ 
     3822        CamelStreamBuffer *stream; 
     3823        char linebuf[1024] = {0}; 
     3824        GByteArray *ba; 
     3825        ssize_t nread; 
     3826         
     3827        g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1); 
     3828        g_return_val_if_fail (dest, -1); 
     3829         
     3830        *dest = NULL; 
     3831         
     3832        /* Check for connectedness. Failed (or cancelled) operations will 
     3833         * close the connection. We can't expect a read to have any 
     3834         * meaning if we reconnect, so always set an exception. 
     3835         */ 
     3836 
     3837        if (!camel_disco_store_check_online((CamelDiscoStore *)store, ex)) 
     3838                return -1; 
     3839 
     3840        camel_imap_store_restore_stream_buffer (store); 
     3841 
     3842        if (!store->istream) 
     3843                return -1; 
     3844 
     3845        stream = CAMEL_STREAM_BUFFER (store->istream); 
     3846 
     3847        ba = g_byte_array_new (); 
     3848        while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) { 
     3849                g_byte_array_append (ba, (const guchar*) linebuf, nread); 
     3850                if (linebuf[nread - 1] == '\n') 
     3851                        break; 
     3852        } 
     3853 
     3854        if (nread <= 0) { 
     3855                if (errno == EINTR) 
     3856                { 
     3857                        CamelException mex = CAMEL_EXCEPTION_INITIALISER; 
     3858                        camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); 
     3859                        camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 
     3860                        camel_service_connect (CAMEL_SERVICE (store), &mex); 
     3861                } else { 
     3862                        camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 
     3863                                              _("Server unexpectedly disconnected: %s"), 
     3864                                              g_strerror (errno)); 
     3865                        camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 
     3866                } 
     3867 
     3868                g_byte_array_free (ba, TRUE); 
     3869                return -1; 
     3870        } 
     3871         
     3872        if (camel_verbose_debug) { 
     3873                fprintf (stderr, "received: "); 
     3874                fwrite (ba->data, 1, ba->len, stderr); 
     3875        } 
     3876         
     3877        /* camel-imap-command.c:imap_read_untagged expects the CRLFs 
     3878           to be stripped off and be nul-terminated *sigh* */ 
     3879        nread = ba->len - 1; 
     3880        ba->data[nread] = '\0'; 
     3881        if (ba->data[nread - 1] == '\r') { 
     3882                ba->data[nread - 1] = '\0'; 
     3883                nread--; 
     3884        } 
     3885         
     3886        *dest = (char *) ba->data; 
     3887        g_byte_array_free (ba, FALSE); 
     3888         
     3889        return nread; 
     3890} 
     3891 
     3892ssize_t 
    38193893camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex) 
    38203894{ 
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h

    r2000 r2050  
    180180ssize_t camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex); 
    181181ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex); 
     182ssize_t camel_imap_store_readline_idle (CamelImapStore *store, char **dest, CamelException *ex); 
    182183gboolean camel_imap_service_connect (CamelService *service, CamelException *ex); 
    183184