merge new vj-client

added threadsafe gethostbyname
fix bug in reloaded set keyframes
drop vj_client_send_buf* functions
drop vj_client_setup_timeout
keep thread local buffer to store incoming frame (unicast stream)
recover gracefully when lock or unlock fails (unicast stream)
adapt poll frequency to find acceptable delay times
recover gracefully from network errors
retry to create connection when it fails while playing
destroy thread when locking functions fail
simpler get_frame for tag
dropped multicast stream for now
fix veejay_strncpy, null terminate string
drop use of bzero, use memset instead
rewrite part of cmd, socket peer-to-peer
rewrite VIMS verify message
rewrite VIMS parsing message
This commit is contained in:
niels
2011-09-11 00:48:18 +02:00
parent 4881749568
commit 846bfa1d40
12 changed files with 459 additions and 561 deletions

View File

@@ -2104,9 +2104,12 @@ void on_curve_buttonstore_clicked(GtkWidget *widget, gpointer user_data )
int len = end - start;
float *data = (float*) vj_calloc(sizeof(float) * len );
int *values = (int*) vj_calloc(sizeof(int) * len );
unsigned char *kf = (unsigned char*) vj_calloc( (len*4)+25);
unsigned char *kkf = (unsigned char*) vj_calloc( (len*4)+64);
int min=0,max=0;
unsigned char *kf = kkf + 9; //@ reserve space for header
_effect_get_minmax( id, &min,&max,j );
int k;
@@ -2115,9 +2118,13 @@ void on_curve_buttonstore_clicked(GtkWidget *widget, gpointer user_data )
for( k = 0 ; k < len ; k++ )
values[k] = ( (int) ( data[k] * max ));
int total_len = 25 + (4 * len);
int total_len = 9;
int row_len = 3 + 2 + 2 + 8 + 8 + 2;
sprintf( (char*)kf, "key%02d%02d%08d%08d%02d",i,j,start,end,type );
unsigned char *ptr = kf + 25;
unsigned char *ptr = kf + row_len;
total_len += row_len;
for( k = 0; k < len; k ++ )
{
unsigned char *p = ptr + (k*4);
@@ -2125,13 +2132,22 @@ void on_curve_buttonstore_clicked(GtkWidget *widget, gpointer user_data )
p[1] = (values[k] >> 8) & 0xff;
p[2] = (values[k] >> 16) & 0xff;
p[3] = (values[k] >> 24) & 0xff;
total_len += 4;
}
free(values);
free(data);
vj_client_send_bufX( info->client, V_CMD, kf,total_len );
free(kf);
char header[10];
snprintf( header,10, "K%08d", total_len );
for( k = 0; k < 9; k ++ )
kkf[k] = header[k];
printf("[%s]: %d\n", kkf,total_len );
vj_client_send_buf( info->client, V_CMD, kkf,total_len );
free(kkf);
vj_msg( VEEJAY_MSG_INFO, "Saved new animation for parameter %d on entry %d, start at frame %d and end at frame %d",j,i,start,end );

View File

