/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Lac - Library for asynchronous communication * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 * Søren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef LAC_H #define LAC_H #include #include #include G_BEGIN_DECLS /* * Addresses */ #define LAC_DNS_ERROR lac_dns_error_quark () GQuark lac_dns_error_quark (void); typedef enum { LAC_DNS_ERROR_NO_SUCH_NAME, LAC_DNS_ERROR_NO_DATA, LAC_DNS_ERROR_CNAME_CYCLE, LAC_DNS_ERROR_TIMEOUT, LAC_DNS_ERROR_SERVER_FAILED, LAC_DNS_ERROR_NO_SERVERS_CONFIGURED, LAC_DNS_ERROR_MALFORMED_NAME, LAC_DNS_ERROR_FAILED } LacDnsError; typedef struct LacAddress LacAddress; typedef void (* LacAddressFunc) (const LacAddress *address, gpointer data, const GError *err); typedef void (* LacAddressesFunc) (const GPtrArray *addresses, gpointer data, const GError *err); typedef void (* LacNameFunc) (const char *name, gpointer data, const GError *err); LacAddress *lac_address_new_from_a_b_c_d (char a, char b, char c, char d); LacAddress *lac_address_new_from_string (const char *str); void lac_address_new_lookup_from_name (const char *name, LacAddressFunc f, gpointer data); void lac_address_new_lookup_all_from_name (const char *name, LacAddressesFunc f, gpointer data); LacAddress *lac_address_new_from_name_wait (const char *name, GError **err); void lac_address_new_lookup_from_localhost (LacAddressFunc f, gpointer data); LacAddress *lac_address_new_from_localhost_wait (GError **err); void lac_address_lookup_name (const LacAddress *addr, LacNameFunc f, gpointer data); char * lac_address_lookup_name_wait (const LacAddress *addr, GError **err); char * lac_address_to_string (const LacAddress *addr); guint lac_address_hash (gconstpointer addr); int lac_address_compare (gconstpointer addr1, gconstpointer addr2); gboolean lac_address_equal (gconstpointer addr1, gconstpointer addr2); LacAddress *lac_address_copy (const LacAddress *addr); void lac_address_free (LacAddress *addr); #ifdef LAC_IPV6_UNSAFE void lac_address_get_a_b_c_d (const LacAddress *addr, int *a, int *b, int *c, int *d); #endif /* * Primitives */ #define LAC_SOCKET_ERROR lac_socket_error_quark () typedef enum { LAC_SOCKET_ERROR_IN_PROGRESS, LAC_SOCKET_ERROR_CONNECTION_REFUSED, LAC_SOCKET_ERROR_NET_UNREACHABLE, LAC_SOCKET_ERROR_TIMEOUT, LAC_SOCKET_ERROR_CONNECTION_RESET, LAC_SOCKET_ERROR_NO_RESOURCES, LAC_SOCKET_ERROR_AGAIN, /* also known as WOULDBLOCK */ LAC_SOCKET_ERROR_FAILED } LacError; GQuark lac_socket_error_quark (void); /* General primitives */ typedef enum { LAC_SHUTDOWN_READ = 0, LAC_SHUTDOWN_WRITE = 1, LAC_SHUTDOWN_NEITHER = 2 } LacShutdownMethod; void lac_sigpipe_ignore (void); void lac_sigpipe_default (void); gboolean lac_close (int fd, GError **err); gboolean lac_shutdown (int fd, LacShutdownMethod how, GError **err); gboolean lac_set_blocking (int fd, gboolean blocking, GError **err); gboolean lac_listen (int fd, guint backlog, GError **err); int lac_send (int fd, const char *msg, guint len, GError **err); int lac_recv (int fd, char *buf, guint len, GError **err); int lac_sendto (int fd, char *buf, guint len, const LacAddress *address, int port, GError **err); int lac_recvfrom (int fd, char *buf, guint len, LacAddress **address, int *port, GError **err); int lac_socket_tcp (GError **err); int lac_socket_udp (GError **err); gboolean lac_set_nagle (int fd, gboolean use_nagle, GError **err); gboolean lac_bind (int fd, const LacAddress *address, int port, GError **err); int lac_accept (int fd, LacAddress **addr, int *port, GError **err); gboolean lac_connect (int fd, const LacAddress *address, int port, GError **err); gboolean lac_getpeername (int fd, LacAddress **addr, int *port, GError **err); char * lac_gethostname (void); /* * Watching file descriptors */ typedef void (* LacWatchCallback) (gpointer data); void lac_fd_add_watch (int fd, gpointer data); void lac_fd_set_read_callback (int fd, LacWatchCallback read_cb); void lac_fd_set_write_callback (int fd, LacWatchCallback write_cb); void lac_fd_set_hangup_callback (int fd, LacWatchCallback hangup_cb); void lac_fd_set_error_callback (int fd, LacWatchCallback error_cb); void lac_fd_set_priority_callback (int fd, LacWatchCallback priority_cb); void lac_fd_remove_watch (int fd); gboolean lac_fd_is_watched (int fd); /* * Connection */ typedef union _LacConnectionEvent LacConnectionEvent; typedef enum { LAC_CONNECTION_EVENT_CONNECT, /* connect successful */ LAC_CONNECTION_EVENT_READ, /* data to read */ LAC_CONNECTION_EVENT_CLOSE, /* Connection closed */ LAC_CONNECTION_EVENT_ERROR, /* error */ } LacConnectionEventType; typedef struct { LacConnectionEventType type; } LacConnectionConnectEvent; typedef struct { LacConnectionEventType type; gpointer _lac_reserved0; gpointer _lac_reserved1; nul_buffer_t *buffer; const char *data; guint len; } LacConnectionReadEvent; typedef struct { LacConnectionEventType type; gboolean remote_closed; /* true: remote closed. false: local closed */ } LacConnectionCloseEvent; typedef struct { LacConnectionEventType type; const GError *err; } LacConnectionErrorEvent; union _LacConnectionEvent { LacConnectionEventType type; LacConnectionConnectEvent connect; LacConnectionReadEvent read; LacConnectionCloseEvent close; LacConnectionErrorEvent error; }; typedef struct _LacConnection LacConnection; typedef void (* LacConnectionFunc) (LacConnection *connection, const LacConnectionEvent *event); LacConnection * lac_connection_new_tcp (const LacAddress *address, int port, LacConnectionFunc callback, gpointer data); LacConnection * lac_connection_new_tls (const LacAddress *address, int port, LacConnectionFunc callback, gpointer data); gpointer lac_connection_get_data (LacConnection *connection); void lac_connection_write (LacConnection *connection, const char *data, guint len); void lac_connection_write_printf (LacConnection *connection, const char *format, ...); void lac_connection_shutdown_write (LacConnection *connection); LacConnection * lac_connection_ref (LacConnection *connection); void lac_connection_unref (LacConnection *connection); const LacAddress *lac_connection_get_address (LacConnection *connection); int lac_connection_get_port (LacConnection *connection); void lac_connection_close (LacConnection *connection); gboolean lac_connection_is_connected (LacConnection *connection); void lac_connection_flush (LacConnection *connection); /* * URI */ typedef enum { LAC_SCHEME_UNKNOWN, LAC_SCHEME_HTTP, LAC_SCHEME_FTP } LacScheme; typedef enum { LAC_FTP_TYPE_A, LAC_FTP_TYPE_I, LAC_FTP_TYPE_D, LAC_FTP_TYPE_NONE, } LacFtpType; typedef struct _LacUri LacUri; struct _LacUri { /* all fields are *read-only* */ LacScheme scheme; union { struct { char *scheme; char *authority; char *path; char *query; } unknown; struct { char *host; guint port; char *path; char *query; gboolean is_https; } http; struct { char *host; char *username; char *password; guint port; char *path; LacFtpType type; } ftp; } u; char *fragment; guint checksum; /* used internally */ }; LacUri * lac_uri_new_from_string (const LacUri *base, const char *str); LacUri * lac_uri_copy (const LacUri *uri); char * lac_uri_string (const LacUri *uri); gboolean lac_uri_equal (const LacUri *uri1, const LacUri *uri2); void lac_uri_free (LacUri *uri); /* * HTTP */ GQuark lac_http_error_quark (void); #define LAC_HTTP_ERROR lac_http_error_quark() typedef enum { LAC_HTTP_ERROR_MALFORMED_RESPONSE, /* server sent an unparsable message */ LAC_HTTP_ERROR_PREMATURE_CLOSE, /* server closed connection before * sending a complete response */ LAC_HTTP_ERROR_PIPELINE_TIMEOUT /* Some servers have a bug that * make them stall in the middle of * a pipelined response. */ } LacHttpError; typedef struct _LacHttpRequest LacHttpRequest; typedef union _LacHttpEvent LacHttpEvent; typedef void (* LacHttpFunc) (LacHttpRequest *request, const LacHttpEvent *event); LacHttpRequest *lac_http_request_new_get (const LacUri *uri, LacHttpFunc func, gpointer data); LacHttpRequest *lac_http_request_new_head (const LacUri *uri, LacHttpFunc func, gpointer data); LacHttpRequest *lac_http_request_new_post (const LacUri *uri, LacHttpFunc func, gpointer data); LacHttpRequest *lac_http_request_new_put (const LacUri *uri, LacHttpFunc func, gpointer data); LacHttpRequest *lac_http_request_new_delete (const LacUri *uri, LacHttpFunc func, gpointer data); void lac_http_request_add_content (LacHttpRequest *request, const char *content, gsize length); void lac_http_request_add_header (LacHttpRequest *request, const char *header, const char *value); gpointer lac_http_request_get_data (LacHttpRequest *request); void lac_http_request_dispatch (LacHttpRequest *request); void lac_http_request_cancel (LacHttpRequest *request); LacHttpRequest *lac_http_request_ref (LacHttpRequest *request); void lac_http_request_unref (LacHttpRequest *request); typedef enum { LAC_HTTP_EVENT_HOST_FOUND, /* dns lookup done */ LAC_HTTP_EVENT_CONNECTING, /* waiting for connect() */ LAC_HTTP_EVENT_SENT, /* request was sent (not pipelined) */ LAC_HTTP_EVENT_STATUS_LINE, /* received status line */ LAC_HTTP_EVENT_NO_STATUS_LINE, /* received HTTP/0.9 response */ LAC_HTTP_EVENT_HEADER, /* received header */ LAC_HTTP_EVENT_BEGIN_CONTENT, /* contents starts now */ LAC_HTTP_EVENT_CONTENT, /* a chunk of content */ LAC_HTTP_EVENT_END_CONTENT, /* end of response */ LAC_HTTP_EVENT_NO_CONTENT, /* response does not contain a body */ LAC_HTTP_EVENT_ERROR /* error */ } LacHttpEventType; typedef struct { LacHttpEventType type; const char * hostname; const LacAddress * address; } LacHttpHostFoundEvent; typedef struct { LacHttpEventType type; int status_code; int major; /* major version number */ int minor; /* minor version number */ const char * reason_phrase; } LacHttpStatusLineEvent; typedef struct { LacHttpEventType type; } LacHttpNoStatusLineEvent; typedef struct { LacHttpEventType type; const char * header; const char * value; } LacHttpHeaderEvent; typedef struct { LacHttpEventType type; gssize total; /* total length of content in bytes, * -1 if unknown */ } LacHttpBeginContentEvent; typedef struct { LacHttpEventType type; nul_buffer_t * buffer; const guint8 * data; gsize length; gssize so_far; /* bytes so far, including this event */ gssize total; /* how much is expected in total, * -1 if unknown */ } LacHttpContentEvent; typedef struct { LacHttpEventType type; gssize total; } LacHttpEndContentEvent; typedef struct { LacHttpEventType type; const GError * err; } LacHttpErrorEvent; union _LacHttpEvent { LacHttpEventType type; LacHttpHostFoundEvent host_found; LacHttpStatusLineEvent status_line; LacHttpNoStatusLineEvent no_status_line; LacHttpHeaderEvent header; LacHttpBeginContentEvent begin_content; LacHttpContentEvent content; LacHttpEndContentEvent end_content; LacHttpErrorEvent error; }; /* make LAC write lots of spam to stdout */ void lac_set_verbose (gboolean verbose); #define lac_debug_checkpoint() lac_debug_out ("reached%s", "") G_END_DECLS #endif