Blame src/srvc_dir.c

Packit 16808d
Packit 16808d
/*
Packit 16808d
  Meanwhile - Unofficial Lotus Sametime Community Client Library
Packit 16808d
  Copyright (C) 2004  Christopher (siege) O'Brien
Packit 16808d
  
Packit 16808d
  This library is free software; you can redistribute it and/or
Packit 16808d
  modify it under the terms of the GNU Library General Public
Packit 16808d
  License as published by the Free Software Foundation; either
Packit 16808d
  version 2 of the License, or (at your option) any later version.
Packit 16808d
  
Packit 16808d
  This library is distributed in the hope that it will be useful,
Packit 16808d
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 16808d
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 16808d
  Library General Public License for more details.
Packit 16808d
  
Packit 16808d
  You should have received a copy of the GNU Library General Public
Packit 16808d
  License along with this library; if not, write to the Free
Packit 16808d
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 16808d
*/
Packit 16808d
Packit ee6627
#include <glib.h>
Packit 16808d
Packit 16808d
#include "mw_channel.h"
Packit 16808d
#include "mw_common.h"
Packit 16808d
#include "mw_debug.h"
Packit 16808d
#include "mw_error.h"
Packit 16808d
#include "mw_message.h"
Packit 16808d
#include "mw_service.h"
Packit 16808d
#include "mw_session.h"
Packit 16808d
#include "mw_srvc_dir.h"
Packit 16808d
#include "mw_util.h"
Packit 16808d
Packit 16808d
Packit 16808d
#define PROTOCOL_TYPE  0x0000001c
Packit 16808d
#define PROTOCOL_VER   0x00000005
Packit 16808d
Packit 16808d
Packit 16808d
enum dir_action {
Packit 16808d
  action_list    = 0x0000,  /**< list address books */
Packit 16808d
  action_open    = 0x0001,  /**< open an addressbook as a directory */
Packit 16808d
  action_close   = 0x0002,  /**< close a directory */
Packit 16808d
  action_search  = 0x0003,  /**< search an open directory */
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
struct mwServiceDirectory {
Packit 16808d
  struct mwService service;
Packit 16808d
Packit 16808d
  struct mwDirectoryHandler *handler;
Packit 16808d
Packit 16808d
  struct mwChannel *channel;
Packit 16808d
 
Packit 16808d
  guint32 counter;       /**< counter of request IDs */
Packit 16808d
  GHashTable *requests;  /**< map of request ID:directory */
Packit 16808d
  GHashTable *books;     /**< book->name:mwAddressBook */
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
struct mwAddressBook {
Packit 16808d
  struct mwServiceDirectory *service;
Packit 16808d
Packit 16808d
  guint32 id;        /**< id or type or something */
Packit 16808d
  char *name;        /**< name of address book */
Packit 16808d
  GHashTable *dirs;  /**< dir->id:mwDirectory */
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
struct mwDirectory {
Packit 16808d
  struct mwServiceDirectory *service;
Packit 16808d
  struct mwAddressBook *book;
Packit 16808d
Packit 16808d
  enum mwDirectoryState state;
Packit 16808d
Packit 16808d
  guint32 id;         /**< id of directory, assigned by server */
Packit 16808d
  guint32 search_id;  /**< id of current search, from srvc->counter++ */
Packit 16808d
Packit 16808d
  mwSearchHandler handler;
Packit 16808d
  struct mw_datum client_data;
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
#define next_request_id(srvc) ( ++((srvc)->counter) )
Packit 16808d
Packit 16808d
Packit 16808d
static guint32 map_request(struct mwDirectory *dir) {
Packit 16808d
  struct mwServiceDirectory *srvc = dir->service;
Packit 16808d
  guint32 id = next_request_id(srvc);
Packit 16808d
Packit 16808d
  dir->search_id = id;
Packit 16808d
  map_guint_insert(srvc->requests, id, dir);
Packit 16808d
Packit 16808d
  return id;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/** called when directory is removed from the service directory map */
Packit 16808d
static void dir_free(struct mwDirectory *dir) {
Packit 16808d
  map_guint_remove(dir->service->requests, dir->search_id);
Packit 16808d
  g_free(dir);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/** remove the directory from the service list and its owning address
Packit 16808d
    book, then frees the directory */
Packit 16808d
static void dir_remove(struct mwDirectory *dir) {
Packit 16808d
  struct mwAddressBook *book = dir->book;
Packit 16808d
  map_guint_remove(book->dirs, dir->id);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
__attribute__((used))
Packit 16808d
static struct mwDirectory *dir_new(struct mwAddressBook *book, guint32 id) {
Packit 16808d
  struct mwDirectory *dir = g_new0(struct mwDirectory, 1);
Packit 16808d
  dir->service = book->service;
Packit 16808d
  dir->book = book;
Packit 16808d
  dir->id = id;
Packit 16808d
  map_guint_insert(book->dirs, id, dir);
Packit 16808d
  return dir;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/** called when book is removed from the service book map. Removed all
Packit 16808d
    directories as well */
Packit 16808d
static void book_free(struct mwAddressBook *book) {
Packit 16808d
  g_hash_table_destroy(book->dirs);
Packit 16808d
  g_free(book->name);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
__attribute__((used))
Packit 16808d
static void book_remove(struct mwAddressBook *book) {
Packit 16808d
  struct mwServiceDirectory *srvc = book->service;
Packit 16808d
  g_hash_table_remove(srvc->books, book->name);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwAddressBook *book_new(struct mwServiceDirectory *srvc,
Packit 16808d
				      const char *name, guint32 id) {
Packit 16808d
  struct mwAddressBook *book = g_new0(struct mwAddressBook, 1);
Packit 16808d
  book->service = srvc;
Packit 16808d
  book->id = id;
Packit 16808d
  book->name = g_strdup(name);
Packit 16808d
  book->dirs = map_guint_new_full((GDestroyNotify) dir_free);
Packit 16808d
  g_hash_table_insert(srvc->books, book->name, book);
Packit 16808d
  return book;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static const char *getName(struct mwService *srvc) {
Packit 16808d
  return "Address Book and Directory";
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static const char *getDesc(struct mwService *srvc) {
Packit 16808d
  return "Address book directory service for user and group lookups";
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwChannel *make_channel(struct mwServiceDirectory *srvc) {
Packit 16808d
  struct mwSession *session;
Packit 16808d
  struct mwChannelSet *cs;
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
Packit 16808d
  session = mwService_getSession(MW_SERVICE(srvc));
Packit 16808d
  cs = mwSession_getChannels(session);
Packit 16808d
  chan = mwChannel_newOutgoing(cs);
Packit 16808d
Packit 16808d
  mwChannel_setService(chan, MW_SERVICE(srvc));
Packit 16808d
  mwChannel_setProtoType(chan, PROTOCOL_TYPE);
Packit 16808d
  mwChannel_setProtoVer(chan, PROTOCOL_VER);
Packit 16808d
Packit 16808d
  return mwChannel_create(chan)? NULL: chan;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void start(struct mwServiceDirectory *srvc) {
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
Packit 16808d
  chan = make_channel(srvc);
Packit 16808d
  if(chan) {
Packit 16808d
    srvc->channel = chan;
Packit 16808d
  } else {
Packit 16808d
    mwService_stopped(MW_SERVICE(srvc));
Packit 16808d
    return;
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void stop(struct mwServiceDirectory *srvc) {
Packit 16808d
  /* XXX */
Packit 16808d
Packit 16808d
  if(srvc->channel) {
Packit 16808d
    mwChannel_destroy(srvc->channel, ERR_SUCCESS, NULL);
Packit 16808d
    srvc->channel = NULL;
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void clear(struct mwServiceDirectory *srvc) {
Packit 16808d
  struct mwDirectoryHandler *handler;
Packit 16808d
Packit 16808d
  if(srvc->books) {
Packit 16808d
    g_hash_table_destroy(srvc->books);
Packit 16808d
    srvc->books = NULL;
Packit 16808d
  }
Packit 16808d
  
Packit 16808d
  /* clear the handler */
Packit 16808d
  handler = srvc->handler;
Packit 16808d
  if(handler && handler->clear)
Packit 16808d
    handler->clear(srvc);
Packit 16808d
  srvc->handler = NULL;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv_create(struct mwServiceDirectory *srvc,
Packit 16808d
			struct mwChannel *chan,
Packit 16808d
			struct mwMsgChannelCreate *msg) {
Packit 16808d
Packit 16808d
  /* no way man, we call the shots around here */
Packit 16808d
  mwChannel_destroy(chan, ERR_FAILURE, NULL);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv_accept(struct mwServiceDirectory *srvc,
Packit 16808d
			struct mwChannel *chan,
Packit 16808d
			struct mwMsgChannelAccept *msg) {
Packit 16808d
Packit 16808d
  g_return_if_fail(srvc->channel != NULL);
Packit 16808d
  g_return_if_fail(srvc->channel == chan);
Packit 16808d
Packit 16808d
  if(MW_SERVICE_IS_STARTING(srvc)) {
Packit 16808d
    mwService_started(MW_SERVICE(srvc));
Packit 16808d
      
Packit 16808d
  } else {
Packit 16808d
    mwChannel_destroy(chan, ERR_FAILURE, NULL);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv_destroy(struct mwServiceDirectory *srvc,
Packit 16808d
			 struct mwChannel *chan,
Packit 16808d
			 struct mwMsgChannelDestroy *msg) {
Packit 16808d
Packit 16808d
  srvc->channel = NULL;
Packit 16808d
  mwService_stop(MW_SERVICE(srvc));
Packit 16808d
  /** @todo session sense service */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv_list(struct mwServiceDirectory *srvc,
Packit 16808d
		      struct mwOpaque *data) {
Packit 16808d
Packit 16808d
  struct mwGetBuffer *b;
Packit 16808d
  guint32 request, code, count;
Packit 16808d
  gboolean foo_1;
Packit 16808d
  guint16 foo_2;
Packit 16808d
  
Packit 16808d
  b = mwGetBuffer_wrap(data);
Packit 16808d
  
Packit 16808d
  guint32_get(b, &request);
Packit 16808d
  guint32_get(b, &code);
Packit 16808d
  guint32_get(b, &count);
Packit 16808d
Packit 16808d
  gboolean_get(b, &foo_1);
Packit 16808d
  guint16_get(b, &foo_2);
Packit 16808d
Packit 16808d
  if(foo_1 || foo_2) {
Packit 16808d
    mw_mailme_opaque(data, "received strange address book list");
Packit 16808d
    mwGetBuffer_free(b);
Packit 16808d
    return;
Packit 16808d
  }
Packit 16808d
Packit 16808d
  while(!mwGetBuffer_error(b) && count--) {
Packit 16808d
    guint32 id;
Packit 16808d
    char *name = NULL;
Packit 16808d
Packit 16808d
    guint32_get(b, &id;;
Packit 16808d
    mwString_get(b, &name);
Packit 16808d
Packit 16808d
    book_new(srvc, name, id);
Packit 16808d
    g_free(name);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv_open(struct mwServiceDirectory *srvc,
Packit 16808d
		      struct mwOpaque *data) {
Packit 16808d
Packit 16808d
  /* look up the directory associated with this request id, 
Packit 16808d
     mark it as open, and trigger the event */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv_search(struct mwServiceDirectory *srvc,
Packit 16808d
			struct mwOpaque *data) {
Packit 16808d
Packit 16808d
  /* look up the directory associated with this request id,
Packit 16808d
     trigger the event */
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void recv(struct mwServiceDirectory *srvc,
Packit 16808d
		 struct mwChannel *chan,
Packit 16808d
		 guint16 msg_type, struct mwOpaque *data) {
Packit 16808d
  
Packit 16808d
  g_return_if_fail(srvc != NULL);
Packit 16808d
  g_return_if_fail(chan != NULL);
Packit 16808d
  g_return_if_fail(chan == srvc->channel);
Packit 16808d
  g_return_if_fail(data != NULL);
Packit 16808d
Packit 16808d
  switch(msg_type) {
Packit 16808d
  case action_list:
Packit 16808d
    recv_list(srvc, data);
Packit 16808d
    break;
Packit 16808d
Packit 16808d
  case action_open:
Packit 16808d
    recv_open(srvc, data);
Packit 16808d
    break;
Packit 16808d
Packit 16808d
  case action_close:
Packit 16808d
    ; /* I don't think we should receive these */
Packit 16808d
    break;
Packit 16808d
Packit 16808d
  case action_search:
Packit 16808d
    recv_search(srvc, data);
Packit 16808d
    break;
Packit 16808d
Packit 16808d
  default:
Packit 16808d
    mw_mailme_opaque(data, "msg type 0x%04x in directory service", msg_type);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwServiceDirectory *
Packit 16808d
mwServiceDirectory_new(struct mwSession *session,
Packit 16808d
		       struct mwDirectoryHandler *handler) {
Packit 16808d
Packit 16808d
  struct mwServiceDirectory *srvc;
Packit 16808d
  struct mwService *service;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(session != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(handler != NULL, NULL);
Packit 16808d
Packit 16808d
  srvc = g_new0(struct mwServiceDirectory, 1);
Packit 16808d
  service = MW_SERVICE(srvc);
Packit 16808d
Packit 16808d
  mwService_init(service, session, SERVICE_DIRECTORY);
Packit 16808d
  service->get_name = getName;
Packit 16808d
  service->get_desc = getDesc;
Packit 16808d
  service->start = (mwService_funcStart) start;
Packit 16808d
  service->stop = (mwService_funcStop) stop;
Packit 16808d
  service->clear = (mwService_funcClear) clear;
Packit 16808d
  service->recv_create = (mwService_funcRecvCreate) recv_create;
Packit 16808d
  service->recv_accept = (mwService_funcRecvAccept) recv_accept;
Packit 16808d
  service->recv_destroy = (mwService_funcRecvDestroy) recv_destroy;
Packit 16808d
  service->recv = (mwService_funcRecv) recv;
Packit 16808d
Packit 16808d
  srvc->handler = handler;
Packit 16808d
  srvc->requests = map_guint_new();
Packit 16808d
  srvc->books = g_hash_table_new_full(g_str_hash, g_str_equal,
Packit 16808d
				      NULL, (GDestroyNotify) book_free);
Packit 16808d
  return srvc;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwDirectoryHandler *
Packit 16808d
mwServiceDirectory_getHandler(struct mwServiceDirectory *srvc) {
Packit 16808d
  g_return_val_if_fail(srvc != NULL, NULL);
Packit 16808d
  return srvc->handler;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwServiceDirectory_refreshAddressBooks(struct mwServiceDirectory *srvc) {
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
  struct mwPutBuffer *b;
Packit 16808d
  struct mwOpaque o;
Packit 16808d
  int ret;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(srvc != NULL, -1);
Packit 16808d
Packit 16808d
  chan = srvc->channel;
Packit 16808d
  g_return_val_if_fail(chan != NULL, -1);
Packit 16808d
Packit 16808d
  b = mwPutBuffer_new();
Packit 16808d
  guint32_put(b, next_request_id(srvc));
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, b);
Packit 16808d
  ret = mwChannel_send(chan, action_list, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
GList *mwServiceDirectory_getAddressBooks(struct mwServiceDirectory *srvc) {
Packit 16808d
  g_return_val_if_fail(srvc != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(srvc->books != NULL, NULL);
Packit 16808d
Packit 16808d
  return map_collect_values(srvc->books);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
GList *mwServiceDirectory_getDirectories(struct mwServiceDirectory *srvc) {
Packit 16808d
  GList *bl, *ret = NULL;
Packit 16808d
  
Packit 16808d
  g_return_val_if_fail(srvc != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(srvc->books != NULL, NULL);
Packit 16808d
Packit 16808d
  bl = map_collect_values(srvc->books);
Packit 16808d
  for( ; bl; bl = g_list_delete_link(bl, bl)) {
Packit 16808d
    struct mwAddressBook *book = bl->data;
Packit 16808d
    ret = g_list_concat(ret, map_collect_values(book->dirs));
Packit 16808d
  }
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
GList *mwAddressBook_getDirectories(struct mwAddressBook *book) {
Packit 16808d
  g_return_val_if_fail(book != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(book->dirs != NULL, NULL);
Packit 16808d
Packit 16808d
  return map_collect_values(book->dirs);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
const char *mwAddressBook_getName(struct mwAddressBook *book) {
Packit 16808d
  g_return_val_if_fail(book != NULL, NULL);
Packit 16808d
  return book->name;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwDirectory *mwDirectory_new(struct mwAddressBook *book) {
Packit 16808d
  struct mwDirectory *dir;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(book != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(book->service != NULL, NULL);
Packit 16808d
Packit 16808d
  dir = g_new0(struct mwDirectory, 1);
Packit 16808d
  dir->service = book->service;
Packit 16808d
  dir->book = book;
Packit 16808d
  dir->state = mwDirectory_NEW;
Packit 16808d
Packit 16808d
  return dir;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
enum mwDirectoryState mwDirectory_getState(struct mwDirectory *dir) {
Packit 16808d
  g_return_val_if_fail(dir != NULL, mwDirectory_UNKNOWN);
Packit 16808d
  return dir->state;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwDirectory_setClientData(struct mwDirectory *dir,
Packit 16808d
			       gpointer data, GDestroyNotify clear) {
Packit 16808d
Packit 16808d
  g_return_if_fail(dir != NULL);
Packit 16808d
  mw_datum_set(&dir->client_data, data, clear);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
gpointer mwDirectory_getClientData(struct mwDirectory *dir) {
Packit 16808d
  g_return_val_if_fail(dir != NULL, NULL);
Packit 16808d
  return mw_datum_get(&dir->client_data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwDirectory_removeClientData(struct mwDirectory *dir) {
Packit 16808d
  g_return_if_fail(dir != NULL);
Packit 16808d
  mw_datum_clear(&dir->client_data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwServiceDirectory *mwDirectory_getService(struct mwDirectory *dir) {
Packit 16808d
  g_return_val_if_fail(dir != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(dir->book != NULL, NULL);
Packit 16808d
  return dir->book->service;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwAddressBook *mwDirectory_getAddressBook(struct mwDirectory *dir) {
Packit 16808d
  g_return_val_if_fail(dir != NULL, NULL);
Packit 16808d
  return dir->book;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static int dir_open(struct mwDirectory *dir) {
Packit 16808d
  struct mwServiceDirectory *srvc;
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
  struct mwPutBuffer *b;
Packit 16808d
  struct mwOpaque o;
Packit 16808d
  int ret;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
Packit 16808d
  srvc = dir->service;
Packit 16808d
  g_return_val_if_fail(srvc != NULL, -1);
Packit 16808d
Packit 16808d
  chan = srvc->channel;
Packit 16808d
  g_return_val_if_fail(chan != NULL, -1);
Packit 16808d
Packit 16808d
  b = mwPutBuffer_new();
Packit 16808d
  guint32_put(b, map_request(dir));
Packit 16808d
Packit 16808d
  /* unsure about these three bytes */
Packit 16808d
  gboolean_put(b, FALSE);
Packit 16808d
  guint16_put(b, 0x0000);
Packit 16808d
Packit 16808d
  guint32_put(b, dir->book->id);
Packit 16808d
  mwString_put(b, dir->book->name);
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, b);
Packit 16808d
  ret = mwChannel_send(chan, action_open, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwDirectory_open(struct mwDirectory *dir, mwSearchHandler cb) {
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
  g_return_val_if_fail(cb != NULL, -1);
Packit 16808d
  g_return_val_if_fail(MW_DIRECTORY_IS_NEW(dir), -1);
Packit 16808d
Packit 16808d
  dir->state = mwDirectory_PENDING;
Packit 16808d
  dir->handler = cb;
Packit 16808d
Packit 16808d
  return dir_open(dir);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwDirectory_next(struct mwDirectory *dir) {  
Packit 16808d
  struct mwServiceDirectory *srvc;
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
  struct mwPutBuffer *b;
Packit 16808d
  struct mwOpaque o;
Packit 16808d
  int ret;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
  g_return_val_if_fail(MW_DIRECTORY_IS_OPEN(dir), -1);
Packit 16808d
Packit 16808d
  srvc = dir->service;
Packit 16808d
  g_return_val_if_fail(srvc != NULL, -1);
Packit 16808d
Packit 16808d
  chan = srvc->channel;
Packit 16808d
  g_return_val_if_fail(chan != NULL, -1);
Packit 16808d
Packit 16808d
  b = mwPutBuffer_new();
Packit 16808d
  guint32_put(b, map_request(dir));
Packit 16808d
  guint32_put(b, dir->id);
Packit 16808d
  guint16_put(b, 0xffff);      /* some magic? */
Packit 16808d
  guint32_put(b, 0x00000000);  /* next results */
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, b);
Packit 16808d
  ret = mwChannel_send(chan, action_search, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwDirectory_previous(struct mwDirectory *dir) {
Packit 16808d
  struct mwServiceDirectory *srvc;
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
  struct mwPutBuffer *b;
Packit 16808d
  struct mwOpaque o;
Packit 16808d
  int ret;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
  g_return_val_if_fail(MW_DIRECTORY_IS_OPEN(dir), -1);
Packit 16808d
Packit 16808d
  srvc = dir->service;
Packit 16808d
  g_return_val_if_fail(srvc != NULL, -1);
Packit 16808d
Packit 16808d
  chan = srvc->channel;
Packit 16808d
  g_return_val_if_fail(chan != NULL, -1);
Packit 16808d
Packit 16808d
  b = mwPutBuffer_new();
Packit 16808d
  guint32_put(b, map_request(dir));
Packit 16808d
  guint32_put(b, dir->id);
Packit 16808d
  guint16_put(b, 0x0061);      /* some magic? */
Packit 16808d
  guint32_put(b, 0x00000001);  /* prev results */
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, b);
Packit 16808d
  ret = mwChannel_send(chan, action_search, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwDirectory_search(struct mwDirectory *dir, const char *query) {
Packit 16808d
  struct mwServiceDirectory *srvc;
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
  struct mwPutBuffer *b;
Packit 16808d
  struct mwOpaque o;
Packit 16808d
  int ret;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
  g_return_val_if_fail(MW_DIRECTORY_IS_OPEN(dir), -1);
Packit 16808d
  g_return_val_if_fail(query != NULL, -1);
Packit 16808d
  g_return_val_if_fail(*query != '\0', -1);
Packit 16808d
Packit 16808d
  srvc = dir->service;
Packit 16808d
  g_return_val_if_fail(srvc != NULL, -1);
Packit 16808d
Packit 16808d
  chan = srvc->channel;
Packit 16808d
  g_return_val_if_fail(chan != NULL, -1);
Packit 16808d
Packit 16808d
  b = mwPutBuffer_new();
Packit 16808d
  guint32_put(b, map_request(dir));
Packit 16808d
  guint32_put(b, dir->id);
Packit 16808d
  guint16_put(b, 0x0061);      /* some magic? */
Packit 16808d
  guint32_put(b, 0x00000008);  /* seek results */
Packit 16808d
  mwString_put(b, query);
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, b);
Packit 16808d
  ret = mwChannel_send(chan, action_search, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static int dir_close(struct mwDirectory *dir) {
Packit 16808d
  struct mwServiceDirectory *srvc;
Packit 16808d
  struct mwChannel *chan;
Packit 16808d
  struct mwPutBuffer *b;
Packit 16808d
  struct mwOpaque o;
Packit 16808d
  int ret;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
Packit 16808d
  srvc = dir->service;
Packit 16808d
  g_return_val_if_fail(srvc != NULL, -1);
Packit 16808d
Packit 16808d
  chan = srvc->channel;
Packit 16808d
  g_return_val_if_fail(chan != NULL, -1);
Packit 16808d
Packit 16808d
  b = mwPutBuffer_new();
Packit 16808d
  guint32_put(b, next_request_id(dir->service));
Packit 16808d
  guint32_put(b, dir->id);
Packit 16808d
Packit 16808d
  mwPutBuffer_finalize(&o, b);
Packit 16808d
  ret = mwChannel_send(chan, action_close, &o);
Packit 16808d
  mwOpaque_clear(&o);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwDirectory_destroy(struct mwDirectory *dir) {
Packit 16808d
  int ret = 0;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(dir != NULL, -1);
Packit 16808d
Packit 16808d
  if(MW_DIRECTORY_IS_OPEN(dir) || MW_DIRECTORY_IS_PENDING(dir)) {
Packit 16808d
    ret = dir_close(dir);
Packit 16808d
  }
Packit 16808d
  dir_remove(dir);
Packit 16808d
Packit 16808d
  return ret;
Packit 16808d
}
Packit 16808d