@@ -1100,8 +1100,6 @@ static int gvr_veejay( veejay_preview_t *vp , veejay_track_t *v, int track_num
}
else
{
vj_client_setup_timeout( v->fd,V_CMD,1);
v->preview = is_button_toggled( "previewtoggle");
v->active = 1;
vj_msg(VEEJAY_MSG_WARNING, "VeejayGrabber: connected with %s:%d on Track %d %d x %d",

View File

@@ -24,4 +24,4 @@ fi
## slackware 13.1 and older
#########################################
#autoreconf -v -fi
autoreconf -v -fi

View File

@@ -45,7 +45,6 @@ typedef struct
int state;
int have_frame;
int error;
int grab;
int repeat;
int w;
int h;
@@ -54,23 +53,22 @@ typedef struct
int in_w;
int in_h;
int af;
uint8_t *buf;
} threaded_t;
static void lock_(threaded_t *t, const char *f, int line)
#define STATE_INACTIVE 0
#define STATE_RUNNING 1
static int lock(threaded_t *t)
{
// veejay_msg(0,"lock thread by %s, line %d",f,line);
pthread_mutex_lock( &(t->mutex ));
return pthread_mutex_lock( &(t->mutex ));
}
static void unlock_(threaded_t *t, const char *f, int line)
static int unlock(threaded_t *t)
{
// veejay_msg(0,"unlock thread by %s, line %d",f,line);
pthread_mutex_unlock( &(t->mutex ));
return pthread_mutex_unlock( &(t->mutex ));
}
#define lock( t ) lock_( t, __FUNCTION__, __LINE__ )
#define unlock( t ) unlock_( t, __FUNCTION__ , __LINE__ )
#define MS_TO_NANO(a) (a *= 1000000)
static void net_delay(long nsec, long sec )
{
@@ -98,6 +96,9 @@ void *reader_thread(void *data)
success = vj_client_connect_dat( v, tag->source_name,tag->video_channel );
t->buf = (uint8_t*) vj_calloc(sizeof(uint8_t) * 2048 * 1500 );
if( success > 0 ) {
veejay_msg(VEEJAY_MSG_INFO, "Connecton established with %s:%d",tag->source_name,
tag->video_channel + 5);
@@ -105,28 +106,32 @@ void *reader_thread(void *data)
else if ( tag->source_type != VJ_TAG_TYPE_MCAST )
{
veejay_msg(0, "Unable to connect to %s: %d", tag->source_name, tag->video_channel+5);
free(t->buf);
pthread_exit(&(t->thread));
return NULL;
}
unsigned int optimistic = 1;
unsigned int optimal = 8;
for( ;; )
{
int error = 0;
int pollres = 0;
int res = 0;
if( t->state == 0 )
{
vj_client_close(v);
veejay_msg(VEEJAY_MSG_INFO, "Closed connection with %s: %d",
tag->source_name,tag->video_channel+5);
vj_client_free(v);
pthread_exit( &(t->thread));
return NULL;
/*
if( t->have_frame == 1 ) {
net_delay(2,0);
int have_frame = 0;
lock(v);
have_frame = t->have_frame;
unlock(v);
if( have_frame == 1 )
continue;
}
*/
lock(t);
if(!error && t->grab && tag->source_type == VJ_TAG_TYPE_NET && retrieve == 0 ) {
if(!error && tag->source_type == VJ_TAG_TYPE_NET && retrieve == 0) {
ret = vj_client_send( v, V_CMD, buf );
if( ret <= 0 )
{
@@ -136,41 +141,53 @@ void *reader_thread(void *data)
tag->video_channel );
error = 1;
}
else
{
t->grab = 0;
} else {
optimistic = optimal;
}
}
if(!error && tag->source_type == VJ_TAG_TYPE_NET )
{
res = vj_client_poll(v, V_CMD );
if( ret )
if( res )
{
retrieve = 1;
} else if ( ret < 0 ) {
if(vj_client_link_can_read( v, V_CMD ) ) {
retrieve = 2;
if( optimistic < optimal && optimistic > 1 )
optimal = (optimistic + optimal) / 2;
}
}
else if ( res < 0 ) {
veejay_msg(VEEJAY_MSG_DEBUG,
"Error polling connection %s:%d",
tag->source_name,
tag->video_channel );
error = 1;
} else if ( res == 0 ) {
retrieve = 1;
net_delay( optimistic ,0); //@ decrease wait time after each try
optimistic --;
if( optimistic == 0 ) {
optimal ++;
if(optimal > 20 )
optimal = 20; //@ upper bound
optimistic = 1;
}
} else if (tag->source_type == VJ_TAG_TYPE_MCAST )
{
error = 0;
retrieve = 1;
res = 1;
continue; //@ keep waiting after SEND_FRAME until like ;; or error
}
}
long wait_time = 0;
if(!error && retrieve)
if(!error && (retrieve == 2))
{
if( res )
{
ret = vj_client_read_i ( v, tag->socket_frame,tag->socket_len );
if(lock(t) != 0 ) //@ lock memory region to write
goto NETTHREADEXIT;
ret = vj_client_read_i ( v, t->buf,0 );
if( ret <= 0 )
{
if( tag->source_type == VJ_TAG_TYPE_NET )
@@ -181,48 +198,45 @@ void *reader_thread(void *data)
tag->video_channel );
error = 1;
}
// else
// {
// wait_time += 10;
// }
ret = 0;
}
else
{
t->in_fmt = v->in_fmt;
t->in_w = v->in_width;
t->in_h = v->in_height;
t->have_frame = ret;
t->grab = 1;
t->have_frame = 1;
retrieve = 0;
}
if(unlock(t) != 0 )
goto NETTHREADEXIT;
/*
#ifdef STRICT_CHECKING
if( vj_client_poll( v, V_CMD ) ) {
char bogus[32];
while( vj_client_link_can_read(v,V_CMD) )
vj_client_read( v, bogus, 1 );
}
else
{
if(tag->source_type == VJ_TAG_TYPE_MCAST )
wait_time = 15;
#endif
*/
}
}
unlock(t);
if( wait_time )
{
if ( wait_time > 15 )
wait_time = 10;
//net_delay( wait_time,0 );
wait_time = 0;
}
NETTHREADRETRY:
if( error )
{
int success = 0;
vj_client_close( v );
vj_client_free( v);
v = vj_client_alloc( t->w, t->h, t->af );
if(!v) {
free(t->buf);
pthread_exit( &(t->thread));
return NULL;
}
net_delay( 0,3 );
v->lzo = lzo_new();
veejay_msg(VEEJAY_MSG_INFO, " ZZzzzzz ... waiting for Link %s:%d to become ready", tag->source_name, tag->video_channel );
net_delay( 0, 5 );
if(tag->source_type == VJ_TAG_TYPE_MCAST )
success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel );
@@ -231,21 +245,45 @@ void *reader_thread(void *data)
if( success <= 0 )
{
wait_time = 4000;
#ifdef STRICT_CHECKING
veejay_msg(VEEJAY_MSG_DEBUG, "Tried to connect to %s:%d code=%d", tag->source_name,tag->video_channel,success);
#endif
goto NETTHREADRETRY;
}
else
{
veejay_msg(VEEJAY_MSG_INFO, "Connecton re-established with %s:%d",tag->source_name,
tag->video_channel + 5);
veejay_msg(VEEJAY_MSG_INFO, "Connecton re-established with %s:%d",tag->source_name,tag->video_channel + 5);
}
t->grab = 0;
retrieve = 0;
}
int cur_state = STATE_RUNNING;
if(lock(t) != 0 )
goto NETTHREADEXIT;
cur_state = t->state;
if(unlock(t) != 0 )
goto NETTHREADEXIT;
if( cur_state == 0 )
{
vj_client_close(v);
veejay_msg(VEEJAY_MSG_INFO, "Network thread with %s: %d was told to exit",tag->source_name,tag->video_channel+5);
vj_client_free(v);
free(t->buf);
pthread_exit( &(t->thread));
return NULL;
}
}
NETTHREADEXIT:
vj_client_close(v);
veejay_msg(VEEJAY_MSG_INFO, "Network thread with %s: %d was aborted",tag->source_name,tag->video_channel+5);
vj_client_free(v);
free(t->buf);
pthread_exit( &(t->thread));
return NULL;
}
@@ -262,14 +300,18 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
threaded_t *t = (threaded_t*) tag->priv;
const uint8_t *buf = tag->socket_frame;
lock(t);
if( t->state == 0 || t->error )
{
if(t->repeat < 0)
veejay_msg(VEEJAY_MSG_INFO, "Connection closed with remote host");
t->repeat++;
unlock(t);
int have_frame = 0;
int state = 0;
if(lock(t) != 0 )
return 0;
have_frame = t->have_frame;
state= t->state;
if(unlock(t) != 0)
return 0;
if( state == 0 || have_frame == 0 ) {
return 1;
}
//@ color space convert frame
@@ -286,17 +328,6 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
break;
}
if(t->have_frame == 1 )
{
veejay_memcpy(buffer[0], tag->socket_frame, len );
veejay_memcpy(buffer[1], tag->socket_frame+len, uv_len );
veejay_memcpy(buffer[2], tag->socket_frame+len+uv_len, uv_len );
t->grab = 1;
unlock(t);
return 1;
}
else if(t->have_frame == 2 )
{
VJFrame *a = NULL;
VJFrame *b = NULL;
@@ -320,19 +351,21 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
break;
}
a =yuv_yuv_template( tag->socket_frame, tag->socket_frame + b_len, tag->socket_frame+b_len+buvlen,
t->in_w,t->in_h, t->in_fmt);
a =yuv_yuv_template( t->buf, t->buf + b_len, t->buf+ b_len+ buvlen,t->in_w,t->in_h, t->in_fmt);
}
b = yuv_yuv_template( buffer[0],buffer[1], buffer[2],t->w,t->h,t->f);
if(lock(t) != 0)
return 0;
yuv_convert_any_ac(a,b, a->format,b->format );
t->have_frame = 0;
if(unlock(t)!=0)
return 0;
free(a);
free(b);
}
t->grab = 1;
unlock(t);
return 1;
}
@@ -341,16 +374,20 @@ int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h )
threaded_t *t = (threaded_t*) tag->priv;
const uint8_t *buf = tag->socket_frame;
lock(t);
if( t->state == 0 || t->error )
{
if(t->repeat < 0)
veejay_msg(VEEJAY_MSG_INFO, "Connection closed with remote host");
t->repeat++;
unlock(t);
int have_frame = 0;
int state = 0;
if(lock(t) != 0 )
return 0;
have_frame = t->have_frame;
state= t->state;
if(unlock(t) != 0 )
return 0;
if( state == 0 || have_frame == 0 ) {
return 1;
}
//@ color space convert frame
int len = t->w * t->h;
int uv_len = len;
@@ -389,9 +426,7 @@ int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h )
free(a);
free(b);
}
t->grab = 1;
unlock(t);
return 1;
}
@@ -403,31 +438,23 @@ int net_thread_start(vj_tag *tag, int wid, int height, int pixelformat)
if(tag->source_type == VJ_TAG_TYPE_MCAST ) {
veejay_msg(0, "MCAST: fixme!");
return 0;
}
//@
// success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel );
/* else
success = vj_client_connect_dat( v, tag->source_name,tag->video_channel );
*/
threaded_t *t = (threaded_t*)tag->priv;
pthread_mutex_init( &(t->mutex), NULL );
t->repeat = 0;
t->w = wid;
t->h = height;
t->af = pixelformat;
t->f = get_ffmpeg_pixfmt(pixelformat);
t->have_frame = 0;
t->error = 0;
t->state = 1;
t->grab = 1;
t->state = STATE_RUNNING;
int p_err = pthread_create( &(t->thread), NULL, &reader_thread, (void*) tag );
if( p_err ==0)
{
veejay_msg(VEEJAY_MSG_INFO, "Created new %s threaded stream to veejay host %s port %d",
tag->source_type == VJ_TAG_TYPE_MCAST ?
"multicast" : "unicast", tag->source_name,tag->video_channel);
@@ -482,11 +509,10 @@ void net_thread_stop(vj_tag *tag)
threaded_t *t = (threaded_t*)tag->priv;
int ret = 0;
lock(t);
if(lock(t) == 0 ) {
t->state = 0;
unlock(t);
}
pthread_mutex_destroy( &(t->mutex));

View File

@@ -209,7 +209,9 @@ static inline unsigned long long int rdtsc()
#define small_memset(to,val,n) memset(to,val,n)
char *veejay_strncpy( char *dest, const char *src, size_t n )
{
return strncpy( dest,src, n-1 );
memcpy ( dest, src, n );
dest[n] = '\0';
return dest;
}
char *veejay_strncat( char *s1, char *s2, size_t n )

View File

@@ -576,7 +576,7 @@ int veejay_get_file_ext( char *file, char *dst, int dlen)
int len = strlen(file)-1;
int i = 0;
char tmp[dlen];
bzero(tmp,dlen);
memset( tmp, 0, dlen );
while(len)
{
if(file[len] == '.')

View File

@@ -27,9 +27,52 @@
#include <libvjmsg/vj-msg.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <pthread.h>
#ifdef STRICT_CHECKING
#include <assert.h>
#endif
struct host_list {
struct hostent hostent;
char h_addr_space[1024];
};
static int ref_count = 0;
static pthread_key_t ghbn_key;
static pthread_once_t ghbn_key_once = PTHREAD_ONCE_INIT;
static void ghbn_cleanup(void *data) {
struct host_list *current = (struct host_list *) data;
ref_count--;
free(current);
}
static void create_ghbn_key() {
pthread_key_create(&ghbn_key, ghbn_cleanup);
}
struct hostent *sock_gethostbyname(const char *name) {
struct hostent *result;
int local_errno;
pthread_once(&ghbn_key_once, create_ghbn_key);
struct host_list *current = (struct host_list *) pthread_getspecific(ghbn_key);
if (!current) {
current = (struct host_list *) calloc(1, sizeof(struct host_list));
current->hostent.h_name = "busy";
ref_count++;
pthread_setspecific(ghbn_key, current);
}
if (gethostbyname_r(name, &(current->hostent), current->h_addr_space,sizeof(current->h_addr_space),&result, &local_errno)) {
h_errno = local_errno;
}
return result;
}
vj_sock_t *alloc_sock_t(void)
{
vj_sock_t *s = (vj_sock_t*) malloc(sizeof(vj_sock_t));
@@ -47,7 +90,7 @@ void sock_t_free(vj_sock_t *s )
int sock_t_connect_and_send_http( vj_sock_t *s, char *host, int port, char *buf, int buf_len )
{
s->he = gethostbyname( host );
s->he = sock_gethostbyname( host );
if(s->he==NULL)
return 0;
s->sock_fd = socket( AF_INET, SOCK_STREAM , 0);
@@ -97,9 +140,11 @@ int sock_t_connect_and_send_http( vj_sock_t *s, char *host, int port, char *bu
int sock_t_connect( vj_sock_t *s, char *host, int port )
{
s->he = gethostbyname( host );
s->he = sock_gethostbyname( host );
if(s->he==NULL)
return 0;
s->sock_fd = socket( AF_INET, SOCK_STREAM , 0);
if(s->sock_fd < 0)
{
@@ -109,6 +154,7 @@ int sock_t_connect( vj_sock_t *s, char *host, int port )
s->port_num = port;
s->addr.sin_family = AF_INET;
s->addr.sin_port = htons( port );
s->addr.sin_addr = *( (struct in_addr*) s->he->h_addr );
if( connect( s->sock_fd, (struct sockaddr*) &s->addr,

View File

@@ -59,19 +59,15 @@ vj_client *vj_client_alloc( int w, int h, int f )
{
return NULL;
}
v->orig_width = w;
v->orig_height = h;
v->cur_width = w;
v->cur_height = h;
v->cur_fmt = get_ffmpeg_pixfmt(f);
v->space = NULL;
v->c = (conn_type_t**) malloc(sizeof(conn_type_t*) * 2);
v->c[0] = (conn_type_t*) malloc(sizeof(conn_type_t));
v->c[1] = (conn_type_t*) malloc(sizeof(conn_type_t));
v->blob = (unsigned char*) malloc(sizeof(unsigned char) * PACKET_LEN );
if(!v->blob ) {
veejay_msg(0, "Memory allocation error.");
free(v->c[1]);
free(v->c[0]);
free(v->c);
free(v);
return NULL;
}
@@ -81,42 +77,22 @@ vj_client *vj_client_alloc( int w, int h, int f )
v->space = (uint8_t*) malloc( sizeof(uint8_t) * w * h * 4 );
memset(v->space,0,sizeof(uint8_t)*w*h*4);
}
return v;
}
#ifdef STRICT_CHECKING
static void vj_client_check( vj_client *v, int sock_type )
{
#ifdef STRICT_CHECKING
if( sock_type == V_STATUS ) {
assert( v->c[1] != NULL );
assert( v->c[1]->fd != NULL );
}
if( sock_type == V_CMD ) {
assert( v->c[0] != NULL );
assert( v->c[0]->fd != NULL );
}
#endif
}
#endif
void vj_client_free(vj_client *v)
{
if(v)
{
int i;
if( v->c ) {
for( i = 0; i < 2; i ++ ) {
if(!v->c[i])
continue;
if( v->fd[0] ) {
sock_t_free( v->fd[0] );
}
if( v->fd[1] ) {
sock_t_free( v->fd[1] );
}
free(v->c[i]);
v->c[i] = NULL;
}
free(v->c);
}
v->fd[0] = NULL;
v->fd[1] = NULL;
if(v->blob)
free(v->blob);
@@ -159,8 +135,7 @@ static int verify_integrity( char *buf, int len ) {
int vj_client_window_sizes( int socket_fd, int *r, int *s )
{
int tmp = sizeof(int);
if( getsockopt( socket_fd, SOL_SOCKET, SO_SNDBUF,(unsigned char*) s, &tmp) == -1 )
{
if( getsockopt( socket_fd, SOL_SOCKET, SO_SNDBUF,(unsigned char*) s, &tmp) == -1 ) {
veejay_msg(0, "Cannot read socket buffer size: %s", strerror(errno));
return 0;
}
@@ -186,17 +161,17 @@ int vj_client_connect_dat(vj_client *v, char *host, int port_id )
return 0;
}
v->c[0]->type = VSOCK_C;
v->c[0]->fd = alloc_sock_t();
v->fd[0] = alloc_sock_t();
if( sock_t_connect( v->c[0]->fd, host, (port_id + 5) ) )
if( sock_t_connect( v->fd[0], host, (port_id + 5) ) )
{
veejay_msg(VEEJAY_MSG_INFO, "Connect to DAT port %d", port_id + 5);
return 1;
}
v->c[1]->fd = alloc_sock_t();
v->c[1]->type = 654321;
v->fd[1] = NULL; // no status port
v->ports[0] = port_id + 5;
v->ports[1] = -1;
return error;
}
@@ -214,47 +189,57 @@ int vj_client_connect(vj_client *v, char *host, char *group_name, int port_id )
{
if(host == NULL)
return error;
#ifdef STRICT_CHECKING
assert(v->fd[0] == NULL );
assert(v->fd[1] == NULL );
#endif
v->c[0]->type = VSOCK_C;
v->c[0]->fd = alloc_sock_t();
v->c[1]->type = VSOCK_S;
v->c[1]->fd = alloc_sock_t();
if(!v->c[0]->fd || !v->c[1]->fd )
{
veejay_msg(0, "Error opening socket");
v->fd[0] = alloc_sock_t();
v->fd[1] = alloc_sock_t();
if(!v->fd[0]) {
return error;
}
if(!v->fd[1] ) {
free(v->fd[0]);
return error;
}
if( sock_t_connect( v->c[0]->fd, host, port_id + VJ_CMD_PORT ) )
{
if( sock_t_connect( v->c[1]->fd, host, port_id + VJ_STA_PORT ) )
{
if( sock_t_connect( v->fd[0], host, port_id + VJ_CMD_PORT ) ) {
if( sock_t_connect( v->fd[1], host, port_id + VJ_STA_PORT ) ) {
return 1;
} else {
veejay_msg(0, "Failed to connect to status port.");
}
} else {
veejay_msg(0, "Failed to connect to command port.");
}
v->ports[0] = port_id + VJ_CMD_PORT;
v->ports[1] = port_id + VJ_STA_PORT;
#ifdef STRICT_CHECKING
veejay_msg( VEEJAY_MSG_DEBUG, "connected CMD port %d (socket %p, type %d)",
v->ports[0], v->fd[0], 0 );
veejay_msg( VEEJAY_MSG_DEBUG, "connected STATUS port %d (socket %p, type %d)",
V->ports[1], v->fd[1], 1 );
#endif
}
else
{
v->c[0]->type = VMCAST_C;
v->c[0]->r = mcast_new_receiver( group_name, port_id + VJ_CMD_MCAST );
if(!v->c[0]->r ) {
v->r = mcast_new_receiver( group_name, port_id + VJ_CMD_MCAST );
if(!v->r ) {
veejay_msg(0 ,"Unable to setup multicast receiver on group %s", group_name );
return error;
}
v->c[0]->s = mcast_new_sender( group_name );
if(!v->c[0]->s ) {
v->s = mcast_new_sender( group_name );
if(!v->s ) {
veejay_msg(0, "Unable to setup multicast sender on group %s", group_name );
return error;
}
v->ports[0] = port_id + VJ_CMD_MCAST;
v->ports[1] = port_id + VJ_CMD_MCAST_IN;
mcast_sender_set_peer( v->c[0]->s , group_name );
mcast_sender_set_peer( v->s , group_name );
v->mcast = 1;
// mcast_receiver_set_peer( v->c[0]->r, group_name);
veejay_msg(VEEJAY_MSG_DEBUG, "Client is interested in packets from group %s : %d, send to %d",
@@ -267,48 +252,36 @@ int vj_client_connect(vj_client *v, char *host, char *group_name, int port_id )
int vj_client_link_can_write( vj_client *v, int sock_type ){
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
int n = sock_t_wds_isset( v->fd[sock_type] );
veejay_msg(VEEJAY_MSG_DEBUG, "%s: type %d, socket %p : result=%d",
__FUNCTION__, sock_type, v->fd[sock_type], n );
return n;
#else
return sock_t_wds_isset( v->fd[sock_type]);
#endif
if(sock_type==VSOCK_S) {
return sock_t_wds_isset( v->c[1]->fd );
} else if (sock_type == VSOCK_C ) {
return sock_t_rds_isset( v->c[0]->fd );
}
return 0;
}
int vj_client_link_can_read( vj_client *v, int sock_type ) {
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
int n = sock_t_rds_isset( v->fd[sock_type] );
veejay_msg(VEEJAY_MSG_DEBUG, "%s: type %d, socket %p : result=%d",
__FUNCTION__, sock_type, v->fd[sock_type], n );
return n;
#else
return sock_t_rds_isset( v->fd[sock_type] );
#endif
if( sock_type == VSOCK_S) {
return sock_t_rds_isset(v->c[1]->fd);
} else if (sock_type == VSOCK_C ) {
return sock_t_rds_isset( v->c[0]->fd);
}
return 0;
}
int vj_client_poll( vj_client *v, int sock_type )
{
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
int n = sock_t_poll( v->fd[sock_type] );
veejay_msg(VEEJAY_MSG_DEBUG, "%s: type %d, socket %p : result=%d",
__FUNCTION__, sock_type, v->fd[sock_type], n );
return n;
#else
return sock_t_poll( v->fd[sock_type ]);
#endif
if(sock_type == V_STATUS )
{
if(v->c[1]->type == VSOCK_S)
return ( sock_t_poll(v->c[1]->fd ) );
}
if(sock_type == V_CMD )
{
if(v->c[0]->type == VSOCK_C)
return ( sock_t_poll( v->c[0]->fd ));
if(v->c[0]->type == VMCAST_C )
return ( mcast_poll( v->c[0]->r ));
}
return 0;
}
static void vj_client_decompress( vj_client *t,uint8_t *in, uint8_t *out, int data_len, int Y, int UV , int header_len,
@@ -387,7 +360,7 @@ static int vj_client_packet_negotiate( vj_client *v, int *tokens )
//@ 1. read 44 bytes and see if its us
veejay_memset( line,0, sizeof(line));
int plen = sock_t_recv( v->c[0]->fd, line, 44 );
int plen = sock_t_recv( v->fd[0], line, 44 );
if( plen == 0 ) {
veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection.");
return -1;
@@ -440,9 +413,9 @@ int vj_client_read_i( vj_client *v, uint8_t *dst, int len )
int conv = 1;
int y_len = 0;
int uv_len = 0;
if( v->c[0]->type == VMCAST_C )
if( v->mcast == 1)
{
uint8_t *in = mcast_recv_frame( v->c[0]->r, &p[0],&p[1], &p[2], &plen );
uint8_t *in = mcast_recv_frame( v->r, &p[0],&p[1], &p[2], &plen );
if( in == NULL )
return 0;
@@ -478,7 +451,7 @@ int vj_client_read_i( vj_client *v, uint8_t *dst, int len )
return 1; //@ caller will memcpy it to destination buffer
}
else if ( v->c[0]->type == VSOCK_C )
else
{
//@ result returns software package id
int result = vj_client_packet_negotiate( v, tokens );
@@ -538,6 +511,15 @@ int vj_client_read_i( vj_client *v, uint8_t *dst, int len )
v->in_height = p[1];
v->in_fmt = p[2];
if( v->in_width != v->orig_width || v->in_height != v->orig_height ) {
free(v->space);
v->space = vj_calloc(sizeof(uint8_t) * v->in_width * v->in_height * 4 );
if(!v->space)
return -1;
v->orig_width = v->in_width;
v->orig_height = v->in_height;
}
uv_len = 0;
y_len = p[0] * p[1];
@@ -555,7 +537,7 @@ int vj_client_read_i( vj_client *v, uint8_t *dst, int len )
break;
}
int n = sock_t_recv( v->c[0]->fd,v->space,p[3] );
int n = sock_t_recv( v->fd[0],v->space,p[3] );
if( n <= 0 ) {
if( n == -1 ) {
veejay_msg(VEEJAY_MSG_ERROR, "Error '%s' while reading socket", strerror(errno));
@@ -584,198 +566,78 @@ int vj_client_read_i( vj_client *v, uint8_t *dst, int len )
return 0;
}
int vj_client_get_status_fd(vj_client *v, int sock_type )
{
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
#endif
if(sock_type == V_STATUS)
{
vj_sock_t *c = v->c[1]->fd;
return c->sock_fd;
}
if(sock_type == V_CMD )
{
if(!v->mcast)
{
vj_sock_t *c = v->c[0]->fd;
return c->sock_fd;
}
else
{
mcast_receiver *c = v->c[0]->r;
return c->sock_fd;
}
}
return 0;
}
int vj_client_setup_timeout( vj_client *v, int sock_type, int timeout )
{
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
#endif
if( sock_type == V_STATUS )
{
sock_t_set_timeout( v->c[1], timeout );
}
if( sock_type == V_CMD )
{
sock_t_set_timeout( v->c[0], timeout );
}
}
int vj_client_read_no_wait(vj_client *v, int sock_type, uint8_t *dst, int bytes )
{
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
int n = sock_t_recv( v->fd[ sock_type ] ,dst, bytes );
veejay_msg(VEEJAY_MSG_DEBUG, "%s: type %d, socket %p: %d bytes [%s]",
__FUNCTION__, sock_type, v->fd[sock_type], bytes, dst );
return n;
#else
return sock_t_recv( v->fd[ sock_type ], dst, bytes );
#endif
if( sock_type == V_STATUS )
{
if(v->c[1] && v->c[1]->fd && v->c[1]->type == VSOCK_S)
return( sock_t_recv( v->c[1]->fd, dst, bytes ) );
}
if( sock_type == V_CMD )
{
if(v->c[0] && v->c[0]->fd && v->c[0]->type == VSOCK_C)
return ( sock_t_recv( v->c[0]->fd, dst, bytes ) );
}
return 0;
}
int vj_client_read(vj_client *v, int sock_type, uint8_t *dst, int bytes )
{
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
#ifndef STRICT_CHECKING
return sock_t_recv( v->fd[ sock_type ], dst, bytes );
#else
int n = sock_t_recv( v->fd[ sock_type ], dst, bytes );
veejay_msg(VEEJAY_MSG_DEBUG, "type %d, read %d bytes '[%s]' from socket %p (port %d)",
sock_type, bytes, dst, v->fd[sock_type], v->ports[ sock_type] );
return n;
#endif
if( sock_type == V_STATUS )
{
if(v->c[1] && v->c[1]->fd && v->c[1]->type == VSOCK_S) {
return( sock_t_recv( v->c[1]->fd, dst, bytes ) );
}
}
if( sock_type == V_CMD )
{
if(v->c[0] && v->c[0]->fd && v->c[0]->type == VSOCK_C) {
return ( sock_t_recv( v->c[0]->fd, dst, bytes ) );
}
}
return 0;
}
int vj_client_send(vj_client *v, int sock_type,char *buf ) {
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
#endif
int vj_client_send_buf(vj_client *v, int sock_type,unsigned char *buf, int len) {
if( v->mcast ) {
return mcast_send( v->s, (void*) buf, len , v->ports[sock_type ] );
}
return sock_t_send( v->fd[ sock_type ], buf, len );
}
if( sock_type == V_CMD )
{
// format msg
int vj_client_send(vj_client *v, int sock_type,unsigned char *buf) {
int len = strlen(buf);
sprintf(v->blob, "V%03dD%s", len, buf);
#ifdef STRICT_CHECKING
if(!verify_integrity(v->blob,strlen(v->blob)) ) {
veejay_msg(0,"VIMS validation error in buf of %d bytes: '%s'", len,buf);
}
#endif
if(v->c[0]->type == VSOCK_C)
return ( sock_t_send( v->c[0]->fd, v->blob, len + 5 ));
if(v->c[0]->type == VMCAST_C)
return ( mcast_send( v->c[0]->s, (void*) v->blob, len + 5,
v->ports[1] ));
}
return 1;
}
int vj_client_send_buf(vj_client *v, int sock_type,unsigned char *buf, int len )
{
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
#endif
if( sock_type == V_CMD )
{
// format msg
if( v->mcast ) {
sprintf( v->blob, "V%03dD", len );
veejay_memcpy( v->blob+5, buf, len );
memcpy( v->blob + 5, buf, len );
return mcast_send( v->s, (void*) v->blob, len + 5, v->ports[sock_type ] );
}
sprintf( v->blob, "V%03dD", len );
memcpy( v->blob + 5, buf, len );
return sock_t_send( v->fd[ sock_type ], v->blob, len + 5 );
}
void vj_client_close( vj_client *v )
{
if( v->mcast == 1 ) {
mcast_close_receiver( v->r );
mcast_close_sender( v->s );
v->s = NULL;
v->r = NULL;
} else {
if( v->fd[0] ) {
#ifdef STRICT_CHECKING
if(!verify_integrity( v->blob, strlen(v->blob) ) ) {
veejay_msg(0,"VIMS validation error in buf of %d bytes: '%s'", len+5,buf);
}
veejay_msg(VEEJAY_MSG_DEBUG, "close connection: socket %p", v->fd[0] );
#endif
if(v->c[0]->type == VSOCK_C)
return ( sock_t_send( v->c[0]->fd, v->blob, len + 5 ));
if(v->c[0]->type == VMCAST_C)
return ( mcast_send( v->c[0]->s, (void*) v->blob, len + 5,
v->ports[1] ));
sock_t_close( v->fd[0] );
sock_t_free( v->fd[0] );
v->fd[0] = NULL;
}
return 1;
}
int vj_client_send_bufX(vj_client *v, int sock_type,unsigned char *buf, int len )
{
if( v->fd[1] ) {
#ifdef STRICT_CHECKING
vj_client_check( v,sock_type);
veejay_msg(VEEJAY_MSG_DEBUG, "close connection: socket %p", v->fd[1] );
#endif
if( sock_type == V_CMD )
{
// format msg
sprintf(v->blob, "K%08d", len);
veejay_memcpy( v->blob+9, buf, len );
if(v->c[0]->type == VSOCK_C)
return ( sock_t_send( v->c[0]->fd, v->blob, len + 9 ));
if(v->c[0]->type == VMCAST_C)
return ( mcast_send( v->c[0]->s, (void*) v->blob, len + 9,
v->ports[1] ));
}
return 1;
}
int vj_client_close( vj_client *v )
{
if(v)
{
if(v->c[0])
{
if(v->c[0]->type == VSOCK_C ) {
#ifdef STRICT_CHECKING
assert( v->c[0]->fd != NULL );
#endif
sock_t_close(v->c[0]->fd );
sock_t_free( v->c[0]->fd);
v->c[0]->fd = NULL;
}
else if ( v->c[0]->type == VMCAST_C )
{
mcast_close_receiver( v->c[0]->r );
mcast_close_sender( v->c[0]->s );
sock_t_close( v->fd[1] );
sock_t_free( v->fd[1] );
v->fd[1] = NULL;
}
}
if(v->c[1])
{
if(v->c[1]->type == VSOCK_S ) {
#ifdef STRICT_CHECKING
assert( v->c[1]->fd != NULL );
#endif
#ifdef STRICT_CHECKING
sock_t_close(v->c[1]->fd );
sock_t_free(v->c[1]->fd);
v->c[1]->fd = NULL;
#endif
}
}
return 1;
}
return 0;
}
int vj_client_test(char *host, int port)

View File

@@ -19,14 +19,6 @@
#ifndef VJ_CLIENT_H
#define VJ_CLIENT_H
typedef struct
{
void *r;
void *s;
void *fd;
int type;
} conn_type_t;
typedef struct
{
int planes[3];
@@ -36,12 +28,20 @@ typedef struct
int in_width;
int in_height;
int in_fmt;
int orig_width;
int orig_height;
uint8_t *space;
conn_type_t **c;
int ports[3];
int mcast;
void *lzo;
unsigned char *blob;
void *r;
void *s;
void *fd[2];
int ports[2];
} vj_client;
int vj_client_link_can_write(vj_client *v, int s);
@@ -50,8 +50,6 @@ int vj_client_link_can_read(vj_client *v,int s );
int vj_client_connect( vj_client *v, char *host, char *group_name, int port_id );
int vj_client_get_status_fd(vj_client *v, int sock_type );
void vj_client_flush( vj_client *v, int delay );
int vj_client_poll( vj_client *v, int sock_type );
@@ -62,9 +60,11 @@ int vj_client_read( vj_client *v, int sock_type, uint8_t *dst, int bytes );
int vj_client_read_no_wait( vj_client *v, int sock_type, uint8_t *dst, int bytes );
int vj_client_close( vj_client *v );
void vj_client_close( vj_client *v );
int vj_client_send( vj_client *v, int sock_type, char *buf);
int vj_client_send( vj_client *v, int sock_type,unsigned char *buf);
int vj_client_send_buf( vj_client *v, int sock_type,unsigned char *buf, int len);
vj_client *vj_client_alloc(int w , int h, int f);
@@ -72,12 +72,9 @@ void vj_client_free(vj_client *v);
int vj_client_test(char *addr, int port );
int vj_client_send_bufX(vj_client *v, int sock_type,unsigned char *buf, int len );
int vj_client_window_sizes( int socket_fd, int *r, int *s );
int vj_client_connect_dat(vj_client *v, char *host, int port_id );
int vj_client_setup_timeout( vj_client *v, int sock_type, int timeout );
#endif

View File

@@ -704,84 +704,58 @@ static int _vj_verify_msg(vj_server *vje,int link_id, char *buf, int buf_len )
int i = 0;
char *s = buf;
int num_msg = 0;
//vj_link **Link = (vj_link**) vje->link;
if( (i+4) > buf_len )
if( buf_len < 5 )
{
_vj_malfunction("VIMS (v) Message too small", buf, buf_len, i );
return 0;
}
while( (i+4) < buf_len )
while( i < buf_len )
{
if( !(s[i]=='V' && s[i+4] == 'D') )
{
if(s[i] != 'K')
if( !(s[i]=='V' && s[i+4] == 'D') && !(s[i] == 'K') )
{
_vj_malfunction( "VIMS (v) Cannot identify message as VIMS message", buf, buf_len, i);
return 0;
}
}
if( s[i] != 'K' )
if( s[i] == 'V' )
{
char tmp_len[4];
char net_id[4];
int slen = 0;
int netid = 0;
bzero(tmp_len,4);
bzero(net_id,4 );
char *str_ptr = &s[i];
str_ptr ++; // skip 'V'
char *str_ptr = &s[(i+1)];
veejay_strncpy( tmp_len,str_ptr, 3 ); // header length
if( sscanf(tmp_len, "%03d", &slen) <= 0 )
{
_vj_malfunction( "VIMS (v) Cannot read header length", buf, buf_len, i + 1);
return 0;
}
if( slen > buf_len )
{
char msg[256];
veejay_memset(msg,0,256);
snprintf(msg, 256,"VIMS (v) Remote %s is sending corrupted packets", (char*) (inet_ntoa( vje->remote.sin_addr ) ) );
_vj_malfunction( NULL, buf, buf_len, i + 1 );
vj_server_close_connection( vje, link_id );
return 0;
}
if ( slen > 999 )
{
char msg[256];
veejay_memset(msg,0,256);
snprintf(msg, 256, "VIMS (v) Remote %s is acting very suspiciously", (char* )( inet_ntoa( vje->remote.sin_addr ) ));
_vj_malfunction( msg, buf, buf_len, i + 1);
vj_server_close_connection( vje, link_id );
return 0;
}
int slen = atoi( tmp_len );
i += 4; // advance to message content
str_ptr += 4;
veejay_strncpy( net_id, str_ptr, 3 );
int netid = 0;
if( sscanf( net_id, "%03d", &netid ) <= 0 )
{
_vj_malfunction( "VIMS (v) Corrupt VIMS selector", buf, buf_len, i );
return 0;
}
if( netid < 0 && netid > 600 )
{
_vj_malfunction( "VIMS (v) selector out of range", buf,buf_len, i );
return 0;
}
if( vje->use_mcast )
{
if( netid >= 400 && netid < 500 )
{
_vj_malfunction( "VIMS (v) multicast doesnt allow querying of data",buf,buf_len,i);
return 0;
}
}
//FIXME: malformed endings
int last_char = slen - 1;
int failed = 1;
if( last_char > 1 )
@@ -791,20 +765,21 @@ static int _vj_verify_msg(vj_server *vje,int link_id, char *buf, int buf_len )
failed = 0;
else if(str_ptr[last_char] == ';' )
failed = 0;
if(!failed)
{
num_msg ++;
i += slen + 1;
}
}
if(failed)
{
_vj_malfunction("VIMS (v) message does not end with ';'", buf, buf_len , i);
return 0;
}
}
else
{
else if( s[i] == 'K' ) {
int len = 0;
char *str_ptr = &s[i];
@@ -812,22 +787,24 @@ static int _vj_verify_msg(vj_server *vje,int link_id, char *buf, int buf_len )
{
i += len;
num_msg ++;
return num_msg;
}
else
{
_vj_malfunction("VIMS (v) keyframe packet length not set", str_ptr, buf_len, i );
}
}
}
if(num_msg > 0 )
return num_msg;
return 0;
}
} else {
veejay_msg(0, "parse error.");
return 0;
}
}
static int _vj_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len, int priority )
return num_msg;
}
static int _vj_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len )
{
int i = 0;
char *s = buf;
@@ -835,20 +812,19 @@ static int _vj_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len, in
vj_link **Link = (vj_link**) vje->link;
vj_message **v = Link[link_id]->m_queue;
while( (i+4) < buf_len )
{
while( i < buf_len ) {
char tmp_len[8];
char net_id[4];
int slen = 0;
int netid = 0;
bzero(tmp_len,8);
bzero(net_id,4 );
char *str_ptr = &s[i];
if(s[i] == 'V')
{
str_ptr ++;
str_ptr ++; //@ [V][ ]
//@ ^
veejay_strncpy( tmp_len,str_ptr, 3 ); // header length
if( sscanf(tmp_len, "%03d", &slen) <= 0 )
@@ -856,46 +832,22 @@ static int _vj_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len, in
veejay_msg(0, "Error parsing header in '%s' (%d bytes)", buf, buf_len );
return 0;
}
i += 4; // advance to message content
str_ptr += 4;
veejay_strncpy( net_id, str_ptr, 3 );
if( sscanf( net_id, "%03d", &netid ) <= 0 )
str_ptr += 4; //@ [V][0][0][5][D][ ]
//@ ^
veejay_strncpy( net_id, str_ptr, 3 ); //@ [V][0][0][5][D][6][0][0][:][;]
//@ ^ ^ ^
if( sscanf( net_id, "%03d", &netid ) )
{
if( strncasecmp(net_id, "key",3) != 0 )
{
veejay_msg(0, "Error parsing VIMS ID in '%s' (%d bytes)",buf,buf_len);
return 0;
}
else
{
v[num_msg]->msg = (char*) vj_malloc( slen );
veejay_memcpy( v[num_msg]->msg, str_ptr, slen );
v[num_msg]->len = slen;
v[num_msg]->msg = strndup( str_ptr, slen ); //@ '600:;'
v[num_msg]->len = slen; //@ 5
#ifdef STRICT_CHECKING
assert( slen == strlen( v[num_msg]->msg ) );
#endif
num_msg++;
}
}
else
{
if(! priority )
{
// store message anyway
int n_len = slen;
v[num_msg]->msg = (char*)strndup( str_ptr , slen );
veejay_chomp_str( v[num_msg]->msg , &n_len );
v[num_msg]->len = n_len;
num_msg++;
}
if(priority && netid > 255 )
{
// store high priority only (reduce load) -
int n_len = slen;
v[num_msg]->msg = (char*)strndup( str_ptr , slen );
veejay_chomp_str( v[num_msg]->msg, &n_len );
v[num_msg]->len = n_len;
num_msg++;
}
}
if(num_msg >= (VJ_MAX_PENDING_MSG-1) )
{
@@ -903,37 +855,41 @@ static int _vj_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len, in
num_msg,VJ_MAX_PENDING_MSG );
return VJ_MAX_PENDING_MSG-1; // cant take more
}
// i += slen;
i += (slen+1); // try next message
i += ( 5 + slen);
}
else if (s[i] == 'K' )
{
str_ptr ++;
veejay_memcpy( tmp_len,str_ptr, 8 );
str_ptr ++; //@ '[K][ ]
//@ ^
veejay_strncpy( tmp_len, str_ptr, 8 );
if( sscanf(tmp_len, "%08d", &slen) <= 0 )
{
veejay_msg(0, "Error parsing KF header in '%s' (%d bytes)", buf, buf_len );
return 0;
}
i += 8; // advance to message content
str_ptr += 8;
str_ptr += 8; // '[K][0][0][0][0][0][0][2][5][ ]'
//@ ^
v[num_msg]->msg = (char*) vj_calloc( slen );
veejay_memcpy( v[num_msg]->msg, str_ptr, slen );
v[num_msg]->msg = strndup( str_ptr, slen );
v[num_msg]->len = slen;
num_msg++;
i += slen;
i += ( 8 + slen + 1);
} else {
veejay_msg(0, "VIMS: blob '%s' not recognized. First token must be either 'V' or 'K' followed by packet length.",
str_ptr );
return 0;
}
}
if( ! priority )
{
Link[link_id]->n_queued = num_msg;
Link[link_id]->n_retrieved = 0;
}
return num_msg;
}
@@ -1056,7 +1012,7 @@ int vj_server_update( vj_server *vje, int id )
if( n_msg < VJ_MAX_PENDING_MSG )
{
int nn = _vj_parse_msg( vje, id, msg_buf, bytes_left,0 );
int nn = _vj_parse_msg( vje, id, msg_buf, bytes_left );
if(nn != n_msg)
{
veejay_msg(VEEJAY_MSG_ERROR, "Veejay's message queue corrupted (end session!)");

View File

@@ -308,12 +308,8 @@ enum {
#define MAX_EDIT_LIST_FILES 4096
#define VSOCK_S 0
#define VSOCK_C 1
#define V_STATUS 0
#define V_CMD 1
#define VMCAST_S 4
#define VMCAST_C 5
#define V_STATUS 1
#define V_CMD 0
enum
{

View File

@@ -2731,8 +2731,7 @@ void vj_event_quit(void *ptr, const char format[], va_list ap)
}
}
veejay_change_state(v, LAVPLAY_STATE_STOP);
veejay_quit(v);
}
void vj_event_sample_mode(void *ptr, const char format[], va_list ap)