Exemple #1
0
/* Wake up the sleepers */
static void low_start(void)
{
  struct object *obj, *next;
  struct output *o;


  add_ref(THISOBJ);		/* dont kill yourself now */
  for(obj=THIS->firstoutput;obj;obj=next)
  {
    /* add_ref(obj); */		/* Hang on PLEASE!! /hubbe */
    o=(struct output *)(obj->storage);
    next=o->next;
    if (o->obj && o->mode==O_SLEEP)
    {
      if (!o->obj->prog)
      {
	output_finish(obj);
      }
      else
      {
	push_int(0);
	push_callback(offset_output_write_callback);
	push_callback(offset_output_close_callback);
	apply_low(o->obj,o->set_nonblocking_offset,3);
	/* output_try_write_some(obj); */
	/* o->mode=O_RUN; */		/* Hubbe */
      }
    }
    /* next=o->next; */
    /* free_object(obj); */
  }

  free_object(THISOBJ);
}
Exemple #2
0
static void func_callback_wrapper(int which, sqlite3_context * ctx, int num_args, sqlite3_value ** values)
{
  CB_Data *	cb_data	= sqlite3_user_data(ctx);
  DB *		db 	= cb_data->db;
  lua_State * 	L	= db->L;
  
  switch(which)
  {
    case 0:	push_callback(L, db, KEY_XFUNC(cb_data)); break;
    case 1:	push_callback(L, db, KEY_XSTEP(cb_data)); break;
    case 2:	push_callback(L, db, KEY_XFINAL(cb_data)); break;
  }
  
  if (lua_isnil(L, -1))
  {
    lua_pop(L, 1);
    fprintf(stderr, "libluasqlite3: func_callback_wrapper: Warning: function is null\n");
    return;
  }
  
  lua_pushlightuserdata(L, ctx);
  
  if (values)
  {
    lua_pushnumber(L, num_args);
    lua_pushlightuserdata(L, values);
  }
  
  if (lua_pcall(L, values ? 3 : 1, 0, 0))
  {
    fprintf(stderr, "libluasqlite3: func_callback_wrapper: Warning: user function error: %s\n", lua_tostring(L, -1));
    sqlite3_result_error(ctx, lua_tostring(L, -1), lua_strlen(L, -1));
    lua_pop(L, 1);
  }
}
Exemple #3
0
/* Free an input */
static INLINE void free_input(input *inp) {
  ninputs--;
  switch(inp->type) {
  case NBIO_STR:
    DERR(fprintf(stderr, "Freeing string input 0x%x\n", (unsigned int)inp));
    free_string(inp->u.data);
    nstrings--;
    break;
#ifdef USE_MMAP
  case NBIO_MMAP:
    DERR(fprintf(stderr, "Freeing mmap input 0x%x\n", (unsigned int)inp));
    if(inp->u.mmap_storage->data != MAP_FAILED) {
      munmap(inp->u.mmap_storage->data, inp->u.mmap_storage->m_len);
      mmapped -= inp->u.mmap_storage->m_len;
    }
    push_int(0);    push_int(0);    push_int(0);
    apply_low(inp->u.mmap_storage->file, inp->set_nb_off, 3);
    apply_low(inp->u.mmap_storage->file, inp->set_b_off, 0);
    pop_n_elems(2);
    free_object(inp->u.mmap_storage->file);
    free(inp->u.mmap_storage);
    break;
#endif
  case NBIO_OBJ:
    push_int(0);    push_int(0);    push_int(0);
    apply_low(inp->u.file, inp->set_nb_off, 3);
    apply_low(inp->u.file, inp->set_b_off, 0);
    pop_n_elems(2);
    /* FALL THROUGH */
    
  case NBIO_BLOCK_OBJ:
    DERR(fprintf(stderr, "Freeing obj input 0x%x\n", (unsigned int)inp));
    free_object(inp->u.file);
    nobjects--;
    break;
    
  }
  if(THIS->last_input == inp)
    THIS->last_input = NULL;
  THIS->inputs = inp->next;
  if(!THIS->finished && THIS->inputs && THIS->inputs->type == NBIO_OBJ) {
    /* Aha! Set read callback here */
    DERR(fprintf(stderr, "Setting read/close callbacks for input 0x%x\n", (unsigned int)THIS->inputs));
    push_callback(input_read_cb_off);
    push_int(0);
    push_callback(input_close_cb_off);
    apply_low(THIS->inputs->u.file, THIS->inputs->set_nb_off, 3);
    THIS->inputs->mode = READING;    
  }
  free(inp);
}
Exemple #4
0
/**
 * \brief Executes the callback of a timer.
 *
 * Then, if the callback returns \c true, the timer is rescheduled,
 * otherwise it is discarded.
 *
 * Does nothing if the timer is already finished.
 *
 * \param timer The timer to execute.
 */
