"Fossies" - the Fresh Open Source Software Archive

Member "links-1.03/connect.c" (20 Nov 2011, 9145 Bytes) of archive /linux/www/links-1.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "connect.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8_vs_1.03.

    1 #include "links.h"
    2 
    3 /*
    4 #define LOG_TRANSFER    "/tmp/log"
    5 */
    6 
    7 #ifdef LOG_TRANSFER
    8 void log_data(unsigned char *data, int len)
    9 {
   10     int fd;
   11     if ((fd = open(LOG_TRANSFER, O_WRONLY | O_APPEND | O_CREAT, 0622)) != -1) {
   12         set_bin(fd);
   13         write(fd, data, len);
   14         close(fd);
   15     }
   16 }
   17 
   18 #else
   19 #define log_data(x, y)
   20 #endif
   21 
   22 void exception(struct connection *c)
   23 {
   24     setcstate(c, S_EXCEPT);
   25     retry_connection(c);
   26 }
   27 
   28 void close_socket(int *s)
   29 {
   30     if (*s == -1) return;
   31     close(*s);
   32     set_handlers(*s, NULL, NULL, NULL, NULL);
   33     *s = -1;
   34 }
   35 
   36 void connected(struct connection *);
   37 
   38 struct conn_info {
   39     void (*func)(struct connection *);
   40     struct sockaddr_in sa;
   41     ip addr;
   42     int port;
   43     int *sock;
   44 };
   45 
   46 void dns_found(struct connection *, int);
   47 
   48 void make_connection(struct connection *c, int port, int *sock, void (*func)(struct connection *))
   49 {
   50     int as;
   51     unsigned char *host;
   52     struct conn_info *b;
   53     if (!(host = get_host_name(c->url))) {
   54         setcstate(c, S_INTERNAL);
   55         abort_connection(c);
   56         return;
   57     }
   58     if (c->newconn)
   59         internal("already making a connection");
   60     b = mem_alloc(sizeof(struct conn_info));
   61     b->func = func;
   62     b->sock = sock;
   63     b->port = port;
   64     c->newconn = b;
   65     log_data("\nCONNECTION: ", 13);
   66     log_data(host, strlen(host));
   67     log_data("\n", 1);
   68     if (c->no_cache >= NC_RELOAD) as = find_host_no_cache(host, &b->addr, &c->dnsquery, (void(*)(void *, int))dns_found, c);
   69     else as = find_host(host, &b->addr, &c->dnsquery, (void(*)(void *, int))dns_found, c);
   70     mem_free(host);
   71     if (as) setcstate(c, S_DNS);
   72 }
   73 
   74 int get_pasv_socket(struct connection *c, int cc, int *sock, unsigned char *port)
   75 {
   76     int s;
   77     struct sockaddr_in sa;
   78     struct sockaddr_in sb;
   79     socklen_t len = sizeof(sa);
   80     memset(&sa, 0, sizeof sa);
   81     memset(&sb, 0, sizeof sb);
   82     if (getsockname(cc, (struct sockaddr *)&sa, &len)) {
   83         e:
   84         setcstate(c, get_error_from_errno(errno));
   85         retry_connection(c);
   86         return -1;
   87     }
   88     if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) goto e;
   89     *sock = s;
   90     fcntl(s, F_SETFL, O_NONBLOCK);
   91     memcpy(&sb, &sa, sizeof(struct sockaddr_in));
   92     sb.sin_port = 0;
   93     if (bind(s, (struct sockaddr *)&sb, sizeof sb)) goto e;
   94     len = sizeof(sa);
   95     if (getsockname(s, (struct sockaddr *)&sa, &len)) goto e;
   96     if (listen(s, 1)) goto e;
   97     memcpy(port, &sa.sin_addr.s_addr, 4);
   98     memcpy(port + 4, &sa.sin_port, 2);
   99     return 0;
  100 }
  101 
  102 #ifdef HAVE_SSL
  103 void ssl_want_read(struct connection *c)
  104 {
  105     struct conn_info *b = c->newconn;
  106 
  107     set_timeout(c);
  108 
  109     if (c->no_tsl) c->ssl->options |= SSL_OP_NO_TLSv1;
  110     switch (SSL_get_error(c->ssl, SSL_connect(c->ssl))) {
  111         case SSL_ERROR_NONE:
  112             c->newconn = NULL;
  113             b->func(c);
  114             mem_free(b);
  115             break;
  116         case SSL_ERROR_WANT_READ:
  117             set_handlers(*b->sock, (void(*)(void *))ssl_want_read, NULL, (void(*)(void *))exception, c);
  118             break;
  119         case SSL_ERROR_WANT_WRITE:
  120             set_handlers(*b->sock, NULL, (void(*)(void *))ssl_want_read, (void(*)(void *))exception, c);
  121             break;
  122         default:
  123             c->no_tsl++;
  124             setcstate(c, S_SSL_ERROR);
  125             retry_connection(c);
  126             break;
  127     }
  128 }
  129 #endif
  130 
  131 void dns_found(struct connection *c, int state)
  132 {
  133     int s;
  134     struct conn_info *b = c->newconn;
  135     if (state) {
  136         setcstate(c, S_NO_DNS);
  137         abort_connection(c);
  138         return;
  139     }
  140     if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
  141         setcstate(c, get_error_from_errno(errno));
  142         retry_connection(c);
  143         return;
  144     }
  145     *b->sock = s;
  146     fcntl(s, F_SETFL, O_NONBLOCK);
  147     memset(&b->sa, 0, sizeof(struct sockaddr_in));
  148     b->sa.sin_family = AF_INET;
  149     b->sa.sin_addr.s_addr = b->addr;
  150     b->sa.sin_port = htons(b->port);
  151     if (connect(s, (struct sockaddr *)&b->sa, sizeof b->sa)) {
  152         if (errno != EALREADY && errno != EINPROGRESS) {
  153 #ifdef BEOS
  154             if (errno == EWOULDBLOCK) errno = ETIMEDOUT;
  155 #endif
  156             setcstate(c, get_error_from_errno(errno));
  157             retry_connection(c);
  158             return;
  159         }
  160         set_handlers(s, NULL, (void(*)(void *))connected, (void(*)(void *))exception, c);
  161         setcstate(c, S_CONN);
  162     } else {
  163         connected(c);
  164     }
  165 }
  166 
  167 void connected(struct connection *c)
  168 {
  169     struct conn_info *b = c->newconn;
  170     int err = 0;
  171     socklen_t len = sizeof(int);
  172     if (getsockopt(*b->sock, SOL_SOCKET, SO_ERROR, (void *)&err, &len))
  173         if (!(err = errno)) {
  174             err = -(S_STATE);
  175             goto bla;
  176         }
  177     if (err >= 10000) err -= 10000; /* Why does EMX return so large values? */
  178     if (err > 0) {
  179         bla:
  180         setcstate(c, get_error_from_errno(err));
  181         retry_connection(c);
  182         return;
  183     }
  184     set_timeout(c);
  185 #ifdef HAVE_SSL
  186     if (c->ssl) {
  187         c->ssl = getSSL();
  188         SSL_set_fd(c->ssl, *b->sock);
  189         if (c->no_tsl) c->ssl->options |= SSL_OP_NO_TLSv1;
  190         switch (SSL_get_error(c->ssl, SSL_connect(c->ssl))) {
  191             case SSL_ERROR_WANT_READ:
  192                 setcstate(c, S_SSL_NEG);
  193                 set_handlers(*b->sock, (void(*)(void *))ssl_want_read, NULL, (void(*)(void *))exception, c);
  194                 return;
  195             case SSL_ERROR_WANT_WRITE:
  196                 setcstate(c, S_SSL_NEG);
  197                 set_handlers(*b->sock, NULL, (void(*)(void *))ssl_want_read, (void(*)(void *))exception, c);
  198                 return;
  199             case SSL_ERROR_NONE:
  200                 break;
  201             default:
  202                 c->no_tsl++;
  203                 setcstate(c, S_SSL_ERROR);
  204                 retry_connection(c);
  205                 return;
  206         }
  207     }
  208 #endif
  209     c->newconn = NULL;
  210     b->func(c);
  211     mem_free(b);
  212 }
  213 
  214 struct write_buffer {
  215     int sock;
  216     int len;
  217     int pos;
  218     void (*done)(struct connection *);
  219     unsigned char data[1];
  220 };
  221 
  222 void write_select(struct connection *c)
  223 {
  224     struct write_buffer *wb;
  225     int wr;
  226     if (!(wb = c->buffer)) {
  227         internal("write socket has no buffer");
  228         setcstate(c, S_INTERNAL);
  229         abort_connection(c);
  230         return;
  231     }
  232     set_timeout(c);
  233     /*printf("ws: %d\n",wb->len-wb->pos);
  234     for (wr = wb->pos; wr < wb->len; wr++) printf("%c", wb->data[wr]);
  235     printf("-\n");*/
  236 
  237 #ifdef HAVE_SSL
  238     if(c->ssl) {
  239         if ((wr = SSL_write(c->ssl, wb->data + wb->pos, wb->len - wb->pos)) <= 0) {
  240             int err;
  241             if ((err = SSL_get_error(c->ssl, wr)) != SSL_ERROR_WANT_WRITE) {
  242                 setcstate(c, wr ? (err == SSL_ERROR_SYSCALL ? get_error_from_errno(errno) : S_SSL_ERROR) : S_CANT_WRITE);
  243                 if (!wr || err == SSL_ERROR_SYSCALL) retry_connection(c);
  244                 else abort_connection(c);
  245                 return;
  246             }
  247             else return;
  248         }
  249     } else
  250 #endif
  251         if ((wr = write(wb->sock, wb->data + wb->pos, wb->len - wb->pos)) <= 0) {
  252 #ifdef ATHEOS
  253     /* Workaround for a bug in Syllable */
  254             if (wr && errno == EAGAIN) {
  255                 return;
  256             }
  257 #endif
  258             setcstate(c, wr ? get_error_from_errno(errno) : S_CANT_WRITE);
  259             retry_connection(c);
  260             return;
  261         }
  262 
  263     /*printf("wr: %d\n", wr);*/
  264     if ((wb->pos += wr) == wb->len) {
  265         void (*f)(struct connection *) = wb->done;
  266         c->buffer = NULL;
  267         set_handlers(wb->sock, NULL, NULL, NULL, NULL);
  268         mem_free(wb);
  269         f(c);
  270     }
  271 }
  272 
  273 void write_to_socket(struct connection *c, int s, unsigned char *data, int len, void (*write_func)(struct connection *))
  274 {
  275     struct write_buffer *wb;
  276     log_data(data, len);
  277     if ((unsigned)len > MAXINT - sizeof(struct write_buffer)) overalloc();
  278     wb = mem_alloc(sizeof(struct write_buffer) + len);
  279     wb->sock = s;
  280     wb->len = len;
  281     wb->pos = 0;
  282     wb->done = write_func;
  283     memcpy(wb->data, data, len);
  284     if (c->buffer) mem_free(c->buffer);
  285     c->buffer = wb;
  286     set_handlers(s, NULL, (void (*)(void *))write_select, (void (*)(void *))exception, c);
  287 }
  288 
  289 #define READ_SIZE   64240
  290 
  291 void read_select(struct connection *c)
  292 {
  293     struct read_buffer *rb;
  294     int rd;
  295     if (!(rb = c->buffer)) {
  296         internal("read socket has no buffer");
  297         setcstate(c, S_INTERNAL);
  298         abort_connection(c);
  299         return;
  300     }
  301     set_handlers(rb->sock, NULL, NULL, NULL, NULL);
  302     if ((unsigned)rb->len > MAXINT - sizeof(struct read_buffer) - READ_SIZE) overalloc();
  303     rb = mem_realloc(rb, sizeof(struct read_buffer) + rb->len + READ_SIZE);
  304     c->buffer = rb;
  305 
  306 #ifdef HAVE_SSL
  307     if(c->ssl) {
  308         if ((rd = SSL_read(c->ssl, rb->data + rb->len, READ_SIZE)) <= 0) {
  309             int err;
  310             if ((err = SSL_get_error(c->ssl, rd)) == SSL_ERROR_WANT_READ) {
  311                 read_from_socket(c, rb->sock, rb, rb->done);
  312                 return;
  313             }
  314             if (rb->close && !rd) {
  315                 rb->close = 2;
  316                 rb->done(c, rb);
  317                 return;
  318             }
  319             setcstate(c, rd ? (err == SSL_ERROR_SYSCALL ? get_error_from_errno(errno) : S_SSL_ERROR) : S_CANT_READ);
  320             /*mem_free(rb);*/
  321             if (!rd || err == SSL_ERROR_SYSCALL) retry_connection(c);
  322             else abort_connection(c);
  323             return;
  324         }
  325     } else
  326 #endif
  327         if ((rd = read(rb->sock, rb->data + rb->len, READ_SIZE)) <= 0) {
  328             if (rb->close && !rd) {
  329                 rb->close = 2;
  330                 rb->done(c, rb);
  331                 return;
  332             }
  333             setcstate(c, rd ? get_error_from_errno(errno) : S_CANT_READ);
  334             /*mem_free(rb);*/
  335             retry_connection(c);
  336             return;
  337         }
  338     log_data(rb->data + rb->len, rd);
  339     rb->len += rd;
  340     rb->done(c, rb);
  341 }
  342 
  343 struct read_buffer *alloc_read_buffer(struct connection *c)
  344 {
  345     struct read_buffer *rb;
  346     rb = mem_alloc(sizeof(struct read_buffer) + READ_SIZE);
  347     memset(rb, 0, sizeof(struct read_buffer));
  348     return rb;
  349 }
  350 
  351 void read_from_socket(struct connection *c, int s, struct read_buffer *buf, void (*read_func)(struct connection *, struct read_buffer *))
  352 {
  353     buf->done = read_func;
  354     buf->sock = s;
  355     if (c->buffer && buf != c->buffer) mem_free(c->buffer);
  356     c->buffer = buf;
  357     set_handlers(s, (void (*)(void *))read_select, NULL, (void (*)(void *))exception, c);
  358 }
  359 
  360 void kill_buffer_data(struct read_buffer *rb, int n)
  361 {
  362     if (n > rb->len || n < 0) {
  363         internal("called kill_buffer_data with bad value");
  364         rb->len = 0;
  365         return;
  366     }
  367     memmove(rb->data, rb->data + n, rb->len - n);
  368     rb->len -= n;
  369 }