Back to index

courier  0.68.2
rfc1035tcp.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "config.h"
00007 #include      "rfc1035.h"
00008 #include      <stdio.h>
00009 #include      <string.h>
00010 #include      "soxwrap/soxwrap.h"
00011 #include      <sys/types.h>
00012 #include      <arpa/inet.h>
00013 #if    HAVE_UNISTD_H
00014 #include      <unistd.h>
00015 #endif
00016 #include      <stdlib.h>
00017 #include      <errno.h>
00018 #include      <fcntl.h>
00019 #if TIME_WITH_SYS_TIME
00020 #include      <sys/time.h>
00021 #include      <time.h>
00022 #else
00023 #if HAVE_SYS_TIME_H
00024 #include      <sys/time.h>
00025 #else
00026 #include      <time.h>
00027 #endif
00028 #endif
00029 
00030 
00031 int rfc1035_open_tcp(struct rfc1035_res *res, const RFC1035_ADDR *addr)
00032 {
00033 RFC1035_NETADDR addrbuf;
00034 int    af;
00035 const struct sockaddr *addrptr;
00036 int    addrptrlen;
00037 
00038 int    fd=rfc1035_mksocket(SOCK_STREAM, 0, &af);
00039 
00040        if (fd < 0)   return (-1);
00041 
00042        if (rfc1035_mkaddress(af, &addrbuf,
00043               addr, htons(53),
00044               &addrptr, &addrptrlen))
00045        {
00046               close(fd);
00047               return (-1);
00048        }
00049 
00050        if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NDELAY) < 0)
00051        {
00052               sox_close(fd);
00053               return (-1);
00054        }
00055 
00056        if (sox_connect(fd, addrptr, addrptrlen) == 0)
00057               return (fd);
00058 
00059        if (errno == EINPROGRESS || errno == EAGAIN)
00060        {
00061        unsigned      w=res->rfc1035_timeout_initial;
00062 
00063               if (!w)       w=RFC1035_DEFAULT_INITIAL_TIMEOUT;
00064               if (rfc1035_wait_query(fd, w) == 0 &&
00065                      (sox_connect(fd, addrptr, addrptrlen) == 0
00066                             || errno == EISCONN))
00067               {
00068                      return (fd);
00069               }
00070        }
00071        sox_close(fd);
00072        return (-1);
00073 }
00074 
00075 int rfc1035_send_tcp(int fd, const char *query, unsigned query_len)
00076 {
00077 int    n=query_len+2;
00078 char   *buf=malloc(n);
00079 char   *p;
00080 int    pl;
00081 
00082        if (!buf)     return (-1);
00083 
00084        buf[0]=query_len >> 8;
00085        buf[1]=query_len;
00086 
00087        memcpy(buf+2, query, query_len);
00088 
00089        p=buf;
00090        pl=n;
00091        while (pl)
00092        {
00093        int    i=sox_write(fd, p, pl);
00094 
00095               if (i < 0 && errno == EINTR)       continue;
00096               if (i <= 0)   break;
00097               p += i;
00098               pl -= i;
00099        }
00100        free(buf);
00101 
00102        if (pl)       return (-1);
00103        return (0);
00104 }
00105 
00106 static int doread(int fd, char *buf, int bufsize)
00107 {
00108 int    len;
00109 
00110        do
00111        {
00112               len=sox_read(fd, buf, bufsize);
00113        } while (len < 0 && errno == EINTR);
00114        return (len);
00115 }
00116 
00117 char *rfc1035_recv_tcp(struct rfc1035_res *res, int fd, int *buflen, unsigned w)
00118 {
00119 int    len;
00120 unsigned response_len;
00121 char lenbuf[2];
00122 char   *mallocedbuf=0;
00123 time_t current_time, finish_time;
00124 
00125        time(&current_time);
00126        finish_time=current_time+w;
00127 
00128        if (rfc1035_wait_reply(fd, w))
00129               return (0);
00130 
00131        len=doread(fd, lenbuf, 2);
00132        if (len <= 0)
00133        {
00134               errno=EIO;
00135               return (0);
00136        }
00137        if (len == 1)
00138        {
00139               time(&current_time);
00140               if (current_time >= finish_time)   return (0);
00141               if (rfc1035_wait_reply(fd, finish_time - current_time))
00142                      return (0);
00143 
00144               len=doread(fd, lenbuf+1, 1);
00145               if (len <= 0)
00146               {
00147                      errno=EIO;
00148                      return (0);
00149               }
00150               ++len;
00151        }
00152 
00153        response_len= ((unsigned)(unsigned char)lenbuf[0] << 8)
00154                      | (unsigned char)lenbuf[1];
00155 
00156        if ((mallocedbuf=malloc(response_len)) == 0)
00157               return (0);
00158 
00159        *buflen=0;
00160 
00161        while ((unsigned)*buflen < response_len)
00162        {
00163               time(&current_time);
00164               if (current_time >= finish_time ||
00165                      rfc1035_wait_reply(fd, finish_time - current_time))
00166               {
00167                      len=0;
00168                      errno=ETIMEDOUT;
00169               }
00170               else
00171                      len=doread(fd, mallocedbuf + *buflen,
00172                                           response_len - *buflen);
00173               if (len <= 0)
00174               {
00175                      free(mallocedbuf);
00176                      return (0);
00177               }
00178               *buflen += len;
00179        }
00180        return (mallocedbuf);
00181 }
00182 
00183 char *rfc1035_query_tcp(struct rfc1035_res *res,
00184        int fd, const char *query, unsigned query_len,
00185        int *buflen, unsigned s)
00186 {
00187 char   *p;
00188 
00189        if ( rfc1035_send_tcp(fd, query, query_len) < 0 ||
00190               (p=rfc1035_recv_tcp(res, fd, buflen, s)) == 0)
00191               return (0);
00192        return (p);
00193 }