Files
TAIXIN/sdk/include/lib/net/urlfile/urlfile.h

477 lines
14 KiB
C
Raw Normal View History

/**
* @file url_file.h
* @brief URL
*
* HTTP, RTSP, FILE URL
*
* 使
*/
#ifndef _URL_FILE_H_
#define _URL_FILE_H_
#include "basic_include.h"
#include "lib/common/rbuffer.h"
#include "lib/posix/stdio.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"
#include "lwip/inet_chksum.h"
#include "netif/etharp.h"
#include "netif/ethernetif.h"
#include "lwip/ip.h"
#include "lwip/init.h"
#include "lib/net/skmonitor/skmonitor.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
/** @brief 通用调试打印宏 */
#define UF_DEBUG(f,...) os_printf("%s:%d:"f, __FUNCTION__, __LINE__, ##__VA_ARGS__)
/** @brief 错误日志打印宏 (带内核错误前缀) */
#define UF_ERR(f,...) os_printf(KERN_ERR"%s:%d:"f, __FUNCTION__, __LINE__, ##__VA_ARGS__)
/** @brief 获取读锁 (阻塞直到获取成功) */
#define UF_LOCK_READ(uf) os_mutex_lock(&uf->r_lock, osWaitForever)
/** @brief 释放读锁 */
#define UF_UNLOCK_READ(uf) os_mutex_unlock(&uf->r_lock)
/** @brief 获取写锁 (阻塞直到获取成功) */
#define UF_LOCK_WRITE(uf) os_mutex_lock(&uf->w_lock, osWaitForever)
/** @brief 释放写锁 */
#define UF_UNLOCK_WRITE(uf) os_mutex_unlock(&uf->w_lock)
/** @brief 获取协议保护锁 (阻塞直到获取成功) */
#define UF_LOCK_PROTO(uf) os_mutex_lock(&uf->lock, osWaitForever)
/** @brief 释放协议保护锁 */
#define UF_UNLOCK_PROTO(uf) os_mutex_unlock(&uf->lock)
/** @brief 检查是否处于读模式 */
#define UF_READ(uf) ((uf)->mode & UF_MODE_RD)
/** @brief 检查是否处于写模式 */
#define UF_WRITE(uf) ((uf)->mode & UF_MODE_WR)
/** @brief 检查是否处于 AV (音视频) 模式 */
#define UF_AVMODE(uf) ((uf)->mode & UF_MODE_AV)
/**
* @brief URL
*/
typedef enum {
UF_CLOSE = -2, /**< 需要关闭,此状态只能由 uf_close 设置 */
UF_ERROR = -1, /**< 发生错误 */
UF_NONE = 0, /**< 初始状态 */
UF_ROPEN = 1, /**< 重新打开中 */
UF_OPEN = 2, /**< 开始打开连接 */
UF_RUN = 3, /**< 数据传输中 */
UF_DONE = 4 /**< 数据传输完成,处于空闲状态 */
} UF_STATE;
/**
* @brief URL
*/
typedef enum {
UF_MODE_AV = BIT(0), /**< AV 模式 (音视频流) */
UF_MODE_RD = BIT(1), /**< 支持读取 */
UF_MODE_WR = BIT(2), /**< 支持写入 */
UF_MODE_RECV = BIT(3), /**< 客户自定义接收模式 (通过回调获取数据) */
UF_MODE_MONITOR = BIT(4), /**< 使用 Socket 监控模式 (不创建独立任务) */
UF_MODE_AUTO_RUN = BIT(5), /**< 自动运行模式 (打开后立即启动传输) */
} UF_MODE;
/**
* @brief
*/
typedef enum {
UF_PLAYLIST_NONE = 0, /**< 无播放列表 */
UF_PLAYLIST_CUST, /**< 自定义格式 */
UF_PLAYLIST_HLS, /**< HLS (.m3u8) */
UF_PLAYLIST_ASX, /**< ASX (Windows Media) */
UF_PLAYLIST_MMSREF, /**< MMS Reference */
UF_PLAYLIST_M3U, /**< M3U */
UF_PLAYLIST_PLS, /**< PLS */
UF_PLAYLIST_NSC, /**< NSC (Netshow) */
UF_PLAYLIST_SMIL, /**< SMIL */
UF_PLAYLIST_XSPF, /**< XSPF */
UF_PLAYLIST_MAX, /**< 类型总数 */
} UF_PLAYLIST_TYPE;
/**
* @brief IO
*/
typedef enum {
UF_IOCTL_CMD_IDLE, /**< 空闲命令 */
UF_IOCTL_CMD_SOCK_ERROR, /**< 获取/设置 Socket 错误 */
UF_IOCTL_CMD_GET_FILESIZE, /**< 获取文件大小 */
UF_IOCTL_CMD_GET_TOTALTIME, /**< 获取总时长 (媒体文件) */
UF_IOCTL_CMD_SET_EVTCB, /**< 设置事件回调函数 */
UF_IOCTL_CMD_SET_BREAKPOINT_CONTINUALLY,/**< 设置断点续传参数 */
UF_IOCTL_CMD_SET_HTTP_HEADER, /**< 设置自定义 HTTP 头 */
UF_IOCTL_CMD_SET_HTTP_UPSIZE, /**< 设置 HTTP 上传大小 */
} UF_IOCTL_CMD;
/**
* @brief URL
*/
typedef enum {
UF_EVENT_RECVD_DATA, /**< 接收到数据事件 (用于 UF_MODE_RECV 模式) */
UF_EVENT_TRANS_COMPLETE, /**< 传输完成事件 */
} UF_EVENT;
struct urlfile;
/**
* @brief
*
* ( http, rtsp, file)
*/
struct ufprotocol_ops {
/** @brief 初始化协议上下文 */
int (*do_init)(struct urlfile *file);
/** @brief 释放协议资源 */
int (*do_release)(struct urlfile *file);
/** @brief 执行主传输循环 */
int (*do_run)(struct urlfile *file);
/** @brief seek 操作 (跳转) */
int (*do_seek)(struct urlfile *file, long offset, int whence);
/** @brief 发送数据 */
int (*do_send)(struct urlfile *file, void *data, size_t size);
/** @brief 协议特定的 IO 控制 */
int (*do_ioctl)(struct urlfile *file, uint32 cmd, uint32 param1, uint32 param2);
};
/**
* @brief
*/
struct ufprotocol {
const char *name; /**< 协议名称 (如 "http", "rtsp") */
const struct ufprotocol_ops *ops; /**< 操作函数集指针 */
};
/**
* @brief
*
* @param file URL
* @param evet (@ref UF_EVENT)
* @param param1 1 ()
* @param param2 2 ()
* @return int32
*/
typedef int32(*uf_evt_cb)(struct urlfile *file, uint32 evet, uint32 param1, uint32 param2);
/**
* @brief
*/
struct uf_playlist_entry {
struct list_head list; /**< 链表节点 */
char *title; /**< 媒体标题 */
char *url; /**< 媒体 URL */
};
/**
* @brief
*/
struct uf_playlist {
uint8 *buff_addr; /**< 缓冲区地址 (用于存储原始播放列表数据) */
uint32 buff_size; /**< 缓冲区总大小 */
uint32 buff_len; /**< 当前已填充长度 */
int16 type; /**< 播放列表类型 (@ref UF_PLAYLIST_TYPE) */
uint16 count; /**< 条目数量 */
struct list_head list;/**< 条目链表头 */
};
/**
* @brief URL
*
* URL
*/
struct urlfile {
uint8 mode; /**< 打开模式: 0:AVMODE, BIT0:read; BIT1:write; others:customize */
int8 state; /**< URL 文件当前状态 (@ref UF_STATE) */
uint16 sock; /**< 关联的 Socket 描述符 */
char *url; /**< 当前打开的 URL 字符串 */
off_t size; /**< 文件总大小。初始为 0连接成功后设置。若未知 (如直播流) 则设为 -1 */
off_t cur_pos; /**< 当前读取位置 */
off_t doffset; /**< 当前下载偏移量 (用于断点续传) */
void *priv; /**< 协议层私有数据指针 */
uf_evt_cb evt_cb; /**< 事件回调函数指针 */
struct os_mutex lock; /**< 全局互斥锁 (保护主要状态) */
struct os_mutex r_lock; /**< 读操作互斥锁 */
struct os_mutex w_lock; /**< 写操作互斥锁 */
uint64 open_tick; /**< 打开时的系统 tick 计数 ,用于统计网络打开延时 */
const struct ufprotocol *proto; /**< 匹配的协议描述符指针 */
struct rbuffer buffer; /**< 接收数据环形缓冲区 */
void *task; /**< 处理任务句柄 (若非监控模式) */
struct uf_playlist playlist; /**< 播放列表信息 */
uint16 playindex; /**< 当前播放的索引 */
uint8 seek_type; /**< Seek 类型标志 */
uint8 rev; /**< 保留字段 */
};
/* ================= 外部API声明 ================= */
/**
* @brief URL
*
* URL
*
* @param url URL ( "http://...", "rtsp://...")
* @param mode :
* - 'v': AV ()
* - 'r':
* - 'w':
* - 'c': ( uf_read UF_EVENT_RECVD_DATA UF_IOCTL_CMD_SET_EVTCB)
* - 'm': 使 Socket ( urlfile )
* - 'a': ()
* @param flags
* @return void* urlfile NULL
*/
void *uf_open(char *url, char *mode, uint32 flags);
/**
* @brief URL
*
*
*
* @param file urlfile
*/
void uf_close(void *file);
/**
* @brief URL
*
* fread
*
* @param ptr
* @param size
* @param nmemb
* @param file urlfile
* @return size_t
*/
size_t uf_read(void *ptr, size_t size, size_t nmemb, void *file);
/**
* @brief URL
*
* fwrite
*
* @param ptr
* @param size
* @param nmemb
* @param file urlfile
* @return size_t
*/
size_t uf_write(void *ptr, size_t size, size_t nmemb, void *file);
/**
* @brief
*
* @param file urlfile
* @param offset
* @param whence (SEEK_SET, SEEK_CUR, SEEK_END)
* @return int 0: ; -1:
*/
int uf_seek(void *file, long offset, int whence);
/**
* @brief
*
* @param file urlfile
* @return off_t
*/
off_t uf_tell(void *file);
/**
* @brief
*
* @param file urlfile
* @return int 1: ; 0:
*/
int uf_eof(void *file);
/**
* @brief IO
*
* (HTTP )
*
* @param file urlfile
* @param cmd (@ref UF_IOCTL_CMD)
* @param param1 1
* @param param2 2
* @return int
*/
int uf_ioctl(void *file, uint32 cmd, uint32 param1, uint32 param2);
/**
* @brief
*
* 0
*
* @param fp urlfile
* @param size
* @return off_t 0
*/
off_t uf_filesize(void *fp, uint32 size);
/**
* @brief Seek
*
* @param fp urlfile
* @return int32 Seek
*/
int32 uf_seektype(void *fp);
/**
* @brief
*
* @param fp urlfile
* @param buffer_level ()
* @return off_t
*/
off_t uf_datasize(void *fp, uint8 *buffer_level);
/**
* @brief -- app_mem.c
* @param size
* @return void*
*/
void *uf_alloc(int32 size);
/**
* @brief -- app_mem.c
* @param ptr
*/
void uf_free(void *ptr);
/**
* @brief
* @param s
* @return char*
*/
char *uf_strdup(char *s);
/**
* @brief urlfile状态切换使
* @param file urlfile
* @param state
*/
void uf_state(struct urlfile *file, UF_STATE state);
/**
* @brief URL
*
*
*
* @param protos
* @param count
*/
void urlfile_init(const struct ufprotocol *protos, int count);
/* ================= 协议内部使用的API ================= */
/**
* @brief
*
* @param file urlfile
* @param data
* @param len
* @return size_t
*/
size_t uf_store_data(struct urlfile *file, char *data, size_t len);
/**
* @brief
*
* @param list
* @param data
* @param len
* @param tot_size
* @return int
*/
int uf_playlist_recieve(struct uf_playlist *list, char *data, int len, uint32 tot_size);
/**
* @brief
*
* @param list
* @param data
* @param size
*/
void uf_playlist_detect(struct uf_playlist *list, void *data, size_t size);
/**
* @brief
*
* @param list
* @param urls URL
* @return int32 0: ; :
*/
int32 uf_playlist_build(struct uf_playlist *list, char *urls);
/**
* @brief
*
* @param list
* @return int32 0:
*/
int32 uf_playlist_free(struct uf_playlist *list);
/**
* @brief URL
*
* @param list
* @param title
* @param url URL
* @return int32 0: ; :
*/
int32 uf_playlist_new_url(struct uf_playlist *list, char *title, char *url);
/**
* @brief URL
*
* @param list
* @param index
* @return char* URL
*/
char *uf_playlist_get_url(struct uf_playlist *list, uint16 index);
/**
* @brief
*
* @param buf
* @param line
* @return char* NULL
*/
char *uf_playlist_get_line(char *buf, char **line);
/**
* @brief URL
*
* @param url URL
* @return const struct ufprotocol* NULL
*/
const struct ufprotocol *uf_findproto(char *url);
/* ================= 外部声明 ================= */
/** @brief 外部声明CURL HTTP 协议操作集 */
extern const struct ufprotocol_ops uf_curl_http;
#ifdef __cplusplus
}
#endif
#endif