$OpenBSD: patch-src_pysilc_callbacks_c,v 1.4 2008/03/23 05:46:29 fgsch Exp $ --- src/pysilc_callbacks.c.orig Sun Jul 9 18:18:27 2006 +++ src/pysilc_callbacks.c Sun Mar 23 05:38:15 2008 @@ -46,6 +46,81 @@ #define PYSILC_SILCBUFFER_TO_PYLIST(source, destination, Type) \ do { } while (0); +static void _pysilc_client_running(SilcClient client, + void *context) +{ + PYSILC_GET_CLIENT_OR_DIE(client, pyclient); + PyObject *callback = NULL, *result = NULL; + + callback = PyObject_GetAttrString((PyObject *)pyclient, "running"); + if (!PyCallable_Check(callback)) + goto cleanup; + if ((result = PyObject_CallObject(callback, NULL)) == 0) + PyErr_Print(); + +cleanup: + Py_XDECREF(callback); + Py_XDECREF(result); +} + +static void _pysilc_client_connect_callback(SilcClient client, + SilcClientConnection conn, + SilcClientConnectionStatus status, + SilcStatus error, + const char *message, + void *context) +{ + PYSILC_GET_CLIENT_OR_DIE(client, pyclient); + PyObject *args = NULL, *callback = NULL, *result = NULL; + + if ((status == SILC_CLIENT_CONN_SUCCESS) || (status == SILC_CLIENT_CONN_SUCCESS_RESUME)) { + if (error != SILC_STATUS_OK) { + // TODO: raise an exception and abort + // call silc_client_close_connection(client, conn); + pyclient->silcconn = NULL; + goto cleanup; + } + + pyclient->silcconn = conn; + + callback = PyObject_GetAttrString((PyObject *)pyclient, "connected"); + if (!PyCallable_Check(callback)) + goto cleanup; + if ((result = PyObject_CallObject(callback, NULL)) == 0) + PyErr_Print(); + } + else if (status == SILC_CLIENT_CONN_DISCONNECTED) { + if (status != SILC_STATUS_OK) { + // TODO: raise an exception and abort + // call silc_client_close_connection(client, conn); + } + + // TODO: we're not letting the user know about ClientConnection atm. + pyclient->silcconn = NULL; + callback = PyObject_GetAttrString((PyObject *)pyclient, "disconnected"); + if (!PyCallable_Check(callback)) + goto cleanup; + + if (!(args = Py_BuildValue("(s)", message))) + goto cleanup; + if ((result = PyObject_CallObject(callback, args)) == 0) + PyErr_Print(); + } + else { + callback = PyObject_GetAttrString((PyObject *)pyclient, "failure"); + if (!PyCallable_Check(callback)) + goto cleanup; + // TODO: pass on protocol, failure parameters + if ((result = PyObject_CallObject(callback, NULL)) == 0) + PyErr_Print(); + } + +cleanup: + Py_XDECREF(args); + Py_XDECREF(callback); + Py_XDECREF(result); +} + static void _pysilc_client_callback_say(SilcClient client, SilcClientConnection conn, SilcClientMessageType type, @@ -72,10 +147,11 @@ cleanup: static void _pysilc_client_callback_command(SilcClient client, SilcClientConnection conn, - SilcClientCommandContext cmd_context, - bool success, + SilcBool success, SilcCommand command, - SilcStatus status) + SilcStatus status, + SilcUInt32 argc, + unsigned char **argv) { PyObject *callback = NULL, *args = NULL, *result = NULL; @@ -155,78 +231,26 @@ cleanup: Py_XDECREF(result); } -static void _pysilc_client_callback_connected(SilcClient client, - SilcClientConnection conn, - SilcClientConnectionStatus status) -{ - PyObject *result = NULL, *callback = NULL; - PYSILC_GET_CLIENT_OR_DIE(client, pyclient); - - if (status != SILC_STATUS_OK) { - // TODO: raise an exception and abort - // call silc_client_close_connection(client, conn); - pyclient->silcconn = NULL; - goto cleanup; - } - - - pyclient->silcconn = conn; - - callback = PyObject_GetAttrString((PyObject *)pyclient, "connected"); - if (!PyCallable_Check(callback)) - goto cleanup; - if ((result = PyObject_CallObject(callback, NULL)) == 0) - PyErr_Print(); -cleanup: - Py_XDECREF(callback); - Py_XDECREF(result); -} - -static void _pysilc_client_callback_disconnected(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - const char *message) -{ - PyObject *result = NULL, *callback = NULL, *args = NULL; - PYSILC_GET_CLIENT_OR_DIE(client, pyclient); - - if (status != SILC_STATUS_OK) { - // TODO: raise an exception and abort - // call silc_client_close_connection(client, conn); - } - - // TODO: we're not letting the user know about ClientConnection atm. - pyclient->silcconn = NULL; - callback = PyObject_GetAttrString((PyObject *)pyclient, "disconnected"); - if (!PyCallable_Check(callback)) - goto cleanup; - - if (!(args = Py_BuildValue("(s)", message))) - goto cleanup; - if ((result = PyObject_CallObject(callback, args)) == 0) - PyErr_Print(); -cleanup: - Py_XDECREF(callback); - Py_XDECREF(args); - Py_XDECREF(result); -} - typedef struct _PySilcClient_Callback_Join_Context { char *channel_name; char *topic; char *hmac_name; + char *cipher; PyObject *pychannel; SilcUInt32 channel_mode; - SilcUInt32 user_limit; + SilcUInt32 user_limit; + SilcHashTableList *user_list; } PySilcClient_Callback_Join_Context; static void _pysilc_client_callback_command_reply_join_finished(SilcClient client, SilcClientConnection conn, - SilcClientEntry *user_list, - SilcUInt32 user_count, - void * context) + void *context) { + SilcUInt32 user_count; + SilcClientEntry user; + SilcChannelUser user_channel; + PyObject *result = NULL, *callback = NULL, *args = NULL; PyObject *pytopic = NULL, *pyhmac_name = NULL, *users = NULL; PySilcClient_Callback_Join_Context *join_context = NULL; @@ -243,13 +267,16 @@ static void _pysilc_client_callback_command_reply_join // extract all the users SilcUInt32 i = 0; - users = PyTuple_New(user_count); - for (i = 0; i < user_count; i++) { - PyObject *u = PySilcUser_New(user_list[i]); + user_count = silc_hash_table_count(join_context->user_list->ht); + users = PyTuple_New(user_count); + i = 0; + while (silc_hash_table_get(join_context->user_list, (void *)&user, (void *)&user_channel)) { + PyObject *u = PySilcUser_New(user); PyTuple_SetItem(users, i, u); + i++; // TODO: we don't DECREF because PyTuple doesn't incr ref count. } - + // prepare some possibly NULL values if (join_context->topic == NULL) { pytopic = Py_None; @@ -292,14 +319,18 @@ static void _pysilc_client_callback_command_reply_join Py_XDECREF(args); Py_XDECREF(result); } - - + + static void _pysilc_client_callback_notify(SilcClient client, SilcClientConnection conn, SilcNotifyType type, ...) { PyObject *args = NULL, *result = NULL, *pyuser = NULL, *pychannel = NULL; PyObject *callback = NULL, *pyarg = NULL; + SilcIdType idtype; + SilcUInt32 mode; + void *entry = NULL; + char *topic = NULL; PYSILC_GET_CLIENT_OR_DIE(client, pyclient); va_list va; @@ -357,30 +388,34 @@ static void _pysilc_client_callback_notify(SilcClient break; case SILC_NOTIFY_TYPE_TOPIC_SET: PYSILC_GET_CALLBACK_OR_BREAK("notify_topic_set"); - int idtype = va_arg(va, int); - void *entry = va_arg(va, void *); - char *topic = va_arg(va, char *); + idtype = va_arg(va, int); + entry = va_arg(va, void *); + topic = va_arg(va, char *); PYSILC_NEW_CHANNEL_OR_BREAK(va_arg(va, SilcChannelEntry), pychannel); switch (idtype) { - case SILC_ID_CLIENT: - PYSILC_NEW_USER_OR_BREAK(entry, pyuser); - if ((args = Py_BuildValue("(iOOs)", idtype, pyuser, pychannel, topic)) == NULL) + case SILC_ID_CLIENT: + PYSILC_NEW_USER_OR_BREAK(entry, pyarg); break; - if ((result = PyObject_CallObject(callback, args)) == 0) - PyErr_Print(); - break; - case SILC_ID_CHANNEL: - PYSILC_NEW_CHANNEL_OR_BREAK(entry, pyarg); - if ((args = Py_BuildValue("(iOOs)", idtype, pyarg, pychannel, topic)) == NULL) + case SILC_ID_CHANNEL: + PYSILC_NEW_CHANNEL_OR_BREAK(entry, pyarg); break; - if ((result = PyObject_CallObject(callback, args)) == 0) - PyErr_Print(); - break; - case SILC_ID_SERVER: - // TODO: Unimplemented - break; + case SILC_ID_SERVER: + pyarg = Py_None; + Py_INCREF(pyarg); // TODO: no server type + break; } + + args = Py_BuildValue("(iOOs)", + idtype, + pyarg, + pychannel, + topic); + + if (args == NULL) + break; + if ((result = PyObject_CallObject(callback, args)) == 0) + PyErr_Print(); break; case SILC_NOTIFY_TYPE_NICK_CHANGE: @@ -394,30 +429,80 @@ static void _pysilc_client_callback_notify(SilcClient break; case SILC_NOTIFY_TYPE_CMODE_CHANGE: - /* - if (!PyCallable_Check(pyclient->notify_cmode_change)) - break; + PYSILC_GET_CALLBACK_OR_BREAK("notify_cmode_change"); + idtype = va_arg(va, int); + entry = va_arg(va, void *); + mode = va_arg(va, SilcUInt32); + char *cipher_name = va_arg(va, char *); + char *hmac_name = va_arg(va, char *); + char *passphrase = va_arg(va, char *); + SilcPublicKey founder_key = va_arg(va, SilcPublicKey); + SilcBuffer channel_pubkeys = va_arg(va, SilcBuffer); PYSILC_NEW_CHANNEL_OR_BREAK(va_arg(va, SilcChannelEntry), pychannel); - PYSILC_NEW_USER_OR_BREAK(va_arg(va, SilcClientEntry), pyuser); - if ((args = Py_BuildValue("(IOO)", status, pychannel, pyuser)) == NULL) + + switch (idtype) { + case SILC_ID_CLIENT: + PYSILC_NEW_USER_OR_BREAK(entry, pyarg); + break; + case SILC_ID_CHANNEL: + PYSILC_NEW_CHANNEL_OR_BREAK(entry, pyarg); + break; + case SILC_ID_SERVER: + pyarg = Py_None; // TODO: no server objects + Py_INCREF(Py_None); + break; + } + + args = Py_BuildValue("(iOOissss)", + idtype, + pyarg, + mode, + cipher_name, + hmac_name, + passphrase, + Py_None, + Py_None, + pychannel); + + if (args == NULL) break; - result = PyObject_CallObject(pyclient->notify_cmode_change, args); - */ - // TODO: wrong implementation + if ((result = PyObject_CallObject(callback, args)) == 0) + PyErr_Print(); break; case SILC_NOTIFY_TYPE_CUMODE_CHANGE: - /* - if (!PyCallable_Check(pyclient->notify_cumode_change)) - break; + PYSILC_GET_CALLBACK_OR_BREAK("notify_cumode_change"); + idtype = va_arg(va, int); + entry = va_arg(va, void *); + mode = va_arg(va, SilcUInt32); PYSILC_NEW_CHANNEL_OR_BREAK(va_arg(va, SilcChannelEntry), pychannel); PYSILC_NEW_USER_OR_BREAK(va_arg(va, SilcClientEntry), pyuser); - if ((args = Py_BuildValue("(IOO)", status, pychannel, pyuser)) == NULL) + switch (idtype) { + case SILC_ID_CLIENT: + PYSILC_NEW_USER_OR_BREAK(entry, pyarg); break; - result = PyObject_CallObject(pyclient->notify_cumode_change, args); - */ - // TODO: wrong implementation + case SILC_ID_CHANNEL: + PYSILC_NEW_CHANNEL_OR_BREAK(entry, pyarg); + break; + case SILC_ID_SERVER: + pyarg = Py_None; // TODO: no server objects + Py_INCREF(Py_None); + break; + } + + args = Py_BuildValue("(iOiOO)", + idtype, + pyarg, + mode, + pychannel, + pyuser); + + if (args == NULL) + break; + + if ((result = PyObject_CallObject(callback, args)) == 0) + PyErr_Print(); break; case SILC_NOTIFY_TYPE_MOTD: @@ -444,9 +529,8 @@ static void _pysilc_client_callback_notify(SilcClient case SILC_NOTIFY_TYPE_KICKED: PYSILC_GET_CALLBACK_OR_BREAK("notify_kicked"); - char *message; - PYSILC_NEW_USER_OR_BREAK(va_arg(va, SilcClientEntry), pyarg); - message = va_arg(va, char *); + PYSILC_NEW_USER_OR_BREAK(va_arg(va, SilcClientEntry), pyarg); + char *message = va_arg(va, char *); PYSILC_NEW_USER_OR_BREAK(va_arg(va, SilcClientEntry), pyuser); PYSILC_NEW_CHANNEL_OR_BREAK(va_arg(va, SilcChannelEntry), pychannel); @@ -457,7 +541,37 @@ static void _pysilc_client_callback_notify(SilcClient break; case SILC_NOTIFY_TYPE_KILLED: - break; // TODO: Unimplemented + PYSILC_GET_CALLBACK_OR_BREAK("notify_killed"); + PYSILC_NEW_USER_OR_BREAK(va_arg(va, SilcClientEntry), pyuser); + char *kill_message = va_arg(va, char *); + idtype = va_arg(va, int); + entry = va_arg(va, void *); + PYSILC_NEW_CHANNEL_OR_BREAK(va_arg(va, SilcChannelEntry), pychannel); + switch (idtype) { + case SILC_ID_CLIENT: + PYSILC_NEW_USER_OR_BREAK(entry, pyarg); + break; + case SILC_ID_CHANNEL: + PYSILC_NEW_CHANNEL_OR_BREAK(entry, pyarg); + break; + case SILC_ID_SERVER: + pyarg = Py_None; // TODO: no server objects + Py_INCREF(Py_None); + break; + } + + args = Py_BuildValue("(OsOO)", + pyuser, // client that was killed + kill_message, + pyarg, // the killer, either a SilcClient or SilcChannel or None + pychannel); + + if (args == NULL) + break; + + if ((result = PyObject_CallObject(callback, args)) == 0) + PyErr_Print(); + break; case SILC_NOTIFY_TYPE_ERROR: PYSILC_GET_CALLBACK_OR_BREAK("notify_error"); @@ -494,30 +608,27 @@ static void _pysilc_client_callback_notify(SilcClient -static void _pysilc_client_callback_command_reply(SilcClient client, +static void _pysilc_client_callback_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommandPayload cmd_payload, - bool success, - SilcCommand command, - SilcStatus status, ...) + SilcCommand command, + SilcStatus status, + SilcStatus error, va_list va) { PyObject *args = NULL, *result = NULL, *pyuser = NULL, *pychannel = NULL; PyObject *callback = NULL, *pyarg = NULL; PYSILC_GET_CLIENT_OR_DIE(client, pyclient); - va_list va; - va_start(va, status); - if (!success) { - // we encounter an error, return the command and status + if (status != SILC_STATUS_OK) { + // we encounter an error, return the command and error callback = PyObject_GetAttrString((PyObject *)pyclient, "command_reply_failed"); if (!PyCallable_Check(callback)) return; if (!(args = Py_BuildValue("(isis)", command, silc_get_command_name(command), - status, - silc_get_status_message(status)))) { + error, + silc_get_status_message(error)))) { Py_DECREF(callback); return; } @@ -677,7 +788,6 @@ static void _pysilc_client_callback_command_reply(Silc case SILC_COMMAND_PING: { PYSILC_GET_CALLBACK_OR_BREAK("command_reply_ping"); - printf("command ping callback found\n") ; if ((result = PyObject_CallObject(callback, args)) == 0) PyErr_Print(); break; @@ -696,14 +806,11 @@ static void _pysilc_client_callback_command_reply(Silc memset(context, 0, sizeof(PySilcClient_Callback_Join_Context)); if (!context) break; - + char *tmpstr = NULL; - int ignored; - void *dummy; SilcUInt32 client_count; SilcBuffer client_list; - - + tmpstr = va_arg(va, char *); if (tmpstr) context->channel_name = strdup(tmpstr); @@ -711,27 +818,19 @@ static void _pysilc_client_callback_command_reply(Silc context->pychannel = pychannel; Py_INCREF(pychannel); context->channel_mode = va_arg(va, SilcUInt32); - ignored = va_arg(va, int); // ignored: ignore - dummy = va_arg(va, void *); // ignored: key_payload - dummy = va_arg(va, void *); // NULL - dummy = va_arg(va, void *); // NULL + context->user_list = va_arg(va, SilcHashTableList *); tmpstr = va_arg(va, char *); if (tmpstr) context->topic = strdup(tmpstr); tmpstr = va_arg(va, char *); + context->cipher = strdup(tmpstr); + tmpstr = va_arg(va, char *); if (tmpstr) context->hmac_name = strdup(tmpstr); - client_count = va_arg(va, SilcUInt32); - client_list = va_arg(va, SilcBuffer); - dummy = va_arg(va, void *); // TODO: SilcBuffer client_mode_list - dummy = va_arg(va, void *); // TODO: SilcPublicKey founder_key - dummy = va_arg(va, void *); // TODO: SilcBuffer channel_pubkeys context->user_limit = va_arg(va, SilcUInt32); - - silc_client_get_clients_by_list(client, conn, - client_count, client_list, - _pysilc_client_callback_command_reply_join_finished, - context); + + _pysilc_client_callback_command_reply_join_finished(client, conn, context); + break; } case SILC_COMMAND_MOTD: @@ -832,21 +931,19 @@ static void _pysilc_client_callback_command_reply(Silc PYSILC_NEW_CHANNEL_OR_BREAK(va_arg(va, SilcChannelEntry), pychannel); // get all users from this channel .. tedious - SilcUInt32 user_count = va_arg(va, SilcUInt32); - pyuser = PyTuple_New(user_count); // hijack pyuser so we get autocleanup int i = 0; SilcHashTableList hash_list; SilcClientEntry user, cached; SilcChannelUser user_channel; PyObject *u = NULL; SilcChannelEntry channel = ((PySilcChannel *)pychannel)->silcobj; + SilcUInt32 user_count = silc_hash_table_count(channel->user_list); + pyuser = PyTuple_New(user_count); // hijack pyuser so we get autocleanup - printf("user: %d\n", user_count); - if (channel && channel->user_list) { silc_hash_table_list(channel->user_list, &hash_list); while (silc_hash_table_get(&hash_list, (void *)&user, (void *)&user_channel)) { - cached = silc_client_get_client_by_id(client, conn, user->id); + cached = silc_client_get_client_by_id(client, conn, &(user->id)); if (cached) { u = PySilcUser_New(cached); PyTuple_SetItem(pyuser, i, u); @@ -880,60 +977,37 @@ cleanup: Py_XDECREF(pyuser); } -static void _pysilc_client_callback_verify_key(SilcClient client, +static void _pysilc_client_callback_verify_key(SilcClient client, SilcClientConnection conn, - SilcSocketType conn_type, - unsigned char *pk, - SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, + SilcConnectionType conn_type, + SilcPublicKey public_key, + SilcVerifyPublicKey completion, void *context) { // TODO: implement me completion(TRUE, context); } -static void _pysilc_client_callback_get_auth_method(SilcClient client, +static void _pysilc_client_callback_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, + char *hostname, SilcUInt16 port, - SilcGetAuthMeth completion, + SilcAuthMethod auth_method, + SilcGetAuthMeth completion, void *context) { // TODO: implement this properly - completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context); + completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context); } -static void _pysilc_client_callback_failure(SilcClient client, - SilcClientConnection conn, - SilcProtocol protocol, - void *failure) +static void _pysilc_client_callback_key_agreement(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry, + const char *hostname, + SilcUInt16 protocol, + SilcUInt16 port) { - PYSILC_GET_CLIENT_OR_DIE(client, pyclient); - PyObject *callback = NULL, *result = NULL; - - callback = PyObject_GetAttrString((PyObject *)pyclient, "failure"); - if (!PyCallable_Check(callback)) - goto cleanup; - // TODO: pass on protocol, failure parameters - if ((result = PyObject_CallObject(callback, NULL)) == 0) - PyErr_Print(); -cleanup: - Py_XDECREF(callback); - Py_XDECREF(result); -} - - -static bool _pysilc_client_callback_key_agreement(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, - SilcUInt16 port, - SilcKeyAgreementCallback *completion, - void **context) -{ // TODO :implement me - return FALSE; } static void _pysilc_client_callback_ftp(SilcClient client, @@ -973,25 +1047,3 @@ cleanup: Py_XDECREF(callback); Py_XDECREF(result); } - -static void _pysilc_client_callback_detach(SilcClient client, - SilcClientConnection conn, - const unsigned char *detach_data, - SilcUInt32 detach_data_len) -{ - PYSILC_GET_CLIENT_OR_DIE(client, pyclient); - PyObject *result = NULL, *callback = NULL, *args = NULL; - callback = PyObject_GetAttrString((PyObject *)pyclient, "detach"); - if (!PyCallable_Check(callback)) - goto cleanup; - - if (!(args = Py_BuildValue("(s#)", detach_data, detach_data_len))) - goto cleanup; - if ((result = PyObject_CallObject(callback, args)) == 0) - PyErr_Print(); - -cleanup: - Py_XDECREF(callback); - Py_XDECREF(args); - Py_XDECREF(result); -}