⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sap.c

📁 Dvbstreamer 用在解析MPTS的部分内容
💻 C
字号:
/*Copyright (C) 2006  Adam CharrettThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USAsap.cSession Announcement Protocol.*/#include "config.h"#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <string.h>#include <netdb.h>#include <pthread.h>#include "main.h"#include "logging.h"#include "list.h"#include "objects.h"#include "udp.h"#include "sap.h"/******************************************************************************** Defines                                                                      ********************************************************************************/#define SAP_PORT (9875)/******************************************************************************** Typedefs                                                                     ********************************************************************************/typedef struct SAPSession_s {    bool deleted;    uint16_t messageIdHash;    struct sockaddr_storage originatingSource;    char sdp[1000];}SAPSession_t;/******************************************************************************** Prototypes                                                                   ********************************************************************************/static void SAPSessionFree(void *data);static int CreateSAPPacket(SAPSession_t *session, uint8_t *packet);static void DetermineSAPMulticast(SAPSession_t *session, struct sockaddr_storage *sockAddr);static void *SAPServer(void *arg);/******************************************************************************** Global variables                                                             ********************************************************************************/static const char mimeType[] = "application/sdp";static List_t *sessionList;static pthread_cond_t messageDelayCond = PTHREAD_COND_INITIALIZER;static pthread_mutex_t sessionListMutex = PTHREAD_MUTEX_INITIALIZER;static pthread_t serverThread;static uint16_t nextMessageIdHash = 1;static bool quit = FALSE;static char SAP[] = "SAP";/******************************************************************************** Global functions                                                             ********************************************************************************/bool IsMulticastAddress(struct sockaddr_storage *addr){    bool result = FALSE;    if (addr->ss_family == PF_INET)    {        struct sockaddr_in *inAddr = (struct sockaddr_in *)addr;        in_addr_t ip = ntohl(inAddr->sin_addr.s_addr);        result = ((ip >= 0xe0000000) && (ip <= 0xefffffff));        LogModule(LOG_DEBUG, SAP, "ip=0x%08x result=%d\n", ip,result);    }    else    {#ifndef __CYGWIN__                struct sockaddr_in6 *in6Addr = (struct sockaddr_in6*)addr;        result = (in6Addr->sin6_addr.s6_addr[0] == 0xff);#endif            }    return result;}void SAPServerInit(void){    ObjectRegisterType(SAPSession_t);    sessionList = ListCreate();    pthread_create(&serverThread, NULL, SAPServer, NULL);}void SAPServerDeinit(void){    quit = TRUE;    pthread_cond_signal(&messageDelayCond);    pthread_join(serverThread, NULL);    ListFree(sessionList, SAPSessionFree);}SAPSessionHandle_t SAPServerAddSession(struct sockaddr_storage *originatingSource, char *sdp){    SAPSession_t *session;    pthread_mutex_lock(&sessionListMutex);    session = ObjectCreateType(SAPSession_t);    if (session)    {        session->messageIdHash = nextMessageIdHash;        nextMessageIdHash ++;        memcpy(&session->originatingSource, originatingSource, sizeof(struct sockaddr_storage));        strcpy(session->sdp, sdp);            ListAdd(sessionList, session);    }    pthread_mutex_unlock(&sessionListMutex);    LogModule(LOG_DEBUG, SAP, "Added SAP session %x sdp:\n%s", session,sdp);    return session;}void SAPServerDeleteSession(SAPSessionHandle_t handle){    SAPSession_t *session = handle;    ListIterator_t iterator;    pthread_mutex_lock(&sessionListMutex);    ListRemove(sessionList, session);    session->deleted = TRUE;    ListIterator_Init(iterator, sessionList);    ListInsertBeforeCurrent(&iterator, session);    pthread_mutex_unlock(&sessionListMutex);        LogModule(LOG_DEBUG, SAP, "Deleted SAP session %x\n", handle);}/******************************************************************************** Local Functions                                                              ********************************************************************************/static void SAPSessionFree(void *data){    ObjectRefDec(data);}static int CreateSAPPacket(SAPSession_t *session, uint8_t *packet){    int mimeTypeOffset = 0;    /* Byte 0 : Version number V1        = 001      (3 bits)          *          Address type   IPv4/IPv6 = 0/1      (1 bit)          *          Reserved                   0        (1 bit)          *          Message Type   ann/del   = 0/1      (1 bit)          *          Encryption     on/off    = 0/1      (1 bit)          *          Compressed     on/off    = 0/1      (1 bit) */    packet[0] = 0x20 | (session->deleted ? 4:0);    packet[1] = 0x00; /* Authentication length (not supported) */    packet[2] = session->messageIdHash & 0xff;    packet[3] = (session->messageIdHash >> 8) & 0xff;    if (session->originatingSource.ss_family == PF_INET)    {        struct sockaddr_in *inAddr =(struct sockaddr_in *)&session->originatingSource;        mimeTypeOffset = 8;        memcpy(&packet[4], &inAddr->sin_addr, 4);    }#ifndef __CYGWIN__    else    {        struct sockaddr_in6 *in6Addr =(struct sockaddr_in6 *)&session->originatingSource;        mimeTypeOffset = 20;        memcpy(&packet[4], &in6Addr->sin6_addr, 16);    }#endif        memcpy(&packet[mimeTypeOffset], mimeType, sizeof(mimeType));    memcpy(&packet[mimeTypeOffset + sizeof(mimeType)], session->sdp, strlen(session->sdp));    return mimeTypeOffset + sizeof(mimeType) + strlen(session->sdp);}static void DetermineSAPMulticast(SAPSession_t *session, struct sockaddr_storage *sockAddr){        if (session->originatingSource.ss_family == PF_INET)    {        struct sockaddr_in *sessionAddr4 = (struct sockaddr_in*)&session->originatingSource;        struct sockaddr_in *sockAddr4 = (struct sockaddr_in *)sockAddr;        /* str is an IPv4 address */        in_addr_t ip = ntohl (sessionAddr4->sin_addr.s_addr);        /* 224.0.0.0/24 => 224.0.0.255 */        if ((ip & 0xffffff00) == 0xe0000000)        {            ip =  0xe00000ff;        }        /* 239.255.0.0/16 => 239.255.255.255 */        else if ((ip & 0xffff0000) == 0xefff0000)        {            ip =  0xefffffff;        }        /* 239.192.0.0/14 => 239.195.255.255 */        else if ((ip & 0xfffc0000) == 0xefc00000)        {            ip =  0xefc3ffff;        }        /* other multicast address => 224.2.127.254 */        else        {            ip = 0xe0027ffe;        }        ip = htonl (ip);        memset (sockAddr4, 0, sizeof (struct sockaddr_in));        sockAddr4->sin_family = AF_INET;        sockAddr4->sin_port = htons (SAP_PORT);        memcpy (&sockAddr4->sin_addr.s_addr, &ip, sizeof (ip));    }#ifndef __CYGWIN__    else    {        struct sockaddr_in6 *sessionAddr6 = (struct sockaddr_in6*)&session->originatingSource;                struct sockaddr_in6 *sockAddr6 = (struct sockaddr_in6 *)sockAddr;        memset (sockAddr6, 0, sizeof (struct sockaddr_in6));        sockAddr6->sin6_family = AF_INET6;        sockAddr6->sin6_scope_id = sessionAddr6->sin6_scope_id;        sockAddr6->sin6_port = htons (SAP_PORT);        memcpy (&sockAddr6->sin6_addr.s6_addr,                 "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x7f\xfe",                16);        sockAddr6->sin6_addr.s6_addr[1] = sessionAddr6->sin6_addr.s6_addr[1] & 0x0f;    }#endif    }static void *SAPServer(void *arg){    struct timespec waitFor;    uint8_t packet[UDP_PAYLOAD_SIZE];     int packetLen;    SAPSession_t *session;    int sessionCount;    ListIterator_t iterator;    struct sockaddr_storage sapMulticastAddr;        int socket4 = UDPCreateSocket(PF_INET);#ifndef __CYGWIN__        int socket6 = UDPCreateSocket(PF_INET6);#endif    int ttl = 255;        setsockopt(socket4,IPPROTO_IP,IP_MULTICAST_TTL, &ttl,sizeof(ttl));#ifndef __CYGWIN__        setsockopt(socket4,IPPROTO_IPV6,IPV6_MULTICAST_HOPS, &ttl,sizeof(ttl));#endif    LogModule(LOG_DEBUG, SAP, "Annoucement thread starting\n");    while (!quit)    {        pthread_mutex_lock(&sessionListMutex);        clock_gettime(CLOCK_REALTIME, &waitFor);        sessionCount = ListCount(sessionList);        if (sessionCount > 0)        {            /* Remove the first message from the front of the list, send it and              * add it to the back.              */            ListIterator_Init(iterator, sessionList);            session = (SAPSession_t*)ListIterator_Current(iterator);            ListRemoveCurrent(&iterator);            if (session->deleted)            {                ObjectRefDec(session);            }            else            {                ListAdd(sessionList, session);            }                        packetLen = CreateSAPPacket(session, packet);            DetermineSAPMulticast(session, &sapMulticastAddr);            /* Send the message */            if (session->originatingSource.ss_family == PF_INET)            {                UDPSendTo(socket4, packet, packetLen, (struct sockaddr *)&sapMulticastAddr, sizeof(struct sockaddr_in));            }#ifndef __CYGWIN__                        else            {                UDPSendTo(socket6, packet, packetLen, (struct sockaddr *)&sapMulticastAddr, sizeof(struct sockaddr_in6));            }#endif        }        waitFor.tv_sec += 1;        pthread_cond_timedwait(&messageDelayCond, &sessionListMutex, &waitFor);        pthread_mutex_unlock(&sessionListMutex);    }    LogModule(LOG_DEBUG, SAP, "Annoucement thread finished.\n");    close(socket4);    return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -