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

📄 rtspapi.c

📁 krtsp
💻 C
📖 第 1 页 / 共 2 页
字号:
/* rtspapi.c - basic rtsp functions for sipum system. * (c) 2000 - 2001 Columbia University. All rights reserved.*/#include <stdio.h>#include <stdlib.h>                 /* malloc */#include <unistd.h>                 /* close */#include <sys/types.h>             #include <sys/socket.h>#include <netinet/in.h>             /* sockaddr_in */#include <arpa/inet.h>              /* inet_ntoa */#include "librtsp.h"                /* rtspapi calls are declared here */#include <errno.h>#include "dstring.h"                /* DString */#include "strdupn.h"                /* free_valid */#include "error.h"                  /* error, debug */#include "string.h"                 /* strcasecmp */#include "sysdep.h"                 /* closesocket */#include "request-common.h"         /* request_common_t */#include "rfc822.h"                 /* Parsing routines */#include "http.h"#include "rtsp.h"                   /* RTSP specific parsing *//** * Global macros for RTSP implementation. * This is used in the request line. */#define RTSP_VERSION  "RTSP/1.0"/**  * A session object stores all information about the * RTSP session. We use a pointer to this object for * identifying a session by rtspcontext_t */typedef struct rtspsession_t {  /* URI for the session */  uri_t uri;  /* Socket */  int sock;  /* CSeq for transmit side, incremented for every message. */  unsigned int cseq_tx;  /* Media IP and port for receiving media. This maps    * to client_ports; and destination for play mode. */  struct sockaddr_storage media_rx;  /* Media IP and port of the server. */  struct sockaddr_storage media_tx;  /* Whether the sock is connected to remote or not */  int connected;  /* double: duration of the file in seconds */  float duration;  /* session identifier */  char *session;  /* mode, record/play */  char *mode;} rtspsession_t;typedef struct rtsp_response_t {  parser_t p;  char *content;} rtsp_response_t;/********************* API Utility functions *****************/rtspcontext_t RTSP_Create(const char* url){  rtspsession_t *s = NULL;  int af;  struct sockaddr_storage sin;  /* Check if argument is valid */  if (url == NULL) {    debug(DEBUG_MISC, "RTSP_Create", "URL passed is NULL\n");    goto failure;  }  /* Allocate a session object */  s = (rtspsession_t *)calloc(1, sizeof(rtspsession_t));  if (s == NULL) {    error("RTSP_Create", "calloc failed\n");    goto failure;  }  s->duration = 0.;    /* Parse the URL */  memset(&s->uri, 0, sizeof(s->uri));  s->uri = URI_Parse(url);  af = AF_INET;  /* use ipv6 if the host is a v6 host and ipv6   * is usable.  */  memset(&sin, 0, sizeof(sin));  if (AFIGetAddrByName(&sin, s->uri.host) == 0) {    if (sin.ss_family == AF_INET6 && AFIIPv6Active()) {      af = AF_INET6;    }  }  s->media_rx.ss_family = af;  s->media_tx.ss_family = af;  /*    * Check if the URL scheme is valid and create   * an TCP socket for rtsp:// and UDP socket for rtspu://   */  if (s->uri.scheme == NULL || *s->uri.scheme == '\0') {    debug(DEBUG_MISC, "RTSP_Create", "Could not parse the URL %s\n", url);    goto failure;  }  if (!strcasecmp(s->uri.scheme, "rtsp")) { /* Start a TCP socket */    s->sock = socket(af, SOCK_STREAM, 0);    if (s->sock < 0) {      error("RTSP_Create", "TCP socket() failed\n");      goto failure;    }  }  else if (!strcasecmp(s->uri.scheme, "rtspu")) {    error("RTSP_Create", "rtspu:// not supported\n");    goto failure;  }  else {    debug(DEBUG_MISC, "RTSP_Create", "Unsupported URL scheme %s\n",          s->uri.scheme);    goto failure;  }  if (s->uri.port == 0) {    debug(DEBUG_MISC, "RTSP_Create", "No port specified, using default.\n");    s->uri.port = 554; /* This is the default port number for RTSP */  }  /* Initialize the cseq on tx side. */  s->cseq_tx = 1;  /* Initialize the client ports */  AFISetPort(&s->media_rx, 0);  return s;  /* Reach here on error condition. */failure:  debug(DEBUG_MISC, "RTSP_Create",  "Failed\n");  if (s != NULL) {    /* Close socket. */    if (s->sock >= 0) {      closesocket(s->sock);    }    /* Free URI */    if (s->uri.scheme != NULL) {      URI_Free(&s->uri);    }  }  free_valid(s);  return NULL;}void RTSP_Destroy(rtspcontext_t c){  rtspsession_t *s = (rtspsession_t *) c;  debug(DEBUG_MISC, "RTSP_Destroy", "called\n");  if (s != NULL) {    /* Close socket. */    if (s->sock >= 0) {      closesocket(s->sock);    }    /* Free URI */    if (s->uri.scheme != NULL) {      URI_Free(&s->uri);    }    free_valid(s->session);    free_valid(s->mode);    memset(s, 0, sizeof(*s));  }  free_valid(s);  return;}void RTSP_SetDestinationAddress(rtspcontext_t c, const char *addr){  struct sockaddr_storage sin;  rtspsession_t *s = (rtspsession_t *) c;  if (s == NULL || addr == NULL) {    debug(DEBUG_MISC, "RTSP_SetDestinationAddress", "context or addr is NULL\n");    return;  }  memset(&sin, 0, sizeof(sin));  if (AFIGetAddrByName(&sin, addr) == 0) {    memcpy(&s->media_rx, &sin, sizeof(sin));    return;  }  else {    error("RTSP_SetDestinationAddress",           "Error resolving %s\n", addr);    return;  }    return;}void RTSP_SetClientPort(rtspcontext_t c, unsigned short port){  rtspsession_t *s = (rtspsession_t *) c;  if (s == NULL) {    debug(DEBUG_MISC, "RTSP_SetClientPort", "Context is NULL\n");    return;  }  AFISetPort(&s->media_rx, port);  return;}char* RTSP_GetServerAddress(rtspcontext_t c){  rtspsession_t *s = (rtspsession_t *) c;  struct sockaddr_storage sin;  socklen_t len;  if (s == NULL || s->sock < 0) {    debug(DEBUG_MISC, "RTSP_GetServerAddress",           "Context is NULL or socket is not connected\n");    return NULL;  }  /* Get the remote name of the connected socket. */  len = sizeof(sin);  if (getpeername(s->sock, (struct sockaddr *)&sin, &len) == 0) {    char *p = AFIGetDottedAddress((struct sockaddr*)&sin);    return p; /* no need for strdup, as the dot fn returns a new str */  }  else {    debug(DEBUG_MISC, "RTSP_GetServerAddress", "getpeername failed\n");    return NULL;  }}unsigned short RTSP_GetServerPort(rtspcontext_t c){  rtspsession_t *s = (rtspsession_t *) c;  if (s == NULL) {    debug(DEBUG_MISC, "RTSP_GetServerPort",           "Context is NULL\n");    return 0;  }    return AFIGetPort(&s->media_tx);}char * RTSP_GetSessionId(rtspcontext_t c){  rtspsession_t *s = (rtspsession_t *) c;  if (s == NULL) {    debug(DEBUG_MISC, "RTSP_GetSessionId",           "Context is NULL\n");    return 0;  }  if (s->session) {    return strdup(s->session);  }  else {    return NULL;  }}float RTSP_GetDuration(rtspcontext_t c){  rtspsession_t *s = (rtspsession_t *) c;  if (s == NULL) {    debug(DEBUG_MISC, "RTSP_GetDuration",           "Context is NULL\n");    return 0;  }    return s->duration;}int RTSP_Connect(rtspcontext_t c){  struct sockaddr_storage sin;  int sinlen;  rtspsession_t *s = (rtspsession_t *) c;  if (s == NULL || s->sock < 0 || s->uri.host == NULL || s->uri.port == 0) {    debug(DEBUG_MISC, "RTSP_Connect", "Parameter is incorrect\n");    return -1;  }  s->connected = 0;    memset(&sin, 0, sizeof(sin));  if (AFIGetAddrByName(&sin, s->uri.host) == 0) {    AFISetPort(&sin, s->uri.port);    sinlen = (sin.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) :                                           sizeof(struct sockaddr_in);    if (connect(s->sock, (const struct sockaddr *)&sin, sinlen) != 0) {      error("RTSP_Connect", "Connect failed\n");      return -1;    }      s->connected = 1;  }  else {    error("RTSP_Connect", "Unable to resolve address %s\n", s->uri.host);  }  return 0;}int RTSP_Send(rtspsession_t *s, DString *msg){  int e, retrycount = 2;  if (s == NULL || msg== NULL) {    debug(DEBUG_MISC, "RTSP_Send", "incorrect parameter\n");    return -1;  }  while (--retrycount >= 0)  {    if (!s->connected && RTSP_Connect(s) < 0) {      error("RTSP_Send", "Couldnot connect to the server\n");      return -1;    }      debug(DEBUG_MISC, "RTSP_Send", "Sending %d bytes to socket %d,\n%s\n",          DStringLength(msg), s->sock, DStringValue(msg));    if ((e = send(s->sock, DStringValue(msg),                   DStringLength(msg), 0)) <= 0) {      if (retrycount && (errno == EBADF || errno == ENOTSOCK)) {        s->connected = 0;         continue;      }      debug(DEBUG_MISC, "RTSP_Send", "send() failed\n");      return -1;    }    else {      break;    }  } /* while */   debug(DEBUG_MISC, "RTSP_Send", "Sent %d bytes\n", e);  return 0;}void RTSP_ResponseFree(rtsp_response_t *r){  if (r) {    free_valid(r->content);    HTTP_Free(&r->p);  }  free_valid(r);}/***************** Parsing related functions ****************/rtsp_response_t *RTSP_ReceiveResponse(rtspsession_t * s){  enum {Header, CR, CRNL, CRNLCR, NL, Body} state = Header;  int content_length;      /* Content-Length field */  int cl = 0;              /* bytes read in content (body) */  int c;                   /* current character */  char ch;                 /* same, as char */  DString header, body;    /* header and body */   rtsp_response_t *r = NULL; /* response message */  FILE_SOCKET *f;          /* socket, as FILE */    if (s == NULL) {    debug(DEBUG_MISC, "RTSP_ReceiveResponse", "incorrect parameter\n");    return NULL;  }  f = fdopen_socket(s->sock, "r");  if (f == NULL) {    error ("RTSP_ReceiveResponse", "Couldn't fdopen socket %d for reading",           s->sock);    return NULL;  }   c = EOF; /* To avoid warning */    /* Once around the loop for each message. */  DStringInit(&header);  DStringInit(&body);    state          = Header;  content_length = INFINITE_CONTENT_LENGTH;  cl             = 0;  r              = NULL;  debug(DEBUG_MISC, "RTSP_ReceiveResponse", "Waiting to receive packet\n");  while ((cl < content_length) && ((c = getc_socket(f)) != EOF)) {    ch = c;    DStringAppend(state == Body ? &body : &header, &ch, 1);    switch (state) {    case Header:      if (c == '\r') state = CR;      else if (c == '\n') state = NL;      break;    case CR:      if (c == '\n') state = CRNL;      else state = Header;      break;    case CRNL:      if (c == '\r') state = CRNLCR;      else state = Header;      break;    case NL:    case CRNLCR:      if (c == '\n') {        if (header.length > 4) {          debug(DEBUG_MISC, "RTSP_ReceiveResponse",                "Incoming TCP message on socket %d (%d bytes)\n%s\n",                s->sock, header.length,                DStringValue(&header));          r = (rtsp_response_t *)calloc(1, sizeof(rtsp_response_t));	              if (HTTP_Parse(DStringValue(&header), &r->p) < 0) {            /* If this was a request whose headers didn't parse, we want             * to try to send a 400 response to it.  On the other hand,             * there's not much we can do with responses that didn't parse,             * so just mark them as the unknown message type so that the             * server ignores them and frees their memory.             */            if (r->p.type == http_request) {              r->p.status = 400;            } else {              r->p.type = http_unknown_type;            }          }	              content_length = HTTP_ContentLength(&r->p);          /* INFINITE_CONTENT_LENGTH is the "default" value returned by             the parser, implying content length was not specified */          if (content_length == INFINITE_CONTENT_LENGTH) {            content_length = 0;

⌨️ 快捷键说明

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