void LuaContext::do_timer_callback(Timer& timer) {

  Debug::check_assertion(timer.is_finished(), "This timer is still running");

  const std::map<Timer*, LuaTimerData>::iterator it = timers.find(&timer);
  if (it != timers.end() && it->second.callback_ref != LUA_REFNIL) {
    const int callback_ref = it->second.callback_ref;
    push_callback(callback_ref);
    const bool success = call_function(0, 1, "timer callback");

    bool repeat = false;
    if (success) {
      repeat = lua_isboolean(l, -1) && lua_toboolean(l, -1);
      lua_pop(l, 1);
    }

    if (repeat) {
      // The callback returned true: reschedule the timer.
      timer.set_expiration_date(timer.get_expiration_date() + timer.get_initial_duration());
      if (timer.is_finished()) {
        // Already finished: this is possible if the duration is smaller than
        // the main loop stepsize.
        do_timer_callback(timer);
      }
    }
    else {
      cancel_callback(callback_ref);
      it->second.callback_ref = LUA_REFNIL;
      timers_to_remove.push_back(&timer);
    }
  }
}
Exemple #5
0
static void tcp_after_close(uv_handle_t* handle) {
  UNWRAP(handle);
  lev_handle_unref(L, (LevRefStruct_t*)self);
  if (push_callback(L, self, "on_close")) {
    lua_call(L, 1, 0);/*, -3*/
  }
}
Exemple #6
0
static void pipe_read_input_callback(INT32 args)
{
  struct input *i;
  struct pike_string *s;

  if (args<2 || sp[1-args].type!=T_STRING)
    Pike_error("Illegal argument to pipe->read_input_callback\n");
   
  i=THIS->firstinput;

  if (!i)
    Pike_error("Pipe read callback without any inputs left.\n");

  s=sp[1-args].u.string;

  if(append_buffer(s))
  {
    /* THIS DOES NOT WORK */
    push_int(0);
    push_int(0);
    push_callback(offset_input_close_callback);
    apply_low(i->u.obj,i->set_nonblocking_offset,3);
    pop_stack();
    THIS->sleeping=1;
  }

  low_start();
  pop_n_elems(args-1);
}
Exemple #7
0
static void on_connection(uv_stream_t* handle, int status) {
  UNWRAP(handle);
  puts(__func__);
  push_callback(L, self, "on_connection");
  lua_pushinteger(L, status);
  lua_pcall(L, 2, 0, -4);
}
Exemple #8
0
int xauth_callback_wrapper(void * cb_data, int auth_request, const char * name1, const char * name2, const char * db_name, const char * trigger_name)
{
    DB *		db = CB_DATA(cb_data)->db;
    lua_State *	L  = db->L;
    int result;

    push_callback(L, db, KEY_XAUTH(cb_data));
    lua_pushnumber(L, auth_request);
    push_nil_or_string(L, name1);
    push_nil_or_string(L, name2);
    push_nil_or_string(L, db_name);
    push_nil_or_string(L, trigger_name);

    if ( lua_pcall(L, 5, 1, 0) )
    {
        lua_pop(L, 1);
        return SQLITE_DENY;		/* On errors, sqlite should deny access */
    }

    if (lua_isnumber(L, -1))
        result = lua_tonumber(L, -1);
    else
        result = SQLITE_DENY;	/* Wrong result values should deny access */

    lua_pop(L, 1);
    return result;
}
Exemple #9
0
enum encoder_action poll_encoder(void)
{
    // Poll switch
    if (!gpio_get(*inputSwitch) && push_callback != NULL) {
        // De-bounce
        _delay_ms( 25 );
        while (!gpio_get(*inputSwitch));
        push_callback();
        return ENCODER_ACTION_PUSH;
    }

