Add evrtsp - RTSP implementation on top of libevent, derived from evhttp

This commit is contained in:
Julien BLACHE 2010-05-02 11:31:30 +02:00
parent 8427707afc
commit 992eb9009a
4 changed files with 2112 additions and 0 deletions

169
src/evrtsp/evrtsp.h Normal file
View File

@ -0,0 +1,169 @@
/*
* Copyright (C) 2010 Julien BLACHE <jb@jblache.org>
* Based on evhttp from libevent 1.4.x
*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EVRTSP_H_
#define _EVRTSP_H_
#include <event.h>
#include <evhttp.h> /* FIXME: forked-daapd's one */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#endif
/* Response codes */
#define RTSP_OK 200
#define RTSP_UNAUTHORIZED 401
struct evrtsp_connection;
/*
* Interfaces for making requests
*/
enum evrtsp_cmd_type {
EVRTSP_REQ_ANNOUNCE,
EVRTSP_REQ_OPTIONS,
EVRTSP_REQ_SETUP,
EVRTSP_REQ_RECORD,
EVRTSP_REQ_PAUSE,
EVRTSP_REQ_GET_PARAMETER,
EVRTSP_REQ_SET_PARAMETER,
EVRTSP_REQ_FLUSH,
EVRTSP_REQ_TEARDOWN,
};
enum evrtsp_request_kind { EVRTSP_REQUEST, EVRTSP_RESPONSE };
struct evrtsp_request {
#if defined(TAILQ_ENTRY)
TAILQ_ENTRY(evrtsp_request) next;
#else
struct {
struct evrtsp_request *tqe_next;
struct evrtsp_request **tqe_prev;
} next;
#endif
/* the connection object that this request belongs to */
struct evrtsp_connection *evcon;
int flags;
#define EVRTSP_REQ_OWN_CONNECTION 0x0001
struct evkeyvalq *input_headers;
struct evkeyvalq *output_headers;
enum evrtsp_request_kind kind;
enum evrtsp_cmd_type type;
char *uri; /* uri after RTSP request was parsed */
char major; /* RTSP Major number */
char minor; /* RTSP Minor number */
int response_code; /* RTSP Response code */
char *response_code_line; /* Readable response */
struct evbuffer *input_buffer; /* read data */
ev_int64_t ntoread;
struct evbuffer *output_buffer; /* outgoing post or data */
/* Callback */
void (*cb)(struct evrtsp_request *, void *);
void *cb_arg;
};
/**
* Creates a new request object that needs to be filled in with the request
* parameters. The callback is executed when the request completed or an
* error occurred.
*/
struct evrtsp_request *evrtsp_request_new(
void (*cb)(struct evrtsp_request *, void *), void *arg);
/** Frees the request object and removes associated events. */
void evrtsp_request_free(struct evrtsp_request *req);
/**
* A connection object that can be used to for making RTSP requests. The
* connection object tries to establish the connection when it is given an
* rtsp request object.
*/
struct evrtsp_connection *evrtsp_connection_new(
const char *address, unsigned short port);
/** Frees an rtsp connection */
void evrtsp_connection_free(struct evrtsp_connection *evcon);
/** Set a callback for connection close. */
void evrtsp_connection_set_closecb(struct evrtsp_connection *evcon,
void (*)(struct evrtsp_connection *, void *), void *);
/**
* Associates an event base with the connection - can only be called
* on a freshly created connection object that has not been used yet.
*/
void evrtsp_connection_set_base(struct evrtsp_connection *evcon,
struct event_base *base);
/** Get the remote address and port associated with this connection. */
void evrtsp_connection_get_peer(struct evrtsp_connection *evcon,
char **address, u_short *port);
/** Get the local address and port associated with this connection. */
void
evrtsp_connection_get_local_address(struct evrtsp_connection *evcon,
char **address, u_short *port);
/** The connection gets ownership of the request */
int evrtsp_make_request(struct evrtsp_connection *evcon,
struct evrtsp_request *req,
enum evrtsp_cmd_type type, const char *uri);
const char *evrtsp_request_uri(struct evrtsp_request *req);
/* Interfaces for dealing with headers */
const char *evrtsp_find_header(const struct evkeyvalq *, const char *);
int evrtsp_remove_header(struct evkeyvalq *, const char *);
int evrtsp_add_header(struct evkeyvalq *, const char *, const char *);
void evrtsp_clear_headers(struct evkeyvalq *);
#ifdef __cplusplus
}
#endif
#endif /* !_EVRTSP_H_ */

