Main Page Data Structures File List Data Fields Globals Related Pages

# inet/httpget.cpp

Go to the documentation of this file.

    00001 /*  httpget.cpp
    00002     A simple http client
    00003
    00004     13.08.2001: tk, initial implementation, based on Beck
    00005                     example code.
    00006
    00007     Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de
    00008
    00009     This program is free software; you can redistribute it and/or
    00010     modify it under the terms of the GNU General Public License as
    00011     published by the Free Software Foundation; either version 2 of
    00012     the License, or (at your option) any later version. Read the
    00013     full License at http://www.gnu.org/copyleft for more details.
    00014 */
    00015
    00016 // include files ----------
    00017 //
    00018 #include <conio.h>
    00019 #include <stdio.h>
    00020 #include <string.h>
    00021 #include <stdlib.h>
    00022 #include <assert.h>
    00023 #include "inet/httpget.h"
    00024 #include "inet/base64.h"
    00025 #include "inet/dns.h"
    00026 #include "inet/url.h"
    00027 #include "clib/rtos.h"
    00028 #include "clib/tcpip.h"
    00029 #include "mpbuf.h"
    00030 #include "misc.h"
    00031 #include "vs1001.h"
    00032
    00049 char *sockgets(char *s, int n, int sd)
    00050 {
    00051   int   error, rcvd;
    00052   char *ptr = s;
    00053
    00054   while (n>1) {
    00055     rcvd = recv(sd, ptr, 1, MSG_TIMEOUT, 10000L, &error);
    00056     if (error != 0 || rcvd != 1)
    00057       return NULL;
    00058
    00059     if (*ptr++ == '\n')
    00060       break;
    00061
    00062     n--;
    00063   }
    00064   *ptr = '\0';
    00065   assert(ptr < s+n);
    00066
    00067   return s;
    00068 }
    00069
    00070
    00082 int sockputs(const char *s, int sd)
    00083 {
    00084   int len, error, sent;
    00085
    00086   len = strlen(s);
    00087   while (len>0) {
    00088     sent = send(sd, (char*)s, len, 0, &error);
    00089     if (error!=0 || sent<0)
    00090       break;
    00091     s   += sent;
    00092     len -= sent;
    00093   }
    00094   assert(len>=0);
    00095
    00096   return (len==0) ? 1 : EOF;
    00097 }
    00098
    00099
    00108 unsigned  http_connect(const char *urlString, int *error)
    00109 {
    00110   unsigned long  ipnumber, ttl;
    00111   char     ipaddr[16];
    00112   unsigned socket = 0;
    00113
    00114   URL  *url = parse_url(urlString);
    00115   if (!url->port)
    00116     url->port = DEFAULT_HTTP_PORT;
    00117
    00118   printf("connecting to %s..\n", url->host);
    00119   if (inet_addr(url->host, &ipnumber)) {
    00120     int ret = gethostbyname(NULL, url->host, &ttl, &ipnumber, ipaddr);
    00121     if (!ret) {
    00122       printf("  can't resolve host address!\n");
    00123       // No route to host error.. not exactly, but close ;)
    00124       //
    00125       *error = 265;
    00126       goto Return;
    00127     } else printf("  resolved to %s.\n", ipaddr);
    00128   } else {
    00129     strncpy(ipaddr, url->host, sizeof(ipaddr));
    00130   }
    00131
    00132   // Send request to server -----
    00133   //
    00134   char  request[512], *r = request;  // worst case !
    00135   r += sprintf(r, "GET /%s HTTP/1.0\r\n", url->path ? url->path : "");
    00136   r += sprintf(r, "Host: %s:%u\r\n", url->host, url->port);
    00137   r += sprintf(r, "User-Agent: mp3v2 client 1.1, www.kreapc.de\r\n");
    00138   r += sprintf(r, "Connection: Keep-Alive\r\n");
    00139 //  r += sprintf(r, "Icy-MetaData: 1\r\n");
    00140
    00141   if (url->user) {
    00142     char *authcode = NULL;
    00143     char str[64], *s = str;
    00144
    00145     s += sprintf(s, "%s", url->user);
    00146     if (url->pass)
    00147       s += sprintf(s, ":%s", url->pass);
    00148     assert((s-str)<sizeof(str));
    00149     authcode = base64encode(str, strlen(str), NULL);
    00150
    00151     if (authcode) {
    00152       r += sprintf(r, "Authorization: Basic %s\r\n", authcode);
    00153       free(authcode);
    00154     }
    00155   }
    00156   r += sprintf(r, "\r\n");
    00157   assert((r-request)<sizeof(request));
    00158
    00159   printf("  opening connection.. ");
    00160   socket = tcp_connect(ipaddr, 0, url->port, error);
    00161   if (*error) {
    00162     printf("error %d.\n", *error);
    00163     goto Return;
    00164   } else printf("ok.\n");
    00165
    00166   printf("  sending request.. ");
    00167   printf("\n%s\n", request);
    00168
    00169   if (!sockputs(request, socket)) {
    00170     printf( "error while sending request\n");
    00171     goto Return;
    00172   } else printf("ok.\n");
    00173
    00174
    00175 Return:
    00176   if (url)
    00177     free_url(url);
    00178   return  socket;
    00179 }
    00180
    00181
    00182 void  getMetaData(int sd)
    00183 {
    00184   int   error, rcvd;
    00185   char  metalen;
    00186   char  metadata[512];
    00187
    00188   rcvd = recv(sd, &metalen, 1, MSG_TIMEOUT, 10000L, &error);
    00189   if (error!=0 || rcvd!=1)
    00190     return;
    00191
    00192   if (metalen) {
    00193     printf("%d bytes: ", metalen*16);
    00194     rcvd = recv(sd, metadata, metalen*16, MSG_TIMEOUT, 10000L, &error);
    00195     if (error!=0)
    00196       return;
    00197     printf("%s\n", metadata);
    00198   }
    00199
    00200 }
    00201
    00202
    00203 void  http_get(const char *urlString)
    00204 {
    00205   int       sd, error;
    00206   unsigned  rcvd;
    00207   char      header[512];
    00208
    00209   int       tcp_delay = 0;
    00210   SetSocketOption options = {
    00211     IP_PROTOTCP_LEVEL, TCP_DELAY_ACK,
    00212     (char*)&tcp_delay, sizeof(tcp_delay)
    00213   };
    00214
    00215   sd = http_connect(urlString, &error);
    00216   if (error)
    00217     goto Return;
    00218
    00219   // set TCP_DELAY_ACK option
    00220   setsockopt(sd, &options, &error);
    00221   printf("setsockopt returned %x\n", error);
    00222
    00223   printf("receiving header.. ");
    00224   while (1) {
    00225     sockgets(header, sizeof(header), sd);
    00226     printf("%s", header);
    00227     if (!strcmp(header, "\r\n"))
    00228       break;
    00229   }
    00230
    00231   // set threshold to 50% to handle slow servers nicely
    00232   //
    00233   BUF_SetThreshold(BUF_GetSize()/2);
    00234   BUF_Play();
    00235
    00236   while (!kbhit() && !error) {
    00237 //    LCD_SetBrightness(((float)BUF_GetCount()/BUF_GetSize())*255);
    00238
    00239     // fill buffer
    00240     //
    00241     if (BUF_GetFreeBytes() > 8192) {
    00242       char *buf1;
    00243       long  len = 8192, len1;
    00244
    00245       while (len>0) {
    00246         BUF_Lock(-1, len, &buf1, &len1, 0, 0 );
    00247         rcvd = recv(sd, buf1, len1, MSG_TIMEOUT, 10000L, &error);
    00248         if (error || rcvd == 0)
    00249           break;
    00250         BUF_Unlock(rcvd);
    00251         len -= rcvd;
    00252       }
    00253 //      getMetaData(sd);
    00254
    00255       printf(".");
    00256     }
    00257     // update display
    00258     //
    00259 /*    cleardevice();
    00260     gotoxy(0,0);
    00261     gprintf(ProgressBar(BUF_GetCount(), 0, BUF_GetSize()));
    00262     LCD_Update();  */
    00263
    00264     // be nice to other apps..
    00265     //
    00266     RTX_Sleep_Time(100);
    00267   }
    00268   BUF_Clear();
    00269   getch();
    00270
    00271 Return:
    00272   if (sd)
    00273     closesocket(sd, &error);
    00274   return;
    00275 }