    // Abort if the position is unchanged
    if (state.inputA == gpio_get(*inputA) && state.inputB == gpio_get(*inputB)) {
        return ENCODER_ACTION_NONE;
    }

    enum encoder_action action = ENCODER_ACTION_NONE;

    // Direction: clockwise
    if ( (!state.inputA && !state.inputB && !gpio_get(*inputA) &&  gpio_get(*inputB)) ||
              (!state.inputA &&  state.inputB &&  gpio_get(*inputA) &&  gpio_get(*inputA)) ||
              ( state.inputA &&  state.inputB && !gpio_get(*inputA) && !gpio_get(*inputB)) )
    {
        action = ENCODER_ACTION_CW;
        ++state.counter;
    }

    // Direction: counter-clockwise
    else if ( ( state.inputA &&  state.inputB && !gpio_get(*inputA) &&  gpio_get(*inputB)) ||
         (!state.inputA &&  state.inputB && !gpio_get(*inputA) && !gpio_get(*inputB)) ||
         (!state.inputA && !state.inputB &&  gpio_get(*inputA) &&  gpio_get(*inputB)) )
    {
        action = ENCODER_ACTION_CCW;
        --state.counter;
    }

    // Update input state variables
    state.inputA = gpio_get(*inputA);
    state.inputB = gpio_get(*inputB);

    // On reception of the third pulse in the same direction
    if (state.counter <= -3 || state.counter >= 3) {
        // Reset counter
        state.counter = 0;

        // Call back
        if (action == ENCODER_ACTION_CW && cw_callback != NULL) {
            cw_callback();
        }
        else if (action == ENCODER_ACTION_CCW && ccw_callback != NULL) {
            ccw_callback();
        }

        return action;
    }

    return ENCODER_ACTION_NONE;
}
/**
* @brief Calls a function stored in the registry with a reference and
* releases this reference.
* @param callback_ref Reference of the function to call (if LUA_REFNIL,
* nothing is done).
*/
void LuaContext::do_callback(int callback_ref) 
{
  if (callback_ref != LUA_REFNIL) 
  {
    push_callback(callback_ref);
    call_function(0, 0, "callback");
    destroy_ref(callback_ref);
  }
}
Exemple #11
0
/* Let's guess what this function does....
 *
 */