51
src/evrtsp/log.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOG_H_
#define _LOG_H_
#ifdef __GNUC__
#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b)))
#else
#define EV_CHECK_FMT(a,b)
#endif
void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3);
void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2);
void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3);
void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2);
void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2);
void _event_debugx(const char *fmt, ...) EV_CHECK_FMT(1,2);
#ifdef USE_DEBUG
#define event_debug(x) _event_debugx x
#else
#define event_debug(x) do {;} while (0)
#endif
#undef EV_CHECK_FMT
#endif

108
src/evrtsp/rtsp-internal.h Normal file
View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2010 Julien BLACHE <jb@jblache.org>
* Based on evhttp from libevent 1.4.x
*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* This header file contains definitions for dealing with RTSP requests
* that are internal to libevent. As user of the library, you should not
* need to know about these.
*/
#ifndef _RTSP_H_
#define _RTSP_H_
#define RTSP_CONNECT_TIMEOUT 45
#define RTSP_WRITE_TIMEOUT 50
#define RTSP_READ_TIMEOUT 50
#define RTSP_PREFIX "rtsp://"
enum message_read_status {
ALL_DATA_READ = 1,
MORE_DATA_EXPECTED = 0,
DATA_CORRUPTED = -1,
REQUEST_CANCELED = -2
};
enum evrtsp_connection_error {
EVCON_RTSP_TIMEOUT,
EVCON_RTSP_EOF,
EVCON_RTSP_INVALID_HEADER
};
struct evbuffer;
struct addrinfo;
struct evrtsp_request;
/* A stupid connection object - maybe make this a bufferevent later */
enum evrtsp_connection_state {
EVCON_DISCONNECTED, /**< not currently connected not trying either*/
EVCON_CONNECTING, /**< tries to currently connect */
EVCON_IDLE, /**< connection is established */
EVCON_READING_FIRSTLINE,/**< reading Request-Line (incoming conn) or
**< Status-Line (outgoing conn) */
EVCON_READING_HEADERS, /**< reading request/response headers */
EVCON_READING_BODY, /**< reading request/response body */
EVCON_READING_TRAILER, /**< reading request/response chunked trailer */
EVCON_WRITING /**< writing request/response headers/body */
};
struct event_base;
struct evrtsp_connection {
int fd;
struct event ev;
struct event close_ev;
struct evbuffer *input_buffer;
struct evbuffer *output_buffer;
char *bind_address; /* address to use for binding the src */
u_short bind_port; /* local port for binding the src */
char *address; /* address to connect to */
u_short port;
int flags;
#define EVRTSP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */
int timeout; /* timeout in seconds for events */
enum evrtsp_connection_state state;
int cseq;
TAILQ_HEAD(evcon_requestq, evrtsp_request) requests;
void (*cb)(struct evrtsp_connection *, void *);
void *cb_arg;
void (*closecb)(struct evrtsp_connection *, void *);
void *closecb_arg;
struct event_base *base;
};
/* resets the connection; can be reused for more requests */
void evrtsp_connection_reset(struct evrtsp_connection *);
/* connects if necessary */
int evrtsp_connection_connect(struct evrtsp_connection *);
/* notifies the current request that it failed; resets connection */
void evrtsp_connection_fail(struct evrtsp_connection *,
enum evrtsp_connection_error error);
int evrtsp_hostportfile(char *, char **, u_short *, char **);
int evrtsp_parse_firstline(struct evrtsp_request *, struct evbuffer*);
int evrtsp_parse_headers(struct evrtsp_request *, struct evbuffer*);
void evrtsp_start_read(struct evrtsp_connection *);
void evrtsp_make_header(struct evrtsp_connection *, struct evrtsp_request *);
void evrtsp_write_buffer(struct evrtsp_connection *,
void (*)(struct evrtsp_connection *, void *), void *);
#endif /* _RTSP_H */

1784
src/evrtsp/rtsp.c Normal file

File diff suppressed because it is too large Load Diff