webradio/utils.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006-2007 by egnite Software GmbH. All rights reserved.
00003  * Copyright (C) 2008 by egnite GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  */
00033 
00045 #include "config.h"
00046 
00047 #include <sys/heap.h>
00048 #include <sys/timer.h>
00049 
00050 #include <stdlib.h>
00051 #include <stdio.h>
00052 #include <string.h>
00053 #include <ctype.h>
00054 
00055 #include <arpa/inet.h>
00056 #include <netdb.h>
00057 
00058 #include "logmsg.h"
00059 #include "utils.h"
00060 
00061 #ifndef MAX_HEADERLINE_SIZE
00062 #define MAX_HEADERLINE_SIZE     255
00063 #endif
00064 
00068 int TcpHostConnect(TCPSOCKET * sock, CONST char * rhost, u_short port)
00069 {
00070     u_long rip;
00071 
00072     if (proxy.proxy_port) {
00073         port = proxy.proxy_port;
00074         rhost = proxy.proxy_host;
00075     }
00076     /* Get remote host IP. */
00077     rip = inet_addr(rhost);
00078     if (rip == (u_long)-1 || rip == 0) {
00079         rip = NutDnsGetHostByName((u_char *)rhost);
00080         if (rip == 0) {
00081             LogMsg(LOG_WARN, "DNS query for %s failed\n", rhost);
00082             return -1;
00083         }
00084     }
00085     if (NutTcpConnect(sock, rip, port)) {
00086         LogMsg(LOG_WARN, "Connection failed with error %d\n", NutTcpError(sock));
00087         return -1;
00088     }
00089     return 0;
00090 }
00091 
00092 FILE *TcpStreamAccept(TCPSOCKET * sock, u_short port, char *mode)
00093 {
00094     FILE *stream = NULL;
00095     u_long avail;
00096     int wcntr;
00097 
00098     /* Wait for connecting client. */
00099     if (NutTcpAccept(sock, port)) {
00100         LogMsg(LOG_WARN, "Failed to listen at TCP port %u\n", port);
00101         return NULL;
00102     }
00103 
00104     /* Wait for required resources. */
00105     for (wcntr = 0; wcntr < 10; wcntr++) {
00106         avail = NutHeapAvailable();
00107         if (avail >= 8192) {
00108             stream = _fdopen((int)((uptr_t) sock), mode);
00109             if (stream) {
00110                 break;
00111             }
00112             LogMsg(LOG_WARN, "Failed to create stream\n");
00113         }
00114         else {
00115             LogMsg(LOG_WARN, "Only %lu bytes free\n", avail);
00116         }
00117         NutSleep(500);
00118     }
00119     return stream;
00120 }
00121 
00143 int TcpGetBuffer(TCPSOCKET * sock, char * buff, u_int size, u_int *status)
00144 {
00145     u_int initial = *status;
00146     int got;
00147 
00148     while (size) {
00149         if (*status != initial || (got = NutTcpReceive(sock, buff, size)) < 0) {
00150             /* Status change or receive error. */
00151             return -1;
00152         }
00153         size -= got;
00154         buff += got;
00155     }
00156     return 0;
00157 }
00158 
00159 int TcpGetTag(TCPSOCKET * sock, char * tag, int size)
00160 {
00161     int rc = 0;
00162     int got;
00163     char *cp = tag;
00164     int in_tag = 0;
00165     int in_spc = 0;
00166     int in_qte = 0;
00167 
00168     if (size > 0) {
00169         for (;;) {
00170             if ((got = NutTcpReceive(sock, cp, 1)) <= 0) {
00171                 rc = -1;
00172                 break;
00173             }
00174             if (!in_tag) {
00175                 if (!in_qte) {
00176                     if (*cp == '"') {
00177                         in_qte = 1;
00178                     }
00179                     else if (*cp == '<') {
00180                         in_tag = 1;
00181                     }
00182                 }
00183             }
00184             else if (in_qte) {
00185             }
00186             else if (isspace(*cp)) {
00187                 if (!in_spc) {
00188                     *cp++ = ' ';
00189                     rc++;
00190                     in_spc = 1;
00191                 }
00192             }
00193             else {
00194                 in_spc = 0;
00195                 if (*cp == '>') {
00196                     *cp = 0;
00197                     break;
00198                 }
00199                 if (rc < size) {
00200                     rc++;
00201                     cp++;
00202                 }
00203             }
00204         }
00205     }
00206     return rc;
00207 }
00208 
00209 char * LocateAttributeString(CONST char * tag, CONST char * name)
00210 {
00211     CONST char *cp;
00212     size_t nlen = strlen(name);
00213     int in_qte = 0;
00214 
00215     cp = tag;
00216     while (*cp) {
00217         /* Skip leading spaces. */
00218         if (isspace(*cp)) {
00219             cp++;
00220             continue;
00221         }
00222         if (strncmp(cp, name, nlen) == 0 && *(cp + nlen) == '=') {
00223             return (char *)(cp + nlen + 2);
00224         }
00225         while (*cp) {
00226             if (!in_qte) {
00227                 if (isspace(*cp)) {
00228                     break;
00229                 }
00230                 if (*cp == '"') {
00231                     in_qte = 1;
00232                 }
00233             }
00234             else {
00235                 if (*cp == '"') {
00236                     in_qte = 0;
00237                 }
00238             }
00239             cp++;
00240         }
00241     }
00242     return NULL;
00243 }
00244 
00261 int TcpGetLine(TCPSOCKET * sock, char * line, u_short size)
00262 {
00263     int rc = 0;
00264     int got;
00265     char *cp = line;
00266 
00267     if (size > 0) {
00268         for (;;) {
00269             if ((got = NutTcpReceive(sock, cp, 1)) <= 0) {
00270                 rc = -1;
00271                 break;
00272             }
00273             if (*cp == '\n') {
00274                 *cp = 0;
00275                 break;
00276             }
00277             if (*cp >= ' ' && rc < (int) size) {
00278                 rc++;
00279                 cp++;
00280             }
00281         }
00282     }
00283     return rc;
00284 }
00285 
00301 int TcpPutString(TCPSOCKET * sock, char * str)
00302 {
00303     int len = (int)strlen(str);
00304     int c;
00305 
00306     while(len) {
00307         if ((c = NutTcpSend(sock, str, (u_short)len)) <= 0) {
00308             break;
00309         }
00310         len -= c;
00311         str += c;
00312     }
00313     return len ? -1 : 0;
00314 }
00315 
00338 int TcpGetHeaderLines(TCPSOCKET * sock, char ***array)
00339 {
00340     int rc = -1;
00341     struct LILI_ {
00342         struct LILI_ *ll_next;
00343         char *ll_line;
00344     };
00345     struct LILI_ *root = NULL;
00346     struct LILI_ *link = NULL;
00347     struct LILI_ **next = &root;
00348     char *buf;
00349     int len;
00350 
00351     /*
00352      * Allocate a line buffer. On success, build a linked list of
00353      * incoming lines. Stop on errors or at the first empty line.
00354      */
00355     if ((buf = malloc(MAX_HEADERLINE_SIZE)) != NULL) {
00356         for (;;) {
00357             if ((len = TcpGetLine(sock, buf, MAX_HEADERLINE_SIZE)) == 0) {
00358                 /* Empty line. */
00359                 break;
00360             }
00361             if (len < 0) {
00362                 /* Error occured. */
00363                 rc = -1;
00364                 break;
00365             }
00366             /* Allocate a linked list item. */
00367             if ((*next = malloc(sizeof(struct LILI_))) == NULL) {
00368                 break;
00369             }
00370             /* Initially set the next link to NULL. */
00371             (*next)->ll_next = NULL;
00372             /* Copy the line to the linked list item. */
00373             (*next)->ll_line = malloc(len + 1);
00374             memcpy((*next)->ll_line, buf, len);
00375             (*next)->ll_line[len] = '\0';
00376             /* Set pointer to the next link. */
00377             next = &((*next)->ll_next);
00378             rc++;
00379         }
00380         free(buf);
00381     }
00382 
00383     if (rc > 0) {
00384         /* Allocate a new string array. */
00385         *array = malloc((rc + 1) * sizeof(char *));
00386         rc = 0;
00387     }
00388     else {
00389         /* Error or single empty line only. Set array pointer to NULL. */
00390         *array = NULL;
00391     }
00392 
00393     /*
00394      * This loop serves two purposes. It moves the strings from the
00395      * linked list to the string array (if one had been allocated)
00396      * and it releases all memory allocated for the linked list.
00397      */
00398     while (root) {
00399         if (*array) {
00400             /* Move string to the array. */
00401             (*array)[rc] = root->ll_line;
00402             rc++;
00403         }
00404         else {
00405             /* No array. Just release the string. */
00406             free(root->ll_line);
00407         }
00408         /* Get the next link and release the current entry. */
00409         link = root;
00410         root = root->ll_next;
00411         free(link);
00412     }
00413 
00414     /* NULL marks the end of the array. */
00415     if (*array) {
00416         (*array)[rc] = NULL;
00417     }
00418     return rc;
00419 }
00420 
00428 void TcpReleaseHeaderLines(char **array)
00429 {
00430     char **ap = array;
00431 
00432     if (ap) {
00433         /* Thanks, Dany. */
00434         while (*ap) {
00435             free(*ap);
00436             ap++;
00437         }
00438         free(array);
00439     }
00440 }
00441 
00442 void HttpSchemeRelease(HTTP_SCHEME *schm)
00443 {
00444     if (schm) {
00445         if (schm->schm_uri) {
00446             free(schm->schm_uri);
00447         }
00448         free(schm);
00449     }
00450 }
00451 
00452 /* [<user>[:<password>]@]<host>[:<port>][/<path>] */
00453 HTTP_SCHEME *HttpSchemeParse(CONST char *uri)
00454 {
00455     HTTP_SCHEME *schm = NULL;
00456     char *cp;
00457 
00458     /* Create a blank scheme structure. */
00459     if (*uri && (schm = malloc(sizeof(HTTP_SCHEME))) != NULL) {
00460         memset(schm, 0, sizeof(HTTP_SCHEME));
00461 
00462         /* Create a local copy of the URI string. */
00463         if ((schm->schm_uri = strdup(uri)) != NULL) {
00464             /* Split the local copy. */
00465             schm->schm_host = schm->schm_uri;
00466             for (cp = schm->schm_uri; *cp; cp++) {
00467                 if (*cp == ':') {
00468                     *cp = '\0';
00469                     schm->schm_port = cp + 1;
00470                 }
00471                 else if (*cp == '/') {
00472                     *cp = 0;
00473                     schm->schm_path = cp + 1;
00474                     break;
00475                 }
00476                 else if (*cp == '@') {
00477                     *cp = 0;
00478                     schm->schm_user = schm->schm_host;
00479                     schm->schm_pass = schm->schm_port;
00480                     schm->schm_host = cp + 1;
00481                     schm->schm_port = NULL;
00482                 }
00483             }
00484             if (schm->schm_port) {
00485                 schm->schm_portnum = (u_short)atoi(schm->schm_port);
00486             }
00487             else {
00488                 schm->schm_portnum = 80;
00489             }
00490             return schm;
00491         }
00492     }
00493     HttpSchemeRelease(schm);
00494     return NULL;
00495 }
00496 
00506 void Led0(int on)
00507 {
00508 #ifdef AT91SAM7X_EK
00509     outr(PIOB_PER, _BV(22));
00510     outr(PIOB_OER, _BV(22));
00511     if (on) {
00512         outr(PIOB_CODR, _BV(22));
00513     }
00514     else {
00515         outr(PIOB_SODR, _BV(22));
00516     }
00517 #elif AT91SAM9260_EK
00518     outr(PIOA_PER, _BV(6));
00519     outr(PIOA_OER, _BV(6));
00520     if (on) {
00521         outr(PIOA_CODR, _BV(6));
00522     }
00523     else {
00524         outr(PIOA_SODR, _BV(6));
00525     }
00526 #endif
00527 }
00528 
00541 char *strdup(CONST char *str)
00542 {
00543     size_t siz;
00544     char *copy;
00545 
00546     siz = strlen(str) + 1;
00547     if ((copy = malloc(siz)) == NULL) {
00548         return NULL;
00549     }
00550     memcpy(copy, str, siz);
00551 
00552     return copy;
00553 }

© 2008 by egnite GmbH - visit www.ethernut.de