static INLINE void input_finish(void)
{
  struct input *i;

  while(1)
  {
    /* Get the next input from the queue */
    i=THIS->firstinput->next;
    free_input(THIS->firstinput);
    THIS->firstinput=i;

    if(!i) break;

    switch(i->type)
    {
    case I_OBJ:
      THIS->sleeping=0;
      push_callback(offset_input_read_callback);
      push_int(0);
      push_callback(offset_input_close_callback);
      apply_low(i->u.obj,i->set_nonblocking_offset,3);
      pop_stack();
      return;

    case I_BLOCKING_OBJ:
      if (read_some_data())
	return;
      continue;

    case I_MMAP:
      if (THIS->fd==-1) return;
      continue;

    case I_STRING:
      append_buffer(i->u.str);

    case I_NONE: break;
    }
  }
  THIS->sleeping=0;

  low_start();
  finished_p();
}
Exemple #12
0
static void on_connection(uv_stream_t* handle, int status) {
  UNWRAP(handle);
  push_callback(L, self, "on_connection");
  if (!status) {
    lua_pushnil(L);
  } else {
    lua_pushinteger(L, status);
  }
  lua_call(L, 2, 0);/*, -4*/
}
Exemple #13
0
static void xtrace_callback_wrapper(void * cb_data, const char * str)
{
    DB *		db = CB_DATA(cb_data)->db;
    lua_State *	L  = db->L;

    push_callback(L, db, KEY_XTRACE(cb_data));
    lua_pushstring(L, str);

    if ( lua_pcall(L, 1, 0, 0) )
        lua_pop(L, 1);		/* pop error message and delete it (errors are ignored) */
}
Exemple #14
0
void xneeded_callback_wrapper(void * cb_data, sqlite3 * sqlite3, int eTextRep, const char * collation_name)
{
    DB * 		db = CB_DATA(cb_data)->db;
    lua_State * 	L  = db->L;

    push_callback(L, db, KEY_XNEEDED(cb_data));
    lua_pushstring(L, collation_name);

    if (lua_pcall(L, 1, 0, 0))
        lua_pop(L, 1);
}
Exemple #15
0
static void on_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
  UNWRAP(handle);
  puts(__func__);
  push_callback(L, self, "on_read");
  lua_pushinteger(L, nread);
  if (nread >= 0)
    lua_pushlstring(L, buf.base, nread);
  else
    lua_pushnil(L);
  lua_pcall(L, 3, 0, -5);
}
Exemple #16
0
static void on_connect(uv_connect_t* req, int status) {
  UNWRAP(req->handle);
  push_callback(L, self, "on_connect");
  if (!status) {
    lua_pushnil(L);
    /*printf("CONNECT ON FD: %d (ref:%d)\n", ( (uv_stream_t*)&self->handle )->fd, ((LevRefStruct_t*)self)->refCount);*/
  } else {
    lua_pushinteger(L, status);
    lev_handle_unref(L, (LevRefStruct_t*)self);
  }
  lua_call(L, 2, 0);/*, -4*/
}
Exemple #17
0
static INLINE void set_outp_write_cb(output *outp) {
  /* Need to set_nonblocking again to trigger the write cb again.
   * FIXME: only call when there is more to write...
   */
  if(outp != NULL) {
    DERR(fprintf(stderr, "Setting output write callback.\n"));
    push_int(0);
    push_callback(output_write_cb_off);
    push_int(0);
    apply_low(outp->file, outp->set_nb_off, 3);
    pop_stack();
  }
}  
Exemple #18
0
int xcommit_callback_wrapper(void * cb_data)
{
    DB *		db = CB_DATA(cb_data)->db;
    lua_State *	L  = db->L;

    push_callback(L, db, KEY_XCOMMIT(cb_data));

    if ( lua_pcall(L, 0, 1, 0) )
    {
        lua_pop(L, 1);
        return 1;		/* on errors, rollback */
    }

    return pop_break_condition(L);
}
Exemple #19
0
int xbusy_callback_wrapper(void * cb_data, int num_called)
{
    DB *		db = CB_DATA(cb_data)->db;
    lua_State *	L  = db->L;

    push_callback(L, db, KEY_XBUSY(cb_data));
    lua_pushnumber(L, num_called);

    if ( lua_pcall(L, 1, 1, 0) )
    {
        lua_pop(L, 1);
        return 0;		/* On errors, sqlite should return SQLITE_BUSY */
    }

    return pop_break_condition(L);	/* WARNING: In reality, the semantic is inverted !!!*/
}
Exemple #20
0
int xcompare_callback_wrapper(void * cb_data, int len_a, const void * str_a, int len_b, const void * str_b)
{
    DB *		db = CB_DATA(cb_data)->db;
    lua_State *	L  = db->L;
    int result;

    push_callback(L, db, KEY_XCOMPARE(cb_data));
    lua_pushlstring(L, str_a, len_a);
    lua_pushlstring(L, str_b, len_b);

    if ( lua_pcall(L, 2, 1, 0) )
        result = 0;			/* No way to signal errors to sqlite */
    else
        result = (int) lua_tonumber(L, -1);

    lua_pop(L, 1);
    return result;
}
Exemple #21
0
static void on_close(uv_handle_t* handle) {
  UNWRAP(handle);
  push_callback(L, self, "on_close");
  lua_pcall(L, 1, 0, -3);
}
Exemple #22
0
/* This function reads some data from the file cache..
 * Called when we want some data to send.
 */
