/* The classic wtap read routine.  This returns TRUE if it found the next packet,
 * else FALSE.
 * If it finds a frame/packet, it should set the pseudo-header info (ie, let Lua set it).
 * Also Lua needs to set data_offset to the beginning of the line we're returning.
 * This will be the seek_off parameter when this frame is re-read.
*/
static gboolean
wslua_filehandler_read(wtap *wth, int *err, gchar **err_info,
                      gint64 *data_offset)
{
    FileHandler fh = (FileHandler)(wth->wslua_data);
    int retval = -1;
    lua_State* L = NULL;
    File *fp = NULL;
    CaptureInfo *fc = NULL;
    FrameInfo *fi = NULL;

    INIT_FILEHANDLER_ROUTINE(read,FALSE);

    /* Reset errno */
    if (err) {
        *err = errno = 0;
    }

    wth->phdr.opt_comment = NULL;

    fp = push_File(L, wth->fh);
    fc = push_CaptureInfo(L, wth, FALSE);
    fi = push_FrameInfo(L, &wth->phdr, wth->frame_buffer);

    switch ( lua_pcall(L,3,1,1) ) {
        case 0:
            /*
             * Return values for FileHandler:read():
             * Integer is the number of read bytes.
             * Boolean false indicates an error.
             * XXX handling of boolean true is not documented. Currently it will
             * succeed without advancing data offset. Should it fail instead?
             */
            if (lua_type(L, -1) == LUA_TNUMBER) {
                *data_offset = wslua_togint64(L, -1);
                retval = 1;
                break;
            }
            retval = wslua_optboolint(L,-1,0);
            break;
        CASE_ERROR_ERRINFO("read")
    }

    END_FILEHANDLER_ROUTINE();

    (*fp)->expired = TRUE;
    (*fc)->expired = TRUE;
    (*fi)->expired = TRUE;
    lua_settop(L,0);

    return (retval == 1);
}
/* Classic wtap seek_read function, called by wtap core.  This must return TRUE on
 * success, FALSE on error.
 */
static gboolean
wslua_filehandler_seek_read(wtap *wth, gint64 seek_off,
                            struct wtap_pkthdr *phdr, Buffer *buf,
                            int *err, gchar **err_info)
{
    FileHandler fh = (FileHandler)(wth->wslua_data);
    int retval = -1;
    lua_State* L = NULL;
    File *fp = NULL;
    CaptureInfo *fc = NULL;
    FrameInfo *fi = NULL;

    INIT_FILEHANDLER_ROUTINE(seek_read,FALSE);

    /* Reset errno */
    if (err) {
        *err = errno = 0;
    }
    phdr->opt_comment = NULL;

    fp = push_File(L, wth->random_fh);
    fc = push_CaptureInfo(L, wth, FALSE);
    fi = push_FrameInfo(L, phdr, buf);
    lua_pushnumber(L, (lua_Number)seek_off);

    switch ( lua_pcall(L,4,1,1) ) {
    case 0:
        if (lua_isstring(L,-1)) {
            size_t len = 0;
            const gchar* fd = lua_tolstring(L, -1, &len);
            if (len < WTAP_MAX_PACKET_SIZE)
                memcpy(ws_buffer_start_ptr(buf), fd, len);
            retval = 1;
            break;
        }
        retval = wslua_optboolint(L,-1,0);
        break;
        CASE_ERROR_ERRINFO("seek_read")
    }

    END_FILEHANDLER_ROUTINE();

    (*fp)->expired = TRUE;
    (*fc)->expired = TRUE;
    (*fi)->expired = TRUE;
    lua_settop(L,0);

    return (retval == 1);
}
/* Classic wtap seek_read function, called by wtap core.  This must return TRUE on
 * success, FALSE on error.
 */
static gboolean
wslua_filehandler_seek_read(wtap *wth, gint64 seek_off,
    struct wtap_pkthdr *phdr, Buffer *buf,
    int *err, gchar **err_info)
{
    FileHandler fh = (FileHandler)(wth->wslua_data);
    int retval = -1;
    lua_State* L = NULL;
    File *fp = NULL;
    CaptureInfo *fc = NULL;
    FrameInfo *fi = NULL;

    INIT_FILEHANDLER_ROUTINE(seek_read,FALSE);

    /* Reset errno */
    if (err) {
        *err = errno = 0;
    }
    phdr->opt_comment = NULL;

    fp = push_File(L, wth->random_fh);
    fc = push_CaptureInfo(L, wth, FALSE);
    fi = push_FrameInfo(L, phdr, buf);
    lua_pushnumber(L, (lua_Number)seek_off);

    switch ( lua_pcall(L,4,1,1) ) {
        case 0:
            /*
             * Return values for FileHandler:seek_read():
             * Boolean true for successful parsing, false/nil on error.
             * Numbers (including zero) are interpreted as success for
             * compatibility to match FileHandker:seek semantics.
             * (Other values are unspecified/undocumented, but happen to be
             * treated as success.)
             */
            retval = lua_toboolean(L, -1);
            break;
        CASE_ERROR_ERRINFO("seek_read")
    }

    END_FILEHANDLER_ROUTINE();

    (*fp)->expired = TRUE;
    (*fc)->expired = TRUE;
    (*fi)->expired = TRUE;
    lua_settop(L,0);

    return (retval == 1);
}
/* The classic wtap read routine.  This returns TRUE if it found the next packet,
 * else FALSE.
 * If it finds a frame/packet, it should set the pseudo-header info (ie, let Lua set it).
 * Also Lua needs to set data_offset to the beginning of the line we're returning.
 * This will be the seek_off parameter when this frame is re-read.
*/
static gboolean
wslua_filehandler_read(wtap *wth, int *err, gchar **err_info,
                       gint64 *data_offset)
{
    FileHandler fh = (FileHandler)(wth->wslua_data);
    int retval = -1;
    lua_State* L = NULL;
    File *fp = NULL;
    CaptureInfo *fc = NULL;
    FrameInfo *fi = NULL;

    INIT_FILEHANDLER_ROUTINE(read,FALSE);

    /* Reset errno */
    if (err) {
        *err = errno = 0;
    }

    wth->phdr.opt_comment = NULL;

    fp = push_File(L, wth->fh);
    fc = push_CaptureInfo(L, wth, FALSE);
    fi = push_FrameInfo(L, &wth->phdr, wth->frame_buffer);

    switch ( lua_pcall(L,3,1,1) ) {
    case 0:
        if (lua_isnumber(L,-1)) {
            *data_offset = wslua_togint64(L, -1);
            retval = 1;
            break;
        }
        retval = wslua_optboolint(L,-1,0);
        break;
        CASE_ERROR_ERRINFO("read")
    }

    END_FILEHANDLER_ROUTINE();

    (*fp)->expired = TRUE;
    (*fc)->expired = TRUE;
    (*fi)->expired = TRUE;
    lua_settop(L,0);

    return (retval == 1);
}