Blame src/srvc_dir.c

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