static INLINE struct pike_string* gimme_some_data(size_t pos)
{
   struct buffer *b;
   ptrdiff_t len;
   struct pipe *this = THIS;

   /* We have a file cache, read from it */
   if (this->fd!=-1)
   {
     char buffer[READ_BUFFER_SIZE];

      if (this->pos<=pos) return NULL; /* no data */
      len=this->pos-pos;
      if (len>READ_BUFFER_SIZE) len=READ_BUFFER_SIZE;
      THREADS_ALLOW();
      fd_lseek(this->fd, pos, SEEK_SET);
      THREADS_DISALLOW();
      do {
	THREADS_ALLOW();
	len = fd_read(this->fd, buffer, len);
	THREADS_DISALLOW();
	if (len < 0) {
	  if (errno != EINTR) {
	    return(NULL);
	  }
	  check_threads_etc();
	}
      } while(len < 0);
      /*
       * FIXME: What if len is 0?
       */
      return make_shared_binary_string(buffer,len);
   }

   if (pos<this->pos)
     return make_shared_string("buffer underflow"); /* shit */

   /* We want something in the next buffer */
   while (this->firstbuffer && pos>=this->pos+this->firstbuffer->s->len) 
   {
     /* Free the first buffer, and update THIS->pos */
      b=this->firstbuffer;
      this->pos+=b->s->len;
      this->bytes_in_buffer-=b->s->len;
      this->firstbuffer=b->next;
      if (!b->next)
	this->lastbuffer=NULL;
      sbuffers-=b->s->len;
      nbuffers--;
      free_string(b->s);
      free((char *)b);

      /* Wake up first input if it was sleeping and we
       * have room for more in the buffer.
       */
      if (this->sleeping &&
	  this->firstinput &&
	  this->bytes_in_buffer<MAX_BYTES_IN_BUFFER)
      {
	if (this->firstinput->type == I_BLOCKING_OBJ) {
	  if (!read_some_data()) {
	    this->sleeping = 0;
	    input_finish();
	  }
	} else {
	  this->sleeping=0;
	  push_callback(offset_input_read_callback);
	  push_int(0);
	  push_callback(offset_input_close_callback);
	  apply(this->firstinput->u.obj, "set_nonblocking", 3);
	  pop_stack();
	}
      }
   }

   while (!this->firstbuffer)
   {
     if (this->firstinput)
     {
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
       if (this->firstinput->type==I_MMAP)
       {
	 char *src;
	 struct pike_string *tmp;

	 if (pos >= this->firstinput->len + this->pos) /* end of mmap */
	 {
	   this->pos += this->firstinput->len;
	   input_finish();
	   continue;
	 }
	 len = this->firstinput->len + this->pos - pos;
	 if (len > READ_BUFFER_SIZE) len=READ_BUFFER_SIZE;
	 tmp = begin_shared_string( len );
	 src = this->firstinput->u.mmap + pos - this->pos;
/* This thread_allow/deny is at the cost of one extra memory copy */
	 THREADS_ALLOW();
	 MEMCPY(tmp->str, src, len);
	 THREADS_DISALLOW();
	 return end_shared_string(tmp);
       }
       else
#endif
       if (this->firstinput->type!=I_OBJ)
       {
	 /* FIXME: What about I_BLOCKING_OBJ? */
	 input_finish();       /* shouldn't be anything else ... maybe a finished object */
       }
     }
     return NULL;		/* no data */
   } 

   if (pos==this->pos)
   {
      add_ref(this->firstbuffer->s);
      return this->firstbuffer->s;
   }
   return make_shared_binary_string(this->firstbuffer->s->str+
				    pos-this->pos,
				    this->firstbuffer->s->len-
				    pos+this->pos);
}
Exemple #23
0
/*! @decl void output(object obj, int|void start_pos)
 *!
 *!   Add an output file object.
 */
