Annotation of embedaddon/miniupnpd/upnphttp.c, revision 1.1

1.1     ! misho       1: /* $Id: upnphttp.c,v 1.57 2009/02/12 23:38:40 nanard Exp $ */
        !             2: /* Project :  miniupnp
        !             3:  * Website :  http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
        !             4:  * Author :   Thomas Bernard
        !             5:  * Copyright (c) 2005-2008 Thomas Bernard
        !             6:  * This software is subject to the conditions detailed in the
        !             7:  * LICENCE file included in this distribution.
        !             8:  * */
        !             9: #include <stdlib.h>
        !            10: #include <unistd.h>
        !            11: #include <stdio.h>
        !            12: #include <string.h>
        !            13: #include <sys/types.h>
        !            14: #include <sys/socket.h>
        !            15: #include <sys/param.h>
        !            16: #include <syslog.h>
        !            17: #include <ctype.h>
        !            18: #include "config.h"
        !            19: #include "upnphttp.h"
        !            20: #include "upnpdescgen.h"
        !            21: #include "miniupnpdpath.h"
        !            22: #include "upnpsoap.h"
        !            23: #include "upnpevents.h"
        !            24: 
        !            25: struct upnphttp * 
        !            26: New_upnphttp(int s)
        !            27: {
        !            28:        struct upnphttp * ret;
        !            29:        if(s<0)
        !            30:                return NULL;
        !            31:        ret = (struct upnphttp *)malloc(sizeof(struct upnphttp));
        !            32:        if(ret == NULL)
        !            33:                return NULL;
        !            34:        memset(ret, 0, sizeof(struct upnphttp));
        !            35:        ret->socket = s;
        !            36:        return ret;
        !            37: }
        !            38: 
        !            39: void
        !            40: CloseSocket_upnphttp(struct upnphttp * h)
        !            41: {
        !            42:        if(close(h->socket) < 0)
        !            43:        {
        !            44:                syslog(LOG_ERR, "CloseSocket_upnphttp: close(%d): %m", h->socket);
        !            45:        }
        !            46:        h->socket = -1;
        !            47:        h->state = 100;
        !            48: }
        !            49: 
        !            50: void
        !            51: Delete_upnphttp(struct upnphttp * h)
        !            52: {
        !            53:        if(h)
        !            54:        {
        !            55:                if(h->socket >= 0)
        !            56:                        CloseSocket_upnphttp(h);
        !            57:                if(h->req_buf)
        !            58:                        free(h->req_buf);
        !            59:                if(h->res_buf)
        !            60:                        free(h->res_buf);
        !            61:                free(h);
        !            62:        }
        !            63: }
        !            64: 
        !            65: /* parse HttpHeaders of the REQUEST */
        !            66: static void
        !            67: ParseHttpHeaders(struct upnphttp * h)
        !            68: {
        !            69:        char * line;
        !            70:        char * colon;
        !            71:        char * p;
        !            72:        int n;
        !            73:        line = h->req_buf;
        !            74:        /* TODO : check if req_buf, contentoff are ok */
        !            75:        while(line < (h->req_buf + h->req_contentoff))
        !            76:        {
        !            77:                colon = strchr(line, ':');
        !            78:                if(colon)
        !            79:                {
        !            80:                        if(strncasecmp(line, "Content-Length", 14)==0)
        !            81:                        {
        !            82:                                p = colon;
        !            83:                                while(*p < '0' || *p > '9')
        !            84:                                        p++;
        !            85:                                h->req_contentlen = atoi(p);
        !            86:                                /*printf("*** Content-Lenght = %d ***\n", h->req_contentlen);
        !            87:                                printf("    readbufflen=%d contentoff = %d\n",
        !            88:                                        h->req_buflen, h->req_contentoff);*/
        !            89:                        }
        !            90:                        else if(strncasecmp(line, "SOAPAction", 10)==0)
        !            91:                        {
        !            92:                                p = colon;
        !            93:                                n = 0;
        !            94:                                while(*p == ':' || *p == ' ' || *p == '\t')
        !            95:                                        p++;
        !            96:                                while(p[n]>=' ')
        !            97:                                {
        !            98:                                        n++;
        !            99:                                }
        !           100:                                if((p[0] == '"' && p[n-1] == '"')
        !           101:                                  || (p[0] == '\'' && p[n-1] == '\''))
        !           102:                                {
        !           103:                                        p++; n -= 2;
        !           104:                                }
        !           105:                                h->req_soapAction = p;
        !           106:                                h->req_soapActionLen = n;
        !           107:                        }
        !           108: #ifdef ENABLE_EVENTS
        !           109:                        else if(strncasecmp(line, "Callback", 8)==0)
        !           110:                        {
        !           111:                                p = colon;
        !           112:                                while(*p != '<' && *p != '\r' )
        !           113:                                        p++;
        !           114:                                n = 0;
        !           115:                                while(p[n] != '>' && p[n] != '\r' )
        !           116:                                        n++;
        !           117:                                h->req_Callback = p + 1;
        !           118:                                h->req_CallbackLen = MAX(0, n - 1);
        !           119:                        }
        !           120:                        else if(strncasecmp(line, "SID", 3)==0)
        !           121:                        {
        !           122:                                p = colon + 1;
        !           123:                                while(isspace(*p))
        !           124:                                        p++;
        !           125:                                n = 0;
        !           126:                                while(!isspace(p[n]))
        !           127:                                        n++;
        !           128:                                h->req_SID = p;
        !           129:                                h->req_SIDLen = n;
        !           130:                        }
        !           131:                        /* Timeout: Seconds-nnnn */
        !           132: /* TIMEOUT
        !           133: Recommended. Requested duration until subscription expires,
        !           134: either number of seconds or infinite. Recommendation
        !           135: by a UPnP Forum working committee. Defined by UPnP vendor.
        !           136:  Consists of the keyword "Second-" followed (without an
        !           137: intervening space) by either an integer or the keyword "infinite". */
        !           138:                        else if(strncasecmp(line, "Timeout", 7)==0)
        !           139:                        {
        !           140:                                p = colon + 1;
        !           141:                                while(isspace(*p))
        !           142:                                        p++;
        !           143:                                if(strncasecmp(p, "Second-", 7)==0) {
        !           144:                                        h->req_Timeout = atoi(p+7);
        !           145:                                }
        !           146:                        }
        !           147: #endif
        !           148:                }
        !           149:                while(!(line[0] == '\r' && line[1] == '\n'))
        !           150:                        line++;
        !           151:                line += 2;
        !           152:        }
        !           153: }
        !           154: 
        !           155: /* very minimalistic 404 error message */
        !           156: static void
        !           157: Send404(struct upnphttp * h)
        !           158: {
        !           159: /*
        !           160:        static const char error404[] = "HTTP/1.1 404 Not found\r\n"
        !           161:                "Connection: close\r\n"
        !           162:                "Content-type: text/html\r\n"
        !           163:                "\r\n"
        !           164:                "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
        !           165:                "<BODY><H1>Not Found</H1>The requested URL was not found"
        !           166:                " on this server.</BODY></HTML>\r\n";
        !           167:        int n;
        !           168:        n = send(h->socket, error404, sizeof(error404) - 1, 0);
        !           169:        if(n < 0)
        !           170:        {
        !           171:                syslog(LOG_ERR, "Send404: send(http): %m");
        !           172:        }*/
        !           173:        static const char body404[] =
        !           174:                "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
        !           175:                "<BODY><H1>Not Found</H1>The requested URL was not found"
        !           176:                " on this server.</BODY></HTML>\r\n";
        !           177:        h->respflags = FLAG_HTML;
        !           178:        BuildResp2_upnphttp(h, 404, "Not Found",
        !           179:                            body404, sizeof(body404) - 1);
        !           180:        SendResp_upnphttp(h);
        !           181:        CloseSocket_upnphttp(h);
        !           182: }
        !           183: 
        !           184: /* very minimalistic 501 error message */
        !           185: static void
        !           186: Send501(struct upnphttp * h)
        !           187: {
        !           188: /*
        !           189:        static const char error501[] = "HTTP/1.1 501 Not Implemented\r\n"
        !           190:                "Connection: close\r\n"
        !           191:                "Content-type: text/html\r\n"
        !           192:                "\r\n"
        !           193:                "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
        !           194:                "<BODY><H1>Not Implemented</H1>The HTTP Method "
        !           195:                "is not implemented by this server.</BODY></HTML>\r\n";
        !           196:        int n;
        !           197:        n = send(h->socket, error501, sizeof(error501) - 1, 0);
        !           198:        if(n < 0)
        !           199:        {
        !           200:                syslog(LOG_ERR, "Send501: send(http): %m");
        !           201:        }
        !           202: */
        !           203:        static const char body501[] = 
        !           204:                "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
        !           205:                "<BODY><H1>Not Implemented</H1>The HTTP Method "
        !           206:                "is not implemented by this server.</BODY></HTML>\r\n";
        !           207:        h->respflags = FLAG_HTML;
        !           208:        BuildResp2_upnphttp(h, 501, "Not Implemented",
        !           209:                            body501, sizeof(body501) - 1);
        !           210:        SendResp_upnphttp(h);
        !           211:        CloseSocket_upnphttp(h);
        !           212: }
        !           213: 
        !           214: static const char *
        !           215: findendheaders(const char * s, int len)
        !           216: {
        !           217:        while(len-->0)
        !           218:        {
        !           219:                if(s[0]=='\r' && s[1]=='\n' && s[2]=='\r' && s[3]=='\n')
        !           220:                        return s;
        !           221:                s++;
        !           222:        }
        !           223:        return NULL;
        !           224: }
        !           225: 
        !           226: #ifdef HAS_DUMMY_SERVICE
        !           227: static void
        !           228: sendDummyDesc(struct upnphttp * h)
        !           229: {
        !           230:        static const char xml_desc[] = "<?xml version=\"1.0\"?>\r\n"
        !           231:                "<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">"
        !           232:                " <specVersion>"
        !           233:                "    <major>1</major>"
        !           234:                "    <minor>0</minor>"
        !           235:                "  </specVersion>"
        !           236:                "  <actionList />"
        !           237:                "  <serviceStateTable />"
        !           238:                "</scpd>\r\n";
        !           239:        BuildResp_upnphttp(h, xml_desc, sizeof(xml_desc)-1);
        !           240:        SendResp_upnphttp(h);
        !           241:        CloseSocket_upnphttp(h);
        !           242: }
        !           243: #endif
        !           244: 
        !           245: /* Sends the description generated by the parameter */
        !           246: static void
        !           247: sendXMLdesc(struct upnphttp * h, char * (f)(int *))
        !           248: {
        !           249:        char * desc;
        !           250:        int len;
        !           251:        desc = f(&len);
        !           252:        if(!desc)
        !           253:        {
        !           254:                static const char error500[] = "<HTML><HEAD><TITLE>Error 500</TITLE>"
        !           255:                   "</HEAD><BODY>Internal Server Error</BODY></HTML>\r\n";
        !           256:                syslog(LOG_ERR, "Failed to generate XML description");
        !           257:                h->respflags = FLAG_HTML;
        !           258:                BuildResp2_upnphttp(h, 500, "Internal Server Error",
        !           259:                                    error500, sizeof(error500)-1);
        !           260:        }
        !           261:        else
        !           262:        {
        !           263:                BuildResp_upnphttp(h, desc, len);
        !           264:        }
        !           265:        SendResp_upnphttp(h);
        !           266:        CloseSocket_upnphttp(h);
        !           267:        free(desc);
        !           268: }
        !           269: 
        !           270: /* ProcessHTTPPOST_upnphttp()
        !           271:  * executes the SOAP query if it is possible */
        !           272: static void
        !           273: ProcessHTTPPOST_upnphttp(struct upnphttp * h)
        !           274: {
        !           275:        if((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
        !           276:        {
        !           277:                if(h->req_soapAction)
        !           278:                {
        !           279:                        /* we can process the request */
        !           280:                        syslog(LOG_INFO, "SOAPAction: %.*s",
        !           281:                           h->req_soapActionLen, h->req_soapAction);
        !           282:                        ExecuteSoapAction(h, 
        !           283:                                h->req_soapAction,
        !           284:                                h->req_soapActionLen);
        !           285:                }
        !           286:                else
        !           287:                {
        !           288:                        static const char err400str[] =
        !           289:                                "<html><body>Bad request</body></html>";
        !           290:                        syslog(LOG_INFO, "No SOAPAction in HTTP headers");
        !           291:                        h->respflags = FLAG_HTML;
        !           292:                        BuildResp2_upnphttp(h, 400, "Bad Request",
        !           293:                                            err400str, sizeof(err400str) - 1);
        !           294:                        SendResp_upnphttp(h);
        !           295:                        CloseSocket_upnphttp(h);
        !           296:                }
        !           297:        }
        !           298:        else
        !           299:        {
        !           300:                /* waiting for remaining data */
        !           301:                h->state = 1;
        !           302:        }
        !           303: }
        !           304: 
        !           305: #ifdef ENABLE_EVENTS
        !           306: static void
        !           307: ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
        !           308: {
        !           309:        const char * sid;
        !           310:        syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path);
        !           311:        syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d",
        !           312:               h->req_CallbackLen, h->req_Callback, h->req_Timeout);
        !           313:        syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
        !           314:        if(!h->req_Callback && !h->req_SID) {
        !           315:                /* Missing or invalid CALLBACK : 412 Precondition Failed.
        !           316:                 * If CALLBACK header is missing or does not contain a valid HTTP URL,
        !           317:                 * the publisher must respond with HTTP error 412 Precondition Failed*/
        !           318:                BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
        !           319:                SendResp_upnphttp(h);
        !           320:                CloseSocket_upnphttp(h);
        !           321:        } else {
        !           322:        /* - add to the subscriber list
        !           323:         * - respond HTTP/x.x 200 OK 
        !           324:         * - Send the initial event message */
        !           325: /* Server:, SID:; Timeout: Second-(xx|infinite) */
        !           326:                if(h->req_Callback) {
        !           327:                        sid = upnpevents_addSubscriber(path, h->req_Callback,
        !           328:                                                       h->req_CallbackLen, h->req_Timeout);
        !           329:                        h->respflags = FLAG_TIMEOUT;
        !           330:                        if(sid) {
        !           331:                                syslog(LOG_DEBUG, "generated sid=%s", sid);
        !           332:                                h->respflags |= FLAG_SID;
        !           333:                                h->req_SID = sid;
        !           334:                                h->req_SIDLen = strlen(sid);
        !           335:                        }
        !           336:                        BuildResp_upnphttp(h, 0, 0);
        !           337:                } else {
        !           338:                        /* subscription renew */
        !           339:                        /* Invalid SID
        !           340: 412 Precondition Failed. If a SID does not correspond to a known,
        !           341: un-expired subscription, the publisher must respond
        !           342: with HTTP error 412 Precondition Failed. */
        !           343:                        if(renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0) {
        !           344:                                BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
        !           345:                        } else {
        !           346:                                BuildResp_upnphttp(h, 0, 0);
        !           347:                        }
        !           348:                }
        !           349:                SendResp_upnphttp(h);
        !           350:                CloseSocket_upnphttp(h);
        !           351:        }
        !           352: }
        !           353: 
        !           354: static void
        !           355: ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
        !           356: {
        !           357:        syslog(LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path);
        !           358:        syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
        !           359:        /* Remove from the list */
        !           360:        if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) {
        !           361:                BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
        !           362:        } else {
        !           363:                BuildResp_upnphttp(h, 0, 0);
        !           364:        }
        !           365:        SendResp_upnphttp(h);
        !           366:        CloseSocket_upnphttp(h);
        !           367: }
        !           368: #endif
        !           369: 
        !           370: /* Parse and process Http Query 
        !           371:  * called once all the HTTP headers have been received. */
        !           372: static void
        !           373: ProcessHttpQuery_upnphttp(struct upnphttp * h)
        !           374: {
        !           375:        char HttpCommand[16];
        !           376:        char HttpUrl[128];
        !           377:        char * HttpVer;
        !           378:        char * p;
        !           379:        int i;
        !           380:        p = h->req_buf;
        !           381:        if(!p)
        !           382:                return;
        !           383:        for(i = 0; i<15 && *p != ' ' && *p != '\r'; i++)
        !           384:                HttpCommand[i] = *(p++);
        !           385:        HttpCommand[i] = '\0';
        !           386:        while(*p==' ')
        !           387:                p++;
        !           388:        for(i = 0; i<127 && *p != ' ' && *p != '\r'; i++)
        !           389:                HttpUrl[i] = *(p++);
        !           390:        HttpUrl[i] = '\0';
        !           391:        while(*p==' ')
        !           392:                p++;
        !           393:        HttpVer = h->HttpVer;
        !           394:        for(i = 0; i<15 && *p != '\r'; i++)
        !           395:                HttpVer[i] = *(p++);
        !           396:        HttpVer[i] = '\0';
        !           397:        syslog(LOG_INFO, "HTTP REQUEST : %s %s (%s)",
        !           398:               HttpCommand, HttpUrl, HttpVer);
        !           399:        ParseHttpHeaders(h);
        !           400:        if(strcmp("POST", HttpCommand) == 0)
        !           401:        {
        !           402:                h->req_command = EPost;
        !           403:                ProcessHTTPPOST_upnphttp(h);
        !           404:        }
        !           405:        else if(strcmp("GET", HttpCommand) == 0)
        !           406:        {
        !           407:                h->req_command = EGet;
        !           408:                if(strcasecmp(ROOTDESC_PATH, HttpUrl) == 0)
        !           409:                {
        !           410:                        sendXMLdesc(h, genRootDesc);
        !           411:                }
        !           412:                else if(strcasecmp(WANIPC_PATH, HttpUrl) == 0)
        !           413:                {
        !           414:                        sendXMLdesc(h, genWANIPCn);
        !           415:                }
        !           416:                else if(strcasecmp(WANCFG_PATH, HttpUrl) == 0)
        !           417:                {
        !           418:                        sendXMLdesc(h, genWANCfg);
        !           419:                }
        !           420: #ifdef HAS_DUMMY_SERVICE
        !           421:                else if(strcasecmp(DUMMY_PATH, HttpUrl) == 0)
        !           422:                {
        !           423:                        sendDummyDesc(h);
        !           424:                }
        !           425: #endif
        !           426: #ifdef ENABLE_L3F_SERVICE
        !           427:                else if(strcasecmp(L3F_PATH, HttpUrl) == 0)
        !           428:                {
        !           429:                        sendXMLdesc(h, genL3F);
        !           430:                }
        !           431: #endif
        !           432:                else
        !           433:                {
        !           434:                        syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl);
        !           435:                        Send404(h);
        !           436:                }
        !           437:        }
        !           438: #ifdef ENABLE_EVENTS
        !           439:        else if(strcmp("SUBSCRIBE", HttpCommand) == 0)
        !           440:        {
        !           441:                h->req_command = ESubscribe;
        !           442:                ProcessHTTPSubscribe_upnphttp(h, HttpUrl);
        !           443:        }
        !           444:        else if(strcmp("UNSUBSCRIBE", HttpCommand) == 0)
        !           445:        {
        !           446:                h->req_command = EUnSubscribe;
        !           447:                ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl);
        !           448:        }
        !           449: #else
        !           450:        else if(strcmp("SUBSCRIBE", HttpCommand) == 0)
        !           451:        {
        !           452:                syslog(LOG_NOTICE, "SUBSCRIBE not implemented. ENABLE_EVENTS compile option disabled");
        !           453:                Send501(h);
        !           454:        }
        !           455: #endif
        !           456:        else
        !           457:        {
        !           458:                syslog(LOG_NOTICE, "Unsupported HTTP Command %s", HttpCommand);
        !           459:                Send501(h);
        !           460:        }
        !           461: }
        !           462: 
        !           463: 
        !           464: void
        !           465: Process_upnphttp(struct upnphttp * h)
        !           466: {
        !           467:        char buf[2048];
        !           468:        int n;
        !           469:        if(!h)
        !           470:                return;
        !           471:        switch(h->state)
        !           472:        {
        !           473:        case 0:
        !           474:                n = recv(h->socket, buf, 2048, 0);
        !           475:                if(n<0)
        !           476:                {
        !           477:                        syslog(LOG_ERR, "recv (state0): %m");
        !           478:                        h->state = 100;
        !           479:                }
        !           480:                else if(n==0)
        !           481:                {
        !           482:                        syslog(LOG_WARNING, "HTTP Connection closed inexpectedly");
        !           483:                        h->state = 100;
        !           484:                }
        !           485:                else
        !           486:                {
        !           487:                        const char * endheaders;
        !           488:                        /* if 1st arg of realloc() is null,
        !           489:                         * realloc behaves the same as malloc() */
        !           490:                        h->req_buf = (char *)realloc(h->req_buf, n + h->req_buflen + 1);
        !           491:                        memcpy(h->req_buf + h->req_buflen, buf, n);
        !           492:                        h->req_buflen += n;
        !           493:                        h->req_buf[h->req_buflen] = '\0';
        !           494:                        /* search for the string "\r\n\r\n" */
        !           495:                        endheaders = findendheaders(h->req_buf, h->req_buflen);
        !           496:                        if(endheaders)
        !           497:                        {
        !           498:                                h->req_contentoff = endheaders - h->req_buf + 4;
        !           499:                                ProcessHttpQuery_upnphttp(h);
        !           500:                        }
        !           501:                }
        !           502:                break;
        !           503:        case 1:
        !           504:                n = recv(h->socket, buf, 2048, 0);
        !           505:                if(n<0)
        !           506:                {
        !           507:                        syslog(LOG_ERR, "recv (state1): %m");
        !           508:                        h->state = 100;
        !           509:                }
        !           510:                else if(n==0)
        !           511:                {
        !           512:                        syslog(LOG_WARNING, "HTTP Connection closed inexpectedly");
        !           513:                        h->state = 100;
        !           514:                }
        !           515:                else
        !           516:                {
        !           517:                        /*fwrite(buf, 1, n, stdout);*/  /* debug */
        !           518:                        h->req_buf = (char *)realloc(h->req_buf, n + h->req_buflen);
        !           519:                        memcpy(h->req_buf + h->req_buflen, buf, n);
        !           520:                        h->req_buflen += n;
        !           521:                        if((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
        !           522:                        {
        !           523:                                ProcessHTTPPOST_upnphttp(h);
        !           524:                        }
        !           525:                }
        !           526:                break;
        !           527:        default:
        !           528:                syslog(LOG_WARNING, "Unexpected state: %d", h->state);
        !           529:        }
        !           530: }
        !           531: 
        !           532: static const char httpresphead[] =
        !           533:        "%s %d %s\r\n"
        !           534:        /*"Content-Type: text/xml; charset=\"utf-8\"\r\n"*/
        !           535:        "Content-Type: %s\r\n"
        !           536:        "Connection: close\r\n"
        !           537:        "Content-Length: %d\r\n"
        !           538:        /*"Server: miniupnpd/1.0 UPnP/1.0\r\n"*/
        !           539:        "Server: " MINIUPNPD_SERVER_STRING "\r\n"
        !           540:        ;       /*"\r\n";*/
        !           541: /*
        !           542:                "<?xml version=\"1.0\"?>\n"
        !           543:                "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
        !           544:                "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
        !           545:                "<s:Body>"
        !           546: 
        !           547:                "</s:Body>"
        !           548:                "</s:Envelope>";
        !           549: */
        !           550: /* with response code and response message
        !           551:  * also allocate enough memory */
        !           552: 
        !           553: void
        !           554: BuildHeader_upnphttp(struct upnphttp * h, int respcode,
        !           555:                      const char * respmsg,
        !           556:                      int bodylen)
        !           557: {
        !           558:        int templen;
        !           559:        if(!h->res_buf)
        !           560:        {
        !           561:                templen = sizeof(httpresphead) + 128 + bodylen;
        !           562:                h->res_buf = (char *)malloc(templen);
        !           563:                h->res_buf_alloclen = templen;
        !           564:        }
        !           565:        h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen,
        !           566:                                 httpresphead, h->HttpVer,
        !           567:                                 respcode, respmsg,
        !           568:                                 (h->respflags&FLAG_HTML)?"text/html":"text/xml",
        !           569:                                                         bodylen);
        !           570:        /* Additional headers */
        !           571: #ifdef ENABLE_EVENTS
        !           572:        if(h->respflags & FLAG_TIMEOUT) {
        !           573:                h->res_buflen += snprintf(h->res_buf + h->res_buflen,
        !           574:                                          h->res_buf_alloclen - h->res_buflen,
        !           575:                                          "Timeout: Second-");
        !           576:                if(h->req_Timeout) {
        !           577:                        h->res_buflen += snprintf(h->res_buf + h->res_buflen,
        !           578:                                                  h->res_buf_alloclen - h->res_buflen,
        !           579:                                                  "%d\r\n", h->req_Timeout);
        !           580:                } else {
        !           581:                        h->res_buflen += snprintf(h->res_buf + h->res_buflen,
        !           582:                                                  h->res_buf_alloclen - h->res_buflen,
        !           583:                                                  "infinite\r\n");
        !           584:                }
        !           585:        }
        !           586:        if(h->respflags & FLAG_SID) {
        !           587:                h->res_buflen += snprintf(h->res_buf + h->res_buflen,
        !           588:                                          h->res_buf_alloclen - h->res_buflen,
        !           589:                                          "SID: %s\r\n", h->req_SID);
        !           590:        }
        !           591: #endif
        !           592:        h->res_buf[h->res_buflen++] = '\r';
        !           593:        h->res_buf[h->res_buflen++] = '\n';
        !           594:        if(h->res_buf_alloclen < (h->res_buflen + bodylen))
        !           595:        {
        !           596:                h->res_buf = (char *)realloc(h->res_buf, (h->res_buflen + bodylen));
        !           597:                h->res_buf_alloclen = h->res_buflen + bodylen;
        !           598:        }
        !           599: }
        !           600: 
        !           601: void
        !           602: BuildResp2_upnphttp(struct upnphttp * h, int respcode,
        !           603:                     const char * respmsg,
        !           604:                     const char * body, int bodylen)
        !           605: {
        !           606:        BuildHeader_upnphttp(h, respcode, respmsg, bodylen);
        !           607:        if(body)
        !           608:                memcpy(h->res_buf + h->res_buflen, body, bodylen);
        !           609:        h->res_buflen += bodylen;
        !           610: }
        !           611: 
        !           612: /* responding 200 OK ! */
        !           613: void
        !           614: BuildResp_upnphttp(struct upnphttp * h,
        !           615:                         const char * body, int bodylen)
        !           616: {
        !           617:        BuildResp2_upnphttp(h, 200, "OK", body, bodylen);
        !           618: }
        !           619: 
        !           620: void
        !           621: SendResp_upnphttp(struct upnphttp * h)
        !           622: {
        !           623:        int n;
        !           624:        n = send(h->socket, h->res_buf, h->res_buflen, 0);
        !           625:        if(n<0)
        !           626:        {
        !           627:                syslog(LOG_ERR, "send(res_buf): %m");
        !           628:        }
        !           629:        else if(n < h->res_buflen)
        !           630:        {
        !           631:                /* TODO : handle correctly this case */
        !           632:                syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
        !           633:                                                n, h->res_buflen);
        !           634:        }
        !           635: }
        !           636: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>