/* Josh Pieper, (c) 2000 */

/* This file is distruted under the GPL, see file COPYING for details */

#ifndef GNUT_THREADS_H
#define GNUT_THREADS_H

#include <sys/types.h>
#ifndef WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include "share.h"
#include "gnut_lib.h"
#include "protocol.h"
#include "gnut_transfer.h"
#include "query.h"


typedef struct _incoming_arg incoming_arg;
typedef struct _push_arg push_arg;
typedef struct _GnutSearch GnutSearch;

struct _incoming_arg {
  int s;
  struct sockaddr_in sin;
};

struct _push_arg {
  share_item *si;
  uchar ip[4];
  uchar port[2];
};

typedef struct bad_ip {
  uint32 ip;
  time_t when;
} bad_ip;

struct _GnutSearch {
  char       *guid;
  char       *query;
  int         responses;
  GnutSearch *next;
};

#ifdef __cplusplus
extern "C" {
#endif

  void free_bip(bad_ip **x, int bugnum);
  void free_gs(GnutSearch **x, int bugnum);
  void free_ia(incoming_arg **x, int bugnum);
  void free_pa(push_arg **x, int bugnum);

  GnutSearch *gnut_search_add(char *guid, char *query);
  void        gnut_search_remove(GnutSearch *s);
  void        gnut_search_foreach(void (*cb)(GnutSearch *search,
					     void       *data),
				  void  *data);
  GnutSearch *gnut_search_find(char (*cb)(GnutSearch *search,
					  void       *data),
			       void  *data);
  GnutSearch *gnut_search_find_by_guid(char *guid);
  GnutSearch *gnut_search_find_by_query(char *query);
  int         gnut_search_count();

  int gnut_threads_num_incoming();
  int gnut_threads_num_outgoing();
  int gnut_threads_num_uploads();
  int gnut_threads_count_downloads();
  int gnut_threads_count_uploads();
  int gnut_threads_num_downloads();

  void * gnut_threads_outgoing(void *arg);
  void * gnut_threads_incoming(void *arg);

  int gnut_threads_dl_handle(query_response *qr, gnut_transfer *gt,
			     int *retry_enable, int *tried_push);
  void * gnut_th_dl(void *arg, int *retry_enable, int *tried_push, int sl);
  void * gnut_threads_dl(void *arg);

  void * gnut_threads_push(void *arg);

  extern gnutella_packet * current_query_packet;
  extern GnutSearch *current_searches;

#ifdef PTHREADS_DRAFT4
  extern pthread_mutex_t gc_list_mutex, send_mutex, _g_debug_mutex,
    make_connection_mutex, transfer_mutex, host_mutex,
    monitor_mutex, push_mutex, query_mutex, route_mutex, 
    share_mutex, cache_mutex;
  void gnut_mutexes_init();

#ifdef hpux
  /*
   * HP-UX does some icky things at 10.20
   */
 
#ifdef sigaction
#undef sigaction
#define sigaction(a,b,c) cma_sigaction(a,b,c)
#endif

#ifdef select
#undef select
#define select(a,b,c,d,e) cma_select(a,(int *)b,(int *)c,(int *)d,e)
#endif

  typedef union {
    pthread_t pthreadpart;
    long  longpart;
  } HPUX_hack;

#endif hpux
#endif /* PTHREADS_DRAFT4 */

  time_t check_push_ip(uint32 tip);
  void remove_push_ip(uint32 tip);
  void add_push_ip(uint32 tip, uint32 wait);

  int incoming_transfer_error(int sock, int err, char *message);
  int incoming_transfer(int sock, struct sockaddr_in *sin, char *request_line);
  int incoming_transfer_handle(gnut_transfer *gt, struct sockaddr_in *sin,
			       char *request_line);

#ifdef __cplusplus
}
#endif

#endif /* GNUT_THREADS_H */