static void pipe_output(INT32 args)
{
  struct object *obj;
  struct output *o;
  int fd;
  struct stat s;
  struct buffer *b;

  if (args<1 || 
      sp[-args].type != T_OBJECT ||
      !sp[-args].u.object ||
      !sp[-args].u.object->prog)
    Pike_error("Bad/missing argument 1 to pipe->output().\n");

  if (args==2 &&
      sp[1-args].type != T_INT)
    Pike_error("Bad argument 2 to pipe->output().\n");
       
  if (THIS->fd==-1)		/* no buffer */
  {
    /* test if usable as buffer */ 
    apply(sp[-args].u.object,"query_fd",0);

    if ((sp[-1].type==T_INT)
	&& (fd=sp[-1].u.integer)>=0
	&& (fstat(fd,&s)==0)
	&& S_ISREG(s.st_mode)
	&& (THIS->fd=fd_dup(fd))!=-1 )
    {
      /* keep the file pointer of the duped fd */
      THIS->pos=fd_lseek(fd, 0L, SEEK_CUR);

      THIS->living_outputs++;

      while (THIS->firstbuffer)
      {
	b=THIS->firstbuffer;
	THIS->firstbuffer=b->next;
	fd_lseek(THIS->fd, THIS->pos, SEEK_SET);
	fd_write(THIS->fd,b->s->str,b->s->len);
	sbuffers-=b->s->len;
	nbuffers--;
	free_string(b->s);
	free((char *)b);
      }
      THIS->lastbuffer=NULL;

      /* keep the file pointer of the duped fd
	 THIS->pos=0; */
      push_int(0);
      apply(sp[-args-2].u.object,"set_id", 1);
      pop_n_elems(args+2);	/* ... and from apply x 2  */
      return;
    }
    pop_stack();		/* from apply */
  } 

  THIS->living_outputs++;
  /* add_ref(THISOBJ); */	/* Weird */

  /* Allocate a new struct output */
  obj=clone_object(output_program,0);
  o=(struct output *)(obj->storage);
  o->next=THIS->firstoutput;
  THIS->firstoutput=obj;
  noutputs++;
  o->obj=NULL;

  add_ref(o->obj=sp[-args].u.object);

  o->write_offset=find_identifier("write",o->obj->prog);
  o->set_nonblocking_offset=find_identifier("set_nonblocking",o->obj->prog);
  o->set_blocking_offset=find_identifier("set_blocking",o->obj->prog);

  if (o->write_offset<0 || o->set_nonblocking_offset<0 ||
      o->set_blocking_offset<0) 
  {
    free_object(o->obj);
    Pike_error("illegal file object%s%s%s\n",
	  ((o->write_offset<0)?"; no write":""),
	  ((o->set_nonblocking_offset<0)?"; no set_nonblocking":""),
	  ((o->set_blocking_offset<0)?"; no set_blocking":""));
  }

  o->mode=O_RUN;
  /* keep the file pointer of the duped fd
     o->pos=0; */
  /* allow start position as 2nd argument for additional outputs
  o->pos=THIS->pos; */

  if(args>=2)
    o->pos=sp[1-args].u.integer;
  else
    o->pos=THIS->pos;

  push_object(obj); /* Ok, David, this is probably correct, but I dare you to explain why :) */
  apply(o->obj,"set_id",1);
  pop_stack();

  push_int(0);
  push_callback(offset_output_write_callback);
  push_callback(offset_output_close_callback);
  apply_low(o->obj,o->set_nonblocking_offset,3);
  pop_stack();
   
  pop_n_elems(args-1);
}
Exemple #24
0
/*! @decl void input(object obj)
 *!
 *! Add an input file to this pipe.
 */
static void pipe_input(INT32 args)
{
   struct input *i;
   int fd=-1;			/* Per, one less warning to worry about... */
   struct object *obj;

   if (args<1 || sp[-args].type != T_OBJECT)
     Pike_error("Bad/missing argument 1 to pipe->input().\n");

   obj=sp[-args].u.object;
   if(!obj || !obj->prog)
     Pike_error("pipe->input() on destructed object.\n");

   push_int(0);
   apply(sp[-args-1].u.object,"set_id", 1);
   pop_stack();

   i=new_input();

#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)

   /* We do not handle mmaps if we have a buffer */
   if(THIS->fd == -1)
   {
     char *m;
     struct stat s;

     apply(obj, "query_fd", 0);
     if(sp[-1].type == T_INT) fd=sp[-1].u.integer;
     pop_stack();

     if (fd != -1 && fstat(fd,&s)==0)
     {
       off_t filep=fd_lseek(fd, 0L, SEEK_CUR); /* keep the file pointer */
       size_t len = s.st_size - filep;
       if(S_ISREG(s.st_mode)	/* regular file */
	  && ((m=(char *)mmap(0, len, PROT_READ,
			      MAP_FILE|MAP_SHARED,fd,filep))+1))
       {
	 mmapped += len;

	 i->type=I_MMAP;
	 i->len = len;
	 i->u.mmap=m;
#if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)
	 /* Mark the pages as sequential read only access... */
	 madvise(m, len, MADV_SEQUENTIAL);
#endif
	 pop_n_elems(args);
	 push_int(0);
	 return;
       }
     }
   }
#endif

   i->u.obj=obj;
   nobjects++;
   i->type=I_OBJ;
   add_ref(i->u.obj);
   i->set_nonblocking_offset=find_identifier("set_nonblocking",i->u.obj->prog);
   i->set_blocking_offset=find_identifier("set_blocking",i->u.obj->prog);

   if (i->set_nonblocking_offset<0 ||
       i->set_blocking_offset<0) 
   {
      if (find_identifier("read", i->u.obj->prog) < 0) {
	 /* Not even a read function */
	 free_object(i->u.obj);
	 i->u.obj=NULL;
	 i->type=I_NONE;

	 nobjects--;
	 Pike_error("illegal file object%s%s\n",
	       ((i->set_nonblocking_offset<0)?"; no set_nonblocking":""),
	       ((i->set_blocking_offset<0)?"; no set_blocking":""));
      } else {
	 /* Try blocking mode */
	 i->type = I_BLOCKING_OBJ;
	 if (i==THIS->firstinput) {
	   /*
	    * FIXME: What if read_som_data() returns 0?
	    */
	   read_some_data();
	 }
	 return;
      }
   }
  
   if (i==THIS->firstinput)
   {
     push_callback(offset_input_read_callback);
     push_int(0);
     push_callback(offset_input_close_callback);
     apply_low(i->u.obj,i->set_nonblocking_offset,3);
     pop_stack();
   }
   else
   {
     /* DOESN'T WORK!!! */
     push_int(0);
     push_int(0);
     push_callback(offset_input_close_callback);
     apply_low(i->u.obj,i->set_nonblocking_offset,3);
     pop_stack();
   }

   pop_n_elems(args);
   push_int(0);
}
Exemple #25
0
 void enqueue(const SimpleBuffer &amf, const std::string& identifier,
              as_object* callback)
 {
     push_amf(amf);
     push_callback(identifier, callback);
 }
