Skip to content

Instantly share code, notes, and snippets.

@gabonator
Created June 15, 2013 07:49
Show Gist options
  • Save gabonator/5787311 to your computer and use it in GitHub Desktop.
Save gabonator/5787311 to your computer and use it in GitHub Desktop.
Yoics/IP9100 video server recorder for linux routers
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/vfs.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#define FILE_STAT "/tmp/mnt/flash/recorder/frames/recorder.log"
#define SRC_LINK0 "http://192.168.1.55/usr/yoics0.jpg"
#define SRC_LINK1 "http://192.168.1.55/usr/yoics1.jpg"
#define SRC_LINK2 "http://192.168.1.55/usr/yoics2.jpg"
#define SRC_LINK3 "http://192.168.1.55/usr/yoics3.jpg"
#define PATH_ARCHIVE "/tmp/mnt/flash/recorder/frames/"
#define DIVIDE0 1
#define DIVIDE1 1
#define DIVIDE2 2
#define DIVIDE3 2
#define INTERVAL 5
#define ERROR(m) {printf(m); printf("\n"); ADDSTAT(m) }
#define ADDSTAT(m) { man_statopen(); fprintf( man_stat, "%s %s\n", man_timestamp(), m ); man_statclose(); }
#define DBG(m) printf("%s\n", m)
#define DBR(m) DBG(m)
#define DEBUG(d) {d}
#define DBG0(d)
#define DEBUG0(d)
int gTerminate = 0;
FILE *man_stat;
char *man_timestamp();
int man_statopen();
int man_statclose();
void tim_format(char *name, char *fmt);
int http_open( char *strRemote )
{
struct sockaddr_in serv_name;
int sockd;
int status = 0;
/* parse link */
char ip[32];
char *slash;
strcpy( ip, strRemote+7 ); /* skip "http://" */
slash = strstr( ip, "/" );
if (slash)
*slash = 0;
/* create socket */
sockd = socket(AF_INET, SOCK_STREAM, 0);
if (sockd == -1)
{
ERROR("Socket creation");
exit(1);
}
/* server address */
serv_name.sin_family = AF_INET;
inet_aton(ip, &serv_name.sin_addr);
serv_name.sin_port = htons(80);
/* connect to the server */
status = connect(sockd, (struct sockaddr*)&serv_name, sizeof(serv_name));
if (status == -1)
{
ERROR("Connection error");
return 0;
}
return sockd;
}
int http_read(int sock, char *buf, int len)
{
int rlen = read(sock, buf, len);
if ( rlen > len )
rlen = len;
return rlen;
}
int http_skipheader(int sock)
{
int i;
char ch;
char fifo[4] = {0};
for (i=0; i<512; i++)
{
read( sock, &ch, 1 );
fifo[0] = fifo[1];
fifo[1] = fifo[2];
fifo[2] = fifo[3];
fifo[3] = ch;
if (fifo[0] == '\r' && fifo[1] == '\n' && fifo[2] == '\r' && fifo[3] == '\n')
return 1;
}
return 0;
}
int http_request( int sockd, char *strRemote )
{
char query[512];
/* parse link */
char ip[32];
char *path;
char *slash;
int ret;
strcpy( ip, strRemote+7 );
slash = strstr( ip, "/" );
if (slash)
*slash = 0;
path = strstr( strRemote+7, "/" );
strcpy( query, "GET " );
strcat( query, path );
strcat( query, " HTTP/1.0\r\nHost: " );
strcat( query, strRemote );
strcat( query, "\r\n\r\n" );
DBG0("http_request:write");
ret = write( sockd, query, strlen(query) );
DBG0("http_request:skipheader");
http_skipheader( sockd );
return 1;
}
void http_close( int handle )
{
close( handle );
}
int tar_padright( char *f, char *string, char pad, int len )
{
int stringlen = strlen(string);
memset( f, pad, len );
memcpy( f, string, stringlen );
return len;
}
int tar_checksum(char *buf)
{
int chksum = 0;
int i;
for (i=0; i<512; i++)
chksum += buf[i];
chksum += ' ' * 8;
return chksum;
}
fpos_t tar_pushpos;
//long tar_pushpos;
void tar_writedummy( FILE *f )
{
char header[512] = {0};
fwrite( header, 512, 1, f );
}
void tar_push( FILE *f )
{
fgetpos (f,&tar_pushpos);
}
void tar_pop( FILE *f )
{
fsetpos (f,&tar_pushpos);
}
void tar_rewind( FILE *f )
{
fseek( f, -512, SEEK_END );
}
void tar_writeheader( FILE *f, char *filename, int size )
{
char header[512] = {0};
int mode = 0100644;
int user_id = 0000764;
int group_id = 0001040;
unsigned long timestamp = 011065464715;
char user_name[] = "Administrator";
char group_name[] = "Administrators";
time_t t;
time (&t);
timestamp = t;
sprintf( header+0, "%s", filename );
sprintf( header+100, "%07o", mode );
sprintf( header+108, "%07o", user_id );
sprintf( header+116, "%07o", group_id );
sprintf( header+124, "%011o", size );
sprintf( header+136, "%011o", (unsigned int)timestamp );
sprintf( header+257, "ustar " );
sprintf( header+265, user_name );
sprintf( header+281, group_name );
header[156] = '0';
sprintf( header+148, "%06o", tar_checksum(header) );
header[155] = ' ';
fwrite( header, 512, 1, f );
}
void tar_finish(FILE *f, int nlen)
{
char header[512] = {0};
int nBlock = nlen & 511;
if (nBlock != 0)
{
nBlock = 512-nBlock;
fwrite( header, nBlock, 1, f );
}
fwrite( header, 512, 1, f );
}
FILE *tar_open(char *name)
{
FILE *f = fopen(name, "r+");
if ( !f )
f = fopen(name, "w+");
return f;
}
void tar_close(FILE *f)
{
fclose(f);
}
void regHand(int signalType, void (*func)(int))
{
struct sigaction sa;
sa.sa_handler = func;
sa.sa_flags = 0;
sa.sa_restorer = NULL;
sigaction(signalType, &sa, NULL);
}
void handler(int status)
{
ERROR("TERM signal received");
//man_clean();
//exit(1);
gTerminate = 1;
}
// fs
#define FS_HANDLES 8
typedef char _fs_name[128];
_fs_name fs_names[FS_HANDLES];
FILE *fs_handles[FS_HANDLES];
int fs_init()
{
int i;
for (i=0; i<FS_HANDLES; i++)
{
memset( fs_names[i], 0, sizeof(_fs_name) );
fs_handles[i] = NULL;
}
return 1;
}
int fs_cleanup()
{
int i;
for (i=0; i<FS_HANDLES; i++)
{
if (fs_handles[i])
{
fclose( fs_handles[i] );
fs_handles[i] = NULL;
}
}
return 1;
}
FILE *fs_open( char *name )
{
int i;
for (i=0; i<FS_HANDLES; i++)
{
if (fs_handles[i])
{
if ( strcmp( name, fs_names[i] ) == 0 )
return fs_handles[i];
} else
break;
}
if (i<FS_HANDLES)
{
fs_handles[i] = tar_open(name);
strcpy(fs_names[i], name);
return fs_handles[i];
}
ERROR("no mem to alloc new file");
return NULL;
}
long fs_free(char *path)
{
struct stat stst;
struct statfs stfs;
long llSize;
if ( stat( path, &stst ) == -1 )
return 0;
if ( statfs( path, &stfs ) == -1 )
return 0;
// printf("bavail=%d, blksize=%d, MB free ", stfs.f_bavail, stst.st_blksize);
llSize = stfs.f_bavail >> 10;
llSize *= stst.st_blksize;
// printf("%d\n", (int)llSize);
return (long) llSize;
//tootal = stfs.f_blocks * ( stst.st_blksize / fKB );
}
// man
char g_buffer[256];
char g_lastfile[256];
char g_lasttar[256];
char man_timestampbuf[32];
char *man_timestamp()
{
tim_format( man_timestampbuf, "%Y/%m/%d %H:%M:%S" );
return man_timestampbuf;
}
int man_appendfile( char *weblink, char *tararchive, char *saveas )
{
int fweb = 0;
FILE *ftar = NULL;
long lSize = 0;
long lRead = 0;
tim_format( g_lasttar, tararchive );
DEBUG0( printf("Append: '%s' into '%s' as '%s'\n", weblink, g_lasttar, saveas); );
ftar = fs_open( g_lasttar );
if (!ftar)
{
ERROR("cant lookup tar archive");
return 0;
}
tar_rewind(ftar);
tar_push(ftar);
tar_writedummy(ftar);
fweb = http_open( weblink );
if (!http_request( fweb, weblink ))
{
ERROR("http request error");
return 0;
}
while( ( lRead = http_read( fweb, g_buffer, 256) ) > 0 )
{
fwrite( g_buffer, lRead, 1, ftar );
lSize += lRead;
}
tar_finish( ftar, lSize );
tar_pop(ftar);
tim_format( g_lastfile, saveas );
tar_writeheader( ftar, g_lastfile, lSize );
http_close(fweb);
return 1;
}
int man_init()
{
if ( !man_statopen() )
return 0;
man_statclose();
ADDSTAT("Starting");
g_lastfile[0] = 0;
return fs_init();
}
int man_cleanup()
{
// if (man_stat)
// fclose(man_stat);
// man_stat = NULL;
ADDSTAT("Stopping");
return fs_cleanup();
}
int man_statopen()
{
man_stat = fopen(FILE_STAT, "a");
if (!man_stat)
return 0;
return 1;
}
int man_statclose()
{
fclose(man_stat);
man_stat = NULL;
return 1;
}
// tim
char tim_lasthour[32] = "";
char tim_lastday[32] = "";
int tim_passed(char *old, char *format)
{
char current[32];
tim_format(current, format);
if ( old[0] )
{
if ( strcmp( old, current ) == 0 )
return 0;
else
{
strcpy( old, current );
return 1;
}
}
strcpy( old, current );
return 0;
}
void tim_format(char *name, char *fmt)
{
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
if (tmp == NULL) {
ERROR("localtime");
exit(1);
}
if ( !fmt )
{
if (strftime(name, 64, "%Y%m%d_%H%M%S.jpg", tmp) == 0)
{
ERROR("strftime returned 0");
}
} else
if (strftime(name, 64, fmt, tmp) == 0)
{
ERROR("strftime returned 0");
}
}
int main(int argc, char* argv[])
{
int i = 0;
char lastDay[32];
regHand(SIGTERM, handler);
regHand(SIGINT, handler);
if (!man_init())
{
printf("Cannot start\n");
return 1;
}
DEBUG( printf("starting, free %d MB\n", (int)( fs_free(PATH_ARCHIVE)) ); );
while (!gTerminate)
{
DEBUG0( printf("pass %d, free %d MB\n", i, (int)( fs_free(PATH_ARCHIVE)) ); );
i++;
if ( fs_free(PATH_ARCHIVE) < 128 )
{
ERROR("free space < 128 MB");
break;
}
if ( tim_passed( tim_lasthour, "%H" ) )
{
fs_cleanup();
strcpy( lastDay, tim_lastday );
//ADDSTAT("dbg hour passed");
if ( tim_passed( tim_lastday, "%Y%m%d" ) )
{
man_statopen();
fprintf( man_stat, "%s Finished %s\n", man_timestamp(), lastDay );
man_statclose();
}
}
if ( (i % DIVIDE0) == 0 )
if ( !man_appendfile( SRC_LINK0, PATH_ARCHIVE "%Y%m%d_a.tar", "%Y%m%d_%H%M%S.jpg" ) )
break;
if ( (i % DIVIDE1) == 0 )
if ( !man_appendfile( SRC_LINK1, PATH_ARCHIVE "%Y%m%d_b.tar", "%Y%m%d_%H%M%S.jpg" ) )
break;
if ( (i % DIVIDE2) == 0 )
if ( !man_appendfile( SRC_LINK2, PATH_ARCHIVE "%Y%m%d_c.tar", "%Y%m%d_%H%M%S.jpg" ) )
break;
if ( (i % DIVIDE3) == 0 )
if ( !man_appendfile( SRC_LINK3, PATH_ARCHIVE "%Y%m%d_d.tar", "%Y%m%d_%H%M%S.jpg" ) )
break;
sleep(INTERVAL);
if (gTerminate)
break;
}
man_cleanup();
return 0;
}
VERSION = 0.9.4
CC = gcc
CFLAGS = -O2 -Wall
OBJS = main.o
LIBS =
camrec: ${OBJS}
${CC} ${CFLAGS} -o camrec ${LIBS} ${OBJS}
main.o: main.c
${CC} ${CFLAGS} -c main.c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment