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

📄 ftpup.c

📁 网络摄像头的webserver
💻 C
字号:
#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <stdarg.h>#include <time.h>#include <sys/time.h>#include <libxml/parser.h>#include "config.h"#include "ftpup.h"#define MODULE_THREAD#include "module.h"#include "mod_handle.h"#include "xmlhelp.h"#include "log.h"#include "filter.h"#include "grab.h"#include "image.h"#include "jpeg.h"#include "socket.h"static int ftpup_load_conf(struct ftpup_ctx *, xmlNodePtr);static int ftpup_read_ftp_resp(struct ftpup_ctx *, int);static void ftpup_cmd(struct ftpup_ctx *, char *, ...)	__attribute__ ((format (printf, 2, 3)));static int ftpup_setup_data_conn(struct ftpup_ctx *);static int ftpup_create_data_conn(struct ftpup_ctx *);#define MODNAME "ftpup"char *name = MODNAME;char *version = VERSION;char *deps[] ={	"jpeg_comp",	"socket",	NULL};intinit(struct module_ctx *mctx){	struct ftpup_ctx fctx;	int ret;		ret = ftpup_load_conf(&fctx, mctx->node);	if (ret)		return -1;		mctx->custom = malloc(sizeof(fctx));	memcpy(mctx->custom, &fctx, sizeof(fctx));		return 0;}void *thread(void *mctx){	struct timeval tstart, tend;	struct ftpup_ctx *fctx;	struct image img;	struct grab_ctx idx;	struct jpegbuf jbuf;	struct peer peer;	int ret;	long usecs;	char tsfnbuf[1024];	struct tm tm;		fctx = ((struct module_ctx *) mctx)->custom;		memset(&idx, 0, sizeof(idx));	for (;;)	{		gettimeofday(&tstart, NULL);		filter_get_image(&img, &idx, ((struct module_ctx *) mctx)->node, NULL);		jpeg_compress(&jbuf, &img, ((struct module_ctx *) mctx)->node);				ret = socket_connect(&peer, fctx->host, fctx->port, 20000);		if (ret)		{			log_log(MODNAME, "Connect to %s:%i failed (code %i, errno: %s)\n",				fctx->host, fctx->port, ret, strerror(errno));			goto freensleep;		}				fctx->peer = &peer;				if (ftpup_read_ftp_resp(fctx, 220))			goto closenstuff;				ftpup_cmd(fctx, "USER %s\r\n", fctx->user);		ret = ftpup_read_ftp_resp(fctx, 0);				if (ret == 331)		{			ftpup_cmd(fctx, "PASS %s\r\n", fctx->pass);			if (ftpup_read_ftp_resp(fctx, 230))				goto closenstuff;		}		else if (ret != 230)		{			log_log(MODNAME, "Ftp login failure? (got code %i after USER command)\n", ret);			goto closenstuff;		}				if (fctx->dir)		{			ftpup_cmd(fctx, "CWD %s\r\n", fctx->dir);			if (ftpup_read_ftp_resp(fctx, 250))				goto closenstuff;		}				ftpup_cmd(fctx, "TYPE I\r\n");		if (ftpup_read_ftp_resp(fctx, 200))			goto closenstuff;		ret = ftpup_setup_data_conn(fctx);		if (ret)			goto closenstuff;				localtime_r(&tstart.tv_sec, &tm);		strftime(tsfnbuf, sizeof(tsfnbuf) - 1, fctx->file, &tm);				if (!fctx->safemode)			ftpup_cmd(fctx, "STOR %s\r\n", tsfnbuf);		else			ftpup_cmd(fctx, "STOR %s.tmp\r\n", tsfnbuf);				ret = ftpup_create_data_conn(fctx);		if (ftpup_read_ftp_resp(fctx, 150))		{			socket_close(&fctx->datapeer);			goto closenstuff;		}				ret = socket_write(&fctx->datapeer, jbuf.buf, jbuf.bufsize, 20000);		if (ret != jbuf.bufsize)		{			log_log(MODNAME, "Write error while uploading: %s\n", strerror(errno));			socket_close(&fctx->datapeer);			goto closenstuff;		}				socket_close(&fctx->datapeer);		if (ftpup_read_ftp_resp(fctx, 226))			goto closenstuff;				if (fctx->safemode)		{			ftpup_cmd(fctx, "RNFR %s.tmp\r\n", tsfnbuf);			if (ftpup_read_ftp_resp(fctx, 350))				goto closenstuff;			ftpup_cmd(fctx, "RNTO %s\r\n", tsfnbuf);			if (ftpup_read_ftp_resp(fctx, 250))				goto closenstuff;		}				socket_printf(&peer, "QUIT\r\n");		ftpup_read_ftp_resp(fctx, 0);		gettimeofday(&tend, NULL);		log_log(MODNAME, "Upload of '%s' completed in %2.2f seconds\n",			tsfnbuf, (tend.tv_sec - tstart.tv_sec) + (tend.tv_usec - tstart.tv_usec)/1000000.0f);closenstuff:		socket_close(&peer);freensleep:		image_destroy(&img);		free(jbuf.buf);		usecs = (tend.tv_sec - tstart.tv_sec) * 1000000 + (tend.tv_usec - tstart.tv_usec);		if (fctx->interval > 0)		{			usecs = 1000000 * fctx->interval - usecs;			if (usecs > 0)				usleep(usecs);		}		else		{			sleep(5);			log_log(MODNAME, "Negative interval specified, exiting now.\n");			exit(0);		}	}		return NULL;}staticintftpup_load_conf(struct ftpup_ctx *fctx, xmlNodePtr node){	char *s;	int mult;		if (!node)		return -1;		memset(fctx, 0, sizeof(*fctx));	fctx->port = 21;	fctx->user = "anonymous";	fctx->pass = "camsource@";		for (node = node->xml_children; node; node = node->next)	{		if (xml_isnode(node, "host"))			fctx->host = xml_getcontent(node);		else if (xml_isnode(node, "port"))			fctx->port = xml_atoi(node, fctx->port);		else if (xml_isnode(node, "user") || xml_isnode(node, "username"))			fctx->user = xml_getcontent_def(node, fctx->user);		else if (xml_isnode(node, "pass") || xml_isnode(node, "password"))			fctx->pass = xml_getcontent_def(node, fctx->pass);		else if (xml_isnode(node, "dir"))			fctx->dir = xml_getcontent(node);		else if (xml_isnode(node, "file"))			fctx->file = xml_getcontent(node);		else if (xml_isnode(node, "passive"))		{			s = xml_getcontent_def(node, "no");			if (!strcmp(s, "yes") || !strcmp(s, "on") || !strcmp(s, "1"))				fctx->passive = 1;			else				fctx->passive = 0;		}		else if (xml_isnode(node, "safemode"))		{			s = xml_getcontent_def(node, "no");			if (!strcmp(s, "yes") || !strcmp(s, "on") || !strcmp(s, "1"))				fctx->safemode = 1;			else				fctx->safemode = 0;		}		else if (xml_isnode(node, "interval"))		{			mult = 1;			s = xml_attrval(node, "unit");			if (!s)				s = xml_attrval(node, "units");			if (s)			{				if (!strcmp(s, "sec") || !strcmp(s, "secs") || !strcmp(s, "seconds"))					;				else if (!strcmp(s, "min") || !strcmp(s, "mins") || !strcmp(s, "minutes"))					mult = 60;				else if (!strcmp(s, "hour") || !strcmp(s, "hours"))					mult = 3600;				else if (!strcmp(s, "day") || !strcmp(s, "days"))					mult = 86400;				else				{					log_log(MODNAME, "Invalid \"unit\" attribute value \"%s\"\n", s);					return -1;				}			}			fctx->interval = xml_atoi(node, 0) * mult;		}	}		if (!fctx->host)	{		log_log(MODNAME, "No host specified\n");		return -1;	}	if (fctx->port <= 0 || fctx->port > 0xffff)	{		log_log(MODNAME, "Invalid port (%i) specified\n", fctx->port);		return -1;	}	if (!fctx->dir || !fctx->file)	{		log_log(MODNAME, "No dir or path specified\n");		return -1;	}	if (fctx->interval == 0)	{		log_log(MODNAME, "No or invalid interval specified\n");		return -1;	}	return 0;}staticintftpup_read_ftp_resp(struct ftpup_ctx *fctx, int expect){	int ret;	char buf[1024];	int gotcode;		if (!fctx || !fctx->peer)		return -1;		gotcode = 0;	for (;;)	{		ret = socket_readline(fctx->peer, buf, sizeof(buf), 20000);		if (ret)		{			log_log(MODNAME, "Connection error or eof on ftp control connection (last command: \"%s\")\n",				fctx->lastcmd);			return -1;		}		if (!gotcode && strlen(buf) < 3)		{			log_log(MODNAME, "Short ftp response line (\"%s\") in response to command \"%s\"\n",				buf, fctx->lastcmd);			return -1;		}		ret = atoi(buf);		if (*buf < '0' || *buf > '9' || !ret)		{			if (gotcode)				continue;invalid:			log_log(MODNAME, "Invalid ftp response line (\"%s\") in response to command \"%s\"\n",				buf, fctx->lastcmd);			return -1;		}				if (buf[3] == ' ')			break;		if (buf[3] != '-')			goto invalid;					gotcode = 1;	}		if (expect > 0)	{		if (ret != expect)		{			log_log(MODNAME, "Did not get expected ftp resonse code after command \"%s\": expected %i, got line \"%s\"\n",				fctx->lastcmd, expect, buf);			return -1;		}		return 0;	}		return ret;}staticvoidftpup_cmd(struct ftpup_ctx *fctx, char *fmt, ...){	va_list vl;	char *p;		strncpy(fctx->lastcmd, fmt, 4);	p = strchr(fctx->lastcmd, ' ');	if (p)		*p = '\0';		va_start(vl, fmt);	socket_vprintf(fctx->peer, fmt, vl);	va_end(vl);}staticintftpup_setup_data_conn(struct ftpup_ctx *fctx){	struct peer localpeer, portpeer;	int ret;	char buf[1024];	int h1, h2, h3, h4, p1, p2;		if (!fctx->passive)	{		fctx->actpasv.act.listen_fd = socket_listen(0, 0);		if (fctx->actpasv.act.listen_fd < 0)		{			log_log(MODNAME, "Error opening listen socket: %s\n", strerror(errno));			return -1;		}		socket_fill(fctx->peer->fd, &localpeer);		socket_fill(fctx->actpasv.act.listen_fd, &portpeer);		ftpup_cmd(fctx, "PORT %u,%u,%u,%u,%u,%u\r\n",			(localpeer.sin.sin_addr.s_addr >>  0) & 0xff,			(localpeer.sin.sin_addr.s_addr >>  8) & 0xff,			(localpeer.sin.sin_addr.s_addr >> 16) & 0xff,			(localpeer.sin.sin_addr.s_addr >> 24) & 0xff,			(portpeer.sin.sin_port >> 0) & 0xff,			(portpeer.sin.sin_port >> 8) & 0xff);		if (ftpup_read_ftp_resp(fctx, 200))		{			close(fctx->actpasv.act.listen_fd);			return -1;		}				return 0;	}	ftpup_cmd(fctx, "PASV\r\n");	ret = socket_readline(fctx->peer, buf, sizeof(buf), 20000);	if (ret || strncasecmp(buf, "227 Entering Passive Mode (", 27))	{		log_log(MODNAME, "Unrecognized response to PASV command: %s\n", buf);		return -1;	}	ret = sscanf(buf + 27, "%i,%i,%i,%i,%i,%i",		&h1, &h2, &h3, &h4, &p1, &p2);	if (ret != 6)	{		log_log(MODNAME, "Response to PASV command didn't match: %s\n", buf);		return -1;	}	snprintf(fctx->actpasv.pasv.ip, sizeof(fctx->actpasv.pasv.ip) - 1, "%i.%i.%i.%i", h1, h2, h3, h4);	fctx->actpasv.pasv.port = p1 << 8 | p2;		return 0;}staticintftpup_create_data_conn(struct ftpup_ctx *fctx){	int ret;		if (!fctx->passive)	{		ret = socket_accept(fctx->actpasv.act.listen_fd, &fctx->datapeer, 20000);		if (ret)		{			log_log(MODNAME, "Accept() error or timeout: %s\n", strerror(errno));			close(fctx->actpasv.act.listen_fd);			return -1;		}		close(fctx->actpasv.act.listen_fd);				return 0;	}	ret = socket_connect(&fctx->datapeer, fctx->actpasv.pasv.ip, fctx->actpasv.pasv.port, 20000);	if (ret)	{		log_log(MODNAME, "Could not connect to %s:%i in passive mode\n",			fctx->actpasv.pasv.ip, fctx->actpasv.pasv.port);		return -1;	}		return 0;}

⌨️ 快捷键说明

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