Exemple #26
0
static void on_connect(uv_connect_t* req, int status) {
  UNWRAP(req->handle);
  push_callback(L, self, "on_connect");
  lua_pushinteger(L, status);
  lua_pcall(L, 2, 0, -4);
}
Exemple #27
0
/* Our write callback */
static void f__output_write_cb(INT32 args)
{
  NBIO_INT_T written = 0, len = 0;
  char *buf = NULL;
  input *inp = THIS->inputs;

  pop_n_elems(args);
  DERR(fprintf(stderr, "output write callback\n"));
  if(THIS->buf_len) {
    /* We currently have buffered data to write */
    len = THIS->buf_len;
    buf = THIS->buf + THIS->buf_pos;
    DERR(fprintf(stderr, "Sending buffered data (%ld bytes left)\n", (long)len));
    written = do_write(THIS->buf + THIS->buf_pos, THIS->buf_len);
    switch(written) {
    case -1: /* We're done here. The write is the weakest link. Goodbye. */
    case 0:  /* Done, but because the write would block or
	      * nothing was written. I.e try again later.
	      */
      set_outp_write_cb(THIS->outp);
      return; 

    default:
      /* Write succeeded */
      THIS->buf_len -= written;
      THIS->buf_pos += written;
      if(THIS->buf_len) {
	/* We couldn't write everything. Return to try later. */
	set_outp_write_cb(THIS->outp);
	return;
      }
      
      /* We wrote all our buffered data. Just fall through to possibly
       * write more.
       */
      THIS->buf_pos = 0;
      THIS->buf_len = 0;
    }
  }
  if(inp == NULL) {
    finished();
    return;
  }
  switch(inp->type) {
  case NBIO_OBJ: /* non-blocking input - if no data available,
		  * just return. once data is available, write_cb will
		  * be called. 
		  */
    THIS->outp->mode = IDLE;
    DERR(fprintf(stderr, "Waiting for NB input data.\n"));
    if(inp->mode == SLEEPING) {
      /* Set read callback here since object is idle */
      push_callback(input_read_cb_off);
      push_int(0);
      push_callback(input_close_cb_off);
      apply_low(THIS->inputs->u.file, THIS->inputs->set_nb_off, 3);
      inp->mode = READING;
    }
    return;
    
  case NBIO_STR: 
    buf = inp->u.data->str + inp->pos;
    len = inp->len - inp->pos;
    DERR(fprintf(stderr, "Sending string data (%ld bytes left)\n", (long)len));
    written = do_write(buf, len);

    if(written >= 0) {
      inp->pos += written;
      if(inp->pos == inp->len) {
	DERR(fprintf(stderr, "Done sending string input (position == length).\n"));
	free_input(inp);
      }
      set_outp_write_cb(THIS->outp);
    }
    break;

#ifdef USE_MMAP
  case NBIO_MMAP:
    len = inp->u.mmap_storage->m_end - inp->pos;
    if(!len) {
      /* need to mmap more data. No need to check if there's more to allocate
       * since the object would have been freed in that case */
      DERR(fprintf(stderr, "mmapping more data from fd %d\n", inp->fd));
      len = MIN(inp->len - inp->pos, MAX_MMAP_SIZE);
      munmap(inp->u.mmap_storage->data, inp->u.mmap_storage->m_len);
      mmapped -= inp->u.mmap_storage->m_len;
      DERR(fprintf(stderr, "trying to mmap %ld bytes starting at pos %ld\n",
		   (long)len, (long)inp->pos));
#ifdef TEST_MMAP_FAILOVER
      inp->u.mmap_storage->data = MAP_FAILED;
#else
      inp->u.mmap_storage->data =
	(char *)mmap(0, len, PROT_READ,
		     MAP_FILE | MAP_SHARED, inp->fd,
		     inp->pos);
#endif
      if(inp->u.mmap_storage->data == MAP_FAILED) {
	struct object *tmp;
	/* FIXME: Better error handling here before falling over to
	 * normal file objects?
	 */
	DERR(perror("additional mmap failed"));
	/* converting to NBIO_OBJ */
	THIS->outp->mode = IDLE;
	tmp = inp->u.mmap_storage->file;
	free(inp->u.mmap_storage);
	inp->u.file = tmp;
#if TEST_MMAP_FAILOVER == NBIO_BLOCK_OBJ
	inp->set_nb_off = -1;	inp->set_b_off  = -1;
#else
	inp->set_nb_off = find_identifier("set_nonblocking",inp->u.file->prog);
	inp->set_b_off  = find_identifier("set_blocking", inp->u.file->prog);
#endif
	if(inp->set_nb_off < 0 || inp->set_b_off < 0)
	{
	  inp->type   = NBIO_BLOCK_OBJ; /* No set_nonblocking/set_blocking funcs */
	  inp->set_nb_off = inp->set_b_off = 0;
	  DERR(fprintf(stderr, "Converting input to NBIO_BLOCK_OBJ.\n"));
	  goto nbio_block_obj_read;
	} else {
	  DERR(fprintf(stderr, "Converting input to NBIO_OBJ.\n"));
	  inp->type   = NBIO_OBJ; /* Fake nonblocking object */
	  push_callback(input_read_cb_off);
	  push_int(0);
	  push_callback(input_close_cb_off);
	  apply_low(inp->u.file, inp->set_nb_off, 3);
	  inp->mode = READING;
	}
	nobjects++;
	break;
      } else {
	inp->u.mmap_storage->m_start = inp->pos;
	inp->u.mmap_storage->m_len   = len;
	inp->u.mmap_storage->m_end   = len + inp->pos;
	mmapped += len;
      }
    }
    buf = inp->u.mmap_storage->data +
      (inp->pos - inp->u.mmap_storage->m_start);
    DERR(fprintf(stderr,"Sending mmapped file (%ld to write, %ld total left)\n"
		 , (long)len, (long)(inp->len - inp->pos)));
    written = do_write(buf, len);

    if(written >= 0) {
      inp->pos += written;
      if(inp->pos == inp->len){
	DERR(fprintf(stderr, "Done sending mmapped input (position == length).\n"));

	free_input(inp);
      }
      set_outp_write_cb(THIS->outp);
    }
#endif
    break;
    
  case NBIO_BLOCK_OBJ:
  nbio_block_obj_read:
    {
      int read;
      read = read_data(); /* At this point we have no data, so read some */
      switch(read) {
      case  -1:
	/* We are done. No more inputs */
	finished();
	return;
      case -2: /* Invalid input for read_data == redo this function */
      case -3: /* We read from a fake object and got a string == redo */
	f__output_write_cb(0);
	return;
      }
      len = THIS->buf_len;
      buf = THIS->buf;
      DERR(fprintf(stderr, "Sending buffered data (%ld bytes left)\n", (long)len));
      written = do_write(buf, len);
      if(written >= 0) {
	THIS->buf_len -= written;
	THIS->buf_pos += written;
	set_outp_write_cb(THIS->outp);
      }
    }
  }   
  if(written < 0) {
    return;
  } 
  if(!THIS->buf_len && THIS->inputs == NULL) {
    finished();
  }
}