📄 sap.c
字号:
#include <time.h>#include <sys/types.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <stdint.h>#include <event.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include "getstream.h"#include "sap.h"#include "socket.h"/* * Implement Mini-SAP Service * * RFC 2974 (Session Announcement Protocol) * http://www.ietf.org/rfc/rfc2974.txt * RFC 2327 (SDP: Session Description Protocol) * http://www.ietf.org/rfc/rfc2327.txt * *//* RFC 2327 v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4o=<username> <session id> <version> <network type> <address type> <address> s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) c=IN IP4 224.2.17.12/127c=<network type> <address type> <connection address> t=2873397496 2873404696 a=recvonly m=audio 49170 RTP/AVP 0 m=video 51372 RTP/AVP 31 m=application 32416 udp wbm=<media> <port> <transport> <fmt list> a=orient:portrait*/static void sap_init_timer_single(struct sap_s *sap);static char sappkt[SAP_MAX_SIZE];static int sid=1; /* MSG Identifier - Unique for each session */#define SAP_VERSION 1#define SAP_VERSION_SHIFT 5static void sap_send(int fd, short event, void *arg) { struct sap_s *sap=arg; char *sp; /* Clear Packet */ memset(&sappkt, 0, SAP_MAX_SIZE); sappkt[0]=SAP_VERSION<<SAP_VERSION_SHIFT; /* Version + Bitfield */ sappkt[1]=0x0; /* Auth len */ sappkt[2]=sap->sid>>8&0xff; /* Unique session ID */ sappkt[3]=sap->sid&0xff; /* * FIXME - This would need to be the originating * not the destination address */ sappkt[4]=sap->addr&0xff; sappkt[5]=sap->addr>>8&0xff; sappkt[6]=sap->addr>>16&0xff; sappkt[7]=sap->addr>>24&0xff; sp=sappkt+8; sp+=sprintf(sp, "v=0\r\n"); sp+=sprintf(sp, "o=%s\r\n", sap->odata); if (sap->output->stream->name) sp+=sprintf(sp, "s=%s\r\n", sap->output->stream->name); sp+=sprintf(sp, "t=0 0\r\n"); sp+=sprintf(sp, "a=tool:getstream\r\n"); sp+=sprintf(sp, "a=type:broadcast\r\n"); sp+=sprintf(sp, "m=%s\r\n", sap->mdata); sp+=sprintf(sp, "c=%s\r\n", sap->cdata); if (sap->playgroup) { sp+=sprintf(sp, "a=x-plgroup:%s\r\n", sap->playgroup); } send(sap->fd, sappkt, sp-sappkt, MSG_DONTWAIT); sap_init_timer_single(sap);}static void sap_init_timer_single(struct sap_s *sap) { static struct timeval tv; /* * Create timer to send out SAPs regularly */ tv.tv_usec=0; tv.tv_sec=1; evtimer_set(&sap->event, &sap_send, sap); evtimer_add(&sap->event, &tv);}static void sap_init_socket_single(struct sap_s *sap) { char *maddr; int port; sap->fd=socket_open(NULL, 0); if (sap->fd == -1) { fprintf(stderr, "Unable to open SAP socket\n"); exit(-1); } /* Last resort Multicast config */ maddr=SAP_V4_GLOBAL_ADDRESS; port=SAP_PORT; /* get SAP remote address from scope or group */ if (sap->scope) { /* Most simple way - We have a scope */ if (strcasecmp(sap->scope, "global") == 0) { maddr=SAP_V4_GLOBAL_ADDRESS; } else if(strcasecmp(sap->scope, "org") == 0) { maddr=SAP_V4_ORG_ADDRESS; } else if(strcasecmp(sap->scope, "local") == 0) { maddr=SAP_V4_LOCAL_ADDRESS; } else { maddr=SAP_V4_LINK_ADDRESS; } port=SAP_PORT; } else if(sap->group) { maddr=sap->group; port=sap->port; } socket_join_multicast(sap->fd, maddr); socket_connect(sap->fd, maddr, port); socket_set_ttl(sap->fd, sap->ttl);}/* Create SDP Connection Data as per RFC2327 */static char *sap_init_cdata(struct sap_s *sap) { char cdata[128]; /* mcast c=IN IP4 ipaddr/ttl */ /* ucast c=IN IP4 ipaddr */ /* Ignore the ucast case for UDP and RTP as it does not make * sense to announce ucast UDP/RTP */ switch(sap->output->type) { case(OTYPE_UDP): case(OTYPE_RTP): sprintf(cdata, "IN IP4 %s/%d", sap->output->remoteaddr, sap->output->ttl); break; case(OTYPE_RTCP): if (sap->output->localaddr) { sprintf(cdata, "IN IP4 %s/%d", sap->output->localaddr, sap->output->ttl); } else { char hname[80]; gethostname(hname, sizeof(hname)); sprintf(cdata, "IN IP4 %s/%d", hname, sap->output->ttl); } break; default: fprintf(stderr, "Unknown stream output type in %s", __FUNCTION__); exit(-1); } return strdup(cdata);}/* Create SDP Media Announcement as per RFC2327 */static char *sap_init_mdata(struct sap_s *sap) { char mdata[128]; /* m=audio/video ipport udp 33 */ /* m=audio/video ipport rtp/avp 31 */ switch(sap->output->type) { case(OTYPE_UDP): sprintf(mdata, "video %d udp 33", sap->output->remoteport); break; case(OTYPE_RTP): sprintf(mdata, "video %d RTP/AVP 33", sap->output->remoteport); break; case(OTYPE_RTCP): sprintf(mdata, "video %d RTP/AVP 33", sap->output->rtpport); break; } return strdup(mdata);}/* Create SDP Origin as per RFC2327 */static char *sap_init_odata(struct sap_s *sap) { char odata[128]; switch(sap->output->type) { case(OTYPE_UDP): case(OTYPE_RTP): sprintf(odata, "- %d %lu IN IP4 %s", sap->sid, time(NULL), sap->output->remoteaddr); break; case(OTYPE_RTCP): if (sap->output->localaddr) { sprintf(odata, "IN IP4 %s", sap->output->localaddr); } else { char hname[80]; gethostname(hname, sizeof(hname)); sprintf(odata, "- %d %lu IN IP4 %s", sap->sid, time(NULL), hname); } break; } return strdup(odata);}int sap_init(struct sap_s *sap) { /* Copy a Session ID into the SAP structure. This needs to be unique * for a SAP sender and needs to be changed in case the SAP announcement * changes */ sap->sid=sid++; /* Open Socket */ sap_init_socket_single(sap); /* Create Stream Connection Data for SDP */ sap->cdata=sap_init_cdata(sap); /* Create Media Announcement Data for SDP */ sap->mdata=sap_init_mdata(sap); /* Create Origin Data for SDP */ sap->odata=sap_init_odata(sap); /* Start timer */ sap_init_timer_single(sap); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -